概要
サービスのマルチデバイス対応をした際に、各デバイスで同じアカウントにログインするのはユーザにとっては非常に手間です。
例えばテレビデバイスに対応した場合にID&パスワードをリモコンで入力させるのはユーザにとって苦痛でしかありません。
なのでサービス側はユーザが苦労なくスムーズにログインできる方法を提供しなくてはいけませんが、一方でセキュリティについても気にする必要があります。
そんなケースの対応方法としてOAuth 2.0 Device Authorization Grantがあるので紹介します。
ユーザの体験
例としてテレビデバイスでログインします。
huluが体験として分かりやすいので実際にやってみます。
ログインしようとする
コードが表示される
カメラで読み取る
QRコードをカメラで読み取ります。
Webページに遷移
QRコードのWebページに遷移します。
未ログインの場合
未ログインだとログインするように言われます。
ログイン済みの場合
ログイン済みだとコード入力された状態になります。
これで「視聴機器を有効化」ボタンを押せばログイン完了です。
非常に簡単ですね。
システム
UXのイメージがついたところで、次にシステム側がどうなっているかを理解します。
シーケンス
システムのシーケンスは以下です。
1. 未ログインデバイスでログインリクエスト
リクエストパラメータは以下です。
パラメータ | 要否 | 説明 |
---|---|---|
client_id | 必須 | クライアントID |
scope | 任意 | 権限のスコープ |
レスポンスパラメータは以下です。
パラメータ | 要否 | 説明 |
---|---|---|
device_code | 必須 | Device Code |
user_code | 必須 | User Code |
verification_uri | 必須 | エンドユーザー検証URI |
verification_uri_complete | 任意 | user_code を含むエンドユーザー検証URI |
expires_in | 必須 | device_code とuser_code の有効期限(秒) |
interval | 任意 | トークンリクエストのポーリング間隔(秒) |
Authサーバ側はuser_code
とdevice_code
をexpires_in
の期限まで紐付けて持つ必要があります。
2. トークンリクエスト(ポーリング)
次にトークンが取得できるまで以下のパラメータを投げ続けます(ポーリング)
パラメータ | 要否 | 説明 |
---|---|---|
grant_type | 必須 | urn:ietf:params:oauth:grant-type:device_code という固定値 |
device_code | 必須 | Device Code |
client_id | 必須 | クライアントID |
Authサーバはuser_code
のチェックが完了するまではauthorization_pending
エラーやslow_down
エラーを返し続けます。
3. ログイン済みスマホデバイスにuser_code
を渡す
QRコードなどで読み込んでverification_uri
のページに遷移します。
huluのようにuser_code
が入力された状態になるとユーザにとって非常に楽ですね。
4. user_code
をAuthサーバへ
未ログインであればログインを促します。
5. user_code
検証
存在するuser_code
か、またexpires_in
の期限内かをチェックします。
問題なければログインユーザと紐付けます。
6. ポーリングの完了
5.
のチェックが通ればポーリングしていたリクエストのレスポンスとして、ブラウザでログインしていたユーザのアクセストークンが返ります。
7. リソースAPIの利用
アクセストークンを用いて各リソースのAPIを叩くことができます。
応用
デバイス側は様々なパターンで利用可能です。
client_id
毎にverification_uri
をWeb用のHTTPスキーマであったり、ディープリンクを用いてネイティブ用にすればブラウザ側も柔軟に変更できます。
デバイス側をネイティブアプリとした場合
U-NextのようなWebブラウザでログインができます。
デバイス側をWebブラウザ、ブラウザ側をネイティブアプリとした場合
アプリでログインしているアカウントにWebブラウザでもログインしたいといったケースでスムーズにログインできます。
まとめ
マルチデバイス対応した際にユーザがスムーズに各デバイスにログインできる方法としてDevice Authorization Grantを紹介しました。