Rotating keys in ACP

Workspace vs the AuthZ server

The key rotation in ACP can be performed on the workspace level. Each workspace is an independent OAuth server with a different set of keys.

Note

Details on this authorization server can be explored using OpenID configuration endpoint https://<acp-domain>:<acp-port>/<tenantid>/<workspaceid>/.well-known/openid-configuration.

Example of the OpenID-configuration endpoint

curl https://acp.example.com:8443/default/demo/.well-known/openid-configuration | jq
{
  "issuer": "https://acp.example.com:8443/default/demo",
  "authorization_endpoint": "https://acp.example.com:8443/default/demo/oauth2/authorize",
  "token_endpoint": "https://acp.example.com.com:8443/default/demo/oauth2/token",
  "jwks_uri": "https://acp.example.com:8443/default/demo/.well-known/jwks.json",
  "subject_types_supported": [
    "public",
    "pairwise"
  ],
  "response_types_supported": [
    "id_token",
    "code",
    "code id_token",
    "token",
    "token id_token",
    "token id_token code"
  ],
  "claims_supported": [
    "sub",
    "acr",
    "amr"
  ],
  "grant_types_supported": [
    "authorization_code",
    "implicit",
    "client_credentials",
    "refresh_token"
  ],
  "response_modes_supported": [
    "query",
    "fragment"
  ],
  "userinfo_endpoint": "https://acp.example.com:8443/default/demo/userinfo",
  "introspection_endpoint": "https://acp.example.com:8443/default/demo/oauth2/introspect",
  "scopes_supported": [
    "email",
    "phone",
    "address",
    "profile",
    "openid",
    "offline_access",
    "view_consents",
    "manage_consents",
    "introspect_tokens",
    "revoke_tokens",
    "list_clients_with_access",
    "revoke_client_access",
    "dcr_register"
  ],
  "token_endpoint_auth_methods_supported": [
    "client_secret_basic",
    "client_secret_post",
    "client_secret_jwt",
    "none",
    "private_key_jwt",
    "self_signed_tls_client_auth",
    "tls_client_auth"
  ],
  "token_endpoint_auth_signing_alg_values_supported": [
    "RS256",
    "ES256",
    "PS256"
  ],
  "userinfo_signing_alg_values_supported": [
    "none",
    "ES256"
  ],
  "id_token_signing_alg_values_supported": [
    "ES256"
  ],
  "request_parameter_supported": true,
  "request_uri_parameter_supported": true,
  "request_object_signing_alg_values_supported": [
    "RS256",
    "ES256",
    "PS256"
  ],
  "require_request_uri_registration": true,
  "claims_parameter_supported": true,
  "revocation_endpoint": "https://acp.example.com:8443/default/demo/oauth2/revoke",
  "registration_endpoint": "https://acp.example.com:8443/default/demo/oauth2/register",
  "backchannel_logout_supported": false,
  "backchannel_logout_session_supported": false,
  "frontchannel_logout_supported": false,
  "frontchannel_logout_session_supported": false,
  "code_challenge_methods_supported": [
    "S256"
  ],
  "tls_client_certificate_bound_access_tokens": true
}

Generate a new key

To rotate a key, you need to generate a new key first.

Note

