Rotate Signing Keys

You can manually rotate your application signing key on a periodic basis. Any application that integrates with Auth0 should be prepared to handle key rotation regardless of how infrequently it may occur. If your application does not handle signing key rotation and attempts to use an expired signing key to verify a token, the authentication request will fail.

Although Auth0 signs with only one signing key at a time, your tenant's OpenID Connect discovery document always contains multiple keys. Specifically, it will always include both the current key and the next key, but it may also include the previous key if the previous key has not yet been revoked. To provide a seamless experience in case of an emergency, your application should be able to use any of the keys specified in the document.

You can rotate your tenant's application signing key using the Auth0 Dashboard and the Auth0 Management API. The application signing key is used to sign ID tokens, access tokens, SAML assertions, and WS-Fed assertions sent to your application.

To allow you time to update your application with the new signing key, all tokens signed with the previous key will still be valid until you revoke the previous key. To learn more, see Revoke Signing Keys.

Use the Dashboard

  1. Go to Dashboard > Settings > Signing Keys.

    Dashboard Tenant Settings Signing Keys tab
  2. Under Rotation Settings, locate Rotate Signing Key, and select Rotate Key.

  3. Click Rotate to confirm.

    Dashboard Settings Signing Keys Tab Rotate Confirm

Use the Management API

Make a POST call to the /signing_keys/post_signing_key endpoint. Be sure to replace the MGMT_API_ACCESS_TOKEN placeholder value with your Management API access token.


curl --request POST \
  --url 'https://YOUR_DOMAIN/api/v2/keys/signing/rotate' \
  --header 'authorization: Bearer MGMT_API_ACCESS_TOKEN'
var client = new RestClient("https://YOUR_DOMAIN/api/v2/keys/signing/rotate");
var request = new RestRequest(Method.POST);
request.AddHeader("authorization", "Bearer MGMT_API_ACCESS_TOKEN");
IRestResponse response = client.Execute(request);
package main

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

func main() {

	url := "https://YOUR_DOMAIN/api/v2/keys/signing/rotate"

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

	req.Header.Add("authorization", "Bearer MGMT_API_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.post("https://YOUR_DOMAIN/api/v2/keys/signing/rotate")
  .header("authorization", "Bearer MGMT_API_ACCESS_TOKEN")
  .asString();
var axios = require("axios").default;

var options = {
  method: 'POST',
  url: 'https://YOUR_DOMAIN/api/v2/keys/signing/rotate',
  headers: {authorization: 'Bearer MGMT_API_ACCESS_TOKEN'}
};

axios.request(options).then(function (response) {
  console.log(response.data);
}).catch(function (error) {
  console.error(error);
});
#import <Foundation/Foundation.h>

NSDictionary *headers = @{ @"authorization": @"Bearer MGMT_API_ACCESS_TOKEN" };

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://YOUR_DOMAIN/api/v2/keys/signing/rotate"]
                                                       cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                   timeoutInterval:10.0];
[request setHTTPMethod:@"POST"];
[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, [
  CURLOPT_URL => "https://YOUR_DOMAIN/api/v2/keys/signing/rotate",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_HTTPHEADER => [
    "authorization: Bearer MGMT_API_ACCESS_TOKEN"
  ],
]);

$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 = { 'authorization': "Bearer MGMT_API_ACCESS_TOKEN" }

conn.request("POST", "/YOUR_DOMAIN/api/v2/keys/signing/rotate", headers=headers)

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

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

url = URI("https://YOUR_DOMAIN/api/v2/keys/signing/rotate")

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["authorization"] = 'Bearer MGMT_API_ACCESS_TOKEN'

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

let headers = ["authorization": "Bearer MGMT_API_ACCESS_TOKEN"]

let request = NSMutableURLRequest(url: NSURL(string: "https://YOUR_DOMAIN/api/v2/keys/signing/rotate")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers

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

Value Description
MGMT_API_ACCESS_TOKEN Access Token for the Management API with the scopes create:signing_keys and update:signing_keys.

Learn more