proyecto26 / react-native-inappbrowser

📱InAppBrowser for React Native (Android & iOS) 🤘
https://www.npmjs.com/package/react-native-inappbrowser-reborn
MIT License
1.3k stars 222 forks source link

While auth in progress, going to background closes the browser. #153

Open nilesh1883 opened 4 years ago

nilesh1883 commented 4 years ago

Platform: Both iOS and Android Device: Device and emulator both.

Steps to reproduce:

  1. Open browser using openAuth call.
  2. Auth should be two factor.
  3. Provide the first factor credentials.
  4. Go to application which will have to second factor code. (In other words take the application to background).
  5. Come back to application.
  6. Browser is dismissed.
  7. In iOS we don't get any response or error, but in Android we get response as {type: 'dismiss'} but this is not the proper response.

Thanks

jdnichollsc commented 4 years ago

Please attach any reproducible demo

nilesh1883 commented 4 years ago

Please attach any reproducible demo

Thanks for replying @jdnichollsc, I really appreciate the work you have done in this library. I will try and attach the demo.

I did some more digging and it looks like on Android the issue only comes when "android:launchMode="singleTask"" and while reopening the application you click on the application rather than using app switcher.

For iOS the issue not reproducible anymore.

Luke-Rogerson commented 3 years ago

@jdnichollsc I'm also having this issue on Android.

Here is working example I made. Simply clone and yarn.

To reproduce:

  1. Click the "PRESS ME" button
  2. Press the home button to return to the home screen.
  3. Open the app again by pressing the icon from home screen or app drawer.
  4. The in app browser will have closed, with {type: "dismiss"} being returned.

{type: "dismiss"} is resolved from the open promise that is called within _openAuthSessionPolyfillAsync. This is in turn originating from the close Java method.

I'm trying to help with a fix, but I need to understand exactly what the correct behaviour of this type: dismiss. Clearly, it should not be retuned at this point, but then when should the result of open or openAuth be type: dismiss? Would you mind explaining what is the expected behaviour?

Many thanks for all your hard work with this library!

jdnichollsc commented 3 years ago

What happen if you use the forceCloseOnRedirection option? 🤔 When the android activity is destroyed, this event is called https://github.com/proyecto26/react-native-inappbrowser/blob/develop/android/src/main/java/com/proyecto26/inappbrowser/ChromeTabsManagerActivity.java#L76 We're returning this event type here https://github.com/proyecto26/react-native-inappbrowser/blob/develop/android/src/main/java/com/proyecto26/inappbrowser/RNInAppBrowser.java#L211

Honestly I don't know if we need to use CustomTabsSession to support this, there's an example https://github.com/EddyVerbruggen/cordova-plugin-safariviewcontroller/blob/4e540732e0ed33a350ca6cede87da520fca864ce/src/android/helpers/CustomTabServiceHelper.java#L25 Let me know what you think

Luke-Rogerson commented 3 years ago

forceCloseOnRedirection seemed to not do anything. I'm still trying to get my head around exactly what causing this, and further debugging tonight revealed it's certainly a native side issue, with dismiss being returned to the open method.

I'm not sure if we need this CustomTabsSession for this? It looks to be we can just handle this in your existing Android code?

oailloud commented 3 years ago

I had the exact same problem and I've finally found a combination of settings that works for me. Try to set:

