Open3

RFC 8628 OAuth 2.0 Device Authorization Grant

yapooyapoo

RFC 8628 - OAuth 2.0 Device Authorization Grant

概要

OAuth 2.0 でアクセストークンを取得したいデバイスが、通常の OAuth 2.0 のフローでは必要となるユーザーと認可サーバーとの間の (認証などの) やり取りで必要なもの (Web ブラウザやパスワード等のための入力インターフェースなど) を備えていない、または使いづらい場合がある。例えばスマートテレビやゲーム機、プリンターなどがこれにあたる。

このような場合に、必要な認証処理を行いやすい別のデバイス (スマートフォンなど) で認証を行うことによって、元のデバイスでアクセストークンを得るための仕組みが本仕様で定義されている Device Authorization Grant (デバイスフロー) である。

主な流れは下図の通り。なお仕様で定義された語ではないが、ユーザーが認可サーバーとの間のやりとりで用いるデバイスをこの記事では User Secondary Device とする。

yapooyapoo

デバイス認可エンドポイント

リクエスト

デバイスフローにおける認可エンドポイントにあたるが、別のエンドポイントとして提供する。メソッドは 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_codeuser_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_uriuser_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 の入力を行う。

yapooyapoo

トークンエンドポイント

リクエスト

トークンエンドポイントは 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 つのデバイス間の通信の仕様などは本仕様では定義されない。