この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
いわさです。
以前の記事で、Azure ADでアクセストークンを取得し、UserInfoエンドポイントへアクセスしてみました。
アクセストークンには有効期限があります。
上記記事で取得したアクセストークンの有効期限は約1~1.5時間ほどでした。
一定間隔でサインインが必要になってしまうので、今回はリフレッシュトークンを使ってみたいと思います。
リフレッシュトークンについては、稲葉純さんの以下の記事で触れられております。
また、Microsoft IDプラットフォームの更新トークンの既定の有効期間は90日で、かつ使用されるたびに新しいトークンに置き換えられます。
このあたりは、都元ダイスケさんが以下の記事内でもリフレッシュトークンの再発行によるセッション期間について言及されています。
リフレッシュトークンの取得条件
まず、前回の方法でアクセストークン取得時の状況を確認してみます。
どうやらリフレッシュトークンは取得されていないようですね。
リフレッシュトークンを取得するためにはいくつか条件があります。
まず、前回まで使用していた暗黙的な(インプリシット)フローではリフレッシュトークンは提供されません。
前回はauthorize
エンドポイントを使ってIDトークンとアクセストークンを同時に取得していましたが、token
エンドポイントを使った承認コードフローを使う必要があります。
そして、更新トークンを受信するには、アプリがoffline_access
スコープを明示的に要求する必要があります。
指定しなかった場合は、エンドポイントからアクセストークンだけが取得されます。
リフレッシュトークンを取得する
スコープでoffline_access
を設定
先程の条件にあったようにoffline_access
をスコープで指定した時にリフレッシュトークンが提供されます。
Azureポータル上で許可設定を行っておきます。
承認コード取得
テナントIDとクライアントIDを指定してブラウザでアクセスします。
Azure ADのサインイン画面で認証操作を行うと、承認コードがパラメータに付与されてリダイレクトされると思います。
https://login.microsoftonline.com/11111111-2222-3333-4444-555555555555/oauth2/v2.0/authorize?client_id=66666666-7777-8888-9999-000000000000&response_type=code&response_mode=query&scope=user.read+openid+profile+email&state=12345
このコードを使って、次はアクセストークンを取得します。
アクセストークン & リフレッシュトークン取得
アクセス時にシークレットあるいは証明書が必要です。
ここではAzure ADアプリケーション上でシークレットを作成し、それを利用しました。
iwasa.takahito@hoge 20211220azuread % curl -X POST -d 'client_id=66666666-7777-8888-9999-000000000000' -d 'code=<承認コード>' -d 'grant_type=authorization_code' -d 'client_secret=<シークレット>' -d 'scope=user.read+openid+profile+email+offline_access' https://login.microsoftonline.com/11111111-2222-3333-4444-555555555555/oauth2/v2.0/token | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 7080 100 5568 100 1512 8224 2233 --:--:-- --:--:-- --:--:-- 10442
{
"token_type": "Bearer",
"scope": "email openid profile User.Read",
"expires_in": 5107,
"ext_expires_in": 5107,
"access_token": "<アクセストークン>",
"refresh_token": "<リフレッシュトークン>",
"id_token": "<IDトークン>"
}
アクセストークンにあわせてリフレッシュトークンが取得出来ました。
まずは、アクセストークンを解析してみましょう。
Microsoftより提供されているJWT.MSを使います。
{
"typ": "JWT",
...
}.{
"aud": "00000003-0000-0000-c000-000000000000",
"iss": "https://sts.windows.net/",
"iat": 1639980148,
"nbf": 1639980148,
"exp": 1639985556,
"acct": 0,
"acr": "1",
"aio": "***",
"altsecid": "1:live.com:*******",
"amr": [
"pwd",
"mfa"
],
...
}.[Signature]
有効期限は、2021年12月20日 16:32:36
でした。
リフレッシュトークンを使ってアクセストークンを更新する
リフレッシュトークンを使う際にはtoken
エンドポイントにリフレッシュトークンをパラメータに設定し、grant_type
はrefresh_token
を指定します。
iwasa.takahito@hoge 20211220azuread % curl -X POST -d 'client_id=66666666-7777-8888-9999-000000000000' -d 'refresh_token=<リフレッシュトークン>' -d 'grant_type=refresh_token' -d 'client_secret=<シークレット>' -d 'scope=user.read+openid+profile+email+offline_access' https://login.microsoftonline.com/11111111-2222-3333-4444-555555555555/oauth2/v2.0/token | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 7492 100 5574 100 1918 8736 3006 --:--:-- --:--:-- --:--:-- 11724
{
"token_type": "Bearer",
"scope": "email openid profile User.Read",
"expires_in": 5294,
"ext_expires_in": 5294,
"access_token": "<新アクセストークン>",
"refresh_token": "<新リフレッシュトークン>",
"id_token": "<IDトークン>"
}
新しいアクセストークンが取得出来ました。
先程と同じ手順で期限を確認してみると、2021年12月20日 17:08:18
でした。
UserInfoエンドポイントへアクセスしてみましょう。
iwasa.takahito@hoge 20211220azuread % curl -H 'Authorization: Bearer <新しいアクセストークン>' https://graph.microsoft.com/oidc/userinfo | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 182 0 182 0 0 846 0 --:--:-- --:--:-- --:--:-- 846
{
"sub": "HOGE",
"name": "いわさ",
"family_name": "いわ",
"given_name": "さ",
"picture": "https://graph.microsoft.com/v1.0/me/photo/$value"
}
UserInfoを取得することが出来ましたね。
古いアクセストークンは使えるのでしょうか。
iwasa.takahito@hoge 20211220azuread % curl -H 'Authorization: Bearer <古いアクセストークン>' https://graph.microsoft.com/oidc/userinfo | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 182 0 182 0 0 579 0 --:--:-- --:--:-- --:--:-- 579
{
"sub": "HOGE",
"name": "いわさ",
"family_name": "いわ",
"given_name": "さ",
"picture": "https://graph.microsoft.com/v1.0/me/photo/$value"
}
古いアクセストークンも期限までは引き続きアクセス可能です。
また、新しいリフレッシュトークンも提供されていましたね。
Microsoft IDプラットフォームでは、期限内の古いトークンは無効になりません。
詳細は以下を参照頂くのが良いですが、新しいトークンを取得出来たらサーバー側で安全に削除してくださいね。となっています。
さいごに
本日は、Azure ADのアクセストークンをリフレッシュトークンを使って更新する方法を紹介しました。
Webでリフレッシュトークンについて調べると、更新に使ったリフレッシュトークンが無効になるIdPもありました。このあたりは実装によるようですね。
Microsoft IDプラットフォームでは無効にならない。とおぼえておきましょう。