Dynamic Application Registration

Dynamic Application Registration

You can dynamically register third-party applications for your tenant. This feature is based on the OpenID Connect Dynamic Client Registration specification.

Enable dynamic client registration

By default, dynamic application registration is disabled for all tenants. To change this, you have to set the enable_dynamic_client_registration flag to true in your tenant's settings.

To do so, go to Dashboard > Settings > Advanced and enable the OIDC Dynamic Application Registration.

Alternatively, you can update this flag using the Management API /Tenant/patch_settings endpoint.


curl --request PATCH \
  --url 'https://{yourDomain}/api/v2/tenants/settings' \
  --header 'authorization: Bearer API2_ACCESS_TOKEN' \
  --header 'cache-control: no-cache' \
  --header 'content-type: application/json' \
  --data '{ "flags": { "enable_dynamic_client_registration": true } }'

Was this helpful?

/
var client = new RestClient("https://{yourDomain}/api/v2/tenants/settings");
var request = new RestRequest(Method.PATCH);
request.AddHeader("content-type", "application/json");
request.AddHeader("authorization", "Bearer API2_ACCESS_TOKEN");
request.AddHeader("cache-control", "no-cache");
request.AddParameter("application/json", "{ \"flags\": { \"enable_dynamic_client_registration\": true } }", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);

Was this helpful?

/
package main

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

func main() {

	url := "https://{yourDomain}/api/v2/tenants/settings"

	payload := strings.NewReader("{ \"flags\": { \"enable_dynamic_client_registration\": true } }")

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

	req.Header.Add("content-type", "application/json")
	req.Header.Add("authorization", "Bearer API2_ACCESS_TOKEN")
	req.Header.Add("cache-control", "no-cache")

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

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

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

}

Was this helpful?

/
HttpResponse<String> response = Unirest.patch("https://{yourDomain}/api/v2/tenants/settings")
  .header("content-type", "application/json")
  .header("authorization", "Bearer API2_ACCESS_TOKEN")
  .header("cache-control", "no-cache")
  .body("{ \"flags\": { \"enable_dynamic_client_registration\": true } }")
  .asString();

Was this helpful?

/
var axios = require("axios").default;

var options = {
  method: 'PATCH',
  url: 'https://{yourDomain}/api/v2/tenants/settings',
  headers: {
    'content-type': 'application/json',
    authorization: 'Bearer API2_ACCESS_TOKEN',
    'cache-control': 'no-cache'
  },
  data: {flags: {enable_dynamic_client_registration: true}}
};

axios.request(options).then(function (response) {
  console.log(response.data);
}).catch(function (error) {
  console.error(error);
});

Was this helpful?

/
#import <Foundation/Foundation.h>

NSDictionary *headers = @{ @"content-type": @"application/json",
                           @"authorization": @"Bearer API2_ACCESS_TOKEN",
                           @"cache-control": @"no-cache" };
NSDictionary *parameters = @{ @"flags": @{ @"enable_dynamic_client_registration": @YES } };

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

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://{yourDomain}/api/v2/tenants/settings"]
                                                       cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                   timeoutInterval:10.0];
[request setHTTPMethod:@"PATCH"];
[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];

Was this helpful?

/
$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://{yourDomain}/api/v2/tenants/settings",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "PATCH",
  CURLOPT_POSTFIELDS => "{ \"flags\": { \"enable_dynamic_client_registration\": true } }",
  CURLOPT_HTTPHEADER => [
    "authorization: Bearer API2_ACCESS_TOKEN",
    "cache-control: no-cache",
    "content-type: application/json"
  ],
]);

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

curl_close($curl);

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

Was this helpful?

/
import http.client

conn = http.client.HTTPSConnection("")

payload = "{ \"flags\": { \"enable_dynamic_client_registration\": true } }"

headers = {
    'content-type': "application/json",
    'authorization': "Bearer API2_ACCESS_TOKEN",
    'cache-control': "no-cache"
    }

conn.request("PATCH", "/{yourDomain}/api/v2/tenants/settings", payload, headers)

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

print(data.decode("utf-8"))

Was this helpful?

/
require 'uri'
require 'net/http'
require 'openssl'

url = URI("https://{yourDomain}/api/v2/tenants/settings")

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

