Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

iOS: redirect after a failed authorize() crashes the app (finished session kept as _currentSession)

オープン
#1,151 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

@federicobartoli がすでに取り組んでいます。

2026年10月9日 から。

  • #1152 @federicobartoli による — オープン

評価

難易度
3/5
見積もり時間
半日
初心者へのやさしさ
35/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
ios, objective-c, react-native, swift

調査の方向性

Start in packages/react-native-app-auth/ios/RNAppAuth.m: read authorizeWithConfiguration: where _currentSession is assigned, the completion block that clears it, and resumeExternalUserAgentFlowWithURL: near the top of the file. The author has already announced a fix and PR, so check for an open PR before starting. Done means a redirect that arrives after a failed authorize() no longer reaches a finished AppAuth session. This needs an iOS simulator with Xcode to verify.

索引モデルが issue の本文から書いたものです。

説明

Issue

When authorize() or logout() fails synchronously on iOS (the browser could not be opened), the native module keeps the failed AppAuth session as _currentSession. Any URL that later matches the redirect URL is forwarded to that finished session. With AppAuth 2.0.0 this terminates the app with an uncaught Objective-C exception:

An OAuth redirect was sent to a OIDExternalUserAgentSession after it already completed.

-[OIDAuthorizationSession resumeExternalUserAgentFlowWithURL:]  (OIDAuthorizationService.m:135)
-[RNAppAuth resumeExternalUserAgentFlowWithURL:]                (RNAppAuth.m:20)
AppDelegate.application(_:open:options:)                        (AppDelegate.swift:51)

It is an NSException, so a Swift AppDelegate cannot catch it.

This is the same exception and stack as #1080, with a different trigger. I have not reproduced the #1080 trigger myself.

Reproduction with examples/demo on the simulator

main at 93d06bc, AppAuth 2.0.0 as pinned by examples/demo/ios/Podfile.lock, Xcode 26.3, iPhone 17 Pro simulator on iOS 26.1.

  1. In examples/demo/App.tsx, add iosCustomBrowser: 'chrome' to the options passed to authorize().
  2. In examples/demo/ios/Example/Info.plist, add googlechromes to LSApplicationQueriesSchemes (AppAuth asserts on this in debug builds).
  3. Run the app on a simulator, where Chrome is not installed, and tap Login with IdentityServer. An alert appears: "Failed to log in", Unable to open Safari.
  4. Dismiss the alert, then deliver a URL that matches the redirect URL:
   xcrun simctl openurl booted "io.identityserver.demo:/oauthredirect?code=x&state=y"
  1. The app crashes with the stack above.

code and state are dummy values on purpose: the app crashes before either of them is read.

How I hit it in a production app

authorize() with iosCustomBrowser: 'safari', on an iPhone where Safari is disabled (Settings > Screen Time > Content & Privacy Restrictions > Allowed Apps) and Chrome is the default browser:

  1. Chrome opens with the login page, but the promise has already been rejected with Unable to open Safari.
  2. The user logs in and Chrome redirects to the app's custom scheme.
  3. The app is terminated with the exception above.

With Safari enabled the same flow works. Why AppAuth reports a failure although a browser did open is a separate problem in AppAuth's custom browser user-agent, which I will report to openid/AppAuth-iOS. Here it is only the trigger.

Cause

Links are to main at 93d06bc and to AppAuth 2.0.0.

  1. authorizeWithConfiguration: stores the session returned by AppAuth (RNAppAuth.m#L441-L443).
  2. AppAuth presents the session before returning it. If presenting fails, it completes the session and invokes the callback synchronously, before that call returns (OIDAuthorizationService.m#L74-L86, through OIDAuthState.m#L167-L169).
  3. The callback clears _currentSession (RNAppAuth.m#L426-L427). Then the call from step 1 returns, and the assignment puts the finished session back.
  4. From then on, every URL that reaches the app delegate is forwarded to that session (RNAppAuth.m#L19-L21). AppAuth accepts the URL if scheme, host and path match the redirect URL (the query is ignored), finds no pending callback and raises (OIDAuthorizationService.m#L123-L135).

The other authorize branches and logout follow the same pattern.

There is a second way to reach the same exception, which I found by reading the code and have not reproduced: _currentSession stays set until the code exchange finishes, while the AppAuth session is already complete once it has consumed the redirect. A second matching URL that arrives during the token request is forwarded to a finished session too.

AppAuth versions

AppAuth 2.1.0 replaced the exception with a NO return value (openid/AppAuth-iOS#955), so the crash needs AppAuth < 2.1.0. The podspec accepts AppAuth >= 1.7.6, and a project that already has 2.0.0 in its Podfile.lock keeps it until pod update. Holding on to a finished session looks wrong on any version, so I think it is worth fixing here as well.

I have a fix ready and will open a PR right after this issue.


Environment

  • Your Identity Provider: Keycloak (production app); the Duende demo server configured in examples/demo (simulator reproduction)
  • Platform that you're experiencing the issue on: iOS
  • Your react-native Version: 0.82.1 (production app, new architecture, Swift AppDelegate); 0.79.2 (examples/demo)
  • Your react-native-app-auth Version: 8.4.1 (production app); main at 93d06bc, i.e. 8.5.0 (examples/demo)
  • Are you using Expo? No
  • AppAuth pod: 2.0.0 in both
  • Device (production app): Apple iPhone 15 iOS: 27.0
主要言語
Java
スター
2.3k
フォーク
472
平均マージ
3日 7時間
マージ済み PR(30日)
3

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

FormidableLabs/react-native-app-auth のほかの issue

FormidableLabs/react-native-app-auth の issue をすべて見る

似ている issue

Java の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。