react-native-inappbrowser: Unable to get proper response post authentication on auth server


async loginButton() {
 const deepLink = getDeepLink("home");
    const uniqueId = DeviceInfo.getUniqueID();
    const url = "https://backend.com/?redirect_uri=${deepLink}";
    console.log(url);
    console.log(uniqueId);
    try {
      await InAppBrowser.isAvailable();
      InAppBrowser.openAuth(url, deepLink, {
        // iOS Properties
        dismissButtonStyle: "cancel",
        preferredBarTintColor: "gray",
        preferredControlTintColor: "white",
        readerMode: false,
        // Android Properties
        showTitle: true,
        toolbarColor: "#E73139",
        secondaryToolbarColor: "black",
        enableUrlBarHiding: true,
        enableDefaultShare: true,
        forceCloseOnRedirection: false,
        // Specify full animation resource identifier(package:anim/name)
        // or only resource name(in case of animation bundled with app).
        animations: {
          startEnter: "slide_in_right",
          startExit: "slide_out_left",
          endEnter: "slide_in_right",
          endExit: "slide_out_left"
        },
        headers: {
          "my-custom-header": "backend"
        }
      }).then(result => {
        console.log(result);
        
      });
    } catch (error) {
      Alert.alert(error.message);
    }
  }

I am using the deep linking auth flow example mentioned in the description of the repo. I was able to successfully open the authentication flow in the browser. I am using a Laravel based server to authenticate the user. Once the user is autheticated the server responds with return redirect('mobileapp://home?token='.$token);

when this happens the browser closes off but then console.log(result); shows me type:dismiss as a result from the browser, I would also like to know if there is a possibility to handle the URL change in the browser component how we do with for WebView onNavigationStateChange with that way also I will have a possibility to see what is the current state of the browser and act accordingly.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 6
  • Comments: 68 (32 by maintainers)

Commits related to this issue

Most upvoted comments

Same issue here … 😦 Working fine on IOS but getting { type: dismiss } on android.

same issue, I encountered.

I ended up discarding the result from open. I liked your proposal and have tried it many times with even longer timeouts but it just isn’t working. Thanks for your support anyway 😃

Honestly @jdnichollsc I believe there is a huge misunderstanding with this library due to the example in the readme. I discovered this randomly after having spent a whole day to implement deep linking and the oatuh2 auth flow with an external provider.

I ported an entire expo app to a bare react native app and I used this module to replace the “authsession” module. On expo I wasn’t used to deep link back to the app after a successful authentication, instead I just awaited the value of the promise returned by the open method and I checked that we can do the same with this lib too. The only thing that prevented us to do so, was this issue because the returned data sometimes were of type dismissed even when the authentication flow went fine and the redirect from the opened webpage went fine and for that reason we were better off using the deep linking flow and handling things manually like @i1990jain showed initially in this issue.

Do you confirm this or I’m wrong about something?

The only other reason I can come up with is that deeplinking must be configured in order to have that response from the promise… is that it?

Just tested Added waitForRedirectDelay: 10000, The delay works but still dismiss is coming up

I got tired of trying to find a solution, a workaround is to do.

    return await InAppBrowser.openAuth(
      authorizationEndpoint,
      redirectUrl,
      {
        // iOS Properties
        dismissButtonStyle: 'cancel',
        // Android Properties
        showTitle: false,
        enableUrlBarHiding: true,
        enableDefaultShare: false,
      },
    ).then(response => {
      if (response.type === 'success' && response.url) {
        return handleURL(response.url);
      }
      // Android bug: response.type is always dismiss, a workaround is to get the url directly with RN's API
      return Linking.getInitialURL().then(url => {
        if (url) {
          return handleURL(url);
        }
      });
    });

Its laravel redirection.

return redirect('myapp://myhost/login?', $queryString); (sends 302 status code)

The issue is that onDestroy is called before _redirectHandler. If I ignore onDismiss event, _redirectHandler gets called and I get the result I want, but the problem remains with handling user closing browser or errors…

I tried a lot of different ways of sending back the redirect from the browser, it always got me { type: 'dismiss' } I also tried using different versions of react-navigation, but it was of no difference. Then I moved towards handling the Linking as that was working fine as I was able to see that the app is invoked on redirect and on using this I am now able to catch the redirect with the data I am sending as parameters from the backend.

componentDidMount() {
  Linking.addEventListener('url', this._handleOpenURL);
}
componentWillUnmount() {
  Linking.removeEventListener('url', this._handleOpenURL);
}
_handleOpenURL(event) {
  console.log(event.url);
//here I am able to parse the url and extract the data for further processing
}

@jdnichollsc I’ve just updated to version 3.3.0 and the issue of “type:dismiss” persists in Android.

Can you please help me with this?

I also ran this example configured by you https://github.com/proyecto26/react-native-inappbrowser/blob/master/example/App.js#L104

It looks like JS redirections doesn’t work in the case of Android, only works with redirections from backend (HTTP 302), check for more details => https://stackoverflow.com/a/41882732/1532821

@jdnichollsc very good news guys! I even managed to remove the error that brought @i1990jain to open this thread (I also think I solved the crash that I was experiencing too)

I previously updated my last comment saying that probably the problem relied in the Android API’s I was using, but actually I was wrong.

