Authentication for Server-side Web Apps

You can use the Auth0 Authentication API to create server-side web applications that uses OAuth 2.0 authorization to authenticate users.

Overview

Auth0 exposes OAuth 2.0 endpoints for authenticating any user. You can redirect the user from your web application to these endpoints in the web browser. Auth0 will handle the authentication of the user, and then redirect the user back to the redirect_uri (also referred to as the Callback URL), returning an authorization_code in the query string parameters of the Callback URL. This authorization_code can then be exchanged for an id_token which contains the identity of the user.

The Authentication Flow

The OAuth 2.0 Authorization Framework allows for different kinds of authorization flows (called Grant Types) depending on the type of application. The flow used for Server-side Web applications is known as the Authorization Code flow.

The Authorization Code flow is initiated by redirecting the user in the web browser to the Auth0 /authorize endpoint. Auth0 will then display the Auth0 Lock dialog, allowing the user to enter their credentials or alternatively sign in with any other configured Identity Provider.

After the user has authenticated, Auth0 will redirect the browser back to the Redirect URI (also called Callback URL), passing along an authorization_code parameter in the query string of the Callback URL. This code can then be exchanged for an id_token by making a request to the /oauth/token endpoint.

The id_token is a JSON Web Token (JWT) and contains various attributes - referred to as Claims - regarding the user, such as the user's name, email address, profile picture etc. The id_token can be decoded to extract the claims and you are free to use these inside of your application, to display a user's name and profile image for example.

  1. The Client initiates the flow and redirects the user to the Authorization Server.
  2. The user authenticates.
  3. The Authorization Server redirects to the redirect_uri with an authorization_code in the query string.
  4. The Client sends the authorization_code together with the redirect_uri and the Client Id/Client Secret to the Authorization Server.
  5. The Authorization Server validates this information and returns an id_token.

Registering your Client

The first thing you need to do is to create a new client in Auth0. An Auth0 client maps to your application and allows it to use Auth0 for authentication.

Navigate to the Auth0 Dashboard and click on the Clients menu option on the left. Create a new Client by clicking on the Create Client button.

The Create Client window will open, allowing you to enter the name of your new application. Choose Regular Web Applications as the Client Type and click on the Create button to create the new client.

Once the client has been created you can navigate to the Settings tab of the client and in the Allowed Callback URLs field add a URL where Auth0 must redirect to after the user has authenticated, e.g. https://YOUR_APP/callback.

This URL must be part of your application, as your application will need to retrieve the code and exchange it for the id_token.

Calling the Authorization URL

The URL used when authenticating a user is https://YOUR_AUTH0_DOMAIN/authorize. This is the initial endpoint to which a user must be redirected. This will handle checking whether any SSO session is active, authenticating the user and also potentially redirect the user directly to any Identity Provider to handle authentication.

This endpoint supports the following query string parameters:

Parameter Description
response_type The response type specifies the Grant Type you want to use. This can be either code or token. For server-side web applications using the Authorization Code Flow this must be set to code
client_id The Client ID of the Client you registered in Auth0. This can be found on the Settings tab of your Client in the Auth0 Dashboard
scope Specifies the claims (i.e. attributes) of the user you want the be returned in the id_token. To obtain an id_token you need to specify at least a scope of openid (if no scope is specified then openid is implied). You can also request other scopes, so for example to return the user's name and profile picture you can request a scope of openid name picture.

You can read up more about scopes.
redirect_uri The URL in your application where the user will be redirected to after they have authenticated, e.g. https://YOUR_APP/callback

Note: Be sure to add this URL to the list of Allowed Callback URLs in the Settings tab of your Client inside the Auth0 Dashboard
connection This is an optional parameter which allows you to force the user to sign in with a specific connection. You can for example pass a value of github to send the user directly to GitHub to log in with their GitHub account.

If this parameter is not specified the user will be presented with the normal Auth0 Lock screen from where they can sign in with any of the available connections. You can see the list of configured connections on the Connections tab of your client.
state The state parameter will be sent back should be used for XSRF and contextual information (like a return url)

Exhanging the access_code for an id_token

After the user has authenticated, Auth0 will call back to the URL specified in the redirect_uri query string parameter which was passed to the /authorize endpoint. When calling back to this URL, Auth0 will pass along an access_token in the code query string parameter of the URL, e.g.

https://YOUR_APP/callback?code=2OKj...

You application will need to handle the request to this callback URL, extract the access_code from the code query string parameter and call the /oauth/token endpoint of the Auth0 Authentication API in order to exchange the access_code for the id_token:


curl --request POST \
  --url 'https://YOUR_AUTH0_DOMAIN/oauth/token' \
  --header 'content-type: application/json' \
  --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"}'
