OIDC / OAuth 2.0

デバイス認可フロー

入力機能が制限されたデバイス(スマートTV、IoTデバイス、CLIツール等)のためのフロー。ユーザーは別のデバイス(スマートフォン等)のブラウザでコードを入力して認証します。

対象デバイスのユースケース

スマートTV・ストリーミングデバイス

Netflix、YouTube、Amazon Prime Video などのストリーミングサービスへのログイン。リモコンでの文字入力は困難なため、スマートフォンで認証します。

ゲームコンソール

PlayStation、Xbox、Nintendo Switch でのアカウントリンクやサービスログイン。コントローラーでの入力を最小限にします。

IoTデバイス・スマートスピーカー

Amazon Echo、Google Home などのスマートスピーカーでのアカウント連携。画面がないか限定的なデバイスに最適です。

CLIツール

GitHub CLI(gh auth login)、AWS CLI、Google Cloud CLI などの開発者ツール。ターミナルから安全にOAuth認証を行います。

ポーリングの動作
authorization_pending

ユーザーがまだ認証を完了していない。ポーリングを継続。

slow_down

ポーリングが速すぎる。interval を5秒延長して再試行。

access_denied

ユーザーがアクセスを拒否した。ポーリングを停止。

expired_token

device_code の有効期限切れ。最初からやり直し。

200 OK (トークン発行)

認証完了。アクセストークンを取得。

シーケンス図

クライアント
ブラウザ
認可サーバー
リソースサーバー
>1. デバイス認可リクエスト
>2. ユーザーコード表示
>3. ユーザーがブラウザでコード入力・認証
>4. デバイスがポーリング
<5. トークン取得

各ステップの詳細

1
デバイス認可リクエスト

クライアント認可サーバー

デバイスが認可サーバーのデバイス認可エンドポイントにリクエストを送信し、ユーザーコードとデバイスコードを取得します。

リクエスト

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 はポーリング間隔(秒)
2
ユーザーコード表示

クライアントブラウザ

デバイスがユーザーコードと検証URIを画面に表示します。ユーザーはスマートフォン等の別デバイスでアクセスします。

リクエスト

DISPLAY (デバイス画面)

以下のURLにアクセスしてください:
https://auth.example.com/device

コードを入力してください: WDJB-MJHT

セキュリティノート

  • !ユーザーコードは推測困難な形式にする
  • !QRコードの表示も一般的
3
ユーザーがブラウザでコード入力・認証

ブラウザ認可サーバー

ユーザーがスマートフォン等のブラウザで検証URIにアクセスし、ユーザーコードを入力して認証・同意します。

リクエスト

POST /device

user_code=WDJB-MJHT

レスポンス

200 /device

認証が完了しました。デバイスに戻ってください。

セキュリティノート

  • !ユーザーは信頼できるブラウザで認証する
  • !デバイスはユーザーの資格情報に一切触れない
  • !フィッシング攻撃に注意(正しいURLか確認する)
4
デバイスがポーリング

クライアント認可サーバー

デバイスがトークンエンドポイントに定期的にポーリングし、ユーザーの認証完了を待ちます。認証が完了するまで 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 を超えたらポーリングを停止する
5
トークン取得

認可サーバークライアント

ユーザーの認証が完了すると、ポーリングに対してアクセストークンが返されます。

リクエスト

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 の有効期限を適切に設定する
  • !ポーリング間隔を守り、サーバーに過度な負荷をかけない
  • !リモートフィッシング攻撃のリスクに注意
  • !ユーザーコードの入力画面でドメインを確認するよう促す