Closed rick-lannan-upgrowth closed 10 months ago
@rick-lannan-upgrowth I tried to reproduce the issue you mentioned and I am not able to. Can you try to reproduce this in our Sample App so that we can take a look.
https://github.com/auth0/react-native-auth0/assets/15910425/38c3dadb-8cf2-4deb-9d9e-a405d7415997
If you look in your video you can see the overlay is getting shut by the system when you background and relaunch the app. What's not immediately evident is that the promise is still awaiting. When you click the LOG IN
button again you are just launching a new promise. This is a problem in our application as we have a loader screen that is cleared when the promise returns. If you modify the sample app to include as awaiting state you can see the problem
auth0-android-awaiting-bug.webm
It should be noted that this bug was introduced in v3 of the package as there used to be onActivityResult code that would handle this
That makes more sense @rick-lannan-upgrowth Do you think opening the authentication page as part of the application's task instead of a seperate task (window) would solve this issue. This is what happens in our Android SDK. Since our RNA SDK is a wrapper around the Android SDK we can check why this is happening in a seperate window.
I have added a sample on how our Android SDK handles this here
https://github.com/auth0/react-native-auth0/assets/15910425/ad0ee9af-4f48-48b1-b09f-4dfe90e3695e
Hi, I'm not sure I quite understand what you mean here but I'm assuming this means that opening the auth overlay won't trigger a change in app focus like it currently does / the OS won't close the overlay when backgrounded and relaunched? This solution would be ideal. Either way, it looks like from your example video that the bug is not reproducible with this solution
@rick-lannan-upgrowth Yes that would be the ideal solution. We will try to figure out why this is not happening in our RNA SDK where as it is the default behaviour in our Android SDK which the RNA SDK depends upon.
Checklist
- [x] The issue can be reproduced in the react-native-auth0 sample app (or N/A).
- [x] I have looked into the Readme, Examples, and FAQ and have not found a suitable solution or answer.
- [x] I have looked into the API documentation and have not found a suitable solution or answer.
- [x] I have searched the issues and have not found a suitable solution or answer.
- [x] I have searched the Auth0 Community forums and have not found a suitable solution or answer.
- [x] I agree to the terms within the Auth0 Code of Conduct.
Description
In v3 versions of the package, there is an Android bug where the
webAuth.authorize
promise never completes when the auth0 overlay gets hidden when the app is minimised and reopened via a deep link or the app icon. The result of this is code awaiting the auth0 authorize action just sits waiting foreverI have managed to patch the issue and would like the patch applied back to the source code in the next release. Here is the patch to
src/webauth/agent.ts
that resolves the issue:import { AppState, AppStateStatus, NativeEventSubscription, NativeModules, Platform } from 'react-native'; import { Credentials } from 'src/types'; import { _ensureNativeModuleIsInitialized } from '../utils/nativeHelper'; import { AgentLoginOptions, AgentLogoutOptions, AgentParameters, Auth0Module, } from 'src/internal-types'; type AuthError = { code: string message: string } const A0Auth0: Auth0Module = NativeModules.A0Auth0; class Agent { async login( parameters: AgentParameters, options: AgentLoginOptions ): Promise<Credentials> { if (!NativeModules.A0Auth0) { return Promise.reject( new Error( 'Missing NativeModule. React Native versions 0.60 and up perform auto-linking. Please see https://github.com/react-native-community/cli/blob/master/docs/autolinking.md.' ) ); } await _ensureNativeModuleIsInitialized( A0Auth0, parameters.clientId, parameters.domain ); let scheme = this.getScheme( options.useLegacyCallbackUrl ?? false, options.customScheme ); let redirectUri = this.callbackUri(parameters.domain, scheme); // Workaround to force the authorize promise to complete when the app becomes active on Android. // This is needed as the overlay is dismissed but the promise never completes on Android // when the app is backgrounded and relaunched via a deep link or the app icon const promiseWrapper = async (authPromise: Promise<Credentials>) => { const DELAY = 500; let forcePromiseRejectOnAuthOverlayDismiss: (reason?: AuthError) => void = () => {}; let subscription: NativeEventSubscription | undefined = undefined; let previousAppState = AppState.currentState subscription = AppState.addEventListener('change', (nextAppState: AppStateStatus) => { if (Platform.OS === 'android' && previousAppState === 'background' && nextAppState === 'active') { setTimeout(() => { forcePromiseRejectOnAuthOverlayDismiss({ code: 'auth_overlay_dismissed_by_os', message: 'The auth was dismissed by the system' }); forcePromiseRejectOnAuthOverlayDismiss = () => {}; subscription?.remove(); }, DELAY); } previousAppState = nextAppState }) return Promise.race([ authPromise, new Promise<Credentials>((resolve, reject) => (forcePromiseRejectOnAuthOverlayDismiss = reject)) ]); } return promiseWrapper(A0Auth0.webAuth( scheme, redirectUri, options.state, options.nonce, options.audience, options.scope, options.connection, options.maxAge ?? 0, options.organization, options.invitationUrl, options.leeway ?? 0, options.ephemeralSession ?? false, options.additionalParameters ?? {} )); } async logout( parameters: AgentParameters, options: AgentLogoutOptions ): Promise<void> { if (!NativeModules.A0Auth0) { return Promise.reject( new Error( 'Missing NativeModule. React Native versions 0.60 and up perform auto-linking. Please see https://github.com/react-native-community/cli/blob/master/docs/autolinking.md.' ) ); } let federated = options.federated ?? false; let scheme = this.getScheme( options.useLegacyCallbackUrl ?? false, options.customScheme ); let redirectUri = this.callbackUri(parameters.domain, scheme); await _ensureNativeModuleIsInitialized( NativeModules.A0Auth0, parameters.clientId, parameters.domain ); return A0Auth0.webAuthLogout(scheme, federated, redirectUri); } private getScheme( useLegacyCustomSchemeBehaviour: boolean, customScheme?: string ) { let scheme = NativeModules.A0Auth0.bundleIdentifier.toLowerCase(); if (!useLegacyCustomSchemeBehaviour) { scheme = scheme + '.auth0'; } return customScheme ?? scheme; } private callbackUri(domain: string, scheme: string) { let bundleIdentifier = NativeModules.A0Auth0.bundleIdentifier.toLowerCase(); return `${scheme}://${domain}/${Platform.OS}/${bundleIdentifier}/callback`; } } export default Agent;
Reproduction
- Trigger an
authorize
call that opens to auth0 overlay on an Android device- While the overlay is still open, minimize the app to the the background
- Relaunch the app via the app icon
- The OS dismisses the web view overlay but the code is still awaiting the promise resolution, the patch resolves this
Additional context
No response
react-native-auth0 version
3+
React Native version
Expo version
Platform
Android
Platform version(s)
@rick-lannan-upgrowth Thank you for providing your patch solution.
useAuth0
hook I'm wondering if you have deep linking already set up in you application and if you needed to change any redirect setups in your AndroidManifest files to get the redirect to work in the first place?
Hi @jonlowrey, just to be clear the promiseWrapper
patch I have suggested is not an ideal solution. Fixing the underlying issue where the auth window gets dismissed when backgrounding and relaunching the app is the correct solution here and it seems what @poovamraj suggested will do just that
As for your questions though, we do have deep linking in our app but there is no specific auth related redirect configuration in place. To be honest, I'm not even really sure by what you mean by 'redirect' though - the auth related deep link we have on the email verified confirmation page on our website simply relaunches the app without any auth deep link related config or code - the code is simply awaiting the authorize
promise to complete. But as you can see from my previous comments I was able to reproduce the issue in the sample app that doesn't have deep linking by simply backgrounding and relaunching the app from the app icon. My theory is this triggers an app navigation event, similar to a deep link, which causes the auth window to close prematurely as the app window has received focus. From what @poovamraj has suggested this is likely because the auth is running in a different task/window
It's also expected you wouldn't get credentials back when this premature auth window dismiss bug is triggered as the auth didn't complete. If you look in the previous v2 version of the Android module (https://github.com/auth0/react-native-auth0/blob/v2/android/src/main/java/com/auth0/react/A0Auth0Module.java) there is actually code in onActivityResult
that forces an a0.session.user_cancelled
promise rejection in this scenario, which was missing from the v3 implementation. This wasn't an ideal solution though as it resulted in the auth being cancelled without credentials returned but at least it caused the promise to complete. We actually have some code in our app to attempt a silent login when we receive the a0.session.user_cancelled
event to streamline the registration process for users so they weren't forced to re-authenticate manually but this was definitely a hack. The intention of the patch I suggested was to implement something similar in the v3 implementation but I used the different error code of auth_overlay_dismissed_by_os
so we could differentiate between a promise rejection due to this bug and a genuine user cancellation, which we weren't able to do with the v2 implementation. However, if possible, a solution to stop the auth window from prematurely closing would be the ideal solution as that would allow the user to complete the auth regardless of app relaunch from background events
@rick-lannan-upgrowth This issue is happening because react-native by default uses android:launchMode="singleTask"
Overriding with the following to your AndroidManifest.xml
seems to fix this issue
<application>
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
android:windowSoftInputMode="adjustResize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
But as of now this is not the suggested solution. We will analyse more on how we can fix this and update in this thread.
onNewIntent
is called back when a new task is created and there is an existing activity alive and we can use that to cancel the promise. This should be the cleanest solution and we will work on this and provide you with the fix soon.
We never faced this in our Android SDK as using singleTask
is not recommended for most applications and only for special edge cases.
@rick-lannan-upgrowth @jonlowrey I have implemented a fix for this issue in this PR. Can you both check it out and let us know your feedback?
I've provided feedback on the PR
We have merged the fix. We will be providing a new release soon with the fix. We will keep you updated on the thread about the release. We will close this for now. Feel free to comment here and we can reopen it if required.
Hi @poovamraj, do you have a rough idea when the new release is going out?
@rick-lannan-upgrowth the release is out. We have implemented more improvements and some fixes along with this.
Error: Missing NativeModule. React Native versions 0.60 and up perform auto-linking. Please see https://github.com/react-native-community/cli/blob/master/docs/autolinking.md.
Many times i was tried getting this error
Checklist
Description
In v3 versions of the package, there is an Android bug where the
webAuth.authorize
promise never completes when the auth0 overlay gets hidden when the app is minimised and reopened via a deep link or the app icon. The result of this is code awaiting the auth0 authorize action just sits waiting foreverI have managed to patch the issue and would like the patch applied back to the source code in the next release. Here is the patch to
src/webauth/agent.ts
that resolves the issue:Reproduction
authorize
call that opens to auth0 overlay on an Android deviceAdditional context
No response
react-native-auth0 version
3+
React Native version
-
Expo version
-
Platform
Android
Platform version(s)
-