var client = new RestClient("https://YOUR_AUTH0_DOMAIN/oauth/token");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/json");
request.AddParameter("application/json", "{\"grant_type\":\"authorization_code\",\"client_id\": \"YOUR_CLIENT_ID\",\"client_secret\": \"YOUR_CLIENT_SECRET\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"redirect_uri\": \"https://YOUR_APP/callback\"}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
package main

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

func main() {

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

	payload := strings.NewReader("{\"grant_type\":\"authorization_code\",\"client_id\": \"YOUR_CLIENT_ID\",\"client_secret\": \"YOUR_CLIENT_SECRET\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"redirect_uri\": \"https://YOUR_APP/callback\"}")

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

	req.Header.Add("content-type", "application/json")

	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_AUTH0_DOMAIN/oauth/token")
  .header("content-type", "application/json")
  .body("{\"grant_type\":\"authorization_code\",\"client_id\": \"YOUR_CLIENT_ID\",\"client_secret\": \"YOUR_CLIENT_SECRET\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"redirect_uri\": \"https://YOUR_APP/callback\"}")
  .asString();
var settings = {
  "async": true,
  "crossDomain": true,
  "url": "https://YOUR_AUTH0_DOMAIN/oauth/token",
  "method": "POST",
  "headers": {
    "content-type": "application/json"
  },
  "processData": false,
  "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\"}"
}

$.ajax(settings).done(function (response) {
  console.log(response);
});
var request = require("request");

var options = { method: 'POST',
  url: 'https://YOUR_AUTH0_DOMAIN/oauth/token',
  headers: { 'content-type': 'application/json' },
  body: 
   { grant_type: 'authorization_code',
     client_id: 'YOUR_CLIENT_ID',
     client_secret: 'YOUR_CLIENT_SECRET',
     code: 'YOUR_AUTHORIZATION_CODE',
     redirect_uri: 'https://YOUR_APP/callback' },
  json: true };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
#import <Foundation/Foundation.h>

NSDictionary *headers = @{ @"content-type": @"application/json" };
NSDictionary *parameters = @{ @"grant_type": @"authorization_code",
                              @"client_id": @"YOUR_CLIENT_ID",
                              @"client_secret": @"YOUR_CLIENT_SECRET",
                              @"code": @"YOUR_AUTHORIZATION_CODE",
                              @"redirect_uri": @"https://YOUR_APP/callback" };

NSData *postData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:nil];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://YOUR_AUTH0_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, array(
  CURLOPT_URL => "https://YOUR_AUTH0_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\": \"YOUR_CLIENT_ID\",\"client_secret\": \"YOUR_CLIENT_SECRET\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"redirect_uri\": \"https://YOUR_APP/callback\"}",
  CURLOPT_HTTPHEADER => array(
    "content-type: application/json"
  ),
));

$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\": \"YOUR_CLIENT_ID\",\"client_secret\": \"YOUR_CLIENT_SECRET\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"redirect_uri\": \"https://YOUR_APP/callback\"}"

headers = { 'content-type': "application/json" }

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

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

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

url = URI("https://YOUR_AUTH0_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/json'
request.body = "{\"grant_type\":\"authorization_code\",\"client_id\": \"YOUR_CLIENT_ID\",\"client_secret\": \"YOUR_CLIENT_SECRET\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"redirect_uri\": \"https://YOUR_APP/callback\"}"

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

let headers = ["content-type": "application/json"]
let parameters = [
  "grant_type": "authorization_code",
  "client_id": "YOUR_CLIENT_ID",
  "client_secret": "YOUR_CLIENT_SECRET",
  "code": "YOUR_AUTHORIZATION_CODE",
  "redirect_uri": "https://YOUR_APP/callback"
]

let postData = NSJSONSerialization.dataWithJSONObject(parameters, options: nil, error: nil)

var request = NSMutableURLRequest(URL: NSURL(string: "https://YOUR_AUTH0_DOMAIN/oauth/token")!,
                                        cachePolicy: .UseProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.HTTPMethod = "POST"
request.allHTTPHeaderFields = headers
request.HTTPBody = postData

let session = NSURLSession.sharedSession()
let dataTask = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    println(error)
  } else {
    let httpResponse = response as? NSHTTPURLResponse
    println(httpResponse)
  }
})

dataTask.resume()

The response from /oauth/token contains an access_token, id_token and token_type values (and also potentially a refresh_token), for example:

{
  "access_token": "AP16...",
  "id_token": "eyJ0...",
  "token_type": "Bearer"
}

The token_type will be set to Bearer and the id_token will be a JSON Web Token (JWT) containing information about the user. You will need to decode the id_token in order to read the claims (i.e. attributes) of the user. The JWT section of our website contains more information about the structure of a JWT.

