expo: WebBrowser.openAuthSessionAsync returns "dismiss" even when the user successfully logged in

šŸ› Bug Report

We’re doing OAuth2 and the user logs in using WebBrowser.openAuthSessionAsync. If the user dismisses the browser without logging in, we catch this by checking result.type == "dismiss".

Unfortunately, we always get 'dismiss', even if the user logged in succesfully. That means our check for whether the browser was dismissed is useless now.

Environment

Expo CLI 3.4.1 environment info: System: OS: Windows 10 Binaries: npm: 6.9.0 - C:\Program Files\nodejs\npm.CMD IDEs: Android Studio: Version 3.5.0.0 AI-191.8026.42.35.5900203

App target is Android.

Steps to Reproduce

  1. Attach a listener to handle linking.

    Linking.addEventListener('url', this.handleOpenURL);
    
  2. Use openAuthSessionAsync to redirect to OAuth2

         const redirectUrl = await Linking.makeUrl(...);
         var result = await WebBrowser.openAuthSessionAsync(
             uri +
             '?response_type=code' +
             '&client_id=' + process.env.OAUTH_CLIENT_ID +
             '&redirect_uri=' + encodeURIComponent(redirectUrl) +
             '&state=' + challenge.state +
             '&code_challenge=' + challenge.code_challenge +
             '&code_challenge_method=' + challenge.method);
    
  3. Right after the await, check the result type for the case where the user canceled the login.

     if (result.type == "dismiss") {
         // Browser was dismissed without logging in. 
         this.setState({ ...this.state, status: 'ERROR', message: "Our error message" });
     }
    
  4. Open the browser and successfully log in.

Expected Behavior

The user logs in and does not see the error that is associated with 'dismiss'. The message "Our error message" should not be shown. In essence, in code I expected type == "opened", because the user didn’t cancel.

Actual Behavior

The error message is shown briefly 😦 After a short pause, the listener catches the redirect and processing the succesful login continues as expected.

I created this as a question, not an issue, because I don’t know if there is another way I should be handling the type == "dismiss" instead of right after the await. Any suggestions are most welcome.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 16 (5 by maintainers)

Most upvoted comments

For those that still couldn’t find an answer, my answer was just adding the redirectUrl into the query. On iOS I didn’t need to - const result = await WebBrowser.openAuthSessionAsync(authUrl) worked fine. But on Android I needed to add the second param - const result = await WebBrowser.openAuthSessionAsync(authUrl, redirectUri) like here - https://docs.expo.io/versions/latest/sdk/webbrowser/#webbrowseropenauthsessionasyncurl-redirecturl

For those struggling to create a redirectUri, you can use expo-linking.

import * as Linking from 'expo-linking';
const redirectUri = Linking.createURL("/");
let login = await WebBrowser.openAuthSessionAsync(url, redirectUri);

let login = await WebBrowser.openAuthSessionAsync(url, redirectUri)

Always returns type: dismiss on Android.

Just ran into this issue on Expo 43 on my Pixel 4 API 30 simulator. The above comment to set redirectUri seems to have resolved it.

SOLUTION!

If your site is deeplinking like: com.fck.you:// the create redirectUri will make com.fck.you:/// just copy ur scheme/ bundle and use com.fck.you:// as redirectUri

this solution was brought to you in the name of JESUS. pray to the Lord and repent for your sins

I’m so confused. I’m just trying to get Google Login working on the Android Standalone app. I’ve been stuck on this for month and don’t even know if I’m on the right thread anymore. 😦

@cruzach the documentation on Handling deep links from the WebBrowser says:

be sure to add a handler with Linking.addEventListener before opening the browser. When the listener fires, you should call dismissBrowser

The older Expo example repo also does this here.

So I think that may be where @DianaKoenraadt’s last question was coming from.

Based on my testing with Expo SDK 36, if you call WebBrowser.openAuthSessionAsync and then cancel the modal web browser on iOS, you get a result.type of ā€˜cancel’. If you do the same on Android you get a result.type of ā€˜dismiss’. The two are inconsistent.

I would expect both platforms to never return ā€˜open’ (unless you are calling WebBrowser.openBrowserAsync instead of WebBrowser.openAuthSessionAsync, since they behave differently on Android).

Another confusing thing in all this: The documentation for both dismissBrowser and openAuthSessionAsync says they are iOS only. And yet using WebBrowser.openAuthSessionAsync() on Android not only seems to work, but works much better than trying to roll your own version with vanilla WebBrowser.openBrowser.

Perhaps that could also be clarified?