RFC 8628 OAuth 2.0 Device Authorization Grant
RFC 8628 - OAuth 2.0 Device Authorization Grant
概要
OAuth 2.0 でアクセストークンを取得したいデバイスが、通常の OAuth 2.0 のフローでは必要となるユーザーと認可サーバーとの間の (認証などの) やり取りで必要なもの (Web ブラウザやパスワード等のための入力インターフェースなど) を備えていない、または使いづらい場合がある。例えばスマートテレビやゲーム機、プリンターなどがこれにあたる。
このような場合に、必要な認証処理を行いやすい別のデバイス (スマートフォンなど) で認証を行うことによって、元のデバイスでアクセストークンを得るための仕組みが本仕様で定義されている Device Authorization Grant (デバイスフロー) である。
主な流れは下図の通り。なお仕様で定義された語ではないが、ユーザーが認可サーバーとの間のやりとりで用いるデバイスをこの記事では User Secondary Device とする。
デバイス認可エンドポイント
リクエスト
デバイスフローにおける認可エンドポイントにあたるが、別のエンドポイントとして提供する。メソッドは POST で、リクエストボディの Content-Type は application/x-www-form-urlencoded
である。
パラメータは以下の 2 つである。
-
client_id
: OAuth 2.0 におけるクライアント識別子 (必須) -
scope
: 要求するスコープをスペース区切りで指定する (任意)
Section 3.1 に記載のリクエスト例である。
POST /device_authorization HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
client_id=1406020730&scope=example_scope
レスポンス
200 OK で以下の値を JSON で返却する
value | description |
---|---|
device_code | (必須) このあとトークンエンドポイントにリクエストする際に用いる |
user_code | (必須) ユーザーが別のデバイスで認証する際に入力する値 |
verification_uri | (必須) ユーザーが別のデバイスで認証するために用いる URL |
verification_uri_complete | (任意) verification_uri であって、user_code を含むもの。ユーザーによる user_code の手入力を省略することができる。 |
expires_in | (必須) device_code と user_code の寿命 (秒) |
interval | (任意) デバイスがトークンエンドポイントをポーリングするときの最低間隔 (秒)。指定されなかったときのデフォルト値は 5 秒 |
以下は Section 3.2 に記載されたレスポンスの例である。
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
{
"device_code": "GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS",
"user_code": "WDJB-MJHT",
"verification_uri": "https://example.com/device",
"verification_uri_complete":
"https://example.com/device?user_code=WDJB-MJHT",
"expires_in": 1800,
"interval": 5
}
エラー時にはトークンエンドポイントのエラーレスポンス (RFC 6749 Section 5.2) と同様のレスポンスを返却する。
レスポンスを受け取ったデバイスは verification_uri
と user_code
を画面に表示する。レスポンスに verification_uri_complete
が含まれる場合、これに対応する QR コードなどを画面に表示してもよいが、その場合も verification_uri
が表示されることが推奨され、user_code
の表示は必須である (混乱を避けるため device_code
は表示するべきではない)。加えて、デバイスはこれ以降 device_code
が失効するかその他のエラーが返却されるまで、後述するトークンエンドポイント (Device Access Token Request) を interval
で指定された以上の間隔を開けて行う。
ユーザーはこの画面を見て User Secondary Device で verification_uri
を開く。その後に行う認証サーバーとの認証などのやり取りの中で user_code
の入力を行う。
トークンエンドポイント
リクエスト
トークンエンドポイントは POST を受け付け、Content-Type は application/x-www-form-urlencoded
であることと、クライアント認証が必要な場合があることは RFC 6749 Section 3.2 と同様である。
デバイスフローの認可グラントの場合のリクエストパラメータは下記の通り。
parameter | description |
---|---|
grant_type | (必須) urn:ietf:params:oauth:grant-type:device_code を指定する |
device_code | (必須) デバイス認可エンドポイントで返却された device_code
|
client_id | RFC 6749 Section 3.2.1 で定められているクライアント認証を行わない場合には必須 |
以下は Section 3.2 に記載のリクエストの例である
POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code
&device_code=GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS
&client_id=1406020730
レスポンス
ユーザーの認可サーバーとのやり取りが完了した後にトークンエンドポイントにリクエストし、その他のリクエストパラメータの不備がない場合には RFC 6749 Section 5.1 にしたがってレスポンスを返却する。
本仕様ではエラー時のレスポンスを RFC 6749 Section 5.2 を拡張してエラーコードが新規に定義されている。
error | description |
---|---|
authorization_pending | ユーザーの認可サーバーとのやりとりが終了していない |
slow_down | ユーザーの認可サーバーとのやりとりが終了していない。この場合トークンエンドポイントへのポーリング間隔を 5 秒長くしなければならない |
expired_token |
device_code が失効している |
access_denied | 仕様には「認可リクエストが拒否された」と書かれている。おそらくユーザーが User Secondary Device 上での認可サーバーとのインタラクションで、デバイスでのログインを拒否した場合。 |
authorization_pending
または slow_down
以外のエラーコードが返却された場合は、トークンエンドポイントへのポーリングを即座に停止しなければならず、ユーザーにエラーになった旨を表示するべきであるとされている。また、接続がタイムアウトした場合は exponential backoff などでポーリングの間隔を長くするべきである。
また、User Secondary Device と Device Client との間で何らかの通信が可能であり、User Secondary Device でのユーザーと認可サーバー間のやりとりが終了したことを Device Client に通知できる場合は、Device Client によるトークンエンドポイントへのリクエストはそれを待ってから行ってもよい。ただし、2 つのデバイス間の通信の仕様などは本仕様では定義されない。