API Authorization: Using the Management API for setting up a Client Credentials Grant scenario

If you do not want to use the Auth0 Dashboard to enable API Authorization, you can achieve the same results using the Auth0 Management API.

You will need the following:

  • Management APIv2 token with the following scopes:
    • create:resource_server
    • create:client_grant
  • Client_Id and Client_Secret for the client application which must already be created and visible in your Auth0 dashboard.

Register your Resource Server

The Resource Server entity represents the API that you want to issue access tokens for, identified by a friendly name and a URN identifier.

The following restrictions that apply for the identifier:

  • It must be a valid URN.
  • It cannot be modified after creation.
  • It must be unique throughout your tenant.

NOTE: Using your public API endpoint as an identifier is recommended.

Let's start by creating the Resource Server that will represent your API. The following example uses "My Sample API" as the name and "https://my-api-uri" as the identifier.


curl --request POST \
  --url 'https://YOUR_AUTH0_DOMAIN.auth0.com/api/v2/resource-servers' \
  --header 'content-type: application/json' \
  --data '{"name":"My Sample API","identifier": "https://my-api-urn","signing_alg": "HS256","scopes": [{ "value": "sample-scope", "description": "Description for Sample Scope"}]}'
var client = new RestClient("https://YOUR_AUTH0_DOMAIN.auth0.com/api/v2/resource-servers");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/json");
request.AddParameter("application/json", "{\"name\":\"My Sample API\",\"identifier\": \"https://my-api-urn\",\"signing_alg\": \"HS256\",\"scopes\": [{ \"value\": \"sample-scope\", \"description\": \"Description for Sample Scope\"}]}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
package main

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

func main() {

	url := "https://YOUR_AUTH0_DOMAIN.auth0.com/api/v2/resource-servers"

	payload := strings.NewReader("{\"name\":\"My Sample API\",\"identifier\": \"https://my-api-urn\",\"signing_alg\": \"HS256\",\"scopes\": [{ \"value\": \"sample-scope\", \"description\": \"Description for Sample Scope\"}]}")

	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.auth0.com/api/v2/resource-servers")
  .header("content-type", "application/json")
  .body("{\"name\":\"My Sample API\",\"identifier\": \"https://my-api-urn\",\"signing_alg\": \"HS256\",\"scopes\": [{ \"value\": \"sample-scope\", \"description\": \"Description for Sample Scope\"}]}")
  .asString();
var settings = {
  "async": true,
  "crossDomain": true,
  "url": "https://YOUR_AUTH0_DOMAIN.auth0.com/api/v2/resource-servers",
  "method": "POST",
  "headers": {
    "content-type": "application/json"
  },
  "processData": false,
  "data": "{\"name\":\"My Sample API\",\"identifier\": \"https://my-api-urn\",\"signing_alg\": \"HS256\",\"scopes\": [{ \"value\": \"sample-scope\", \"description\": \"Description for Sample Scope\"}]}"
}

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

var options = { method: 'POST',
  url: 'https://YOUR_AUTH0_DOMAIN.auth0.com/api/v2/resource-servers',
  headers: { 'content-type': 'application/json' },
  body: 
   { name: 'My Sample API',
     identifier: 'https://my-api-urn',
     signing_alg: 'HS256',
     scopes: 
      [ { value: 'sample-scope',
          description: 'Description for Sample Scope' } ] },
  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 = @{ @"name": @"My Sample API",
                              @"identifier": @"https://my-api-urn",
                              @"signing_alg": @"HS256",
                              @"scopes": @[ @{ @"value": @"sample-scope", @"description": @"Description for Sample Scope" } ] };

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

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://YOUR_AUTH0_DOMAIN.auth0.com/api/v2/resource-servers"]
                                                       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.auth0.com/api/v2/resource-servers",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "{\"name\":\"My Sample API\",\"identifier\": \"https://my-api-urn\",\"signing_alg\": \"HS256\",\"scopes\": [{ \"value\": \"sample-scope\", \"description\": \"Description for Sample Scope\"}]}",
  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 = "{\"name\":\"My Sample API\",\"identifier\": \"https://my-api-urn\",\"signing_alg\": \"HS256\",\"scopes\": [{ \"value\": \"sample-scope\", \"description\": \"Description for Sample Scope\"}]}"

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

conn.request("POST", "/YOUR_AUTH0_DOMAIN.auth0.com/api/v2/resource-servers", payload, headers)

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

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

url = URI("https://YOUR_AUTH0_DOMAIN.auth0.com/api/v2/resource-servers")

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 = "{\"name\":\"My Sample API\",\"identifier\": \"https://my-api-urn\",\"signing_alg\": \"HS256\",\"scopes\": [{ \"value\": \"sample-scope\", \"description\": \"Description for Sample Scope\"}]}"

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

let headers = ["content-type": "application/json"]
let parameters = [
  "name": "My Sample API",
  "identifier": "https://my-api-urn",
  "signing_alg": "HS256",
  "scopes": [
    [
      "value": "sample-scope",
      "description": "Description for Sample Scope"
    ]
  ]
]

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

var request = NSMutableURLRequest(URL: NSURL(string: "https://YOUR_AUTH0_DOMAIN.auth0.com/api/v2/resource-servers")!,
                                        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()

NOTE: You can include multiple scopes. This array represents the universe of scopes your API will support. You can modify this later by issuing a PATCH operation.

Response:

{
    "id": "56f0131ffdf1c311694f4cc7",
    "name": "My Sample API",
    "identifier": "https://my-api-urn",
    "scopes": [
        {
            "value": "sample-scope",
            "description": "Description for Sample Scope"
        }
    ],
    "signing_alg": "HS256",
    "signing_secret": "FF1prn9UxZotnFEfPVwEJhqqyRmwdSu5",
    "token_lifetime": 86400
}

Authorize the consumer Client

Now that the API and the Client are represented in Auth0, you can create a trust relationship between them.


curl --request POST \
  --url 'https://YOUR_AUTH0_DOMAIN.auth0.com/api/v2/client-grants' \
  --header 'content-type: application/json' \
  --data '{"client_id": "N99orgWBg8WDHOOfL4p6LXT7wEAliSik","audience": "https://my-api-urn","scope":["sample-scope"]}'
var client = new RestClient("https://YOUR_AUTH0_DOMAIN.auth0.com/api/v2/client-grants");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/json");
request.AddParameter("application/json", "{\"client_id\": \"N99orgWBg8WDHOOfL4p6LXT7wEAliSik\",\"audience\": \"https://my-api-urn\",\"scope\":[\"sample-scope\"]}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
package main

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

func main() {

	url := "https://YOUR_AUTH0_DOMAIN.auth0.com/api/v2/client-grants"

	payload := strings.NewReader("{\"client_id\": \"N99orgWBg8WDHOOfL4p6LXT7wEAliSik\",\"audience\": \"https://my-api-urn\",\"scope\":[\"sample-scope\"]}")

	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.auth0.com/api/v2/client-grants")
  .header("content-type", "application/json")
  .body("{\"client_id\": \"N99orgWBg8WDHOOfL4p6LXT7wEAliSik\",\"audience\": \"https://my-api-urn\",\"scope\":[\"sample-scope\"]}")
  .asString();
var settings = {
  "async": true,
  "crossDomain": true,
  "url": "https://YOUR_AUTH0_DOMAIN.auth0.com/api/v2/client-grants",
  "method": "POST",
  "headers": {
    "content-type": "application/json"
  },
  "processData": false,
  "data": "{\"client_id\": \"N99orgWBg8WDHOOfL4p6LXT7wEAliSik\",\"audience\": \"https://my-api-urn\",\"scope\":[\"sample-scope\"]}"
}

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

var options = { method: 'POST',
  url: 'https://YOUR_AUTH0_DOMAIN.auth0.com/api/v2/client-grants',
  headers: { 'content-type': 'application/json' },
  body: 
   { client_id: 'N99orgWBg8WDHOOfL4p6LXT7wEAliSik',
     audience: 'https://my-api-urn',
     scope: [ 'sample-scope' ] },
  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": @"N99orgWBg8WDHOOfL4p6LXT7wEAliSik",
                              @"audience": @"https://my-api-urn",
                              @"scope": @[ @"sample-scope" ] };

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

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://YOUR_AUTH0_DOMAIN.auth0.com/api/v2/client-grants"]
                                                       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.auth0.com/api/v2/client-grants",
  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\": \"N99orgWBg8WDHOOfL4p6LXT7wEAliSik\",\"audience\": \"https://my-api-urn\",\"scope\":[\"sample-scope\"]}",
  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\": \"N99orgWBg8WDHOOfL4p6LXT7wEAliSik\",\"audience\": \"https://my-api-urn\",\"scope\":[\"sample-scope\"]}"

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

conn.request("POST", "/YOUR_AUTH0_DOMAIN.auth0.com/api/v2/client-grants", payload, headers)

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

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

url = URI("https://YOUR_AUTH0_DOMAIN.auth0.com/api/v2/client-grants")

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\": \"N99orgWBg8WDHOOfL4p6LXT7wEAliSik\",\"audience\": \"https://my-api-urn\",\"scope\":[\"sample-scope\"]}"

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

let headers = ["content-type": "application/json"]
let parameters = [
  "client_id": "N99orgWBg8WDHOOfL4p6LXT7wEAliSik",
  "audience": "https://my-api-urn",
  "scope": ["sample-scope"]
]

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

var request = NSMutableURLRequest(URL: NSURL(string: "https://YOUR_AUTH0_DOMAIN.auth0.com/api/v2/client-grants")!,
                                        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 client_id is the id of the consumer application, audience will be the identifier of the API, and scope is an array of strings, which must be a subset of those defined in the API.

Response:

{
    "id": "cgr_JGa6ZckLjnt60rWe",
    "client_id": "N99orgWBg8WDHOOfL4p6LXT7wEAliSik",
    "audience": "https://test-api",
    "scope": [
        "sample-scope"
    ]
}

Next, update your API to parse the token from the request and validate it. You will need to use the signing_secret of the API, which was used for signing the access tokens with the HS256 algorithm.

Request access tokens

Now that all the elements are in place, you can request access tokens for your API from Auth0.

For details on generating access tokens, see: API Authorization: Asking for Access Tokens