The broken thing, at least for me, was this page here put up by the owner of this lib: https://github.com/proyecto26/react-native-inappbrowser/blob/gh-pages/index.html

Basically the way he links back to the app is faulty and it can crash your app and result in a “dismissed” action for the lib (at least restructuring that in another way, didn’t let my app crash or report a dismissed inappbrowser). So I basically tried to switch to this page I put up (I put it on gh pages but it still gives back a 404): http://www.webdevout.net/test?04y&raw and everything worked out nice and perfect for me.

Now, what this probably means? While triaging this issue I’ve encountered some blog posts where there was written that in order to test deep linking you can’t just open chrome and insert your custom link in the url bar for several reasons. (https://medium.com/react-native-training/deep-linking-your-react-native-app-d87c39a1ad5e) In fact, one advised way, is to use an “a” tag. Now I’m about to test it out with a meta tag and see what happens in order to make it automatic

UPDATE: not working with

<meta http-equiv = "refresh" content = "2; url = my-demo://demo/home" />

damn… same crash and same “dismissed” alert when I open it back And it has nothing to do with the “waitforredirectdelay” option, you can raise it up, it won’t work

UPDATE2: to me it seems like there is no solution other than using an a tag and let the user tap it. For some more info you can see here: https://paul.kinlan.me/deep-app-linking-on-android-and-chrome/

If you find a way, let us know 😃

@viewpnt1 as I said, I’m using the example https://github.com/proyecto26/react-native-inappbrowser/blob/master/example/App.js#L104 and as you can see there is 1 redirect in that login flow.

Plus I tried the deep link externally (just using Linking.openURL) and it is working. So can’t understand why it’s crashing…

@jdnichollsc can you tell me what info you need from debugging, and is it native debug or js debug? I tried almost everything the result is always “dismiss”. Also, I noticed that android:launchMode="singleTask"is present in the example app, but same thing happens with or without it. EDIT: only tested it on android.

mmm very odd, we have this Android intent:

<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="app-scheme" android:host="app-host" android:pathPrefix="" />
</intent-filter>

even after adding android:pathPrefix=“” it still gets me {type : dismiss}

Ok so I tried using the same with iOS and it works perfectly but still I haven’t been able to get it working for android tell me if I am going wrong anywhere with the app manifest

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mobileapp">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-feature android:name="android.hardware.camera" android:required="false" />
    <uses-feature android:name="android.hardware.camera.front" android:required="false" />

    <application
      android:name=".MainApplication"
      android:label="@string/app_name"
      android:icon="@mipmap/ic_launcher"
      android:allowBackup="false"
      android:theme="@style/AppTheme">
      <activity
        android:name=".MainActivity"
        android:launchMode="singleTask"
        android:label="@string/app_name"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustResize">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="mobileapp" android:host="mobile-host"/>            
    </intent-filter>
      </activity>
      <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
    </application>

</manifest>

Also for the confguration of the android app I have MainApplication.java and MainActivity.java

package com.mobileapp;

import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;


public class MainActivity extends ReactActivity {

    /**
     * Returns the name of the main component registered from JavaScript.
     * This is used to schedule rendering of the component.
     */
    @Override
    protected String getMainComponentName() {
        return "mobileapp";
    }

    @Override
    protected ReactActivityDelegate createReactActivityDelegate() {
      return new ReactActivityDelegate(this, getMainComponentName()) {
        @Override
        protected ReactRootView createRootView() {
         return new RNGestureHandlerEnabledRootView(MainActivity.this);
        }
      };
    }
}
package com.mobileapp;

import android.app.Application;

import com.facebook.react.ReactApplication;
import com.learnium.RNDeviceInfo.RNDeviceInfo;
import com.proyecto26.inappbrowser.RNInAppBrowserPackage;
import io.github.elyx0.reactnativedocumentpicker.DocumentPickerPackage;
import com.reactnative.ivpusic.imagepicker.PickerPackage;
import com.oblador.vectoricons.VectorIconsPackage;
import com.swmansion.gesturehandler.react.RNGestureHandlerPackage;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;

import java.util.Arrays;
import java.util.List;

public class MainApplication extends Application implements ReactApplication {

  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    public boolean getUseDeveloperSupport() {
      return BuildConfig.DEBUG;
    }

    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
            new RNDeviceInfo(),
            new RNInAppBrowserPackage(),
            new DocumentPickerPackage(),
            new PickerPackage(),
            new VectorIconsPackage(),
            new RNGestureHandlerPackage()
      );
    }

    @Override
    protected String getJSMainModuleName() {
      return "index";
    }
  };

  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }

  @Override
  public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
  }
}

and my utilities.js

import { Platform } from "react-native";
export const getDeepLink = (path = "") => {
  const scheme = "mobileapp";
  const prefix =
    Platform.OS == "android" ? `${scheme}://mobile-host/` : `${scheme}://`;
  return prefix + path;
};

would like to repeat that it is working fine in iOS … but in android I am unable to get a proper response and have to use the Linking eventListener to get the incoming url

Android 8.0.0 iOS 12.1.1

yes I have configured these and the server responds based on the platform … but in either of the case I just get type:dismiss as the result in the function

"native-base": "^2.8.1",
    "react": "16.6.1",
    "react-native": "0.57.7",
  "react-navigation": "^3.0.8",
"react-native-inappbrowser-reborn": "^1.3.11",