Add Login Using the Authorization Code Flow

You can add login to your regular web application using the Authorization Code Flow. To learn how the flow works and why you should use it, read Authorization Code Flow. To call your API from a regular web app, read Call Your API Using the Authorization Code Flow.

To implement the Authorization Code Flow, Auth0 provides the following resources:

Following a successful login, your application will have access to the user's ID token and access token. The ID token contains basic user profile information, and the access token can be used to call the Auth0 /userinfo endpoint or your own protected APIs. To learn more about ID tokens, read ID Tokens. To learn more about access tokens, read Access Tokens.

You will request the user's authorization and redirect back to your app with an authorization_code. Then you will exchange the code for tokens.

Prerequisites

Register your app with Auth0. To learn more, read Register Regular Web Applications.

  • Select Regular Web App as the Application Type.

  • Add an Allowed Callback URL of https://YOUR_APP/callback.

  • Make sure your application's Grant Types include Authorization Code. To learn more, read Update Grant Types.

Authorize user

To begin the flow, you'll need to get the user's authorization. This step may include one or more of the following processes:

  • Authenticating the user;

  • Redirecting the user to an Identity Provider to handle authentication;

  • Obtaining user consent for the requested permission level, unless consent has been previously given.

To authorize the user, your app must send the user to the authorization URL.

Authorization URL example

https://YOUR_DOMAIN/authorize?
    response_type=code&
    client_id=YOUR_CLIENT_ID&
    redirect_uri=https://YOUR_APP/callback&
    scope=SCOPE&
    state=STATE

Parameters

Parameter Name Description
response_type Denotes the kind of credential that Auth0 will return (code or token). For this flow, the value must be code.
client_id Your application's Client ID. You can find this value in your Application Settings.
redirect_uri The URL to which Auth0 will redirect the browser after authorization has been granted by the user. The Authorization Code will be available in the code URL parameter. You must specify this URL as a valid callback URL in your Application Settings.

Warning: Per the OAuth 2.0 Specification, Auth0 removes everything after the hash and does not honor any fragments.
scope Specifies the scopes for which you want to request authorization, which dictate which claims (or user attributes) you want returned. These must be separated by a space. To get an ID Token in the response, you need to specify a scope of at least openid. If you want to return the user's full profile, you can request openid profile. You can request any of the standard OpenID Connect (OIDC) scopes about users, such as email, or custom claims conforming to a namespaced format. Include offline_access to get a Refresh Token (make sure that the Allow Offline Access field is enabled in the Application Settings).
state (recommended) An opaque arbitrary alphanumeric string your app adds to the initial request that Auth0 includes when redirecting back to your application. To see how to use this value to prevent cross-site request forgery (CSRF) attacks, see Mitigate CSRF Attacks With State Parameters.
connection (optional) Forces the user to sign in with a specific connection. For example, you can pass a value of github to send the user directly to GitHub to log in with their GitHub account. When not specified, the user sees the Auth0 Lock screen with all configured connections. You can see a list of your configured connections on the Connections tab of your application.
organization (optional) ID of the organization to use when authenticating a user. When not provided, if your application is configured to Display Organization Prompt, the user will be able to enter the organization name when authenticating.
invitation (optional) Ticket ID of the organization invitation. When inviting a member to an Organization, your application should handle invitation acceptance by forwarding the invitation and organization key-value pairs when the user accepts the invitation.

As an example, your HTML snippet for your authorization URL when adding login to your app might look like:

<a href="https://YOUR_DOMAIN/authorize?
  response_type=code&
  client_id=YOUR_CLIENT_ID&
  redirect_uri=https://YOUR_APP/callback&
  scope=openid%20profile&
  state=xyzABC123">
  Sign In
</a>

Response

If all goes well, you'll receive an HTTP 302 response. The authorization code is included at the end of the URL:

HTTP/1.1 302 Found
Location: https://YOUR_APP/callback?code=AUTHORIZATION_CODE&state=xyzABC123

Request tokens

Now that you have an Authorization Code, you must exchange it for tokens. Using the extracted Authorization Code (code) from the previous step, you will need to POST to the token URL.

POST to token URL example


curl --request POST \
  --url 'https://YOUR_DOMAIN/oauth/token' \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data grant_type=authorization_code \
  --data 'client_id=YOUR_CLIENT_ID' \
  --data client_secret=YOUR_CLIENT_SECRET \
  --data code=YOUR_AUTHORIZATION_CODE \
  --data 'redirect_uri=https://YOUR_APP/callback'