InAppBrowser.open(url, {
    ...
    forceCloseOnRedirection: false,
    showInRecents: true,
    ...
}

Strangely enough, it doesn't show a new task in the "recents" but it leaves the in-app browser on top of the original application and allows switching through other apps.

Concretely, it creates the intent (the one that launches the chrome custom tab) without any flag, neither FLAG_ACTIVITY_NEW_TASK nor FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS/FLAG_ACTIVITY_NO_HISTORY. I'm a noob when it comes to the Android platform but here's my understanding:

Hope that helps!

Kiran0791 commented 3 years ago

I had the exact same problem and I've finally found a combination of settings that works for me. Try to set:

InAppBrowser.open(url, {
    ...
    forceCloseOnRedirection: false,
    showInRecents: true,
    ...
}

Strangely enough, it doesn't show a new task in the "recents" but it leaves the in-app browser on top of the original application and allows switching through other apps.

Concretely, it creates the intent (the one that launches the chrome custom tab) without any flag, neither FLAG_ACTIVITY_NEW_TASK nor FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS/FLAG_ACTIVITY_NO_HISTORY. I'm a noob when it comes to the Android platform but here's my understanding:

  • WhenforceCloseOnRedirection: true is set (FLAG_ACTIVITY_NEW_TASK enabled), Android launches the chrome custom tab (the browser) in a new task that appears in the recents, whatever the value of showInRecents. But that task is closed from the moment when you exit it (either switching via the recents screen or going back to the home). Maybe there's a magic flag that would prevent that behavior?
  • On the other way, if forceCloseOnRedirection: false is set with showInRecents: false, the browser does stay in the original application tab but when switching back to it, onResume is called on the ChromeTabsManagerActivity and it closes the browser because it doesn't know how to differentiate between coming back from explicitly closing the browser or coming back from another app as onResume is legitimately called in both cases. That may be more of a bug in the lib but I have no idea what it would take to figure out the case which it's in.

Hope that helps!

Above fix works when switching between the app. But when the app is opened by clicking on app icon the inapp browser gets closed.

Any Solution for this

jdnichollsc commented 3 years ago

Hello folks, do you have examples of another apps supporting this workflow?

Kiran0791 commented 3 years ago

Hello folks, do you have examples of another apps supporting this workflow?

@jdnichollsc am not sure if Instagram is on react-native. But when you open any ad link which comes on feed screen it gets open in a similar kind of in-app browser. And when you put app in background and click on the app icon you can still see the link opened.

jdnichollsc commented 3 years ago

@Kiran0791 any example using auth flow? :)

niljaisw commented 3 years ago

I had the exact same problem and I've finally found a combination of settings that works for me. Try to set:

InAppBrowser.open(url, {
    ...
    forceCloseOnRedirection: false,
    showInRecents: true,
    ...
}

Strangely enough, it doesn't show a new task in the "recents" but it leaves the in-app browser on top of the original application and allows switching through other apps. Concretely, it creates the intent (the one that launches the chrome custom tab) without any flag, neither FLAG_ACTIVITY_NEW_TASK nor FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS/FLAG_ACTIVITY_NO_HISTORY. I'm a noob when it comes to the Android platform but here's my understanding:

  • WhenforceCloseOnRedirection: true is set (FLAG_ACTIVITY_NEW_TASK enabled), Android launches the chrome custom tab (the browser) in a new task that appears in the recents, whatever the value of showInRecents. But that task is closed from the moment when you exit it (either switching via the recents screen or going back to the home). Maybe there's a magic flag that would prevent that behavior?
  • On the other way, if forceCloseOnRedirection: false is set with showInRecents: false, the browser does stay in the original application tab but when switching back to it, onResume is called on the ChromeTabsManagerActivity and it closes the browser because it doesn't know how to differentiate between coming back from explicitly closing the browser or coming back from another app as onResume is legitimately called in both cases. That may be more of a bug in the lib but I have no idea what it would take to figure out the case which it's in.

Hope that helps!

Above fix works when switching between the app. But when the app is opened by clicking on app icon the inapp browser gets closed.

Any Solution for this

I can confirm this is happening.

asami95 commented 2 years ago

@jdnichollsc Thank you so much for your efforts here!

I have an issue that may be related to this issue, I am trying to build a simple application to demonstrate the use of the library.

It works really fine with iOS but I face strange behavior in Android here's a gif:

_gif

And I have this response in the console:

{message: 'chrome tabs activity closed', type: 'cancel'}

And here is my simple code which is executed when I press on "Authorize":

const url = `${URLS.authorizationEndpoint}?state=hello&client_id=${SECRETS.clientId}&redirect_uri=${URLS.redirectUrl}&response_type=token`;
  try {
    InAppBrowser.openAuth(url, URLS.redirectUrl, {
      forceCloseOnRedirectionL: false,
      showInRecents: true,
    })
      .then(async response => {
        if (response.type === 'success' && response.url) {
          const parsed = qs.parse(response.url);
          await AsyncStorage.setItem('@SSO_CRDS', JSON.stringify(parsed))
            .then(() => {
              onSuccess && onSuccess();
            })
            .catch(e => alert(e));
        }
      })
      .catch(err => console.log(err));
  } catch (error) {
    console.log(error);
  }
GautierT commented 2 years ago

I had the exact same problem and I've finally found a combination of settings that works for me. Try to set:

InAppBrowser.open(url, {
    ...
    forceCloseOnRedirection: false,
    showInRecents: true,
    ...
}

Strangely enough, it doesn't show a new task in the "recents" but it leaves the in-app browser on top of the original application and allows switching through other apps. Concretely, it creates the intent (the one that launches the chrome custom tab) without any flag, neither FLAG_ACTIVITY_NEW_TASK nor FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS/FLAG_ACTIVITY_NO_HISTORY. I'm a noob when it comes to the Android platform but here's my understanding:

  • WhenforceCloseOnRedirection: true is set (FLAG_ACTIVITY_NEW_TASK enabled), Android launches the chrome custom tab (the browser) in a new task that appears in the recents, whatever the value of showInRecents. But that task is closed from the moment when you exit it (either switching via the recents screen or going back to the home). Maybe there's a magic flag that would prevent that behavior?
  • On the other way, if forceCloseOnRedirection: false is set with showInRecents: false, the browser does stay in the original application tab but when switching back to it, onResume is called on the ChromeTabsManagerActivity and it closes the browser because it doesn't know how to differentiate between coming back from explicitly closing the browser or coming back from another app as onResume is legitimately called in both cases. That may be more of a bug in the lib but I have no idea what it would take to figure out the case which it's in.

Hope that helps!

Above fix works when switching between the app. But when the app is opened by clicking on app icon the inapp browser gets closed.

Any Solution for this

Same issue, when I switch between app using the recent screen the in-app browser is kept open but if I go back to the homescreen then click on the app icon, the in-app browser is dismissed...

const result = await InAppBrowser.open(url, {
    forceCloseOnRedirection: false,
    showInRecents: false
})

Btw, thanks for this awesome lib !

jdnichollsc commented 2 years ago

@jdnichollsc Thank you so much for your efforts here!

I have an issue that may be related to this issue, I am trying to build a simple application to demonstrate the use of the library.

It works really fine with iOS but I face strange behavior in Android here's a gif:

_gif

And I have this response in the console:

{message: 'chrome tabs activity closed', type: 'cancel'}

And here is my simple code which is executed when I press on "Authorize":

const url = `${URLS.authorizationEndpoint}?state=hello&client_id=${SECRETS.clientId}&redirect_uri=${URLS.redirectUrl}&response_type=token`;
  try {
    InAppBrowser.openAuth(url, URLS.redirectUrl, {
      forceCloseOnRedirectionL: false,
      showInRecents: true,
    })
      .then(async response => {
        if (response.type === 'success' && response.url) {
          const parsed = qs.parse(response.url);
          await AsyncStorage.setItem('@SSO_CRDS', JSON.stringify(parsed))
            .then(() => {
              onSuccess && onSuccess();
            })
            .catch(e => alert(e));
        }
      })
      .catch(err => console.log(err));
  } catch (error) {
    console.log(error);
  }

Hey mate, please create another issue and attach a reproducible demo to be able to debug your error 👍

rogierslag commented 2 years ago

I encountered the same problem, and solved it using https://github.com/proyecto26/react-native-inappbrowser/issues/213#issuecomment-878915862

It boils down that pressing the app icon in the launcher relaunches the activity which closes the browser when relaunched. Preventing a relauch from happening ensures the browser stays in place

rubina-shakhkyan commented 2 years ago

I had the exact same problem and I've finally found a combination of settings that works for me. Try to set:

InAppBrowser.open(url, {
    ...
    forceCloseOnRedirection: false,
    showInRecents: true,
    ...
}

Strangely enough, it doesn't show a new task in the "recents" but it leaves the in-app browser on top of the original application and allows switching through other apps.

Concretely, it creates the intent (the one that launches the chrome custom tab) without any flag, neither FLAG_ACTIVITY_NEW_TASK nor FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS/FLAG_ACTIVITY_NO_HISTORY. I'm a noob when it comes to the Android platform but here's my understanding:

  • WhenforceCloseOnRedirection: true is set (FLAG_ACTIVITY_NEW_TASK enabled), Android launches the chrome custom tab (the browser) in a new task that appears in the recents, whatever the value of showInRecents. But that task is closed from the moment when you exit it (either switching via the recents screen or going back to the home). Maybe there's a magic flag that would prevent that behavior?
  • On the other way, if forceCloseOnRedirection: false is set with showInRecents: false, the browser does stay in the original application tab but when switching back to it, onResume is called on the ChromeTabsManagerActivity and it closes the browser because it doesn't know how to differentiate between coming back from explicitly closing the browser or coming back from another app as onResume is legitimately called in both cases. That may be more of a bug in the lib but I have no idea what it would take to figure out the case which it's in.

Hope that helps!

Did you manage to solve the problem for iOS?

oailloud commented 2 years ago

If I remember correctly, I didn't have any problem with iOS, it was already working for me...

thuongtv-vn commented 2 years ago

I have such issue on Android. I see that while the authenticate is processing. If the authorize URI is matched with your deeplinks declared on your android manifest. Then it will get back to your app and interrupt the authentication process before redirectUrl is called.

Do you guys have any idea?

jdnichollsc commented 2 years ago

Hey folks, can you help me to review the new Release 3.7.0 please? https://github.com/proyecto26/react-native-inappbrowser/pull/375

sonuwise commented 1 year ago

While auth process, once the authentication is done it try to go back the app but the application gets closed without throwing error. In ios its working find but on android I'm facing problem. Kindly help me out to resolve this asap.

nitesh-habilelabs commented 11 months ago

anyone got any fixes or workaround for that? i am using keycloak for authentication in my react native application and as soon as i enter my credentials and otp, in-app browser gets closed with message {"message": "chrome tabs activity destroyed", "type": "dismiss"}

it is working totally fine in IOS. issue is only in android. any help would be appreciated. Here is my code to handle Login which is working fine for ios but not for android.

`

export async function login() {
  InAppBrowser.close();
  const challenge = pkceChallenge();
  const stateValue = generateRandomState();
  const Loginurl = `${ENDPOINT_URL}/auth?client_id=${CLIENT_ID}&response_type=${response_type}&redirect_uri=${
    Platform.OS === 'ios' ? redirectUriIos : redirectUriAndroid
  }&scope=${scope}&nonce&state=${stateValue}&code_challenge=${
    challenge.codeChallenge
  }&code_challenge_method=S256`;
  const localCodeVerifier = challenge.codeVerifier;

  try {
    if (await InAppBrowser.isAvailable()) {
      const result: any = await InAppBrowser.openAuth(
        Loginurl,
        Platform.OS === 'ios' ? redirectUriIos : redirectUriAndroid,
        {
          forceCloseOnRedirection: false,
          showInRecents: true,
          // iOS Properties
          ephemeralWebSession: false,
          // Android Properties
          showTitle: false,

          enableUrlBarHiding: true,
          enableDefaultShare: false,
        },
      );

      if (result.type === 'success') {
        const match_auth_token = result.url.match('code=([^&"]+)');
        if (match_auth_token && match_auth_token[1]) {
          const authToken = match_auth_token[1];

          const resFromFetchToken = await getAccessTokenFromAuthCode(
            authToken,
            localCodeVerifier,
          );
          return resFromFetchToken;
        } else {
          console.error('Access token not found');
          return null;
        }
      }
      // when the users presses the cancel/close button
      if (result.type === 'cancel') {
        onCancel();
        return null;
      }
    } else {
      Linking.openURL(Loginurl);
    }
  } catch (error) {
    console.debug(' error: ', error);
    return null;
  }
}
TamasSzigeti commented 11 months ago

@nitesh-habilelabs Been a while since I had worked with this but looking at my code it seems this same android issue I solved by passing a deep link url as a redirect one (second param of openAuth()). iOS doesn't care what you pass in there, but for Android it is myapp:/// – and I use the same as the second redirect from the html page which I pass in as redirectUrl for the third party OAuth provider. Hope it's clear, let me know.

nitesh-habilelabs commented 11 months ago

@nitesh-habilelabs Been a while since I had worked with this but looking at my code it seems this same android issue I solved by passing a deep link url as a redirect one (second param of openAuth()). iOS doesn't care what you pass in there, but for Android it is myapp:/// – and I use the same as the second redirect from the html page which I pass in as redirectUrl for the third party OAuth provider. Hope it's clear, let me know.

Hi @TamasSzigeti , Thank you for your help. It is fixed now. issue was with my intent filter. i had to pass host in that. <data android:scheme="app" android:host="main" />

krini commented 7 months ago

I had to set showInRecents to true.