ACP supports both RS and EC based signatures keys. Due to performance reasons, the EC-based keys are recommended and configured by default.

  1. To generate a new signature, you need to start with a new key and a certificate.

    openssl req -x509 -nodes -days 3650 -newkey ec:<(openssl ecparam -name prime256v1) -keyout ecdsakey.pem -out ecdsacert.pem
    Generating an EC private key
    writing new private key to 'ecdsakey.pem'
    -----
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    Country Name (2 letter code) [AU]:US
    State or Province Name (full name) [Some-State]:WA
    Locality Name (eg, city) []:Seattle
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:Cloudentity
    Organizational Unit Name (eg, section) []:
    Common Name (e.g. server FQDN or YOUR name) []:acp.example.com
    Email Address []: ....
    
    

    Result

    You get the key in the X509 PEM format.

  2. Convert your new key to the JWKS format.

    Note

    ACP has an embedded conversion tool that helps with the conversion process.

    acp jwks convert --cert-path ./ecdsacert.pem --key-path ./ecdsakey.pem  --private-jwks-path ./jwks-priv.json --public-jwks-path ./jwks-pub.json
    

    Exemplary output

    Here is an example of the generated JWT Key Set:

    cat jwks-priv.json
    
    {
      "keys": [
        {
          "use": "sig",
          "kty": "EC",
          "kid": "244861745913611684766818513248687510777770339898",
          "crv": "P-256",
          "alg": "ES256",
          "x": "5H1NpP-YTJbOwM-M_8wk5d4MFSA-2bIEXwr92vOXTlM",
          "y": "48cfpJpP9EuERXYIyJXgwaQPMCqtccBKV42Ec9kkZVc",
          "d": "XxpxSGD4ZDn8p3a_pgOb8aeuFSptUKliV-Hs6ik9G0w",
          "x5c": [
            "MIICIzCCAcmgAwIBAgIUKuP6/aKEXOAR3lgCxmKR0dHA7jowCgYIKoZIzj0EAwIwZzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMRQwEgYDVQQKDAtDbG91ZGVudGl0eTEjMCEGA1UEAwwaYWNwLnYxNi5jbG91ZGVudGl0eS1zZS5jb20wHhcNMjEwMTMwMjA0NjAyWhcNMzEwMTI4MjA0NjAyWjBnMQswCQYDVQQGEwJVUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxFDASBgNVBAoMC0Nsb3VkZW50aXR5MSMwIQYDVQQDDBphY3AudjE2LmNsb3VkZW50aXR5LXNlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOR9TaT/mEyWzsDPjP/MJOXeDBUgPtmyBF8K/drzl05T48cfpJpP9EuERXYIyJXgwaQPMCqtccBKV42Ec9kkZVejUzBRMB0GA1UdDgQWBBR0XtNqn673m+X0lVlTxjWWk12fCTAfBgNVHSMEGDAWgBR0XtNqn673m+X0lVlTxjWWk12fCTAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIA7ajABMU1Q5sFoa1vVvN7IBaFzCZPCvalhYDM8TxfyqAiEAq6bkOL4vuAPZtq7RPFIQPBzly6mfZuA30ciK6Sc4ab0="
          ],
          "x5t": "6xfvlWhPypSwWGct_WXzjENOHNk",
          "x5t#S256": "mrRCyDKOreVilIQmcz2HSWQD5PGzMaIMqaKkpZEy2Zs"
        }
      ]
    }
    
    

Obtain the old key

Note

