Rotate Client Secrets

You can change an app's client secret using Auth0's Dashboard or the Management API. When you rotate a client secret, you must update any authorized apps with the new value.

Your global client ID and secret can be found in Dashboard > Settings > Advanced. To learn more, read View Client Secrets and Signing Keys.

New secrets may be delayed while rotating. To minimize downtime, we suggest you store the new client secret in your application's code as a fallback to the previous secret. This way, if the connection doesn't work with the old secret, your app will use the new secret.

Secrets can be stored in a list (or similar structure) until they're no longer needed. Once you're sure that an old secret is obsolete, you can remove its value from your app's code.

Where to store client secrets

Where to store the secret depends on the scope of the secret:

  • Is it just one secret per application? Then client_metadata would be a good place. But if this is the case, you should consider storing the secret directly in the application instead, to avoid putting the secret in the ID token.

  • Is it the same secret for the whole system (i.e., for all applications or many)? Then the rule’s configuration values might be a better choice

  • Is it a different secret for each user? Then storing in app_metadata might be better.

Use the Dashboard

  1. Go to Dashboard > Applications > Applications and select the name of the application to view.

    Dashboard Applications List
  2. Scroll to the bottom of the Settings page, locate the Danger Zone, select Rotate, and confirm.

  3. View your new secret by scrolling to the top of the Settings page, locating Client Secret, and selecting its eye icon.

    Dashboard Applications Application Settings Tab Basic Information

  4. Update authorized applications with the new value.

Use the Management API

  1. Make a POST call to the /Clients/post_rotate_secret endpoint. Be sure to replace YOUR_CLIENT_ID and MGMT_API_ACCESS_TOKEN placeholder values with your client ID and Management API access token, respectively.

    
    

    to configure this snippet with your account

    curl --request POST \
      --url 'https://YOUR_DOMAIN/api/v2/clients/YOUR_CLIENT_ID/rotate-secret' \
      --header 'authorization: Bearer MGMT_API_ACCESS_TOKEN'

    to configure this snippet with your account

    var client = new RestClient("https://YOUR_DOMAIN/api/v2/clients/YOUR_CLIENT_ID/rotate-secret");
    var request = new RestRequest(Method.POST);
    request.AddHeader("authorization", "Bearer MGMT_API_ACCESS_TOKEN");
    IRestResponse response = client.Execute(request);

    to configure this snippet with your account

    package main
    
    import (
    	"fmt"
    	"net/http"
    	"io/ioutil"
    )
    
    func main() {
    
    	url := "https://YOUR_DOMAIN/api/v2/clients/YOUR_CLIENT_ID/rotate-secret"
    
    	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))
    
    }

    to configure this snippet with your account

    HttpResponse<String> response = Unirest.post("https://YOUR_DOMAIN/api/v2/clients/YOUR_CLIENT_ID/rotate-secret")
      .header("authorization", "Bearer MGMT_API_ACCESS_TOKEN")
      .asString();

    to configure this snippet with your account

    var axios = require("axios").default;
    
    var options = {
      method: 'POST',
      url: 'https://YOUR_DOMAIN/api/v2/clients/YOUR_CLIENT_ID/rotate-secret',
      headers: {authorization: 'Bearer MGMT_API_ACCESS_TOKEN'}
    };
    
    axios.request(options).then(function (response) {
      console.log(response.data);
    }).catch(function (error) {
      console.error(error);
    });

    to configure this snippet with your account

    #import <Foundation/Foundation.h>
    
    NSDictionary *headers = @{ @"authorization": @"Bearer MGMT_API_ACCESS_TOKEN" };
    
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://YOUR_DOMAIN/api/v2/clients/YOUR_CLIENT_ID/rotate-secret"]
                                                           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];

    to configure this snippet with your account

    $curl = curl_init();
    
    curl_setopt_array($curl, [
      CURLOPT_URL => "https://YOUR_DOMAIN/api/v2/clients/YOUR_CLIENT_ID/rotate-secret",
      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;
    }

    to configure this snippet with your account

    import http.client
    
    conn = http.client.HTTPSConnection("")
    
    headers = { 'authorization': "Bearer MGMT_API_ACCESS_TOKEN" }
    
    conn.request("POST", "/YOUR_DOMAIN/api/v2/clients/YOUR_CLIENT_ID/rotate-secret", headers=headers)
    
    res = conn.getresponse()
    data = res.read()
    
    print(data.decode("utf-8"))

    to configure this snippet with your account

    require 'uri'
    require 'net/http'
    require 'openssl'
    
    url = URI("https://YOUR_DOMAIN/api/v2/clients/YOUR_CLIENT_ID/rotate-secret")
    
    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

    to configure this snippet with your account

    import Foundation
    
    let headers = ["authorization": "Bearer MGMT_API_ACCESS_TOKEN"]
    
    let request = NSMutableURLRequest(url: NSURL(string: "https://YOUR_DOMAIN/api/v2/clients/YOUR_CLIENT_ID/rotate-secret")! 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
    YOUR_CLIENT_ID Τhe ID of the application to be updated.
    MGMT_API_ACCESS_TOKEN Access Tokens for the Management API with the scope update:client_keys.

  2. Update authorized applications with the new value.

Learn more