はじめに
2019 年 8 月に公開された RFC 8628(OAuth 2.0 Device Authorization Grant)、いわゆる『デバイスフロー』(Device Flow)について説明します。
#デバイスコードフローとは
Web ブラウザ非搭載のデバイスや、文字入力が困難なデバイスが API クライアントとなる場合に、
ユーザーの承認に基づいてアクセストークンを発行する認可フローです。
例えば、スマートテレビでNETFLIXなどにログインしようとする際にログインIDやパスワードを求められた際、スマホなどの別の端末で代わりにログインできるフローのことを指します。
図で表すと以下のような形となります。
実際に実装してみた
以下githubに上がっているサンプルソースがあったので、Azure ADB2Cと繋げて実装することができます。
https://github.com/ltwlf/azure-ad-b2c-device-flow
以下、デバイスクライアントから認可サーバーに対してのリクエストとレスポンスをまとめています。
デバイス認可リクエスト
POST /device_authorization
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
client_id=1406020730&scope=example_scope
デバイス認可レスポンス
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
{
"device_code": "4e3ac03a-ad18-4f10-973a-535e473245c2",
"user_code": "487019",
"verification_uri": "http://localhost:7071/api/user_code_get",
"expires_in": 300
}
トークンリクエスト
リクエスト例
POST /token
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
client_id=140612899&grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=993124a9-e905-43b1-b21e-0845a25228a5
トークンレスポンス
レスポンス 成功例
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IkFVQTV5Uy...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "eyJraWQiOiJiU0NITG1NZGNjMW5fdnlaRXhacjkyakNTTzI3YkdTaX...",
"scope": null
}
レスポンス authorization_pending例
HTTP/1.1 400 Bad Request
Content-Length: 33
Content-Type: application/json; charset=utf-8
Set-Cookie: ARRAffinity=dd716a6def04e48f4e433f7740cecb7f8a4f1c77d318c5480b769fc5157ad936;Path=/;HttpOnly;Domain=service-device-auth-flow.azurewebsites.net
Date: Wed, 30 Sep 2020 12:37:11 GMT
authorization_pending
レスポンス expired_token例
HTTP/1.1 400 Bad Request
Content-Length: 13
Content-Type: text/plain; charset=utf-8
Set-Cookie: ARRAffinity=dd716a6def04e48f4e433f7740cecb7f8a4f1c77d318c5480b769fc5157ad936;Path=/;HttpOnly;Domain=service-device-auth-flow.azurewebsites.net
Date: Wed, 30 Sep 2020 12:44:33 GMT
expired_token
サンプルのソースにはトークンリクエスト時authorization_pendingとexpired_tokenのどちらかが予期されるエラーコードとして返されます。
authorization_pendingは、ユーザーの承認/否認処理が完了するまでトークンエンドポイントはこのエラーを返し続け、expired_tokenは、その名の通り有効期限が切れた際に返されるエラーです。
よって成功応答を受け取るか、authorization_pending以外のエラーコードを受け取った場合、クライアントアプリからのトークンリクエストは終了します。