var client = new RestClient("https://YOUR_DOMAIN/oauth/token");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddParameter("application/x-www-form-urlencoded", "grant_type=authorization_code&client_id=%24%7Baccount.clientId%7D&client_secret=YOUR_CLIENT_SECRET&code=YOUR_AUTHORIZATION_CODE&redirect_uri=%24%7Baccount.callback%7D", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io/ioutil"
)

func main() {

	url := "https://YOUR_DOMAIN/oauth/token"

	payload := strings.NewReader("grant_type=authorization_code&client_id=%24%7Baccount.clientId%7D&client_secret=YOUR_CLIENT_SECRET&code=YOUR_AUTHORIZATION_CODE&redirect_uri=%24%7Baccount.callback%7D")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("content-type", "application/x-www-form-urlencoded")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.post("https://YOUR_DOMAIN/oauth/token")
  .header("content-type", "application/x-www-form-urlencoded")
  .body("grant_type=authorization_code&client_id=%24%7Baccount.clientId%7D&client_secret=YOUR_CLIENT_SECRET&code=YOUR_AUTHORIZATION_CODE&redirect_uri=%24%7Baccount.callback%7D")
  .asString();
var axios = require("axios").default;

var options = {
  method: 'POST',
  url: 'https://YOUR_DOMAIN/oauth/token',
  headers: {'content-type': 'application/x-www-form-urlencoded'},
  data: {
    grant_type: 'authorization_code',
    client_id: 'YOUR_CLIENT_ID',
    client_secret: 'YOUR_CLIENT_SECRET',
    code: 'YOUR_AUTHORIZATION_CODE',
    redirect_uri: 'https://YOUR_APP/callback'
  }
};

axios.request(options).then(function (response) {
  console.log(response.data);
}).catch(function (error) {
  console.error(error);
});
#import <Foundation/Foundation.h>

NSDictionary *headers = @{ @"content-type": @"application/x-www-form-urlencoded" };

NSMutableData *postData = [[NSMutableData alloc] initWithData:[@"grant_type=authorization_code" dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[@"&client_id=YOUR_CLIENT_ID" dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[@"&client_secret=YOUR_CLIENT_SECRET" dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[@"&code=YOUR_AUTHORIZATION_CODE" dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[@"&redirect_uri=https://YOUR_APP/callback" dataUsingEncoding:NSUTF8StringEncoding]];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://YOUR_DOMAIN/oauth/token"]
                                                       cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                   timeoutInterval:10.0];
[request setHTTPMethod:@"POST"];
[request setAllHTTPHeaderFields:headers];
[request setHTTPBody:postData];

NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
                                            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                if (error) {
                                                    NSLog(@"%@", error);
                                                } else {
                                                    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
                                                    NSLog(@"%@", httpResponse);
                                                }
                                            }];
[dataTask resume];
$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://YOUR_DOMAIN/oauth/token",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "grant_type=authorization_code&client_id=%24%7Baccount.clientId%7D&client_secret=YOUR_CLIENT_SECRET&code=YOUR_AUTHORIZATION_CODE&redirect_uri=%24%7Baccount.callback%7D",
  CURLOPT_HTTPHEADER => [
    "content-type: application/x-www-form-urlencoded"
  ],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}
import http.client

conn = http.client.HTTPSConnection("")

payload = "grant_type=authorization_code&client_id=%24%7Baccount.clientId%7D&client_secret=YOUR_CLIENT_SECRET&code=YOUR_AUTHORIZATION_CODE&redirect_uri=%24%7Baccount.callback%7D"

headers = { 'content-type': "application/x-www-form-urlencoded" }

conn.request("POST", "/YOUR_DOMAIN/oauth/token", payload, headers)

res = conn.getresponse()
data = res.read()

print(data.decode("utf-8"))
require 'uri'
require 'net/http'
require 'openssl'

url = URI("https://YOUR_DOMAIN/oauth/token")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/x-www-form-urlencoded'
request.body = "grant_type=authorization_code&client_id=%24%7Baccount.clientId%7D&client_secret=YOUR_CLIENT_SECRET&code=YOUR_AUTHORIZATION_CODE&redirect_uri=%24%7Baccount.callback%7D"

response = http.request(request)
puts response.read_body
import Foundation

let headers = ["content-type": "application/x-www-form-urlencoded"]

let postData = NSMutableData(data: "grant_type=authorization_code".data(using: String.Encoding.utf8)!)
postData.append("&client_id=YOUR_CLIENT_ID".data(using: String.Encoding.utf8)!)
postData.append("&client_secret=YOUR_CLIENT_SECRET".data(using: String.Encoding.utf8)!)
postData.append("&code=YOUR_AUTHORIZATION_CODE".data(using: String.Encoding.utf8)!)
postData.append("&redirect_uri=https://YOUR_APP/callback".data(using: String.Encoding.utf8)!)

let request = NSMutableURLRequest(url: NSURL(string: "https://YOUR_DOMAIN/oauth/token")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()

Parameters

Parameter Name Description
grant_type Set this to authorization_code.
code The authorization_code retrieved in the previous step of this tutorial.
client_id Your application's Client ID. You can find this value in your Application Settings.
client_secret Your application's Client Secret. You can find this value in your Application Settings.
redirect_uri The valid callback URL set in your Application settings. This must exactly match the redirect_uri passed to the authorization URL in the previous step of this tutorial. Note that this must be URL encoded.

Response

If all goes well, you'll receive an HTTP 200 response with a payload containing access_token, refresh_token, id_token, and token_type values:

{
  "access_token": "eyJz93a...k4laUWw",
  "refresh_token": "GEbRxBN...edjnXbL",
  "id_token": "eyJ0XAi...4faeEoQ",
  "token_type": "Bearer"
}

You should validate your tokens before saving them. To learn how, see Validate ID Tokens and Validate Access Tokens.

ID Tokens contain user information that must be decoded and extracted.

Access Tokens are used to call the Auth0 Authentication API's /userinfo endpoint or another API. If you are calling your own API, the first thing your API will need to do is verify the Access Token.

Refresh Tokens are used to obtain a new Access Token or ID Token after the previous one has expired. The refresh_token will only be present in the response if you included the offline_access scope and enabled Allow Offline Access for your API in the Dashboard.

Refresh Tokens must be stored securely since they allow a user to remain authenticated essentially forever.

Use cases

Basic authentication request

This example shows the most basic request you can make when authorizing the user in step 1. It displays the Auth0 login screen and allows the user to sign in with any of your configured connections:

https://YOUR_DOMAIN/authorize?
    response_type=code&
    client_id=YOUR_CLIENT_ID&
    redirect_uri=https://YOUR_APP/callback&
    scope=openid
Now, when you request tokens, your ID Token will contain the most basic claims. When you decode the ID Token, it will look similar to:
{
  "iss": "https://auth0pnp.auth0.com/",
  "sub": "auth0|581...",
  "aud": "xvt9...",
  "exp": 1478112929,
  "iat": 1478076929
}

Request user's name and profile picture

In addition to the usual user authentication, this example shows how to request additional user details, such as name and picture.

To request the user's name and picture, you need to add the appropriate scopes when authorizing the user:

https://YOUR_DOMAIN/authorize?
    response_type=code&
    client_id=YOUR_CLIENT_ID&
    redirect_uri=https://YOUR_APP/callback&
    scope=openid%20name%20picture&
    state=STATE
Now, when you request tokens, your ID token will contain the requested name and picture claims. When you decode the ID token, it will look similar to:
{
  "name": "jerrie@...",
  "picture": "https://s.gravatar.com/avatar/6222081fd7dcea7dfb193788d138c457?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fje.png",
  "iss": "https://auth0pnp.auth0.com/",
  "sub": "auth0|581...",
  "aud": "xvt...",
  "exp": 1478113129,
  "iat": 1478077129
}

Request user log in with GitHub

In addition to the usual user authentication, this example shows how to send users directly to a social identity provider, such as GitHub. You will first need to configure the appropriate connection in Auth0 Dashboard > Authentication > Social and get the connection name from the Settings tab.

To send users directly to the GitHub login screen, you need to pass the connection parameter and set its value to the connection name (in this case, github) when authorizing the user in step 1:

https://YOUR_DOMAIN/authorize?
    response_type=code&
    client_id=YOUR_CLIENT_ID&
    redirect_uri=https://YOUR_APP/callback&
    scope=openid%20name%20picture&
    state=STATE&
    connection=github
Now, when you request tokens, your ID Token will contain a sub claim with the user's unique ID returned from GitHub. When you decode the ID token, it will look similar to:
{
  "name": "Jerrie Pelser",
  "nickname": "jerriep",
  "picture": "https://avatars.githubusercontent.com/u/1006420?v=3",
  "iss": "https://auth0pnp.auth0.com/",
  "sub": "github|100...",
  "aud": "xvt...",
  "exp": 1478114742,
  "iat": 1478078742
}
To learn more about possible connections, read Set Up Social Connections.

Learn more