Call Your API Using the Mobile Login Flow

This tutorial will help you call your own API from a native/mobile app using the mobile login flow. If you want to learn how the flow works and why you should use it, see Mobile Login Flow. If you want to learn to add login to your native/mobile app, see Add Login to Your Native/Mobile App.

Auth0 makes it easy for your app to implement the mobile login flow using:

  • Auth0 Mobile SDKs: The easiest way to implement the mobile login flow, which will do most of the heavy-lifting for you. Our Mobile Quickstarts will walk you through the process.
  • Authentication API: If you prefer to roll your own, keep reading to learn how to call our API directly.

Prerequisites

Before beginning this tutorial:

Steps

When your app needs to access

  1. Create a code verifier: Generate a code_verifier that will be sent to Auth0 to request tokens.
  2. Create a code challenge: Generate a code_challenge from the code_verifier that will be sent to Auth0 to request an authorization_code.
  3. Authorize the user: Request the user's authorization and redirect back to your app with an authorization_code.
  4. Request Tokens: Exchange your authorization_code and code_verifier for tokens.
  5. Call Your API: Use the retrieved Access Token to call your API.
  6. Refresh Tokens: Use a refresh token to request new tokens when the existing ones expire.

Optional: Explore Sample Use Cases

Create a Code Verifier

Create a code_verifier, which is a cryptographically-random key that will eventually be sent to Auth0 to request an authorization_code.

// Dependency: Node.js crypto module
// https://nodejs.org/api/crypto.html#crypto_crypto
function base64URLEncode(str) {
    return str.toString('base64')
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=/g, '');
}
var verifier = base64URLEncode(crypto.randomBytes(32));
// Dependency: Apache Commons Codec
// https://commons.apache.org/proper/commons-codec/
// Import the Base64 class.
// import org.apache.commons.codec.binary.Base64;
SecureRandom sr = new SecureRandom();
byte[] code = new byte[32];
sr.nextBytes(code);
String verifier = Base64.encodeToString(code, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);
var buffer = [UInt8](repeating: 0, count: 32)
_ = SecRandomCopyBytes(kSecRandomDefault, buffer.count, &buffer)
let verifier = Data(bytes: buffer).base64EncodedString()
    .replacingOccurrences(of: "+", with: "-")
    .replacingOccurrences(of: "/", with: "\_")
    .replacingOccurrences(of: "=", with: "")
    .trimmingCharacters(in: .whitespaces)
NSMutableData *data = [NSMutableData dataWithLength:32];
int result __attribute__((unused)) = SecRandomCopyBytes(kSecRandomDefault, 32, data.mutableBytes);
NSString *verifier = [[[[data base64EncodedStringWithOptions:0]
                        stringByReplacingOccurrencesOfString:@"+" withString:@"-"]
                        stringByReplacingOccurrencesOfString:@"/" withString:@"_"]
                        stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"="]];

Create a Code Challenge

Generate a code_challenge from the code_verifier that will be sent to Auth0 to request an authorization_code.

// Dependency: Node.js crypto module
// https://nodejs.org/api/crypto.html#crypto_crypto
function sha256(buffer) {
    return crypto.createHash('sha256').update(buffer).digest();
}
var challenge = base64URLEncode(sha256(verifier));
// Dependency: Apache Commons Codec
// https://commons.apache.org/proper/commons-codec/
// Import the Base64 class.
// import org.apache.commons.codec.binary.Base64;
byte[] bytes = verifier.getBytes("US-ASCII");
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(bytes, 0, bytes.length);
byte[] digest = md.digest();
String challenge = Base64.encodeBase64URLSafeString(digest);
// Dependency: Apple Common Crypto library
// http://opensource.apple.com//source/CommonCrypto
guard let data = verifier.data(using: .utf8) else { return nil }
var buffer = [UInt8](repeating: 0,  count: Int(CC_SHA256_DIGEST_LENGTH))
data.withUnsafeBytes {
    _ = CC_SHA256($0, CC_LONG(data.count), &buffer)
}
let hash = Data(bytes: buffer)
let challenge = hash.base64EncodedString()
    .replacingOccurrences(of: "+", with: "-")
    .replacingOccurrences(of: "/", with: "\_")
    .replacingOccurrences(of: "=", with: "")
    .trimmingCharacters(in: .whitespaces)
