OIDC CIBAで作る「スマートフォンでログイン」機能

こんばんは、ritouです。

今日は OpenID Connect Client Initiated Backchannel Authentication Flow 通称CIBA のユースケースについて書きます。

CIBA は決済や送金のためのもの?

自分の記事でも、CIBAのユースケースとしてコンビニ決済への導入例を挙げてみたりしました。 そして、CIBAにやたらと詳しい某Authlete社の記事を見ても、送金とか決済などで使えそうな話がプンプンします。

www.authlete.com

www.authlete.com

お金周りはUX改善のメリットとして伝え安いですし、クレカ決済のDecoupled AuthNの実例もあります。 CIBAもFAPIとの絡みがあるのでこの辺りを例示しがちではありますが、今回はそんな流れに逆張りとばかりにシンプルなユースケースに注目します。

スマートフォンでログイン」の要件とCIBAの機能

例えば Google アカウントにログインする際、Androidバイスなどを用いた次のような認証方式が利用可能です。

  • パスワードの代わりにスマートフォンで使用する <- パスワードレス!?
  • 2 段階認証プロセスを有効にした場合に、パスワードに加えて使用する <- 2段階認証!?

support.google.com

Googleは次のようなメリットを挙げています。

f:id:ritou:20201020034338p:plain

  • SMSで受信した認証コードを盗まれるなどのリスクを回避
  • リッチなUI
  • 拒否機能あり

SMSやOTPを使うよりは安心感が出そうですが、なかなか実装の敷居が高そうな機能です。言い換えると、これを簡単に実装できそうだとしたら面白くないですか?

このような機能を実現するための要件としては

  • ユーザーと端末が紐づいている : ユーザーとADの関係
  • 端末にプッシュなどでの通知ができる : CIBA の AuthN Request を受けた OP が ADにプッシュ通知を送って...
  • 必要ならば通知先の端末でユーザー認証 : CIBAではブラックボックスになっているがこの辺はよしなにやるべき内容
  • 環境などリッチな情報を表示して許可を求める : AuthN Requestに情報を載せてやれば良い
  • ユーザーが拒否したら認証フローを終わらせられる : ADでユーザーが拒否したらエラーが返る

ということで、今回はこの「スマートフォンでログイン」をCIBAを使って実装するとどうなるか?っていう話をします。

GOAL

パスワードレス

Google の 「スマートフォンでログイン」のUXを見てみましょう。 まずはメールアドレスなどを入れてユーザーを特定します。

f:id:ritou:20201021215500p:plain

ここで設定が済んでいると、スマートフォンでログインのフローに入ります。 スマートフォン見てみろやと。許可しろやと。そして下に書いてるのと同じ数字をタップしろやと。

f:id:ritou:20201021220705p:plain

ここで、手元のスマートフォンに通知が来ます。 2FAではなくこれだけでログインさせるので設定時に「この機能使う時、画面ロックかかるよ」って言われています。

スマートフォンで表示される画面はこんなんです。 リッチな...とか言ってましたがあんまり情報ないですね。まぁいいか。

f:id:ritou:20201021220719p:plain

「はい」を押すと、さっき言ってた同じ数字をタップしろやと言ってきます。

f:id:ritou:20201021220731p:plain

これでログインできます。

2段階認証

違いとしては

  • ユーザー特定後、パスワード認証
  • パスワードがあっていたら「スマートフォンを確認しろ」画面(上述したような数字のくだりはなし)

というあたりです。

CIBAを用いた実装案

ここでは一旦、「利用するスマートフォンの設定が済んでいる」前提とします。

上で紹介したGoogleの例と揃えると、CIBAの仕様におけるOP/RPという役割がどちらも同一サービス(Google)とする方がイメージしやすいかもしれません。

  • RP : Webアプリやモバイルアプリ
  • OP : 認証基盤的なやーつ

最初に、RPはHTMLフォームなどでユーザー特定に必要な値を受け取ります。 ここではメールアドレスとしましょう。

次に、RPからOPにバックチャンネルで AuthN Request を送ります。 (Client認証部分は省略しています。)

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

   scope=openid&
   binding_message=93&
   login_hint=user@example.com

パラメータとしては

  • login_hint : 対象ユーザーのメアド
  • scope : ログインできたらいいので openid のみ
  • binding_message : 上述のGoogleの例に揃え 93 を指定

というあたりがあれば十分そうです。 レスポンスはこうなります。 パスワードレス、2FAのコンテキストを指定したい場合は acr_values あたりを使っても良いかもしれません。

    HTTP/1.1 200 OK
    Content-Type: application/json
    Cache-Control: no-store

    {
      "auth_req_id": "1c266114-a1be-4252-8ad1-04986c5b9ac1",
      "expires_in": 120,
      "interval": 2
    }

このレスポンスを受けたら、RPはユーザーに「スマートフォンを確認しろ」「binding_messageで指定した値を選択しろ」という画面が出せます。 一方、OPはAuthN Requestを受けたらユーザーのAD(スマートフォンのアプリなど)に通知を送ります。

通知を受けたADでは

  • (パスワードレスをうたうなら)画面ロックなどの再認証要求
  • 対象ユーザーのプロフィール画像、メアドの取得
  • ログインしますか?とユーザーに聞く
  • 「はい」の場合に、binding_message に指定した値とそれ以外の値を払い出し、選択させる

binding_message のあたりは独自でルールを決めつつって感じですが、1 ~ 99 までの数とかに制限しておくと Google のような画面が作れそうです。 OKならRPはIDTokenを取得でき、認証成功したことを検証できます。

ということで、ほぼCIBAの仕様範囲内で実装できそうです。 まぁ、ここまで理解してできる開発者ならもうちょっとシンプルに設計/実装できそうな気もしなくはないですが。

CIBAを利用するにあたり、考えるべき点

RPがWebアプリの例を示しましたが、モバイルアプリでも同様に実装できそうです。 ただし、CIBAはConfidential Clientを対象としているのでリクエストを送るWebサーバーを間に置いておく必要があるかもしれません。

あとは前提のあたりで書いた「RP/OP」が別サービスの場合ですが、

  • 最初にRP(example.com) 内でユーザー特定し、そこから先(AD上の表示など)はOP(example.net)のコンテキストで行われるあたりのユーザーへの見せ方
  • RP->OPのAuthN Requestの login_hint に指定する値

あたりをよく検討してユーザーが気持ち悪く思わないようなUXに仕上げる必要があるでしょう。

登録

上にも書きましたが、CIBAの仕様では、ADとの紐付けは仕様の対象外です。 この辺りはよしなに...とすると悩んじゃいそうなので、この前書いたDevice AuthZ GrantっぽいUXを使って登録フローを考えても良いと思います。

ritou.hatenablog.com

リッチなUI、環境に関する情報

Googleでは2FAの時の画面では

  • バイス(OS情報?)
  • 場所(ネットワーク情報?)
  • 時刻

などを表示していました。 ユーザーへの表示以外にもOP側でリスク判定などに使える値だったりするので、目的外利用とか言われないようにちゃんと同意を得た上で環境に関する情報をやりとりしても良いでしょう。

まとめ

  • CIBAを使って「スマートフォンでログイン」的なパスワードレス、2FAの仕組みが作れそう
  • RP/OPが同一サービスだったらシンプルに作れそう
  • RP/OPが別で「2FA専用SaaS」みたいなのも面白そう

この辺りはプッシュ通知を受けられるPWAなWebアプリでも作れることはわかってるので、どこかでデモできればいいなと思っております。 これからもAuthentication Device (AD)を使うユースケースを探究できたらと思います。

ではまた!

f:id:ritou:20201021234131p:plain