デバイス認可フロー
入力機能が制限されたデバイス(スマートTV、IoTデバイス、CLIツール等)のためのフロー。ユーザーは別のデバイス(スマートフォン等)のブラウザでコードを入力して認証します。
対象デバイスのユースケース
Netflix、YouTube、Amazon Prime Video などのストリーミングサービスへのログイン。リモコンでの文字入力は困難なため、スマートフォンで認証します。
PlayStation、Xbox、Nintendo Switch でのアカウントリンクやサービスログイン。コントローラーでの入力を最小限にします。
Amazon Echo、Google Home などのスマートスピーカーでのアカウント連携。画面がないか限定的なデバイスに最適です。
GitHub CLI(gh auth login)、AWS CLI、Google Cloud CLI などの開発者ツール。ターミナルから安全にOAuth認証を行います。
authorization_pendingユーザーがまだ認証を完了していない。ポーリングを継続。
slow_downポーリングが速すぎる。interval を5秒延長して再試行。
access_deniedユーザーがアクセスを拒否した。ポーリングを停止。
expired_tokendevice_code の有効期限切れ。最初からやり直し。
200 OK (トークン発行)認証完了。アクセストークンを取得。
シーケンス図
各ステップの詳細
クライアント → 認可サーバー
デバイスが認可サーバーのデバイス認可エンドポイントにリクエストを送信し、ユーザーコードとデバイスコードを取得します。
リクエスト
POST /device/code
Content-Type: application/x-www-form-urlencoded
client_id=my-tv-app&scope=openid profile
レスポンス
200 /device/code
{ "device_code": "GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNh", "user_code": "WDJB-MJHT", "verification_uri": "https://auth.example.com/device", "verification_uri_complete": "https://auth.example.com/device?user_code=WDJB-MJHT", "expires_in": 1800, "interval": 5 }
セキュリティノート
- !device_code はデバイスが保持する秘密の値
- !user_code はユーザーに表示する短いコード
- !interval はポーリング間隔(秒)
クライアント → ブラウザ
デバイスがユーザーコードと検証URIを画面に表示します。ユーザーはスマートフォン等の別デバイスでアクセスします。
リクエスト
DISPLAY (デバイス画面)
以下のURLにアクセスしてください: https://auth.example.com/device コードを入力してください: WDJB-MJHT
セキュリティノート
- !ユーザーコードは推測困難な形式にする
- !QRコードの表示も一般的
ブラウザ → 認可サーバー
ユーザーがスマートフォン等のブラウザで検証URIにアクセスし、ユーザーコードを入力して認証・同意します。
リクエスト
POST /device
user_code=WDJB-MJHT
レスポンス
200 /device
認証が完了しました。デバイスに戻ってください。
セキュリティノート
- !ユーザーは信頼できるブラウザで認証する
- !デバイスはユーザーの資格情報に一切触れない
- !フィッシング攻撃に注意(正しいURLか確認する)
クライアント → 認可サーバー
デバイスがトークンエンドポイントに定期的にポーリングし、ユーザーの認証完了を待ちます。認証が完了するまで authorization_pending エラーが返されます。
リクエスト
POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNh&client_id=my-tv-app
レスポンス
400 /token
{ "error": "authorization_pending" }
セキュリティノート
- !interval で指定された間隔を守ってポーリングする
- !slow_down エラーの場合は間隔を5秒延長する
- !expires_in を超えたらポーリングを停止する
認可サーバー → クライアント
ユーザーの認証が完了すると、ポーリングに対してアクセストークンが返されます。
リクエスト
POST /token
レスポンス
200 /token
{ "access_token": "eyJhbGciOiJSUzI1NiIs...", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "dGhpcyBpcyBhIHJlZnJlc2g...", "scope": "openid profile" }
セキュリティノート
- !リフレッシュトークンも発行されることが多い
- !デバイスにトークンを安全に保存する
- +スマートTV、ストリーミングデバイス
- +IoTデバイス、スマートスピーカー
- +CLIツール(GitHub CLI、AWS CLI等)
- +入力機能が制限されたデバイス全般
- -ブラウザベースのアプリ → 認可コード + PKCE を使用
- -サーバー間通信 → クライアントクレデンシャルを使用
- -通常のWebアプリ → 認可コードフローを使用
セキュリティ上の考慮事項
- !ユーザーコードは十分なエントロピーを持たせる
- !device_code の有効期限を適切に設定する
- !ポーリング間隔を守り、サーバーに過度な負荷をかけない
- !リモートフィッシング攻撃のリスクに注意
- !ユーザーコードの入力画面でドメインを確認するよう促す