MS_DeviceAuthorizationGrant - NetDevInfraWGinOSSConsortium/NetDevInfraWiki GitHub Wiki

OAuth 2.0 Device Authorization Grant

概要

「Device Flow」から「Device Authorization Grant」へ名称が変更された(v15 から)。

移行メモ(改称の理由): OAuth 2.0 の用語体系では、
認可の与え方を grant(付与) と呼ぶ
authorization_code grant、client_credentials grant など)。
「Flow」ではなく「Grant」に揃えることで、
grant_type パラメタとの対応が明確になった。
RFC 8628(2019年)として発行されている。

前提

  1. Device(≒ Public Client)は、
    • 既にインターネットに接続されている状態。
    • EndUser(≒ Resource Owner)に URI とコードを表示できる。
  2. EndUser(≒ Resource Owner)は、
    セカンダリデバイス(PC やスマホなど)を持っている。

補足(どんな場面で使うのか): 入力が困難なデバイスが対象である。

対象 理由
スマート TV / セットトップ ボックス リモコンで ID/パスワードを打つのが苦痛
CLI ツール ブラウザを開けない SSH 越しの端末
プリンタ / IoT 機器 そもそも入力装置が無い
ゲーム機 同上

実例として、Azure CLIaz login --use-device-code や、
gh auth login、Netflix / YouTube のテレビ アプリのログインが
このフローである。

フロー

+----------+                                +----------------+
|          |>---(A)-- Client Identifier --->|                |
|          |                                |                |
|          |<---(B)-- Device Code,      ---<|                |
|          |          User Code,            |                |
|  Device  |          & Verification URI    |                |
|  Client  |                                |                |
|          |  [polling]                     |                |
|          |>---(E)-- Device Code,      --->|                |
|          |          & Client Identifier   |                |
|          |                                |  Authorization |
|          |<---(F)-- Access Token      ---<|     Server     |
+----------+   (& Optional Refresh Token)   |                |
      v                                     |                |
      :                                     |                |
     (C) User Code & Verification URI       |                |
      :                                     |                |
      v                                     |                |
+----------+                                |                |
| End user |                                |                |
|    at    |<---(D)-- End user reviews  --->|                |
|  Browser |          authorization request |                |
+----------+                                +----------------+
  1. Client は Authorization Server への認可リクエストに client_id を含める(A)。
  2. Authorization Server は、下記を応答する(B)。
    • デバイス・コード / エンドユーザ・コード / エンドユーザ検証 URI
  3. Client は、EndUser に(別のデバイス上の)User-Agent を使用し、
    エンドユーザ検証 URI にアクセスしエンドユーザ・コードを入力するように指示(C)。
  4. Authorization Server は User-Agent を介し EndUser を認証。
    同意した場合、エンドユーザ・コードを入力し検証(D)。
  5. Client は Authorization Server を繰り返し Polling
    (デバイス・コードと client_id)(E)
  6. Authorization Server は検証し、EndUser が
    • 許可した場合は access_token で応答し(F)
    • 拒否した場合はエラーを返す。

詳細

認可エンドポイント

認証リクエストを受け付けて直ちにレスポンスする(以後、非同期的に処理)。

認可リクエスト

  • ポイントは
    • POST であること。
    • client_secret は不要
POST /device_authorization HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded

client_id=459691054427

認可レスポンス

パラメタ 要否 内容
device_code 必須 デバイスを検証するコード。高いエントロピーを要求
user_code 必須 エンドユーザー確認コード。BCDFGHJKLMNPQRSTVWXZ(基数20)から8文字(XXXX-XXXX)、または9桁の有効数字(nnn-nnn-nnn)
verification_uri 必須 承認のエンドユーザー検証 URI。手動入力可能なように短く
verification_uri_complete オプション QueryString に user_code を含む verification_uriQRコードや NFC で使用
expires_in 必須 device_codeuser_code の有効期間(秒)
interval オプション Polling 間隔の最小待機時間(秒)。既定は 5
{
  "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
}

補足(user_code の文字集合が絞られている理由): BCDFGHJKLMNPQRSTVWXZ
という一見奇妙な集合は、母音を除いた 20 文字である。

除外 理由
母音 (A/E/I/O/U) 偶然、意味のある単語(特に不快な語)ができるのを防ぐ
数字と紛らわしい文字(0/O、1/I/l) 読み間違い・打ち間違いを防ぐ

人がテレビ画面を見ながら手で打つことを前提に設計されているため、
可読性と誤入力防止が優先されている。

ユーザへの指示

EndUser への指示には user_codeverification_uri
(オプションで verification_uri_complete)を使う。

device_code は、混乱を招くため、対話中に表示しない。

+-----------------------------------------------+
|                                               |
|  Using a browser on another device, visit:    |
|  https://example.com/device                   |
|                                               |
|  And enter the code:                          |
|  WDJB-MJHT                                    |
|                                               |
+-----------------------------------------------+

QR コードを併用する形もある。

+-------------------------------------------------+
|                                                 |
|  Scan the QR code, or using     +------------+  |
|  a browser on another device,   |[_]..  . [_]|  |
|  visit:                         | .  ..   . .|  |
|  https://example.com/device     | . .  . ....|  |
|                                 |.   . . .   |  |
|  And enter the code:            |[_]. ... .  |  |
|  WDJB-MJHT                      +------------+  |
|                                                 |
+-------------------------------------------------+

手順

  1. EndUser は、Authorization Server の verification_uri(HTTPS)に移動、
  2. user_code を入力し送信(デバイス認可セッションの識別のため)
  3. 表示される画面で、同意 / 拒否 を回答して再送信。
  4. Device は device_code で Token エンドポイントを継続的に Polling

セキュリティ考慮事項

user_code 入力の試行回数は、5回(アルファベットで8文字程度)。

補足(verification_uri_complete の落とし穴): QR コードで
user_code 込みの URI を渡すと UX は良くなるが、
「コードを打つ」という確認ステップが消える

このため RFC 8628 は、
verification_uri_complete を使う場合でも、
同意画面で user_code を表示して照合させる
ことを求めている
(表示されたコードがデバイス画面と一致するかをユーザーに確認させる)。

これを省くと、攻撃者が用意した QR を読ませるだけで
攻撃者のデバイスを認可させられる
(デバイス コード フィッシング)。
実際に標的型攻撃で悪用が報告されている手口である。

Tokenエンドポイント

デバイス上のプロンプトに表示した後、Token リクエストの Polling を始める。

POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:device_code
&device_code=GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS
&client_id=459691054427

Polling 中のエラー コード

エラー 意味 Client の対応
authorization_pending まだユーザーが操作していない interval 秒待って再試行
slow_down Polling が速すぎる interval を 5 秒増やして再試行
access_denied ユーザーが拒否した 中止
expired_token device_code の期限切れ 中止(最初からやり直す)

補足(authorization_pending はエラーではない): HTTP 400 で
返るが、正常な待機状態である。
これをエラーとして扱って中断してしまう実装ミスが多い。
上表の 4 つを正しく区別して扱うことが、
このフローの実装で最も重要な点である。

参考


Tags: 移行, IT国際標準, 認証基盤, クレームベース認証, OAuth

⚠️ **GitHub.com Fallback** ⚠️