You can refer to the libraries section on the JWT.io website in order to obtain a library for your programming language of choice which will assist you in decoding the id_token.

Once the JWT is decoded, you can extract the information about the user from the Payload of the id_token. This is a JSON structure and will contain the claims (attributes) about the user as well as some other metadata.

The id_token Payload

An example payload for an id_token may look something like this:

{
  "name": "Jerrie Pelser",
  "email": "jerrie@j...",
  "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
}

The payload above contains the following claims:

Parameter Description
name The name of the user which is returned from the Identity Provider.
email The email address of the user which is returned from the Identity Provider.
picture The profile picture of the user which is returned from the Identity Provider.
sub The unique identifier of the user. This is guaranteed to be unique per user and will be in the format (identity provider)|(unique id in the provider), e.g. github|1234567890.
iss The issuer. A case-sensitive string or URI that uniquely identifies the party that issued the JWT. For an Auth0 issued id_token, this will be the URL of your Auth0 tenant.

This is a registered claim according to the JWT Specification
aud The audience. Either a single case-sensitive string or URI or an array of such values that uniquely identify the intended recipients of this JWT. For an Auth0 issued id_token, this will be the Client ID of your Auth0 Client.

This is a registered claim according to the JWT Specification
exp The expiration time. A number representing a specific date and time in the format “seconds since epoch” as defined by POSIX6. This claim sets the exact moment from which this JWT is considered invalid.

This is a registered claim according to the JWT Specification
iat The issued at time. A number representing a specific date and time (in the same format as exp) at which this JWT was issued.

This is a registered claim according to the JWT Specification

The exact claims contained in the id_token will depend on the scope parameter you sent to the /authorize endpoint. In an id_token issued by Auth0, the registered claims and the sub claim will always be present, but the other claims depends on the scope. You can refer to the examples below to see examples of how the scope influences the claims being returned.

Debugging a JWT

The JWT.io website has a handy debugger which will allow you to debug any JSON Web Token. This is useful is you quickly want to decode a JWT to see the information contained in the token.

Keeping the user logged in

Auth0 will assist you in authenticating a user, but it is up to you to keep track in your application of whether or not a user is logged in. You can use a cookie or other session storage to keep track of whether a user is logged in or not, and also to store the claims of the user which was extracted from the id_token.

You can then use those claims inside of your application to display the user's information or otherwise personalize the user's experience.

Examples

A Basic Authentication Request

The following is the most basic request you can make to the /authorize endpoint. It will display the Lock screen and allow a user to sign in with any of the configured connections.

https://YOUR_AUTH0_DOMAIN/authorize
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=https://YOUR_APP/callback

After the user has authenticated, they will be redirected back to the redirect_uri with the access_code in the code query string parameter:

https://YOUR_APP/callback?code=2OKj...

You can then exchange the access_code for an id_token. This is an example of the decoded payload of the id_token which will be returned:

{
  "iss": "https://auth0pnp.auth0.com/",
  "sub": "auth0|581...",
  "aud": "xvt9...",
  "exp": 1478112929,
  "iat": 1478076929
}

Requesting the Name and Profile Picture

You can request a user's name and profile picture by requesting the name and picture scopes.

https://YOUR_AUTH0_DOMAIN/authorize
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=https://YOUR_APP/callback
  &scope=openid%20name%20picture

After the user has authenticated, they will be redirected back to the redirect_uri with the access_code in the code query string parameter:

https://YOUR_APP/callback?code=2OKj...

You can then exchange the access_code for an id_token. The name and profile picture will be available in the name and picture claims of the returned id_token:

{
  "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
}

Requesting a User Log In With GitHub

You can send a user directly to the GitHub authentication screen by passing the value of github to the connection parameter. Note that we also request the openid, name, picture and email scopes:

https://YOUR_AUTH0_DOMAIN/authorize
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=https://YOUR_APP/callback
  &scope=openid%20name%20picture%20email
  &connection=github

After the user has authenticated, they will be redirected back to the redirect_uri with the id_token and token_type passed as parameters in the hash fragment:

After the user has authenticated, they will be redirected back to the redirect_uri with the access_code in the code query string parameter:

https://YOUR_APP/callback?code=2OKj...

You can then exchange the access_code for an id_token. The user's name and profile picture and email address will be available in the name, picture and email claims of the returned id_token. You will also notice that the sub claim contains the User's unique ID returned from GitHub:

{
  "name": "Jerrie Pelser",
  "picture": "https://avatars.githubusercontent.com/u/1006420?v=3",
  "email": "jerrie@...",
  "email_verified": true,
  "iss": "https://auth0pnp.auth0.com/",
  "sub": "github|100...",
  "aud": "xvt...",
  "exp": 1478114742,
  "iat": 1478078742
}