OAuth 2.0 Device Flow 概要 ~OpenID Technight #15より~

# OAuth 2.0 Device Flow 概要

先日、2018/3/23金に開催された、OpenID Technight #15に参加した際、Yahoo!JAPANさんがOAuth 2.0 Device Flowの紹介をされていました。
しかし自分、その時点でまだ仕様を読んでおらず･･･Yahoo!JAPANさんでの活用例は理解したが、Device Flow の仕様ってどんなもの:question::exclamation:

ということで、ざっくり概要を。

## OAuth 2.0 Device Flow とは？

下記で定義されているOAuthの仕様です。
> OAuth 2.0 Device Flow for Browserless and Input Constrained Devices
> draft-ietf-oauth-device-flow-09
> https://tools.ietf.org/html/draft-ietf-oauth-device-flow-09

和訳例は下記参照:bulb::bulb:
> OAuth 2.0 Device Flow draft-09 ​和訳例
> https://sam-l.gitbook.io/docs/device-flow

### Device Flow の特徴
Device Flowの特徴は大まかに下記

- クライアントがブラウザレスや入力制約付きデバイス
    - ただし、インターネット接続はあるもの
    - テレビ、メディアコンソール、ピクチャーフレーム、プリンタ、スピーカー、など
- クライアントではなく二次デバイス（一般的にはユーザの携帯電話）を利用して認証/認可を行う
- クライアント⇔二次デバイス間の通信はなく、認証/認可とユーザ操作は全く紐づかないセッションにて行われる
    - 認証/認可完了を確認するため途中ポーリングを行う
    - セッションの紐付けはユーザコードを使用
- Token取得の際の`grant_type`に`urn:ietf:params:oauth:grant-type:device_code`を使う
    - Token取得に試用するのは、認可コードではなく、デバイスコード