To rotate the keys, both the new key and the old one are needed. The old key is available as a part of the configuration to the authorization server using GET Authorization Server Admin API https://docs.authorization.cloudentity.com/api/admin/#operation/getAuthorizationServer. The authorization access token with admin privileges is needed to perform this operation.

  1. To retrieve the authorization access token with admin privileges, execute

    curl -X GET "https://acp.example.com:8443/api/admin/default/servers/demo" -H "accept: application/json" -H "authorization: Bearer $ADMIN_ACCESS_TOKEN" | jq .jwks
    
    {
      "keys": [
        {
          "use": "sig",
          "kty": "EC",
          "kid": "303446885349823077582433662447357289206",
          "crv": "P-256",
          "alg": "ES256",
          "x": "2NBblGjHBkT0Toaci9JwrZ-fSuaMGrWshneP_4G8J_E",
          "y": "XDdYypQZXuUWN0O69aZIFQLNf3RVqxLO0CLIlh0knlo",
          "d": "fIY9g9OU9I0N6AHJbg-xDmN8UZNPEePRz1vTmNawrmg",
          "x5c": [
            "MIIBxTCCAWqgAwIBAgIRAORJvoqd7wNKrzlLyWGgYvYwCgYIKoZIzj0EAwIwLDEUMBIGA1UEChMLQ2xvdWRlbnRpdHkxFDASBgNVBAMTC0Nsb3VkZW50aXR5MB4XDTIxMDEyOTIwMTAzMFoXDTIxMDMwMTIwMTAzMFowLDEUMBIGA1UEChMLQ2xvdWRlbnRpdHkxFDASBgNVBAMTC0Nsb3VkZW50aXR5MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2NBblGjHBkT0Toaci9JwrZ+fSuaMGrWshneP/4G8J/FcN1jKlBle5RY3Q7r1pkgVAs1/dFWrEs7QIsiWHSSeWqNtMGswDgYDVR0PAQH/BAQDAgKkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFA3MMurUsdpPAbXnalVcpuDwEl1JMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDAKBggqhkjOPQQDAgNJADBGAiEAx0dKT57UMu9jDiQ/beOeYHlRqjEJhoMSPZzh8I0amPUCIQDpiuS+8Qo7R/Qa5ttUHBvWIb+ctlcEHyx2HsdAkIW2jA=="
          ],
          "x5t": "uyOjbQzdzjVMr91rOHFagag2fFg",
          "x5t#S256": "uCXSufaU9pmSNS0PKFUYRgOCDB67HDz6wpuAoYzOwMo"
        }
      ]
    }
    
  2. Combine the new key with the old one.

    Watch it

    It’s important that the the new key is listed as the first one.

    "jwks": {
      "keys": [{
        "use": "sig",
        "kty": "EC",
        "kid": "244861745913611684766818513248687510777770339898",
        "crv": "P-256",
        "alg": "ES256",
        "x": "5H1NpP-YTJbOwM-M_8wk5d4MFSA-2bIEXwr92vOXTlM",
        "y": "48cfpJpP9EuERXYIyJXgwaQPMCqtccBKV42Ec9kkZVc",
        "d": "XxpxSGD4ZDn8p3a_pgOb8aeuFSptUKliV-Hs6ik9G0w",
        "x5c": [
        "MIICIzCCAcmgAwIBAgIUKuP6/aKEXOAR3lgCxmKR0dHA7jowCgYIKoZIzj0EAwIwZzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMRQwEgYDVQQKDAtDbG91ZGVudGl0eTEjMCEGA1UEAwwaYWNwLnYxNi5jbG91ZGVudGl0eS1zZS5jb20wHhcNMjEwMTMwMjA0NjAyWhcNMzEwMTI4MjA0NjAyWjBnMQswCQYDVQQGEwJVUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxFDASBgNVBAoMC0Nsb3VkZW50aXR5MSMwIQYDVQQDDBphY3AudjE2LmNsb3VkZW50aXR5LXNlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOR9TaT/mEyWzsDPjP/MJOXeDBUgPtmyBF8K/drzl05T48cfpJpP9EuERXYIyJXgwaQPMCqtccBKV42Ec9kkZVejUzBRMB0GA1UdDgQWBBR0XtNqn673m+X0lVlTxjWWk12fCTAfBgNVHSMEGDAWgBR0XtNqn673m+X0lVlTxjWWk12fCTAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIA7ajABMU1Q5sFoa1vVvN7IBaFzCZPCvalhYDM8TxfyqAiEAq6bkOL4vuAPZtq7RPFIQPBzly6mfZuA30ciK6Sc4ab0="
        ],
        "x5t": "6xfvlWhPypSwWGct_WXzjENOHNk",
        "x5t#S256": "mrRCyDKOreVilIQmcz2HSWQD5PGzMaIMqaKkpZEy2Zs"
      },
      {
        "use": "sig",
        "kty": "EC",
        "kid": "303446885349823077582433662447357289206",
        "crv": "P-256",
        "alg": "ES256",
        "x": "2NBblGjHBkT0Toaci9JwrZ-fSuaMGrWshneP_4G8J_E",
        "y": "XDdYypQZXuUWN0O69aZIFQLNf3RVqxLO0CLIlh0knlo",
        "d": "fIY9g9OU9I0N6AHJbg-xDmN8UZNPEePRz1vTmNawrmg",
        "x5c": [
        "MIIBxTCCAWqgAwIBAgIRAORJvoqd7wNKrzlLyWGgYvYwCgYIKoZIzj0EAwIwLDEUMBIGA1UEChMLQ2xvdWRlbnRpdHkxFDASBgNVBAMTC0Nsb3VkZW50aXR5MB4XDTIxMDEyOTIwMTAzMFoXDTIxMDMwMTIwMTAzMFowLDEUMBIGA1UEChMLQ2xvdWRlbnRpdHkxFDASBgNVBAMTC0Nsb3VkZW50aXR5MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2NBblGjHBkT0Toaci9JwrZ+fSuaMGrWshneP/4G8J/FcN1jKlBle5RY3Q7r1pkgVAs1/dFWrEs7QIsiWHSSeWqNtMGswDgYDVR0PAQH/BAQDAgKkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFA3MMurUsdpPAbXnalVcpuDwEl1JMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDAKBggqhkjOPQQDAgNJADBGAiEAx0dKT57UMu9jDiQ/beOeYHlRqjEJhoMSPZzh8I0amPUCIQDpiuS+8Qo7R/Qa5ttUHBvWIb+ctlcEHyx2HsdAkIW2jA=="
        ],
        "x5t": "uyOjbQzdzjVMr91rOHFagag2fFg",
        "x5t#S256": "uCXSufaU9pmSNS0PKFUYRgOCDB67HDz6wpuAoYzOwMo"
      }
      ]
    }
    
    
  3. To update the keys, use Update Authorization Server API https://docs.authorization.cloudentity.com/api/admin/#operation/updateAuthorizationServer.

    curl -X PUT "https://acp.example.com:8443/api/admin/default/servers/demo" -H "accept: application/json" -H "authorization: Bearer $ADMIN_ACCESS_TOKEN" -H "Content-Type: application/json" -d "{ \"tenant_id\": \"default\", \"id\": \"demo\", \"profile\": \"default\", \"name\": \"Demo\", \"type\": \"regular\", \"color\": \"#007FFF\", \"secret\": \"a7PsnLjCoqfzWPbya_6ZE1gmOed0sjHm5g3z0AHo8SM\", \"rotated_secrets\": [], \"access_token_strategy\": \"jwt\", \"key_type\": \"ecdsa\", \"logo_uri\": \"\", \"issuer_url\": \"https://acp.example.com:8443/default/demo\", \"dynamic_client_registration\": { \"enabled\": false, \"initial_access_token\": { \"required\": false }, \"software_statement\": { \"required\": false, \"jwks\": { \"keys\": null }, \"jwks_uri\": \"\" }, \"payload\": { \"format\": \"json\", \"jws_payload\": { \"jwks\": { \"keys\": null }, \"jwks_uri\": \"\" } } }, \"grant_types\": [ \"authorization_code\", \"implicit\", \"client_credentials\", \"refresh_token\" ], \"token_endpoint_authn_methods\": [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"self_signed_tls_client_auth\", \"tls_client_auth\", \"none\" ], \"access_token_ttl\": \"3h0m0s\", \"refresh_token_ttl\": \"720h0m0s\", \"authorization_code_ttl\": \"10m0s\", \"id_token_ttl\": \"3h0m0s\", \"cookie_max_age\": \"1h0m0s\", \"jwks\": {\t\t\"keys\": [{\t\t\t\t\"use\": \"sig\",\t\t\t\t\"kty\": \"EC\",\t\t\t\t\"kid\": \"244861745913611684766818513248687510777770339898\",\t\t\t\t\"crv\": \"P-256\",\t\t\t\t\"alg\": \"ES256\",\t\t\t\t\"x\": \"5H1NpP-YTJbOwM-M_8wk5d4MFSA-2bIEXwr92vOXTlM\",\t\t\t\t\"y\": \"48cfpJpP9EuERXYIyJXgwaQPMCqtccBKV42Ec9kkZVc\",\t\t\t\t\"d\": \"XxpxSGD4ZDn8p3a_pgOb8aeuFSptUKliV-Hs6ik9G0w\",\t\t\t\t\"x5c\": [\t\t\t\t\t\"MIICIzCCAcmgAwIBAgIUKuP6/aKEXOAR3lgCxmKR0dHA7jowCgYIKoZIzj0EAwIwZzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMRQwEgYDVQQKDAtDbG91ZGVudGl0eTEjMCEGA1UEAwwaYWNwLnYxNi5jbG91ZGVudGl0eS1zZS5jb20wHhcNMjEwMTMwMjA0NjAyWhcNMzEwMTI4MjA0NjAyWjBnMQswCQYDVQQGEwJVUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxFDASBgNVBAoMC0Nsb3VkZW50aXR5MSMwIQYDVQQDDBphY3AudjE2LmNsb3VkZW50aXR5LXNlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOR9TaT/mEyWzsDPjP/MJOXeDBUgPtmyBF8K/drzl05T48cfpJpP9EuERXYIyJXgwaQPMCqtccBKV42Ec9kkZVejUzBRMB0GA1UdDgQWBBR0XtNqn673m+X0lVlTxjWWk12fCTAfBgNVHSMEGDAWgBR0XtNqn673m+X0lVlTxjWWk12fCTAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIA7ajABMU1Q5sFoa1vVvN7IBaFzCZPCvalhYDM8TxfyqAiEAq6bkOL4vuAPZtq7RPFIQPBzly6mfZuA30ciK6Sc4ab0=\"\t\t\t\t],\t\t\t\t\"x5t\": \"6xfvlWhPypSwWGct_WXzjENOHNk\",\t\t\t\t\"x5t#S256\": \"mrRCyDKOreVilIQmcz2HSWQD5PGzMaIMqaKkpZEy2Zs\"\t\t\t},\t\t\t{\t\t\t\t\"use\": \"sig\",\t\t\t\t\"kty\": \"EC\",\t\t\t\t\"kid\": \"303446885349823077582433662447357289206\",\t\t\t\t\"crv\": \"P-256\",\t\t\t\t\"alg\": \"ES256\",\t\t\t\t\"x\": \"2NBblGjHBkT0Toaci9JwrZ-fSuaMGrWshneP_4G8J_E\",\t\t\t\t\"y\": \"XDdYypQZXuUWN0O69aZIFQLNf3RVqxLO0CLIlh0knlo\",\t\t\t\t\"d\": \"fIY9g9OU9I0N6AHJbg-xDmN8UZNPEePRz1vTmNawrmg\",\t\t\t\t\"x5c\": [\t\t\t\t\t\"MIIBxTCCAWqgAwIBAgIRAORJvoqd7wNKrzlLyWGgYvYwCgYIKoZIzj0EAwIwLDEUMBIGA1UEChMLQ2xvdWRlbnRpdHkxFDASBgNVBAMTC0Nsb3VkZW50aXR5MB4XDTIxMDEyOTIwMTAzMFoXDTIxMDMwMTIwMTAzMFowLDEUMBIGA1UEChMLQ2xvdWRlbnRpdHkxFDASBgNVBAMTC0Nsb3VkZW50aXR5MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2NBblGjHBkT0Toaci9JwrZ+fSuaMGrWshneP/4G8J/FcN1jKlBle5RY3Q7r1pkgVAs1/dFWrEs7QIsiWHSSeWqNtMGswDgYDVR0PAQH/BAQDAgKkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFA3MMurUsdpPAbXnalVcpuDwEl1JMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDAKBggqhkjOPQQDAgNJADBGAiEAx0dKT57UMu9jDiQ/beOeYHlRqjEJhoMSPZzh8I0amPUCIQDpiuS+8Qo7R/Qa5ttUHBvWIb+ctlcEHyx2HsdAkIW2jA==\"\t\t\t\t],\t\t\t\t\"x5t\": \"uyOjbQzdzjVMr91rOHFagag2fFg\",\t\t\t\t\"x5t#S256\": \"uCXSufaU9pmSNS0PKFUYRgOCDB67HDz6wpuAoYzOwMo\"\t\t\t}\t\t]\t}, \"enforce_pkce\": false, \"enforce_pkce_for_public_clients\": false, \"root_cas\": \"\", \"read_client_certificate_from_header\": false, \"client_certificate_header\": \"\", \"subject_identifier_types\": [ \"public\", \"pairwise\" ], \"subject_identifier_algorithm_salt\": \"IASuYx0ffeiRJGnzkqCmcY-gH0HnGKMT9fFRlFvSrNQ\"}"
    
  4. To verify if the key set has been updated successfully, execute

    ubuntu curl -X GET "https://acp.example.com:8443/api/admin/default/servers/demo" -H "accept: application/json" -H "authorization: Bearer $ADMIN_ACCESS_TOKEN" | jq .jwks
    
    {
      "keys": [
        {
          "use": "sig",
          "kty": "EC",
          "kid": "244861745913611684766818513248687510777770339898",
          "crv": "P-256",
          "alg": "ES256",
          "x": "5H1NpP-YTJbOwM-M_8wk5d4MFSA-2bIEXwr92vOXTlM",
          "y": "48cfpJpP9EuERXYIyJXgwaQPMCqtccBKV42Ec9kkZVc",
          "d": "XxpxSGD4ZDn8p3a_pgOb8aeuFSptUKliV-Hs6ik9G0w",
          "x5c": [
            "MIICIzCCAcmgAwIBAgIUKuP6/aKEXOAR3lgCxmKR0dHA7jowCgYIKoZIzj0EAwIwZzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMRQwEgYDVQQKDAtDbG91ZGVudGl0eTEjMCEGA1UEAwwaYWNwLnYxNi5jbG91ZGVudGl0eS1zZS5jb20wHhcNMjEwMTMwMjA0NjAyWhcNMzEwMTI4MjA0NjAyWjBnMQswCQYDVQQGEwJVUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxFDASBgNVBAoMC0Nsb3VkZW50aXR5MSMwIQYDVQQDDBphY3AudjE2LmNsb3VkZW50aXR5LXNlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOR9TaT/mEyWzsDPjP/MJOXeDBUgPtmyBF8K/drzl05T48cfpJpP9EuERXYIyJXgwaQPMCqtccBKV42Ec9kkZVejUzBRMB0GA1UdDgQWBBR0XtNqn673m+X0lVlTxjWWk12fCTAfBgNVHSMEGDAWgBR0XtNqn673m+X0lVlTxjWWk12fCTAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIA7ajABMU1Q5sFoa1vVvN7IBaFzCZPCvalhYDM8TxfyqAiEAq6bkOL4vuAPZtq7RPFIQPBzly6mfZuA30ciK6Sc4ab0="
          ],
          "x5t": "6xfvlWhPypSwWGct_WXzjENOHNk",
          "x5t#S256": "mrRCyDKOreVilIQmcz2HSWQD5PGzMaIMqaKkpZEy2Zs"
        },
        {
          "use": "sig",
          "kty": "EC",
          "kid": "303446885349823077582433662447357289206",
          "crv": "P-256",
          "alg": "ES256",
          "x": "2NBblGjHBkT0Toaci9JwrZ-fSuaMGrWshneP_4G8J_E",
          "y": "XDdYypQZXuUWN0O69aZIFQLNf3RVqxLO0CLIlh0knlo",
          "d": "fIY9g9OU9I0N6AHJbg-xDmN8UZNPEePRz1vTmNawrmg",
          "x5c": [
            "MIIBxTCCAWqgAwIBAgIRAORJvoqd7wNKrzlLyWGgYvYwCgYIKoZIzj0EAwIwLDEUMBIGA1UEChMLQ2xvdWRlbnRpdHkxFDASBgNVBAMTC0Nsb3VkZW50aXR5MB4XDTIxMDEyOTIwMTAzMFoXDTIxMDMwMTIwMTAzMFowLDEUMBIGA1UEChMLQ2xvdWRlbnRpdHkxFDASBgNVBAMTC0Nsb3VkZW50aXR5MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2NBblGjHBkT0Toaci9JwrZ+fSuaMGrWshneP/4G8J/FcN1jKlBle5RY3Q7r1pkgVAs1/dFWrEs7QIsiWHSSeWqNtMGswDgYDVR0PAQH/BAQDAgKkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFA3MMurUsdpPAbXnalVcpuDwEl1JMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDAKBggqhkjOPQQDAgNJADBGAiEAx0dKT57UMu9jDiQ/beOeYHlRqjEJhoMSPZzh8I0amPUCIQDpiuS+8Qo7R/Qa5ttUHBvWIb+ctlcEHyx2HsdAkIW2jA=="
          ],
          "x5t": "uyOjbQzdzjVMr91rOHFagag2fFg",
          "x5t#S256": "uCXSufaU9pmSNS0PKFUYRgOCDB67HDz6wpuAoYzOwMo"
        }
      ]
    }
    

