Skip to content

/ciba_authz が、宛先のユーザに端末が登録されていないとき HTTP 500 で JSON でない本文を返す #210

Description

@OsscJpDevInfra

現象

CIBA の認証リクエスト(POST /ciba_authz)で、login_hint のユーザは存在するが、認証デバイス(DeviceToken)が登録されていないとき、
プッシュ通知の送信(FcmService.SendAsync)で例外になり、処理されずに HTTP 500 になる。

応答の本文は JSON のエラー応答ではない。

  • 開発モード(ASPNETCORE_ENVIRONMENT=Development): UseDeveloperExceptionPage により、例外の平文System.…Exception: … とスタック トレース)
  • それ以外: UseExceptionHandler("/Home/Error") により、HTML のエラー画面

実測(#205 の確認中。net10.0 版、UserStoreType=mem、送信箱なし=本物の FCM):
認証サイトを起動し直した直後で、tanaka@gmail.com に端末が未登録の状態のまま、
CIBA の自己テスト(/Home/Saml2OAuth2Starters →「Test FAPI CIBA Profile (FAPI2)」)を実行すると、自己テスト側が次で落ちた。

JsonReaderException: Unexpected character encountered while parsing value: S. Path '', line 0, position 0.
   at MultiPurposeAuthSite.Controllers.HomeController.AssembleFAPICibaProfileStarterAsync()

自己テストは /ciba_authz の応答を JSON として読むので、本文が S で始まっていた(=例外の平文)と見られる。
サーバ側の例外の型とメッセージは記録していない。 同じユーザで端末を登録した後は、同じ操作が成功した。

環境

バージョン 1st_agent_ph1d560c1d 時点)
構成要素 MultiPurposeAuthSiteCore / MultiPurposeAuthSite(CommonLibrary の FcmService
ターゲット net10.0 で実測。net48 は同じ形のコード(実測していない)
UserStoreType mem

再現手順

  1. 送信箱(FcmOutboxDirectory)を設定せずに認証サイトを起動する(本物の FCM に送る設定。FirebaseServiceAccountKey に実物の鍵)
  2. 端末を登録していないユーザを login_hint にして、CIBA の認証リクエストを送る
    (自己テストの宛先は tanaka@gmail.com に固定。起動直後の mem ストアでは、どのユーザも未登録)
  3. /ciba_authz が HTTP 500 になる

期待する動作

  • 例外を外に出さず、JSON のエラー応答を返す(CIBA Core §13)
  • 端末が無いことは、FCM に送る前に判定できる(user.DeviceToken が空)
  • FCM への送信そのものが失敗した場合(宛先のトークンが無効など)も、同じく JSON のエラー応答にする
  • エラー コードと HTTP ステータスの選び方は、対応時に決める

調べたこと

  • OAuth2EndpointController.CibaAuthorizeAsync は、FcmService.GetInstance().SendAsync(user.DeviceToken, "CIBA", …)try / catch なしで呼んでいる
    • net10.0 : MultiPurposeAuthSiteCore/Controllers/OAuth2EndpointController.cs:815
    • net48 : MultiPurposeAuthSite/Controllers/OAuth2EndpointController.cs:790
  • 呼ぶ前に、CibaProvider.Create で CIBA の要求は保存済み。送信に失敗しても、要求は期限(CibaExpireTimeSpanFromSeconds、既定 600 秒)まで残る
  • login_hint のユーザが見つからない場合は、400 と unknown_user_id を返すよう直してある(Error responses return HTTP 200 instead of 400 / 401. #196、E2E の RT-196.18)。ユーザは見つかるが端末が無い場合が抜けている
  • E2E(test.ps1 -Launch)ではこの失敗は再現しない。 FcmService.SendAsync は、送信箱(テスト用)を使うときは宛先を検証せずにファイルへ書くため。
    テストを足すなら、端末の有無をサーバが送る前に判定する形にする必要がある
  • 本番で、宛先のトークンが古い / 無効になったとき(FCM が宛先を拒否したとき)も、同じ経路で 500 になると見られる(実測していない)

利用者への影響

あり。 CIBA を使う RP が、端末を登録していないユーザ(または FCM が宛先を拒否したユーザ)に認証リクエストを送ると、
JSON でない HTTP 500 を受け取る。RP 側はエラー コードで扱いを分けられない。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions