Skip to content

feat: Add resumeSession() to recover Web Auth logins after Android process death#1566

Merged
subhankarmaiti merged 4 commits into
masterfrom
feat/android-process-death-resume-session
Jun 19, 2026
Merged

feat: Add resumeSession() to recover Web Auth logins after Android process death#1566
subhankarmaiti merged 4 commits into
masterfrom
feat/android-process-death-resume-session

Conversation

@subhankarmaiti

@subhankarmaiti subhankarmaiti commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Description

On Android, the OS can kill the app's process while the user is completing login in the browser — common on devices with aggressive memory management (Samsung One UI, Xiaomi MIUI), especially during MFA when the user switches apps to fetch a code. When the browser redirects back, the app cold-starts and the in-flight login is silently lost, dropping the user back on the login screen.

This PR adds resumeSession(), which recovers that login. The underlying native SDK finishes the token exchange after the process restarts and buffers the result; calling resumeSession() once on cold start drains it and returns the recovered Credentials (or null if there was nothing to recover).

// Hooks
const { resumeSession } = useAuth0();                                                                                            
useEffect(() => {
  resumeSession().then((credentials) => {                                                                                        
    if (credentials) {                                                                                                    
      // login interrupted by process death was recovered                                                                        
    }                                                                                                                     
  });                                  
}, [resumeSession]);
                                                                                                                                 
// Auth0 class
const credentials = await auth0.webAuth.resumeSession();                                                                         
  • Android-only; a no-op resolving null on iOS and web, so it is safe to call unconditionally.
  • No native MainActivity changes required, so it works the same in bare React Native and Expo.
  • Bumps the bundled Auth0.Android dependency to 3.19.0+, which adds the process-death token-exchange recovery (including DPoP).

References

Checklist

  • Unit tests added/updated and passing
  • Docs updated (EXAMPLES.md, FAQ.md)
  • Verified on a real Android device (Home → kill process → complete login → recovered on relaunch)

Summary by CodeRabbit

  • New Features
    • Added Android process-death authentication recovery via resumeSession(), with lifecycle-aware, main-thread-safe behavior.
    • Exposed session recovery across the web/auth layers; iOS/web resolve to null when nothing is recoverable.
  • Documentation
    • Added “Recovering Login After Process Death (Android)” docs (Hooks + class examples) and expanded the FAQ with the recommended flow.
  • Example App
    • Updated the Android demo to automatically attempt recovery and show a “Resume Session” action.
  • Bug Fixes
    • Improved handling when the current activity is unavailable and ensured recovery promises settle safely.
  • Dependencies
    • Bumped the Android Auth0 SDK to 3.19.0 (and added required AndroidX Credentials versions in the example).

@subhankarmaiti subhankarmaiti requested a review from a team as a code owner June 17, 2026 20:17
@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ec31c6ca-3938-4900-a16c-088322c76db4

📥 Commits

Reviewing files that changed from the base of the PR and between 443d5ba and c679a26.

📒 Files selected for processing (1)
  • android/src/main/java/com/auth0/react/A0Auth0Module.kt

📝 Walkthrough

Walkthrough

Adds resumeSession() across the full react-native-auth0 stack to recover interrupted Android web login flows after OS process death. The feature spans a bumped Android SDK dependency, a reworked native Kotlin module with lifecycle-aware callback registration and main-thread scheduling, an iOS no-op bridge, TypeScript bridge/adapter/provider layers, React hooks context updates, example app changes, and new documentation in EXAMPLES.md and FAQ.md.

Changes

resumeSession() — Android process-death login recovery

Layer / File(s) Summary
Public contracts and TurboModule spec
src/core/interfaces/IWebAuthProvider.ts, src/platforms/native/bridge/INativeBridge.ts, src/specs/NativeA0Auth0.ts, android/src/main/oldarch/com/auth0/react/A0Auth0Spec.kt
resumeSession(): Promise<Credentials | null> is declared on IWebAuthProvider, INativeBridge, the TurboModule Spec, and the old-arch abstract bridge class.
Android native implementation and iOS no-op
android/build.gradle, android/src/main/java/com/auth0/react/A0Auth0Module.kt, ios/A0Auth0.mm
Bumps com.auth0.android:auth0 to 3.19.0. resumeWebAuthSession is reworked to check for LifecycleOwner, register callbacks via WebAuthProvider.registerCallbacks, use an AtomicBoolean for single-resolve guarantee, and post a RESUME_SESSION_GRACE_MS fallback to resolve null. webAuth and webAuthLogout starts are wrapped in UiThreadUtil.runOnUiThread for main-thread lifecycle observer registration. iOS bridge resolves null unconditionally.
TypeScript bridge, adapters, and tests
src/platforms/native/bridge/NativeBridgeManager.ts, src/platforms/native/adapters/NativeWebAuthProvider.ts, src/platforms/web/adapters/WebWebAuthProvider.ts, src/platforms/native/bridge/__tests__/NativeBridgeManager.spec.ts, src/platforms/native/adapters/__tests__/NativeWebAuthProvider.spec.ts, src/platforms/web/adapters/__tests__/WebWebAuthProvider.spec.ts
NativeBridgeManager.resumeSession delegates to resumeWebAuthSession and wraps the result in CredentialsModel. NativeWebAuthProvider.resumeSession forwards to the bridge and converts errors to WebAuthError. WebWebAuthProvider.resumeSession is a null no-op. All three are covered by new unit tests verifying credential recovery, null return, and error handling.
React hooks context and Auth0Provider
src/hooks/Auth0Context.ts, src/hooks/Auth0Provider.tsx, src/hooks/__tests__/Auth0Provider.spec.tsx
Auth0ContextInterface gains resumeSession, initialContext is stubbed, and Auth0Provider implements the callback — deriving user from ID token, saving credentials, dispatching LOGIN_COMPLETE or ERROR — wired into the context useMemo. Test mock extends webAuth with a resolves-null stub.
Example app integration
example/android/app/src/main/java/com/auth0example/MainActivity.kt, example/src/navigation/HooksDemoNavigator.tsx, example/src/screens/hooks/Home.tsx, example/android/app/build.gradle
MainActivity overrides onCreate to pass null savedInstanceState preventing fragment restoration after process death. HooksDemoNavigator adds an Android-only useEffect calling resumeSession on mount. HomeScreen adds an onResumeSession handler and a conditional Android-only Resume Session button. Example app build gradle pins AndroidX Credentials dependencies.
Documentation
EXAMPLES.md, FAQ.md
EXAMPLES.md adds a TOC link and a new "Recovering Login After Process Death (Android)" section with Hooks and Auth0 Class code examples showing how to call resumeSession on app startup and save recovered credentials. FAQ.md adds a recommended resumeSession() recovery subsection with example code and platform notes, and renames the singleTask solution heading for clarity.

Sequence Diagram(s)

sequenceDiagram
  participant App as React Native App (cold start)
  participant Provider as Auth0Provider
  participant Adapter as NativeWebAuthProvider
  participant Bridge as NativeBridgeManager
  participant Native as A0Auth0Module (Android)
  participant SDK as WebAuthProvider (Auth0 Android SDK)

  rect rgba(255, 165, 0, 0.5)
    note over App,SDK: Android process-death recovery path
    App->>Provider: resumeSession()
    Provider->>Adapter: bridge.resumeSession()
    Adapter->>Bridge: resumeWebAuthSession()
    Bridge->>Native: resumeWebAuthSession (native call)
    Native->>SDK: WebAuthProvider.registerCallbacks(lifecycle, ...)
    SDK-->>Native: onSuccess(credentials) or timeout → null
    Native-->>Bridge: Credentials | null
    Bridge-->>Adapter: CredentialsModel | null
    Adapter-->>Provider: Credentials | null
    alt credentials returned
      Provider->>Provider: derive user, saveCredentials, dispatch LOGIN_COMPLETE
      Provider-->>App: Credentials
    else null returned
      Provider-->>App: null (no pending session)
    end
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 Hop, hop — the app was slain mid-auth,
The Android OS, ruthless in its wrath.
But now resumeSession leads the way,
Recovering logins from process-death's fray!
A grace-period timer, an AtomicBoolean neat,
Makes every cold-start login complete. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and concisely summarizes the main feature: adding resumeSession() to recover Web Auth logins after Android process death, which is the primary change across all modified files.
Linked Issues check ✅ Passed The PR implements all objectives from issues #1541 and #1549: exposes a JS-accessible resumeSession() method via both hooks and class APIs, enables recovery of credentials after Android process death, requires no MainActivity changes, and includes comprehensive documentation and tests.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing resumeSession() recovery functionality. AndroidX Credentials libraries in example/android/app/build.gradle are required dependencies for PasskeyModule, and the Auth0 SDK version bump to 3.19.0 includes the native process-death recovery mechanism.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/android-process-death-resume-session

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

object : com.auth0.android.callback.Callback<Credentials, AuthenticationException> {
// start() registers a LifecycleObserver internally (Auth0.Android 3.19.0+ for
// process-death recovery), which must happen on the main thread.
UiThreadUtil.runOnUiThread {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where is UiThreadUtil located? is it auth0.android api or inbuilt api from android SDK

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its from com.facebook.react.bridge.UiThreadUtil a react native built-in library

object : com.auth0.android.callback.Callback<Credentials, AuthenticationException> {
// start() registers a LifecycleObserver internally (Auth0.Android 3.19.0+ for
// process-death recovery), which must happen on the main thread.
UiThreadUtil.runOnUiThread {

@pmathew92 pmathew92 Jun 18, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whats the need to explicitly put it to uiThread here ? Isn't this callback executed in UI thread ? Would there be any issues if this is not added ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as auth0.android usage LifecycleObserver, that can't be run on without main thread, otherwise it throws IllegalStateException.

// Safety net for the rare case where the restored token exchange is still in
// flight: give it a short grace window, then resolve null if nothing arrived.
if (!resolved.get()) {
Handler(Looper.getMainLooper()).postDelayed({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can cause memory leak , if the activity is cleared / destroyed before the RESUME_SESSION_GRACE_MS elapses . Ideally we should clear any pending handler callbacks in such scenarios

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated code to cleared the handler

@subhankarmaiti subhankarmaiti merged commit 1b1b1a0 into master Jun 19, 2026
5 checks passed
@subhankarmaiti subhankarmaiti deleted the feat/android-process-death-resume-session branch June 19, 2026 07:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants