こんばんは、OAuth👮♂️です。
緊急事態宣言、外出自粛、みなさまどうお過ごしでしょうか? お家に高い椅子と4KディスプレイとYouTuber並みのマイクを準備し、ようやくOAuth/OIDCを用いたID連携機能の実装に手をつけられるようになった頃かと思います。
本日はID連携時のCSRF対策について、動くものがある状態からのチェックの方法を紹介します。 手元で開発したサービスの登録とかログインにソーシャルログイン機能をつけて「おっ、IdPと繋がった!」ってなったら、Qiitaにその手順を晒すまえにこういうのを試してみましょう。
IdPに遷移する時のURLを確認する
ライブラリとかで作る場合は、登録もログインも既存アカウントへの連携も同じような処理が行われるはずです。 なのでだいたいどこでも良いと思います。
※画像はイメージです
※画像はイメージです
Googleでログイン機能とかをブラウザの開発者向けの何かとかで見張っておきましょう。
※画像はイメージです
※画像はイメージです
こんな感じになると思います。
https://accounts.google.com/signin/oauth? response_type=code& access_type=offline& client_id=hogehoge.apps.googleusercontent.com& scope=profile+email& redirect_uri=https://(戻り先)& state=(stateの値)
OAuth 2.0やOpenID Connectでいわゆる認可/認証リクエストって言われるものです。
この時に、
- state や nonce とかいうパラメータが存在しない
- ブラウザを変えても state や nonce とかいうパラメータがいつも一緒
だと、だいたいダメです。 とはいえ、まだWeb Application Frameworkによっては何らかの対策をしているかもしれません。 IdPからサービスに戻る部分を見てみる必要があります。
サービスに戻る際の挙動を確認する
先ほどのURLの「stateを変えたらどうなるかな〜...イッヒッヒ!!!」なんてやらなくていいです。 先ほどのURLを「コピ」して、そのまま別のブラウザを立ち上げて「ぺ」してみましょう。 ID連携を導入している場所にもよりますが、
- ログイン : ログイン成功したり「このアカウント登録されてねーよ?」とかになる
- 登録 : ●●さん初めまして!とかになる
- 既存アカウントとの紐付け : 紐付け完了しちゃう
という挙動をとったら、認可/認証リクエストがセッションと紐づけられていない、つまりCSRF対策が漏れている可能性があります。
どう直せば良いのか?
このへんの記事を読んで
stateやnonceを設定できるかどうか、検証できるかどうかを調べましょう。
stateやnonceを使わずにCSRF対策を実現できている場合も、どうやって実現しているかを確認することをおすすめします。 例えば、「何とかでログイン」っていうリンクを踏んだ時に一時的にセッションに何かの値を持ち、その値がないと処理を受け付けないなどの実装を見たことがありますが、事前に何かのURLを踏ませるなどでCSRFが可能となるような場合はstate/nonceなどを用いる場合に比べると対策が不十分と言えるかもしれません。
外部のサービスでこういうのを見つけたら?
これが自分とこのサービスではない場合は、適切に報告しましょう。
以上です。