### 概要フロー
概要フロー（テレビでの例）は下記の通り。
![DeviceFlowpng.png](https://qiita-image-store.s3.amazonaws.com/0/246440/ee93ae73-7092-9c1f-64e5-553d4cb3fc06.png)

- ユーザが認証/認可を行っている間、クライアントは認可サーバへトークンリクエストをポーリングし続ける。
    - ユーザの操作が完了するまで、まだ操作中であるのでポーリング継続せよという内容のレスポンスが返却される。
- ユーザ認証後に、クライアントに示されているユーザコードを入力させることで、クライアントとユーザの紐付けが可能となっている。

## セキュリティに関する考察
[OAuth 2.0 Device Flow](https://tools.ietf.org/html/draft-ietf-oauth-device-flow-09) の [5章](https://tools.ietf.org/html/draft-ietf-oauth-device-flow-09#section-5)にセキュリティに関する考察が6件記載されている。6件について、それぞれどのような内容が記載されているのか詳細を確認する。

### 1. ユーザコード ブルートフォース
ユーザコードにブルートフォースを仕掛けて成功した場合、ターゲットのデバイスに対して実行しているフローの7,8,9,10を攻撃者が実行することとなる。

![DeviceFlow-Security1.png](https://qiita-image-store.s3.amazonaws.com/0/246440/fe851313-a806-ef59-6a32-1f4a35987472.png)

これにより、ターゲットのデバイスに攻撃者のアカウントが紐付けられてしまい、ターゲットは攻撃者のアカウントでログインして操作することとなる。

攻撃者のアカウントで買い物ができる程度の場合の被害ですむ場合もあるが、攻撃者がアクセス制御権を持ってしまうことによる被害が生じる場合がある。

これを防ぐには、下記が有効である。

- ***ユーザコードに十分なエントロピーを確保する***

ただし、ユーザが手動で入力する値であるため、あまり複雑にしすぎるとユーザビリティが低下してしまう。レート制御などと組み合わせるなどにより十分なエントロピーを確保できるよう要考慮である。こららを踏まえてユーザコード形式としてどのようなものが適切であるかについて6.1章に記載があるため参照のこと。

### 2. デバイスの信頼性

デバイスの信頼性がない場合、例えば、デバイス製造元が攻撃者である／中間者攻撃を実行するものがデバイスに埋め込まれているなどの場合、攻撃者により運営されている認可サーバに接続してしまい、バックチャネル通信の途中で他の認可サーバに接続させられる可能性がある。

本仕様に記載されているフローは、一般的なネイティブアプリのOAuth 2.0フローとは異なり、認可リクエストを行うデバイスがユーザがアクセス同意の操作を行うデバイスと同じではなく、デバイスの信頼性は保障されない．

これを防ぐには、下記が有効である。

- ***エンドユーザが攻撃者のサービスの認可ページで終了するため、攻撃者の介在を確認する機会がある。アクセスしている認可サーバと異なるサーバであることに気付けるよう注意深く観察する。***

### 3. リモートフィッシング
リモートフィッシングは、ユーザコードのブルートフォース攻撃と逆のことが起こる。
攻撃者のデバイスに対して実行しているフローの7,8,9,10をターゲットが実行するよう攻撃者が仕掛けるのだ。

![DeviceFlow-Security3.png](https://qiita-image-store.s3.amazonaws.com/0/246440/c561190d-1f2a-d330-c333-06d05013f715.png)

これにより、攻撃者のデバイスにターゲットのアカウントが紐付けられてしまい、攻撃者はターゲットのアカウントでログインして操作できることとなる。

これを防ぐには、下記が有効である。

- ***ユーザコードを入力する際に自身の所有する端末が表示しているコードであることを確認させる***
- ***ユーザコードの有効期限を十分短くする***

ただし、ユーザコードの有効期限は、ユーザが2次デバイスを用意したり、検証URIへのアクセスやログインなどを促すのに十分な時間にする必要もあるので要注意。

### 4. セッションスパイ
この攻撃が成功した場合の影響は、ユーザコードのブルートフォース攻撃が成功した場合と同じである。違いは、画面に表示されているユーザコードを何らかの方法を使って盗聴することで乗取りをはかる点である。

これを防ぐには、下記が有効である。

- ***OS環境まで考慮に入れて、コードをユーザに伝達する方法を検討する***

### 5. Confidentialでないクライアント
デバイスの場合、ほとんどのクライアントがConfidentialではない。よって、アプリ間などのCSRFが発生する可能性がある。

これを防ぐためには、下記が有効である。

- ***十分なエントロピーの*** `state`***値を使ってリクエストとレスポンスの整合性をチェックする***

### 6. 視覚的でないコード送付方法
ユーザコードが視覚的に表示される必要はなく、text-to-speechオーディオやBluetooth Low Energyなどの他の一方向通信も使用できるが、攻撃者が自分のクレデンシャルを自分が制御できないデバイスに紐付てしまう可能性がある。

これを防ぐためには、下記が有効である。

- ***選択された通信チャネルは近接した人々のみアクセス可能とする***

## Yahoo!JAPANさんでの使われ方
###OpenID Tech Night vol.15 での資料
テレビ版GYAO!アプリでのDevice Flowを紹介してくださっていた。
![DeviceFlow_YJ.png](https://qiita-image-store.s3.amazonaws.com/0/246440/d7b974b8-8f0a-484c-4afe-e2aebd6148f9.png)
https://www.slideshare.net/HiromitsuHomma/20180323-openid-technight-vol15

###画面遷移
まずはテレビ版GYAO!アプリを立ち上げ。
![DeviceFlow_YJ-1.png](https://qiita-image-store.s3.amazonaws.com/0/246440/5b631ac9-3e2f-6bad-4432-0057f2ac51a6.png)
※図はスライドより抜粋

QRコードが表示されるため、スマホで読み込み、操作。
ログインし、テレビに表示されているコードを入力し、完了。
![DeviceFlow_YJ-2.png](https://qiita-image-store.s3.amazonaws.com/0/246440/8b7d293c-4712-5fb5-9058-255d540724c5.png)![DeviceFlow_YJ-3.png](https://qiita-image-store.s3.amazonaws.com/0/246440/dfcc31fc-741c-56e2-55e7-83383a9e0697.png)![DeviceFlow_YJ-4.png](https://qiita-image-store.s3.amazonaws.com/0/246440/d7bccf21-85ce-7ab8-ba58-c34073589068.png)
※図はスライドより抜粋

操作が完了すると、テレビ画面の方の画面もログイン済に遷移。
![DeviceFlow_YJ-5.png](https://qiita-image-store.s3.amazonaws.com/0/246440/5703a2a9-3fed-241d-3ebe-2b7faa2c4b52.png)
※図はスライドより抜粋

###特徴は？

- URLを手打ちしなくて良いようにQRコードで開けるようになっている
    - しかし、ユーザコードは必ず手打ちさせることで乗取りのリスク低減
- ユーザコードのブルートフォースアタック耐性を考慮
    - 試行回数の制限を設けている

###どのアプリで動いている？
ずばり、テレビのGYAO!アプリ:point_up::point_up:
![gyao.jpg](https://qiita-image-store.s3.amazonaws.com/0/246440/262441e8-59b6-51cc-bf13-49c60914a0f8.jpeg)

## おわりに
ブラウザや充実した入力のインタフェースがないデバイスにおいても、OAuthを利用できるようになるため、非常に可能性が広がる仕様である。

一方で、考慮しなければならないセキュリティ項目が多く、下手な使い方をすると大きなセキュリティホールを作ってしまうこととなってしまうため、仕様をしっかりと理解し、注意深く検討して使う必要があると感じた。

自分もいまいち理解しきれないSecurity Considerationの項目があったので、引き続き読み込んでいきたい。