// Dependency: Apple Common Crypto library
// http://opensource.apple.com//source/CommonCrypto
u_int8_t buffer[CC_SHA256_DIGEST_LENGTH * sizeof(u_int8_t)];
memset(buffer, 0x0, CC_SHA256_DIGEST_LENGTH);
NSData *data = [verifier dataUsingEncoding:NSUTF8StringEncoding];
CC_SHA256([data bytes], (CC_LONG)[data length], buffer);
NSData *hash = [NSData dataWithBytes:buffer length:CC_SHA256_DIGEST_LENGTH];
NSString *challenge = [[[[hash base64EncodedStringWithOptions:0]
                         stringByReplacingOccurrencesOfString:@"+" withString:@"-"]
                         stringByReplacingOccurrencesOfString:@"/" withString:@"_"]
                         stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"="]];

Authorize the User

Once you've created the code_verifier and the code_challenge, you'll need to get the user's authorization. This is technically the beginning of the authorization flow, and this step may include one or more of the following processes:

  • Authenticating the user;
  • Redirecting the user to an Identity Provider to handle authentication;
  • Checking for active SSO sessions;
  • 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, including the code_challenge you generated in the previous step and the method you used to generate the code_challenge.

Example authorization URL

https://YOUR_AUTH0_DOMAIN/authorize?
    response_type=code&
    code_challenge=CODE_CHALLENGE&
    code_challenge_method=S256&
    client_id=YOUR_CLIENT_ID&
    redirect_uri=YOUR_CALLBACK_URL&
    scope=SCOPE&
    audience=API_AUDIENCE&
    state=STATE

Parameters

Note that for authorizing a user when calling an API, you:

  • must include an audience parameter
  • can include additional scopes supported by the target API
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.
code_challenge Generated challenge from the code_verifier.
code_challenge_method Method used to generate the challenge (e.g., S256). The PKCE spec defines two methods, S256 and plain, the former is used in this example and is the only one supported by Auth0 since the latter is discouraged.
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 The scopes for which you want to request authorization. These must be separated by a space. You can request any of the standard OIDC scopes about users, such as profile and email, custom claims conforming to a namespaced format, or any scopes supported by the target API (e.g., read:contacts). Include offline_access to get a Refresh Token (make sure that the Allow Offline Access field is enabled in the Application Settings). For more information on this, refer to the Namespacing Custom Claims panel.
audience The unique identifier of the API your mobile app wants to access. Use the Identifier value on the Settings tab for the API you created as part of the prerequisites for this tutorial.
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 Use the State Parameter Against CSRF Attacks.

As an example, your HTML snippet for your authorization URL when calling an API might look like:

<a href="https://YOUR_AUTH0_DOMAIN/authorize?
  response_type=code&
  client_id=YOUR_CLIENT_ID&
  code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&
  code_challenge_method=S256&
  redirect_uri=YOUR_CALLBACK_URL&
  scope=appointments%20contacts&
  audience=appointments:api&
  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: YOUR_CALLBACK_URL?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 sending along the code_verifier.

Example POST to token URL


curl --request POST \
  --url 'https://YOUR_AUTH0_DOMAIN/oauth/token' \
  --header 'content-type: application/json' \
  --data '{"grant_type":"authorization_code","code_verifier": "YOUR_GENERATED_CODE_VERIFIER","code": "YOUR_AUTHORIZATION_CODE","client_id": "YOUR_CLIENT_ID","redirect_uri": "YOUR_CALLBACK_URL" }'
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\",\"code_verifier\": \"YOUR_GENERATED_CODE_VERIFIER\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"client_id\": \"YOUR_CLIENT_ID\",\"redirect_uri\": \"YOUR_CALLBACK_URL\" }", 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\",\"code_verifier\": \"YOUR_GENERATED_CODE_VERIFIER\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"client_id\": \"YOUR_CLIENT_ID\",\"redirect_uri\": \"YOUR_CALLBACK_URL\" }")

	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\",\"code_verifier\": \"YOUR_GENERATED_CODE_VERIFIER\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"client_id\": \"YOUR_CLIENT_ID\",\"redirect_uri\": \"YOUR_CALLBACK_URL\" }")
  .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\",\"code_verifier\": \"YOUR_GENERATED_CODE_VERIFIER\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"client_id\": \"YOUR_CLIENT_ID\",\"redirect_uri\": \"YOUR_CALLBACK_URL\" }"
}

$.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',
     code_verifier: 'YOUR_GENERATED_CODE_VERIFIER',
     code: 'YOUR_AUTHORIZATION_CODE',
     client_id: 'YOUR_CLIENT_ID',
     redirect_uri: 'YOUR_CALLBACK_URL' },
  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",
                              @"code_verifier": @"YOUR_GENERATED_CODE_VERIFIER",
                              @"code": @"YOUR_AUTHORIZATION_CODE",
                              @"client_id": @"YOUR_CLIENT_ID",
                              @"redirect_uri": @"YOUR_CALLBACK_URL" };

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\",\"code_verifier\": \"YOUR_GENERATED_CODE_VERIFIER\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"client_id\": \"YOUR_CLIENT_ID\",\"redirect_uri\": \"YOUR_CALLBACK_URL\" }",
  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\",\"code_verifier\": \"YOUR_GENERATED_CODE_VERIFIER\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"client_id\": \"YOUR_CLIENT_ID\",\"redirect_uri\": \"YOUR_CALLBACK_URL\" }"

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\",\"code_verifier\": \"YOUR_GENERATED_CODE_VERIFIER\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"client_id\": \"YOUR_CLIENT_ID\",\"redirect_uri\": \"YOUR_CALLBACK_URL\" }"

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

let headers = ["content-type": "application/json"]
let parameters = [
  "grant_type": "authorization_code",
  "code_verifier": "YOUR_GENERATED_CODE_VERIFIER",
  "code": "YOUR_AUTHORIZATION_CODE",
  "client_id": "YOUR_CLIENT_ID",
  "redirect_uri": "YOUR_CALLBACK_URL"
]

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()

Parameters

Parameter Name Description
grant_type Set this to "authorization_code".
code_verifier The cryptographically-random key that was generated in the first step of this tutorial.
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.
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.

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",
  "expires_in":86400
}

You should validate your tokens before saving them. To learn how, see Validate an ID Token and Verify 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.

Call your API

To call your API from a native/mobile application, the application must pass the retrieved Access Token as a Bearer token in the Authorization header of your HTTP request.


curl --request GET \
  --url https://myapi.com/api \
  --header 'authorization: Bearer ACCESS_TOKEN' \
  --header 'content-type: application/json'
var client = new RestClient("https://myapi.com/api");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Bearer ACCESS_TOKEN");
request.AddHeader("content-type", "application/json");
IRestResponse response = client.Execute(request);
package main

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

func main() {

	url := "https://myapi.com/api"

	req, _ := http.NewRequest("GET", url, nil)

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

	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.get("https://myapi.com/api")
  .header("content-type", "application/json")
  .header("authorization", "Bearer ACCESS_TOKEN")
  .asString();
var settings = {
  "async": true,
  "crossDomain": true,
  "url": "https://myapi.com/api",
  "method": "GET",
  "headers": {
    "content-type": "application/json",
    "authorization": "Bearer ACCESS_TOKEN"
  }
}

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

var options = { method: 'GET',
  url: 'https://myapi.com/api',
  headers: 
   { authorization: 'Bearer ACCESS_TOKEN',
     'content-type': 'application/json' } };

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",
                           @"authorization": @"Bearer ACCESS_TOKEN" };

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://myapi.com/api"]
                                                       cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                   timeoutInterval:10.0];
[request setHTTPMethod:@"GET"];
[request setAllHTTPHeaderFields:headers];

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://myapi.com/api",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_HTTPHEADER => array(
    "authorization: Bearer ACCESS_TOKEN",
    "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("myapi.com")

headers = {
    'content-type': "application/json",
    'authorization': "Bearer ACCESS_TOKEN"
    }

conn.request("GET", "/api", headers=headers)

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

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

url = URI("https://myapi.com/api")

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

request = Net::HTTP::Get.new(url)
request["content-type"] = 'application/json'
request["authorization"] = 'Bearer ACCESS_TOKEN'

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

let headers = [
  "content-type": "application/json",
  "authorization": "Bearer ACCESS_TOKEN"
]

var request = NSMutableURLRequest(URL: NSURL(string: "https://myapi.com/api")!,
                                        cachePolicy: .UseProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.HTTPMethod = "GET"
request.allHTTPHeaderFields = headers

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()

Refresh Tokens

You have already received a Refresh Token if you've been following this tutorial and completed the following:

  • configured your API to allow offline access
  • included the offline_access scope when you initiated the authentication request through the authorize endpoint

You can use the Refresh Token to get a new Access Token. Usually, a user will need a new Access Token only after the previous one expires or when gaining access to a new resource for the first time. It's bad practice to call the endpoint to get a new Access Token every time you call an API, and Auth0 maintains rate limits that will throttle the amount of requests to the endpoint that can be executed using the same token from the same IP.

To refresh your token, make a POST request to the /token endpoint in the Authentication API, using grant_type=refresh_token.

Example POST to token URL


curl --request POST \
  --url 'https://YOUR_AUTH0_DOMAIN/oauth/token' \
  --header 'content-type: application/json' \
  --data '{ "grant_type": "refresh_token", "client_id": "YOUR_CLIENT_ID", "refresh_token": "YOUR_REFRESH_TOKEN" }'
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\": \"refresh_token\", \"client_id\": \"YOUR_CLIENT_ID\", \"refresh_token\": \"YOUR_REFRESH_TOKEN\" }", 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\": \"refresh_token\", \"client_id\": \"YOUR_CLIENT_ID\", \"refresh_token\": \"YOUR_REFRESH_TOKEN\" }")

	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\": \"refresh_token\", \"client_id\": \"YOUR_CLIENT_ID\", \"refresh_token\": \"YOUR_REFRESH_TOKEN\" }")
  .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\": \"refresh_token\", \"client_id\": \"YOUR_CLIENT_ID\", \"refresh_token\": \"YOUR_REFRESH_TOKEN\" }"
}

$.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: 'refresh_token',
     client_id: 'YOUR_CLIENT_ID',
     refresh_token: 'YOUR_REFRESH_TOKEN' },
  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": @"refresh_token",
                              @"client_id": @"YOUR_CLIENT_ID",
                              @"refresh_token": @"YOUR_REFRESH_TOKEN" };

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\": \"refresh_token\", \"client_id\": \"YOUR_CLIENT_ID\", \"refresh_token\": \"YOUR_REFRESH_TOKEN\" }",
  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\": \"refresh_token\", \"client_id\": \"YOUR_CLIENT_ID\", \"refresh_token\": \"YOUR_REFRESH_TOKEN\" }"

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\": \"refresh_token\", \"client_id\": \"YOUR_CLIENT_ID\", \"refresh_token\": \"YOUR_REFRESH_TOKEN\" }"

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

let headers = ["content-type": "application/json"]
let parameters = [
  "grant_type": "refresh_token",
  "client_id": "YOUR_CLIENT_ID",
  "refresh_token": "YOUR_REFRESH_TOKEN"
]

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()

Parameters

Parameter Name Description
grant_type Set this to "refresh_token".
client_id Your application's Client ID. You can find this value in your Application Settings.
refresh_token The Refresh Token to use.
scope (Optional) A space-delimited list of requested scope permissions. If not sent, the original scopes will be used; otherwise you can request a reduced set of scopes.

Response

If all goes well, you'll receive an HTTP 200 response with a payload containing a new access_token, its lifetime in seconds (expires_in), granted scope values, and token_type. If the scope of the initial token included openid, then the response will also include a new id_token:

{
  "access_token": "eyJ...MoQ",
  "expires_in": 86400,
  "scope": "openid offline_access",
  "id_token": "eyJ...0NE",
  "token_type": "Bearer"
}

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

Sample Use Cases

Customize Tokens

You can use Rules to change the returned scopes of Access Tokens and/or add claims to Access and ID Tokens. To do so, add the following rule, which will run after the user authenticates:

function(user, context, callback) {

  // add custom claims to Access Token and ID Token
  context.accessToken['http://foo/bar'] = 'value';
  context.idToken['http://fiz/baz'] = 'some other value';

  // change scope
  context.accessToken.scope = ['array', 'of', 'strings'];

  callback(null, user, context);
}

Namespacing Custom Claims

Auth0 returns profile information in a structured claim format as defined by the OIDC specification. This means that custom claims added to ID Tokens or Access Tokens must conform to a namespaced format to avoid possible collisions with standard OIDC claims. For example, if you choose the namespace https://foo.com/ and you want to add a custom claim named myclaim, you would name the claim https://foo.com/myclaim, instead of myclaim.

View Sample Application: Mobile App + API

For an sample implementation, see the Mobile + API architecture scenario. This series of tutorials is accompanied by a code sample that you can access in GitHub.

Keep Reading