request = Net::HTTP::Patch.new(url)
request["content-type"] = 'application/json'
request["authorization"] = 'Bearer API2_ACCESS_TOKEN'
request["cache-control"] = 'no-cache'
request.body = "{ \"flags\": { \"enable_dynamic_client_registration\": true } }"

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

Was this helpful?

/
import Foundation

let headers = [
  "content-type": "application/json",
  "authorization": "Bearer API2_ACCESS_TOKEN",
  "cache-control": "no-cache"
]
let parameters = ["flags": ["enable_dynamic_client_registration": true]] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://{yourDomain}/api/v2/tenants/settings")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "PATCH"
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()

Was this helpful?

/

You need to update the API2_ACCESS_TOKEN with a valid token with the scope update:tenant_settings. To learn more, read Management API Access Tokens.

Use dynamic client registration

In this section, we will see how you can dynamically register and configure an application.

Register your application

To dynamically register an application with Auth0, you need to send an HTTP POST message to the Application Registration endpoint: https://{yourDomain}/oidc/register. Note that Auth0 supports Open Dynamic Registration, which means that the endpoint will accept a registration request without an access token.

To create an application with the name My Dynamic application and the callback URLs https://application.example.com/callback and https://application.example.com/callback2, use the following snippet:


curl --request POST \
  --url 'https://{yourDomain}/oidc/register' \
  --header 'content-type: application/json' \
  --data '{"client_name":"My Dynamic Application","redirect_uris": ["https://application.example.com/callback", "https://application.example.com/callback2"]}'

Was this helpful?

/
var client = new RestClient("https://{yourDomain}/oidc/register");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/json");
request.AddParameter("application/json", "{\"client_name\":\"My Dynamic Application\",\"redirect_uris\": [\"https://application.example.com/callback\", \"https://application.example.com/callback2\"]}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);

Was this helpful?

/
package main

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

func main() {

	url := "https://{yourDomain}/oidc/register"

	payload := strings.NewReader("{\"client_name\":\"My Dynamic Application\",\"redirect_uris\": [\"https://application.example.com/callback\", \"https://application.example.com/callback2\"]}")

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

}

Was this helpful?

/
HttpResponse<String> response = Unirest.post("https://{yourDomain}/oidc/register")
  .header("content-type", "application/json")
  .body("{\"client_name\":\"My Dynamic Application\",\"redirect_uris\": [\"https://application.example.com/callback\", \"https://application.example.com/callback2\"]}")
  .asString();

Was this helpful?

/
var axios = require("axios").default;

var options = {
  method: 'POST',
  url: 'https://{yourDomain}/oidc/register',
  headers: {'content-type': 'application/json'},
  data: {
    client_name: 'My Dynamic Application',
    redirect_uris: [
      'https://application.example.com/callback',
      'https://application.example.com/callback2'
    ]
  }
};

axios.request(options).then(function (response) {
  console.log(response.data);
}).catch(function (error) {
  console.error(error);
});

Was this helpful?

/
#import <Foundation/Foundation.h>

NSDictionary *headers = @{ @"content-type": @"application/json" };
NSDictionary *parameters = @{ @"client_name": @"My Dynamic Application",
                              @"redirect_uris": @[ @"https://application.example.com/callback", @"https://application.example.com/callback2" ] };

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

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://{yourDomain}/oidc/register"]
                                                       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];

Was this helpful?

/
$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://{yourDomain}/oidc/register",
  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_name\":\"My Dynamic Application\",\"redirect_uris\": [\"https://application.example.com/callback\", \"https://application.example.com/callback2\"]}",
  CURLOPT_HTTPHEADER => [
    "content-type: application/json"
  ],
]);

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

curl_close($curl);

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

Was this helpful?

/
import http.client

conn = http.client.HTTPSConnection("")

payload = "{\"client_name\":\"My Dynamic Application\",\"redirect_uris\": [\"https://application.example.com/callback\", \"https://application.example.com/callback2\"]}"

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

conn.request("POST", "/{yourDomain}/oidc/register", payload, headers)

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

print(data.decode("utf-8"))

Was this helpful?

/
require 'uri'
require 'net/http'
require 'openssl'

url = URI("https://{yourDomain}/oidc/register")

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_name\":\"My Dynamic Application\",\"redirect_uris\": [\"https://application.example.com/callback\", \"https://application.example.com/callback2\"]}"

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

Was this helpful?

/
import Foundation

let headers = ["content-type": "application/json"]
let parameters = [
  "client_name": "My Dynamic Application",
  "redirect_uris": ["https://application.example.com/callback", "https://application.example.com/callback2"]
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://{yourDomain}/oidc/register")! 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()

Was this helpful?

/

Where:

  • client_name: The name of the Dynamic Application to be created

  • redirect_uris (required): An array of URLs that Auth0 will deem valid to call at the end of an authentication flow

Optionally, you can set a value for token_endpoint_auth_method, which can be none or client_secret_post (default value). Use token_endpoint_auth_method: none in the request payload if creating a SPA.

The response includes the basic application information.

HTTP/1.1 201 Created
Content-Type: application/json
{
  "client_name": "My Dynamic Application",
  "client_id": "8SXWY6j3afl2CP5ntwEOpMdPxxy49Gt2",
  "client_secret": "Q5O...33P",
  "redirect_uris": [
    "https://application.example.com/callback",
    "https://application.example.com/callback2"
  ],
  "client_secret_expires_at": 0
}

Was this helpful?

/

Where:

  • client_id: Unique client identifier. This is the ID you will use while configuring your apps to use Auth0. It is generated by the system and it cannot be modified.

  • client_secret: Alphanumeric 64-bit client secret. This value is used by applications to authenticate to the Authentication API /token and for signing and validating ID tokens.

  • client_secret_expires_at: Time at which the client_secret will expire. For Auth0 this value will always be zero (0) which means that the application never expires.

Make a note of the client ID and client secret, as these are the most important pieces for executing authentication and authorization flows. To learn more, read Authentication and Authorization Flows.

Also, keep in mind that third-party developers are not allowed to modify the application settings. In case this is necessary, they need to contact the tenant owner with their request.

Configure your application

Now that you have a Client ID and Secret, you can configure your application to authenticate users with Auth0.

We will go through a simple example, that shows how to call an API from a client-side web app, using the Implicit Flow.

First, you need to configure your application to send the user to the authorization URL:

https://{yourDomain}/authorize?
  audience={API_AUDIENCE}&
  scope={SCOPE}&
  response_type={RESPONSE_TYPE}&
  client_id={yourClientId}&
  redirect_uri={https://yourApp/callback}&
  nonce={NONCE}
  state={OPAQUE_VALUE}

Was this helpful?

/

Where:

  • audience (optional): The target API for which the Application is requesting access on behalf of the user. Set this parameter if you need API access.

  • scope (optional): 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 for users, such as profile and email, custom claims that must conform to a namespaced format, or any scopes supported by the target API (for example, read:contacts). Set this parameter if you need API access. To learn more, read API Scopes.

  • response_type: The response type. For Implicit Grant you can either use token or id_token token. This will specify the type of token you will receive at the end of the flow. Use token to get only an access token, or id_token token to get both an ID token and an access token.

  • client_id: Your application's client ID.

  • redirect_uri: The URL to which the authorization server (Auth0) will redirect the User Agent (Browser) after authorization has been granted by the User. The access token (and optionally an ID token) will be available in the hash fragment of this URL. This URL must be specified as a valid callback URL under the Application Settings of your application.

  • state: An opaque value the applications add to the initial request that the authorization server includes when redirecting the back to the application. This value must be used by the application to prevent CSRF attacks.

  • nonce: A string value that will be included in the ID token response from Auth0, used to prevent token replay attacks. It is required for response_type=id_token token.

For example:

<a href="https://{yourDomain}/authorize?scope=appointments%20contacts&audience=appointments:api&response_type=id_token%20token&client_id={yourClientId}&redirect_uri={https://yourApp/callback}">
  Sign In
</a>

Was this helpful?

/

This call will redirect the user to Auth0, and upon successful authentication, back to your application (specifically to the redirect_uri).

If you need API access, then following the authentication, you need to extract the access token from the hash fragment of the URL, and use it to make calls to the API, by passing it as a Bearer token in the Authorization header of the HTTP request.

Learn more