Call an Identity Provider API

Upon successful authentication of a user with an external Identity Provider (Facebook, Github, etc.), the IdP often provides an access token with the appropriate scope in the user profile that can be used to call their API.

To avoid leaking in the browser, this access token has been removed from the user profile. If you need to get the user's IDP access token, you will need to call the Get Users by ID endpoint with read:user_idp_tokens scope.

This document details the recommended method for calling a third-party IdP without exposing the access token.

The basic flow is the following:

  • Create a client that will be used to get an access token with the read:user_idp_tokens scope valid to obtain authorized access to the Auth0 Management API.
  • Write code on your backend to handle your request to the external IdP API which will:
    1. Execute the client credentials exchange to obtain a valid Auth0 access token.
    2. Use the Auth0 access token to execute the request to the /api/v2/users/{user_id} endpoint.
    3. Use the IdP access token extracted from the user profile to make calls to the IdP API.

These steps are explained in detail below.

Create a client

You will need to create a client that you will call from your service to interact with the Auth0 Management API to obtain an Auth0 access token.

To create a client, follow these steps:

  1. Go to the Clients section of the Auth0 dashboard and click Create Client. Select Non Interactive Clients and click Create. Once the cient is created, copy the Client ID and Client Secret from the Settings page.

  2. Next, go to the APIs section of the Auth0 dashboard and select the Auth0 Management API.

    NOTE: If you do not see the APIs option in the left menu, you must enable it. Go to Account Settings > Advanced and select Enable APIs Section.

  3. Select the Non Interactive Clients tab and authorize the app you just created.

  4. From the list of available scopes, select read:user_idp_tokens and click Update.

Auth0 Management API Scopes

For more information on creating a client to access the Auth0 API, see: API Authorization: Using the Auth0 Dashboard.

On the backend

Create a service to execute the following three steps:

1. Obtain an Auth0 access token

To execute a client credentials exchange to obtain an access token to get authorized access to the Auth0 Management API, include the following code:


curl --request POST \
  --url 'https://YOUR_AUTH0_DOMAIN/oauth/token' \
  --header 'content-type: application/json' \
  --data '{ "client_id": "YOUR_CLIENT_ID", "client_secret": "YOUR_CLIENT_SECRET", "audience": "https://YOUR_AUTH0_DOMAIN/api/v2/", "grant_type": "client_credentials" }'
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", "{ \"client_id\": \"YOUR_CLIENT_ID\", \"client_secret\": \"YOUR_CLIENT_SECRET\", \"audience\": \"https://YOUR_AUTH0_DOMAIN/api/v2/\", \"grant_type\": \"client_credentials\" }", 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("{ \"client_id\": \"YOUR_CLIENT_ID\", \"client_secret\": \"YOUR_CLIENT_SECRET\", \"audience\": \"https://YOUR_AUTH0_DOMAIN/api/v2/\", \"grant_type\": \"client_credentials\" }")

	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("{ \"client_id\": \"YOUR_CLIENT_ID\", \"client_secret\": \"YOUR_CLIENT_SECRET\", \"audience\": \"https://YOUR_AUTH0_DOMAIN/api/v2/\", \"grant_type\": \"client_credentials\" }")
  .asString();
var settings = {
  "async": true,
  "crossDomain": true,
  "url": "https://YOUR_AUTH0_DOMAIN/oauth/token",
  "method": "POST",
  "headers": {
    "content-type": "application/json"
  },
  "processData": false,
  "data": "{ \"client_id\": \"YOUR_CLIENT_ID\", \"client_secret\": \"YOUR_CLIENT_SECRET\", \"audience\": \"https://YOUR_AUTH0_DOMAIN/api/v2/\", \"grant_type\": \"client_credentials\" }"
}

$.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: 
   { client_id: 'YOUR_CLIENT_ID',
     client_secret: 'YOUR_CLIENT_SECRET',
     audience: 'https://YOUR_AUTH0_DOMAIN/api/v2/',
     grant_type: 'client_credentials' },
  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 = @{ @"client_id": @"YOUR_CLIENT_ID",
                              @"client_secret": @"YOUR_CLIENT_SECRET",
                              @"audience": @"https://YOUR_AUTH0_DOMAIN/api/v2/",
                              @"grant_type": @"client_credentials" };

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 => "{ \"client_id\": \"YOUR_CLIENT_ID\", \"client_secret\": \"YOUR_CLIENT_SECRET\", \"audience\": \"https://YOUR_AUTH0_DOMAIN/api/v2/\", \"grant_type\": \"client_credentials\" }",
  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 = "{ \"client_id\": \"YOUR_CLIENT_ID\", \"client_secret\": \"YOUR_CLIENT_SECRET\", \"audience\": \"https://YOUR_AUTH0_DOMAIN/api/v2/\", \"grant_type\": \"client_credentials\" }"

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 = "{ \"client_id\": \"YOUR_CLIENT_ID\", \"client_secret\": \"YOUR_CLIENT_SECRET\", \"audience\": \"https://YOUR_AUTH0_DOMAIN/api/v2/\", \"grant_type\": \"client_credentials\" }"

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

let headers = ["content-type": "application/json"]
let parameters = [
  "client_id": "YOUR_CLIENT_ID",
  "client_secret": "YOUR_CLIENT_SECRET",
  "audience": "https://YOUR_AUTH0_DOMAIN/api/v2/",
  "grant_type": "client_credentials"
]

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 body of the request must include the following:

  • audience: APIv2 base url - https://YOUR_AUTH0_DOMAIN/api/v2/
  • client_id: The client id of the new client you created.
  • client_secret: The client secret of the new client you created.
  • grant_type: Grant type should be client_credentials.

2. Get the user profile

With the Auth0 access token, call the /api/v2/users/{user-id} endpoint to get the user profile containing the IdP access token:


curl --request GET \
  --url 'https://YOUR_AUTH0_DOMAIN/api/v2/users/USER-ID' \
  --header 'content-type: application/json'
var client = new RestClient("https://YOUR_AUTH0_DOMAIN/api/v2/users/USER-ID");
var request = new RestRequest(Method.GET);
request.AddHeader("content-type", "application/json");
IRestResponse response = client.Execute(request);
package main

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

func main() {

	url := "https://YOUR_AUTH0_DOMAIN/api/v2/users/USER-ID"

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

	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.get("https://YOUR_AUTH0_DOMAIN/api/v2/users/USER-ID")
  .header("content-type", "application/json")
  .asString();
var settings = {
  "async": true,
  "crossDomain": true,
  "url": "https://YOUR_AUTH0_DOMAIN/api/v2/users/USER-ID",
  "method": "GET",
  "headers": {
    "content-type": "application/json"
  }
}

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

var options = { method: 'GET',
  url: 'https://YOUR_AUTH0_DOMAIN/api/v2/users/USER-ID',
  headers: { '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" };

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://YOUR_AUTH0_DOMAIN/api/v2/users/USER-ID"]
                                                       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://YOUR_AUTH0_DOMAIN/api/v2/users/USER-ID",
  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(
    "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("")

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

conn.request("GET", "/YOUR_AUTH0_DOMAIN/api/v2/users/USER-ID", headers=headers)

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

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

url = URI("https://YOUR_AUTH0_DOMAIN/api/v2/users/USER-ID")

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'

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

let headers = ["content-type": "application/json"]

var request = NSMutableURLRequest(URL: NSURL(string: "https://YOUR_AUTH0_DOMAIN/api/v2/users/USER-ID")!,
                                        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()

NOTE: For Native and SPA applications you will need to send the id_token to your backend and verify it using the client secret. For regular apps you can use the user_id from the user profile.

The request must include an Authorization header with Bearer bearer-token, where bearer-token is the Auth0 token you obtained in the previous step.

The body of the request must include the following:

  • user-id: The value of the user_id property of the user profile.

3. Extract the IdP access token

Use the IdP access token extracted from user.identities[0].access_token to make calls to the IdP API.

NOTE: In most cases, there will be only one identity in the identities array, but if you have used the account linking feature, there may be several.

The IdP access_token obtained here will have access to call the APIs you specified in the Auth0 dashboard when creating the connection.

Call your service

Now, in your application, you can call your service to execute requests to the IdP API.

NOTE: To prevent leaking the token, make sure not to expose the IdP access token to your client-side application.