Auth0の署名鍵をローテーションしてみる

Auth0に署名鍵をローテーションする機能が追加されたので、試しに鍵を更新してみました。

## はじめに
IDトークンやアクセストークンなど、Auth0が発行するJWT形式のトークンにはRS256で署名されるものがあります。これらのトークンへの署名に使用される鍵の更新を管理DashBoardとManagement APIで行うことができます。

本記事では主に管理Dashboardでの操作について紹介します。

## 注意点
署名鍵のローテーションを行う場合、署名検証を行うClientまたはJWT形式のアクセストークンを受け取るリソースサーバーがJWTのヘッダーの`kid`クレームの値で、JWK Setエンドポイント（`https://{テナントドメイン}/.well-known/jwks.json`）から公開鍵を引き当てて署名検証に利用している必要があります。
でないと、署名鍵をローテーションしても署名検証する側がそれに追随できず、署名検証が突然失敗するようになったり、失効済みの秘密鍵で署名されたトークンを受け入れ続けたりする、などといったトラブルに見舞われることになります。

## 管理Dashboadの署名鍵管理メニュー

管理Dashboardのテナント設定から署名鍵の管理ができます。

<img width="860" alt="スクリーンショット 2020-04-24 10.50.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490013/62bd948b-c9c6-64e3-b3a2-08298be84857.png">

署名鍵のローテーションとしての操作は以下の3つぐらいなので、特に悩む点は無いと思います。

- 「ROTATE KEY」ボタンのクリック
- 「ROTATE & REVOKE KEY」ボタンのクリック
- 「List of Vaild Keys」からローテーション済みの署名鍵を無効化

また、JWK Setエンドポイントにアクセスすると、「List of Valid Keys」に表示されているものと同じKey ID(kid)のJWK Setが取得できます。

```json
{
  "keys": [
    {
      "alg": "RS256",
      "kty": "RSA",
      "use": "sig",
      "n": "4mLkF48v4zaYjEQEcPr1DHMuf68DonZVncE5LdES_NMolp0SpseJYdRvW1-njbV4SnJegMSecf9dqQoBsBP_M7VciEbP0QRGoMl57mO_S5r3hLPPNZeJ-lmxCTBDxRYW55otyBgsC9SW4Wtxm0j1QPqGLF8pe9ruthqeYBt419Go6APh84iWNag_I-RqzsOB2rvI0xV9I3V-KME9E6LhY2g3D1d0UquB0yiK4qhvqlsAC6AoDKPyr0MMslzQEvkqpUSUpN9hDDEuflFcsCvRZHYFS2xwFVYw-zl9K46L5sqf1UGFzAwF6kVKd4xEIKYryVeyHgdVi2hy-1Pj4pgcuw",
      "e": "AQAB",
      "kid": "QTJCRDQ2NTIzMTUzMkIzMDk1RjNGMEVCNEQ3MjBDNDYzMjQxRjA0QQ",
      "x5t": "QTJCRDQ2NTIzMTUzMkIzMDk1RjNGMEVCNEQ3MjBDNDYzMjQxRjA0QQ",
      "x5c": [
        "MIIC+zCCAeOgAwIBAgIJdMTvsPXXIkwBMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNVBAMTEG9oYmlsbC5hdXRoMC5jb20wHhcNMTkwNzEyMDIwNzIxWhcNMzMwMzIwMDIwNzIxWjAbMRkwFwYDVQQDExBvaGJpbGwuYXV0aDAuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4mLkF48v4zaYjEQEcPr1DHMuf68DonZVncE5LdES/NMolp0SpseJYdRvW1+njbV4SnJegMSecf9dqQoBsBP/M7VciEbP0QRGoMl57mO/S5r3hLPPNZeJ+lmxCTBDxRYW55otyBgsC9SW4Wtxm0j1QPqGLF8pe9ruthqeYBt419Go6APh84iWNag/I+RqzsOB2rvI0xV9I3V+KME9E6LhY2g3D1d0UquB0yiK4qhvqlsAC6AoDKPyr0MMslzQEvkqpUSUpN9hDDEuflFcsCvRZHYFS2xwFVYw+zl9K46L5sqf1UGFzAwF6kVKd4xEIKYryVeyHgdVi2hy+1Pj4pgcuwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRxHzW/6U0OthUGcej8AwjAFdBFjjAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQELBQADggEBAG575otNvargct7+RzZuDzXxN4syHJSk9d+CYuIkPXwjE5U8wch1VMGjzw05eqAU3jGSbie2VygFu00v+BQKqIvDsJZmCo95dtXil8dbHf3fD63hgFBDUmOuSspvCFxcgn8W9M9xp/Hn/1bGc7/GdjUKBPd2TdiGyHnbZEnMSVp/MWVHzyMLTETY3rYzl7riSmIblresWUBKXZR88iic7wrzE1yxVHk5NKXtF9gjfMLhOw9mCROXE5I8ETOYcy7UCyDmSfP6q+9qdA4t0AWAmUbqesrNdlgbQIPpdy3usx4PwhtQMYGLZyiq/AGHQHBfimXfAP80JO/bcaQTFbG32JM="
      ]
    },
    {
      "alg": "RS256",
      "kty": "RSA",
      "use": "sig",
      "n": "2BAgNcHzqOhFA0AZVggxoLoUejGsnjpcru4yOijwGPkzDVd9jLbiKT9hpoz39YTqoMYpaX3w2O_UAcQHrzg-z2672BKPFtl1NF74_VLDYSNR7sQRM1fwdKuuMKlEMfhrVm3Fdyfka26wLh-TkrRKv7inYhZ73PanmeHG240-aUfOXu0H3zIdMRCvuh4s6POIgjaVhZ2ZY9MgBS3FPMNj8SKXLwVEMYoaSiyXRsatmgrMhBmyAMXapnOt2ZMdEin3MJHIsJlwBHiC1HrLtjlO4vrkSkQTo-NBeW11Xlnw49BpYELHQKSLxeYlovRYSlAXzeuW9oPomglPLdsKbryYpw",
      "e": "AQAB",
      "kid": "mkDK3u6Ac3csr-pdWRofP",
      "x5t": "M76BV2RZqu8-z9K8fBi06sSuRa0",
      "x5c": [
        "MIIC+zCCAeOgAwIBAgIJU42EDfUWXl5bMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNVBAMTEG9oYmlsbC5hdXRoMC5jb20wHhcNMjAwMzExMjIzNzAxWhcNMzMxMTE4MjIzNzAxWjAbMRkwFwYDVQQDExBvaGJpbGwuYXV0aDAuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2BAgNcHzqOhFA0AZVggxoLoUejGsnjpcru4yOijwGPkzDVd9jLbiKT9hpoz39YTqoMYpaX3w2O/UAcQHrzg+z2672BKPFtl1NF74/VLDYSNR7sQRM1fwdKuuMKlEMfhrVm3Fdyfka26wLh+TkrRKv7inYhZ73PanmeHG240+aUfOXu0H3zIdMRCvuh4s6POIgjaVhZ2ZY9MgBS3FPMNj8SKXLwVEMYoaSiyXRsatmgrMhBmyAMXapnOt2ZMdEin3MJHIsJlwBHiC1HrLtjlO4vrkSkQTo+NBeW11Xlnw49BpYELHQKSLxeYlovRYSlAXzeuW9oPomglPLdsKbryYpwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR0lbIzIrv7E1QVHrvgLPUclhqe7jAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQELBQADggEBAHo1Ky9JisL2n8qbHkkH50zJQJZWSzB+hfETWls+LkbmxkFy1zw3WcpqoiDGxrTDI+4WOpf/6sWCcPrX3fDzs38FpyX713Nale/5oOG/WpH/aYpwQb3Po5I+FzfWAW1yf0TVugmXDULEh/gumdm5Ur2am4ego+UpfnvcOUwBnq9u0ZJMnfvxwcCPLwddZ+Nu5mpKtSa7MmKjY6M7gor+7zz11xqnwZUeiPhrKTqcXYCGX81IOR5JPupRp8aeD99QOt7rgnt0Y7xUZ3NS2BDppdoSzSuDr8f0VDwiZDIGazHC5qwhudiLbitUh8rtgBx8xqkzAh1/3MDe3uHJ9LlB3Jk="
      ]
    }
  ]
}
```

この初期状態で既に鍵が2つ存在していますが、この時点でAuth0が使用する署名鍵はステータスが`CURRENTLY USED`となっているものです。

この状態で発行されたIDトークンのヘッダーを例として載せておきます。`kid`はステータスが`CURRENTLY USED`の鍵のKey IDと同じ値になっています。

```json
{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "QTJCRDQ2NTIzMTUzMkIzMDk1RjNGMEVCNEQ3MjBDNDYzMjQxRjA0QQ"
}
```

## ROTATE KEY
署名鍵の管理メニューの「ROTATE KEY」ボタンをクリックすると、「List of Valid Keys」に新しい鍵が追加され、元々ステータスが`CURRENTLY USED`だった鍵は`PREVIOUSLY USED`へとステータスが更新されます。

<img width="682" alt="スクリーンショット 2020-04-24 10.54.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490013/f3965e2f-02a9-77c2-a4bd-014e6a8ec2aa.png">

ステータスが`PREVIOUSLY USED`となった鍵はまだ有効なのでJWK Setにも残っています。この鍵で署名されたトークンの署名検証もうまくいくでしょう。

```json
{
  "keys": [
    {
      "alg": "RS256",
      "kty": "RSA",
      "use": "sig",
      "n": "2BAgNcHzqOhFA0AZVggxoLoUejGsnjpcru4yOijwGPkzDVd9jLbiKT9hpoz39YTqoMYpaX3w2O_UAcQHrzg-z2672BKPFtl1NF74_VLDYSNR7sQRM1fwdKuuMKlEMfhrVm3Fdyfka26wLh-TkrRKv7inYhZ73PanmeHG240-aUfOXu0H3zIdMRCvuh4s6POIgjaVhZ2ZY9MgBS3FPMNj8SKXLwVEMYoaSiyXRsatmgrMhBmyAMXapnOt2ZMdEin3MJHIsJlwBHiC1HrLtjlO4vrkSkQTo-NBeW11Xlnw49BpYELHQKSLxeYlovRYSlAXzeuW9oPomglPLdsKbryYpw",
      "e": "AQAB",
      "kid": "mkDK3u6Ac3csr-pdWRofP",
      "x5t": "M76BV2RZqu8-z9K8fBi06sSuRa0",
      "x5c": [
        "MIIC+zCCAeOgAwIBAgIJU42EDfUWXl5bMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNVBAMTEG9oYmlsbC5hdXRoMC5jb20wHhcNMjAwMzExMjIzNzAxWhcNMzMxMTE4MjIzNzAxWjAbMRkwFwYDVQQDExBvaGJpbGwuYXV0aDAuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2BAgNcHzqOhFA0AZVggxoLoUejGsnjpcru4yOijwGPkzDVd9jLbiKT9hpoz39YTqoMYpaX3w2O/UAcQHrzg+z2672BKPFtl1NF74/VLDYSNR7sQRM1fwdKuuMKlEMfhrVm3Fdyfka26wLh+TkrRKv7inYhZ73PanmeHG240+aUfOXu0H3zIdMRCvuh4s6POIgjaVhZ2ZY9MgBS3FPMNj8SKXLwVEMYoaSiyXRsatmgrMhBmyAMXapnOt2ZMdEin3MJHIsJlwBHiC1HrLtjlO4vrkSkQTo+NBeW11Xlnw49BpYELHQKSLxeYlovRYSlAXzeuW9oPomglPLdsKbryYpwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR0lbIzIrv7E1QVHrvgLPUclhqe7jAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQELBQADggEBAHo1Ky9JisL2n8qbHkkH50zJQJZWSzB+hfETWls+LkbmxkFy1zw3WcpqoiDGxrTDI+4WOpf/6sWCcPrX3fDzs38FpyX713Nale/5oOG/WpH/aYpwQb3Po5I+FzfWAW1yf0TVugmXDULEh/gumdm5Ur2am4ego+UpfnvcOUwBnq9u0ZJMnfvxwcCPLwddZ+Nu5mpKtSa7MmKjY6M7gor+7zz11xqnwZUeiPhrKTqcXYCGX81IOR5JPupRp8aeD99QOt7rgnt0Y7xUZ3NS2BDppdoSzSuDr8f0VDwiZDIGazHC5qwhudiLbitUh8rtgBx8xqkzAh1/3MDe3uHJ9LlB3Jk="
      ]
    },
    {
      "alg": "RS256",
      "kty": "RSA",
      "use": "sig",
      "n": "4mLkF48v4zaYjEQEcPr1DHMuf68DonZVncE5LdES_NMolp0SpseJYdRvW1-njbV4SnJegMSecf9dqQoBsBP_M7VciEbP0QRGoMl57mO_S5r3hLPPNZeJ-lmxCTBDxRYW55otyBgsC9SW4Wtxm0j1QPqGLF8pe9ruthqeYBt419Go6APh84iWNag_I-RqzsOB2rvI0xV9I3V-KME9E6LhY2g3D1d0UquB0yiK4qhvqlsAC6AoDKPyr0MMslzQEvkqpUSUpN9hDDEuflFcsCvRZHYFS2xwFVYw-zl9K46L5sqf1UGFzAwF6kVKd4xEIKYryVeyHgdVi2hy-1Pj4pgcuw",
      "e": "AQAB",
      "kid": "QTJCRDQ2NTIzMTUzMkIzMDk1RjNGMEVCNEQ3MjBDNDYzMjQxRjA0QQ",
      "x5t": "QTJCRDQ2NTIzMTUzMkIzMDk1RjNGMEVCNEQ3MjBDNDYzMjQxRjA0QQ",
      "x5c": [
        "MIIC+zCCAeOgAwIBAgIJdMTvsPXXIkwBMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNVBAMTEG9oYmlsbC5hdXRoMC5jb20wHhcNMTkwNzEyMDIwNzIxWhcNMzMwMzIwMDIwNzIxWjAbMRkwFwYDVQQDExBvaGJpbGwuYXV0aDAuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4mLkF48v4zaYjEQEcPr1DHMuf68DonZVncE5LdES/NMolp0SpseJYdRvW1+njbV4SnJegMSecf9dqQoBsBP/M7VciEbP0QRGoMl57mO/S5r3hLPPNZeJ+lmxCTBDxRYW55otyBgsC9SW4Wtxm0j1QPqGLF8pe9ruthqeYBt419Go6APh84iWNag/I+RqzsOB2rvI0xV9I3V+KME9E6LhY2g3D1d0UquB0yiK4qhvqlsAC6AoDKPyr0MMslzQEvkqpUSUpN9hDDEuflFcsCvRZHYFS2xwFVYw+zl9K46L5sqf1UGFzAwF6kVKd4xEIKYryVeyHgdVi2hy+1Pj4pgcuwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRxHzW/6U0OthUGcej8AwjAFdBFjjAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQELBQADggEBAG575otNvargct7+RzZuDzXxN4syHJSk9d+CYuIkPXwjE5U8wch1VMGjzw05eqAU3jGSbie2VygFu00v+BQKqIvDsJZmCo95dtXil8dbHf3fD63hgFBDUmOuSspvCFxcgn8W9M9xp/Hn/1bGc7/GdjUKBPd2TdiGyHnbZEnMSVp/MWVHzyMLTETY3rYzl7riSmIblresWUBKXZR88iic7wrzE1yxVHk5NKXtF9gjfMLhOw9mCROXE5I8ETOYcy7UCyDmSfP6q+9qdA4t0AWAmUbqesrNdlgbQIPpdy3usx4PwhtQMYGLZyiq/AGHQHBfimXfAP80JO/bcaQTFbG32JM="
      ]
    },
    {
      "alg": "RS256",
      "kty": "RSA",
      "use": "sig",
      "n": "8eGwp8bt1bmma-pk0l9oD4g5SI3TSrfq3hW6H7-dT-kQENBL87anWsETg7enY9dt1Sbrobx4QYQPPUo-48vN5X1nR9Wo64orINBxImu53aIQsZ6d2vFN5FqY-hEZZrliP8hbng85rk_ncVdgO7ssuNjXxHtzAKS-iF3sqzy_WWe5aPXGTqdt_bE7DEsRK-cG4xq9nCrz9Hlf0_UVmGAUW3T4Dwy7KqcvCOWWO0w7PEdEDjmpYlblJFri5JFhnTQqeaPvr-oiYk6Xap2yTurYklFxsWvuiL0ZK4pPi-UkBrusr8QnRrqsFBIwK0h-2pofRnjy58wvZlyIIxXbDxLi2Q",
      "e": "AQAB",
      "kid": "I9bOQwY0BU3mgJOTY9-QW",
      "x5t": "GJdo2zlljsUI6pD8gvQ_gwqu8fc",
      "x5c": [
        "MIIC+zCCAeOgAwIBAgIJLtKvntSYTZytMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNVBAMTEG9oYmlsbC5hdXRoMC5jb20wHhcNMjAwNDI0MDE1NDA3WhcNMzQwMTAxMDE1NDA3WjAbMRkwFwYDVQQDExBvaGJpbGwuYXV0aDAuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8eGwp8bt1bmma+pk0l9oD4g5SI3TSrfq3hW6H7+dT+kQENBL87anWsETg7enY9dt1Sbrobx4QYQPPUo+48vN5X1nR9Wo64orINBxImu53aIQsZ6d2vFN5FqY+hEZZrliP8hbng85rk/ncVdgO7ssuNjXxHtzAKS+iF3sqzy/WWe5aPXGTqdt/bE7DEsRK+cG4xq9nCrz9Hlf0/UVmGAUW3T4Dwy7KqcvCOWWO0w7PEdEDjmpYlblJFri5JFhnTQqeaPvr+oiYk6Xap2yTurYklFxsWvuiL0ZK4pPi+UkBrusr8QnRrqsFBIwK0h+2pofRnjy58wvZlyIIxXbDxLi2QIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTEEXNv3pe7LyK2SgzlyIGwGBd9/zAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQELBQADggEBAK7MlJQ75ccXQtZDVlcfncnrr6QLapr+Z4ro5QXDKYweQktboNYq8vZl+j82muIo2t49dpxCTfCc5sOppSUmihVZEaw85Qyj8vdD6jjSlDJ/vPAFrvLRGRlZADGUZaiDCkwMcSlsza4/3RYmbs2ks4n4kWpEL/q+A92wDiNjIyVLnkMOjrps7TEk3oscXOzmsGZWVRzVyPeBLU1mLU3fKizo4/0ISKIO8tbgwBE9Cg891Z7tK1SxsLx3QPZ+zLC9OK6XY3YpdRxRxVh/LTRI3dJ+eq8UtO3TSBCW6H1E1tTSLOuK3tS91pcNu9G3U5zAWQeFREOIQTDGdTy9fK5C+WQ="
      ]
    }
  ]
```

この状態で新たに発行されるIDトークンのヘッダーの例です。`kid`はステータスが`CURRENTLY USED`の鍵のものと同じ値になっています。

```json
{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "mkDK3u6Ac3csr-pdWRofP"
}
```

## ローテーション済みの署名鍵を無効化する
「List of Valid Keys」に表示されている鍵のうち、ステータスが`PREVIOUSLY USED`になっている鍵はメニューから無効化することができます。

<img width="682" alt="スクリーンショット 2020-04-24 10.55.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490013/8c616574-ab64-fc5b-868c-d3584b83698b.png">

「ROTATE KEY」ボタンで鍵をローテーションしたあと、任意のタイミングで過去の鍵を無効するといった運用が可能です。

## ROTATE & REVOKE KEY
署名鍵の管理メニューの「ROTATE & REVOKE KEY」ボタンをクリックすると、署名鍵がローテーションされ既存の鍵が無効化されます。

以下のこの状態から「ROTATE & REVOKE KEY」ボタンをクリックすると
<img width="682" alt="スクリーンショット 2020-04-24 10.54.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490013/f3965e2f-02a9-77c2-a4bd-014e6a8ec2aa.png">

こうなります。

<img width="680" alt="スクリーンショット 2020-04-24 11.02.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490013/3f88aac3-e023-926b-419b-128e3bc26bfc.png">