Verify

Access token

After generating the new access token with the use of the token endpoint or the demo application, check if it is similar to the example token provided.

Example token

eyJhbGciOiJFUzI1NiIsImtpZCI6IjI0NDg2MTc0NTkxMzYxMTY4NDc2NjgxODUxMzI0ODY4NzUxMDc3Nzc3MDMzOTg5OCIsInR5cCI6IkpXVCJ9.eyJhY3IiOiIxIiwiYWlkIjoiZGVtbyIsImFtciI6WyJwd2QiXSwiYXVkIjpbImRlbW8tZGVtbyIsInNwaWZmZTovL2FjcC52MTYuY2xvdWRlbnRpdHktc2UuY29tL2RlZmF1bHQvZGVtby9jMGE2bmRpZjViaW8xdG9uMHUxZyJdLCJleHAiOjE2MTIwNTEzNjAsImlhdCI6MTYxMjA0MDU2MCwiaWRwIjoiYzBhNm5tMmY1YmlvMXRvbjB1OWciLCJpc3MiOiJodHRwczovL2FjcC52MTYuY2xvdWRlbnRpdHktc2UuY29tOjg0NDMvZGVmYXVsdC9kZW1vIiwianRpIjoiMzg1YTQzMWMtMTFjNS00N2VmLWJkMTItMTc5MTk3NmFkNzRmIiwibmJmIjoxNjEyMDQwNTYwLCJzY3AiOlsiZW1haWwiLCJvcGVuaWQiLCJwcm9maWxlIl0sInN0IjoicHVibGljIiwic3ViIjoidXNlciIsInRpZCI6ImRlZmF1bHQifQ.5RPLAoBJZwwXiJHBjzn5BLH2JTs6CiaEA_1vQeEUPDMvfC8wzteOYDb5vAdsflpVj5HbAWSFQGLRtbjhWgiQvw

