OAuth認証時にWebAuthnでログインするとOAuth許可画面でなくWebUIのホームに飛ばされる
#Mastodon/bug (fixed)
条件
Mastodon v3.4.1
iOS 15.1 Safari, Windows 11 Edge 96.0.1054.34
非ログイン状態でOAuth認証を開始したとき
OTP入力だと起こらない
原因
WebAuthnだけ内部的なログイン方法が違う
/app/controllers/concerns/two_factor_authentication_concern.rb#L60
credentialが正しければ {redirect_path: root_path} を返す
root_pathは多分Rails由来で、実体は "/"
/app/javascript/packs/two_factor_authentication.js#L30
location.replace(response.data.redirect_path) する
通常はDeviseというlibraryを使っている
/app/controllers/auth/sessions_controller.rb#L80-L88
Deviseで定義されたmethodのafter_sign_in_path_forを上書きし、ログイン後にリダイレクトされるページを指定
ログイン前にアクセスされたURL (stored_location_for) がhome_pathsに含まれていればroot_pathに、それ以外なら
home_pathsは /about と、シングルユーザーモードの場合はアカウントのURL (同ファイルで定義)
時系列
iOS 15.1 Safariで発生確認 (2021-11-26 15:14)
Amaroqでfedibirdにログインできなかった
セキュリティキーでログインすると、OAuthの許可画面ではなくWebUIのホームに飛ばされた
Amaroqの場合はOAuth認証開始の度にセッションがリセットされるようで、再度認証を試すとまたセキュリティキーを要求され一生ログインできなかった
他のアプリではセッションがリセットされないようで、一度アプリに戻って再度認証を試すと許可画面に進めたため気にならなかった
この時点では、2FAログイン自体ができない不具合だと認識
なぜ誰も報告していない?と思った
Mastodon v3.4.1の自鯖でも同様のbugを確認
いま自鯖にはS3 prefix関係の変更しか適用していないため、plainなMastodonでも起きる問題っぽい
布団の前にノートPC設置
睡眠 (16:55-20:10)
布団で作業開始
他ブラウザでも起きるか
Win11 Edge 96.0.1054.34でも発生
リダイレクト処理がどうなっているか
EdgeのDevtoolsのNetworkタブを開いた状態でログインしてみる
セキュリティキーでのログインだとLocationヘッダが見当たらず、通常のログインとは違う方法でやってると推測
WebAuthn実装したことないけど、HTMLだけで完結はしなさそう
ふと思いついて、セキュリティキーではなくOTPなら認証できるか試す
OTPの場合は入力したコードがそのままPOSTされ、Locationヘッダで許可画面に飛ぶことを確認
誰も報告していないのはWebAuthn限定の不具合だからかもと納得
関係ないけど、 / → /web/ → /web/getting-started にリダイレクトしてるように見えたのが、実際には / にしかリクエストしておらず、 / に配置されたjsで行われていることを知った
原因を探す
VSCodeを起動し、Mastodonのコードをsecurity_key, webauthn, credential (json requestにあった単語) などで検索
わりとすぐ判明 (上述)
通常のサインインでリダイレクト先を決める処理を探す
上述
Scrapboxにこれまでの経緯をメモ (23:00)
経緯と書いて「いきさつ」とも読むことを知った
必要な変更箇所を把握する
/app/controllers/concerns/two_factor_authentication_concern.rb#L60
原因なので
ここで通常のリダイレクトURLを取得する処理を呼び出したい
/spec/controllers/auth/sessions_controller_spec.rb#L380-L389
redirect_path == root_path をassertしてる
#L252-L259 で、OTPに対しても同じことしてるから大丈夫かも
specのことがいまいち分かってなかったけど、最近これは実際の動作には関係ないテストコードっぽい? って理解した
ここでも email: 'x@y.com', password: 'abcdefgh' とか WebAuthn::FakeClient とか使ってるし
でも間違いなく参考にはなる
コードの動作が1つ1つ文章で説明されてて非常にわかりやすい
今回だと、OTPのところは redirects to home 、WebAuthnのところは instructs the browser to redirect to home と説明されてる
branch名を決める (2021-11-27 0:18)
PR, commit名ほど難しくない
fix-webauthn-oauth-redirect にした
main branchで起きるか確認
多分起きてる (3:42)
WebAuthnにリダイレクト先を決める処理を適用する
commit名、PR名を考える
とりあえずissue出した
PR出すことにした
出した