さらに、メニュー下部の「List of Revoked Keys」に以下の2つのKey IDが表示されるはずです。（スクショ撮り忘れた）

- `mkDK3u6Ac3csr-pdWRofP`
- `QTJCRDQ2NTIzMTUzMkIzMDk1RjNGMEVCNEQ3MjBDNDYzMjQxRjA0QQ`

JWK Setはこうなって

```json
{
  "keys": [
    {
      "alg": "RS256",
      "kty": "RSA",
      "use": "sig",
      "n": "8eGwp8bt1bmma-pk0l9oD4g5SI3TSrfq3hW6H7-dT-kQENBL87anWsETg7enY9dt1Sbrobx4QYQPPUo-48vN5X1nR9Wo64orINBxImu53aIQsZ6d2vFN5FqY-hEZZrliP8hbng85rk_ncVdgO7ssuNjXxHtzAKS-iF3sqzy_WWe5aPXGTqdt_bE7DEsRK-cG4xq9nCrz9Hlf0_UVmGAUW3T4Dwy7KqcvCOWWO0w7PEdEDjmpYlblJFri5JFhnTQqeaPvr-oiYk6Xap2yTurYklFxsWvuiL0ZK4pPi-UkBrusr8QnRrqsFBIwK0h-2pofRnjy58wvZlyIIxXbDxLi2Q",
      "e": "AQAB",
      "kid": "I9bOQwY0BU3mgJOTY9-QW",
      "x5t": "GJdo2zlljsUI6pD8gvQ_gwqu8fc",
      "x5c": [
        "MIIC+zCCAeOgAwIBAgIJLtKvntSYTZytMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNVBAMTEG9oYmlsbC5hdXRoMC5jb20wHhcNMjAwNDI0MDE1NDA3WhcNMzQwMTAxMDE1NDA3WjAbMRkwFwYDVQQDExBvaGJpbGwuYXV0aDAuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8eGwp8bt1bmma+pk0l9oD4g5SI3TSrfq3hW6H7+dT+kQENBL87anWsETg7enY9dt1Sbrobx4QYQPPUo+48vN5X1nR9Wo64orINBxImu53aIQsZ6d2vFN5FqY+hEZZrliP8hbng85rk/ncVdgO7ssuNjXxHtzAKS+iF3sqzy/WWe5aPXGTqdt/bE7DEsRK+cG4xq9nCrz9Hlf0/UVmGAUW3T4Dwy7KqcvCOWWO0w7PEdEDjmpYlblJFri5JFhnTQqeaPvr+oiYk6Xap2yTurYklFxsWvuiL0ZK4pPi+UkBrusr8QnRrqsFBIwK0h+2pofRnjy58wvZlyIIxXbDxLi2QIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTEEXNv3pe7LyK2SgzlyIGwGBd9/zAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQELBQADggEBAK7MlJQ75ccXQtZDVlcfncnrr6QLapr+Z4ro5QXDKYweQktboNYq8vZl+j82muIo2t49dpxCTfCc5sOppSUmihVZEaw85Qyj8vdD6jjSlDJ/vPAFrvLRGRlZADGUZaiDCkwMcSlsza4/3RYmbs2ks4n4kWpEL/q+A92wDiNjIyVLnkMOjrps7TEk3oscXOzmsGZWVRzVyPeBLU1mLU3fKizo4/0ISKIO8tbgwBE9Cg891Z7tK1SxsLx3QPZ+zLC9OK6XY3YpdRxRxVh/LTRI3dJ+eq8UtO3TSBCW6H1E1tTSLOuK3tS91pcNu9G3U5zAWQeFREOIQTDGdTy9fK5C+WQ="
      ]
    },
    {
      "alg": "RS256",
      "kty": "RSA",
      "use": "sig",
      "n": "xeUPNIIGjv7RLkl2ZECuYTug8iKQsIBv6Ub2frlMRDRMoSIPb1sL1bDD7F9CUlI1Nb3oYfYTsnV69IifE2JUx8RNepaJKmukaUNVY1HlzMokMZJZnVmY8w_YjrC2Z966HiZ32K9qSs4f51g6BKTZWRONHSvDcKhWW5jgOeiZLn6S9oyi3sHwRHpWL9XKB4yI9JyewgBcn7t4YQZDfe5l5tdBhRCRyUesY9p6PqblIOvHMJTC2XjtPf5eyBYJMEMjXWxbEA8rSYDOLvc34A768Ot2qzKJ7XCxYcQSet_pw_csmsZRENLlK5HrFuTsS_0hqPPkL9vVBtEZOk-Sf0lzSw",
      "e": "AQAB",
      "kid": "dLPlnohYXhYr_wUYJPs9l",
      "x5t": "4uMUzCndFkOr_PastxacUpukrzs",
      "x5c": [
        "MIIC+zCCAeOgAwIBAgIJC0igQZFsztlAMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNVBAMTEG9oYmlsbC5hdXRoMC5jb20wHhcNMjAwNDI0MDIwMjA4WhcNMzQwMTAxMDIwMjA4WjAbMRkwFwYDVQQDExBvaGJpbGwuYXV0aDAuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxeUPNIIGjv7RLkl2ZECuYTug8iKQsIBv6Ub2frlMRDRMoSIPb1sL1bDD7F9CUlI1Nb3oYfYTsnV69IifE2JUx8RNepaJKmukaUNVY1HlzMokMZJZnVmY8w/YjrC2Z966HiZ32K9qSs4f51g6BKTZWRONHSvDcKhWW5jgOeiZLn6S9oyi3sHwRHpWL9XKB4yI9JyewgBcn7t4YQZDfe5l5tdBhRCRyUesY9p6PqblIOvHMJTC2XjtPf5eyBYJMEMjXWxbEA8rSYDOLvc34A768Ot2qzKJ7XCxYcQSet/pw/csmsZRENLlK5HrFuTsS/0hqPPkL9vVBtEZOk+Sf0lzSwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTsi9/Wb8tqD2t57bGqw/llFDT3njAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQELBQADggEBAGdqb3192ThS/69erVT/ARZfZel//BgNqhQILmWxkselSoN3MKoUBCZoymJyVao4oMOtfkbtKEPTmt/otZMukoCyMjz5aASZL8rhMKK2s0DblFxUSxPeGWZFGygBX2D4OAvBTj2BFGJN8YhcMoBMMidCyU5/5/5UGk4pzMqnukuIk6nO7+5K1rTjmRW7SugYdzUag33Ny1Qq4ET6U6F8RynuK5ltmgswyu9AlTfgDCtu3aHH4m+Z3785V0fuFMxIxE6clTx6RDkaoYF33fa0/N01glJA4yXd7v1eDesJZP7XZbIfSXuYsNXxsZt4bTOm7ukFosccypOhL9IJcp0AAJM="
      ]
    }
  ]
}
```

この状態で発行されるIDトークンのヘッダーはこうなります。

```json
{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "I9bOQwY0BU3mgJOTY9-QW"
}
```

## Management APIで署名鍵のローテーション
Management APIにも署名鍵に関するAPIが追加されています。

- [Get all Application Signing Keys] (https://auth0.com/docs/api/management/v2#!/Keys/get_signing_keys)
- [Get an Application Signing Key by its key id](https://auth0.com/docs/api/management/v2#!/Keys/get_signing_key)
- [Rotate the Application Signing Key](https://auth0.com/docs/api/management/v2#!/Keys/post_signing_keys)
- [Revoke an Application Signing Key by its key id](https://auth0.com/docs/api/management/v2#!/Keys/put_signing_keys)

Auth0のドキュメント（[Rate Limit Policy For Auth0 APIs](https://auth0.com/docs/policies/rate-limits#management-api-v2)）によると、署名鍵のローテーションは1日あたり5回までに制限されているようです。
ちなみに、管理Dashboardでのローテーションも5回を超えるとエラーメッセージが表示されるようになりました。

## まとめ
Auth0に署名鍵をローテーションする機能が追加されたので管理Dashboad上での操作を紹介してみました。
Management APIからも実施できるので定期的な署名鍵のローテーションを自動化することもできそうです。

この辺は、Auth0を触り始めた頃に「え？鍵更新できないの？」って思った部分なので、できるようになって嬉しいです。