Decode the key

Decode the signature and check if the key_id matches the newly-configured key.

echo eyJhbGciOiJFUzI1NiIsImtpZCI6IjI0NDg2MTc0NTkxMzYxMTY4NDc2NjgxODUxMzI0ODY4NzUxMDc3Nzc3MDMzOTg5OCIsInR5cCI6IkpXVCJ9 | base64 -d | jq .kid
"244861745913611684766818513248687510777770339898"

Check the JWKS OIDC endpoint

Check if now the JWKS OIDC endpoint includes the new key and the old.

ubuntu@:$ curl https://acp.example.com:8443/default/demo/.well-known/jwks.json  | jq
 {
  "keys": [
    {
      "use": "sig",
      "kty": "EC",
      "kid": "244861745913611684766818513248687510777770339898",
      "crv": "P-256",
      "alg": "ES256",
      "x": "5H1NpP-YTJbOwM-M_8wk5d4MFSA-2bIEXwr92vOXTlM",
      "y": "48cfpJpP9EuERXYIyJXgwaQPMCqtccBKV42Ec9kkZVc",
      "x5c": [
        "MIICIzCCAcmgAwIBAgIUKuP6/aKEXOAR3lgCxmKR0dHA7jowCgYIKoZIzj0EAwIwZzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMRQwEgYDVQQKDAtDbG91ZGVudGl0eTEjMCEGA1UEAwwaYWNwLnYxNi5jbG91ZGVudGl0eS1zZS5jb20wHhcNMjEwMTMwMjA0NjAyWhcNMzEwMTI4MjA0NjAyWjBnMQswCQYDVQQGEwJVUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxFDASBgNVBAoMC0Nsb3VkZW50aXR5MSMwIQYDVQQDDBphY3AudjE2LmNsb3VkZW50aXR5LXNlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOR9TaT/mEyWzsDPjP/MJOXeDBUgPtmyBF8K/drzl05T48cfpJpP9EuERXYIyJXgwaQPMCqtccBKV42Ec9kkZVejUzBRMB0GA1UdDgQWBBR0XtNqn673m+X0lVlTxjWWk12fCTAfBgNVHSMEGDAWgBR0XtNqn673m+X0lVlTxjWWk12fCTAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIA7ajABMU1Q5sFoa1vVvN7IBaFzCZPCvalhYDM8TxfyqAiEAq6bkOL4vuAPZtq7RPFIQPBzly6mfZuA30ciK6Sc4ab0="
      ],
      "x5t": "6xfvlWhPypSwWGct_WXzjENOHNk",
      "x5t#S256": "mrRCyDKOreVilIQmcz2HSWQD5PGzMaIMqaKkpZEy2Zs"
    },
    {
      "use": "sig",
      "kty": "EC",
      "kid": "303446885349823077582433662447357289206",
      "crv": "P-256",
      "alg": "ES256",
      "x": "2NBblGjHBkT0Toaci9JwrZ-fSuaMGrWshneP_4G8J_E",
      "y": "XDdYypQZXuUWN0O69aZIFQLNf3RVqxLO0CLIlh0knlo",
      "x5c": [
        "MIIBxTCCAWqgAwIBAgIRAORJvoqd7wNKrzlLyWGgYvYwCgYIKoZIzj0EAwIwLDEUMBIGA1UEChMLQ2xvdWRlbnRpdHkxFDASBgNVBAMTC0Nsb3VkZW50aXR5MB4XDTIxMDEyOTIwMTAzMFoXDTIxMDMwMTIwMTAzMFowLDEUMBIGA1UEChMLQ2xvdWRlbnRpdHkxFDASBgNVBAMTC0Nsb3VkZW50aXR5MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2NBblGjHBkT0Toaci9JwrZ+fSuaMGrWshneP/4G8J/FcN1jKlBle5RY3Q7r1pkgVAs1/dFWrEs7QIsiWHSSeWqNtMGswDgYDVR0PAQH/BAQDAgKkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFA3MMurUsdpPAbXnalVcpuDwEl1JMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDAKBggqhkjOPQQDAgNJADBGAiEAx0dKT57UMu9jDiQ/beOeYHlRqjEJhoMSPZzh8I0amPUCIQDpiuS+8Qo7R/Qa5ttUHBvWIb+ctlcEHyx2HsdAkIW2jA=="
      ],
      "x5t": "uyOjbQzdzjVMr91rOHFagag2fFg",
      "x5t#S256": "uCXSufaU9pmSNS0PKFUYRgOCDB67HDz6wpuAoYzOwMo"
    }
  ]
}

Delete the old key

When the old JWT Key is no longer needed, it can be deleted using the same Update Authorization Server API https://docs.authorization.cloudentity.com/api/admin/#operation/updateAuthorizationServer.

curl -X PUT "https://acp.example.com:8443/api/admin/default/servers/demo" -H "accept: application/json" -H "authorization: Bearer $ADMIN_ACCESS_TOKEN" -H "Content-Type: application/json" -d "{ \"tenant_id\": \"default\", \"id\": \"demo\", \"profile\": \"default\", \"name\": \"Demo\", \"type\": \"regular\", \"color\": \"#007FFF\", \"secret\": \"a7PsnLjCoqfzWPbya_6ZE1gmOed0sjHm5g3z0AHo8SM\", \"rotated_secrets\": [], \"access_token_strategy\": \"jwt\", \"key_type\": \"ecdsa\", \"logo_uri\": \"\", \"issuer_url\": \"https://acp.example.com:8443/default/demo\", \"dynamic_client_registration\": { \"enabled\": false, \"initial_access_token\": { \"required\": false }, \"software_statement\": { \"required\": false, \"jwks\": { \"keys\": null }, \"jwks_uri\": \"\" }, \"payload\": { \"format\": \"json\", \"jws_payload\": { \"jwks\": { \"keys\": null }, \"jwks_uri\": \"\" } } }, \"grant_types\": [ \"authorization_code\", \"implicit\", \"client_credentials\", \"refresh_token\" ], \"token_endpoint_authn_methods\": [ \"client_secret_basic\", \"client_secret_post\", \"client_secret_jwt\", \"private_key_jwt\", \"self_signed_tls_client_auth\", \"tls_client_auth\", \"none\" ], \"access_token_ttl\": \"3h0m0s\", \"refresh_token_ttl\": \"720h0m0s\", \"authorization_code_ttl\": \"10m0s\", \"id_token_ttl\": \"3h0m0s\", \"cookie_max_age\": \"1h0m0s\", \"jwks\": {\t\t\"keys\": [{\t\t\t\t\"use\": \"sig\",\t\t\t\t\"kty\": \"EC\",\t\t\t\t\"kid\": \"244861745913611684766818513248687510777770339898\",\t\t\t\t\"crv\": \"P-256\",\t\t\t\t\"alg\": \"ES256\",\t\t\t\t\"x\": \"5H1NpP-YTJbOwM-M_8wk5d4MFSA-2bIEXwr92vOXTlM\",\t\t\t\t\"y\": \"48cfpJpP9EuERXYIyJXgwaQPMCqtccBKV42Ec9kkZVc\",\t\t\t\t\"d\": \"XxpxSGD4ZDn8p3a_pgOb8aeuFSptUKliV-Hs6ik9G0w\",\t\t\t\t\"x5c\": [\t\t\t\t\t\"MIICIzCCAcmgAwIBAgIUKuP6/aKEXOAR3lgCxmKR0dHA7jowCgYIKoZIzj0EAwIwZzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0dGxlMRQwEgYDVQQKDAtDbG91ZGVudGl0eTEjMCEGA1UEAwwaYWNwLnYxNi5jbG91ZGVudGl0eS1zZS5jb20wHhcNMjEwMTMwMjA0NjAyWhcNMzEwMTI4MjA0NjAyWjBnMQswCQYDVQQGEwJVUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxFDASBgNVBAoMC0Nsb3VkZW50aXR5MSMwIQYDVQQDDBphY3AudjE2LmNsb3VkZW50aXR5LXNlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOR9TaT/mEyWzsDPjP/MJOXeDBUgPtmyBF8K/drzl05T48cfpJpP9EuERXYIyJXgwaQPMCqtccBKV42Ec9kkZVejUzBRMB0GA1UdDgQWBBR0XtNqn673m+X0lVlTxjWWk12fCTAfBgNVHSMEGDAWgBR0XtNqn673m+X0lVlTxjWWk12fCTAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIA7ajABMU1Q5sFoa1vVvN7IBaFzCZPCvalhYDM8TxfyqAiEAq6bkOL4vuAPZtq7RPFIQPBzly6mfZuA30ciK6Sc4ab0=\"\t\t\t\t],\t\t\t\t\"x5t\": \"6xfvlWhPypSwWGct_WXzjENOHNk\",\t\t\t\t\"x5t#S256\": \"mrRCyDKOreVilIQmcz2HSWQD5PGzMaIMqaKkpZEy2Zs\"\t\t\t}\t\t]\t}, \"enforce_pkce\": false, \"enforce_pkce_for_public_clients\": false, \"root_cas\": \"\", \"read_client_certificate_from_header\": false, \"client_certificate_header\": \"\", \"subject_identifier_types\": [ \"public\", \"pairwise\" ], \"subject_identifier_algorithm_salt\": \"IASuYx0ffeiRJGnzkqCmcY-gH0HnGKMT9fFRlFvSrNQ\"}"