Fails to open native app with javascript, but same code works when initialized through button

Viewed 165

This questions concernes a web app build in React that will be accessed with smartphones through their browsers. I use iPhone with both Safari and Chrome for testing.

One step involves opening a native authentication app. According to the docs of the native app, it can be open from the browser by doing this:

  const openAuthApp = () =>
    (window.location = "https://app.bankid.com/?autostarttoken=&redirect=");

This works fine if I call the function when clicking a button, like this:

<button onClick={openAuthApp}>Open</button>

The above code triggers the opening of the authentication app immediately when clicking the button.

But when I trigger the function immediately after page has loaded, without using a button, like this

  useEffect(() => {
    openAuthApp();
  }, []);

I get an error in the browser saying that the app was not found on this device.

Idk much about how browsers work but my first guess was that it takes some time for the browser to acquire information about all installed apps, so I added a timeout before executing the method:

  useEffect(() => {
    setTimeout(openAuthApp, 5000);
  }, []);

It still failed. It works if I press the button less than 5 seconds after page load, so the time of initiation after page load shouldn't be the factor here.

I don't know how to proceed with this, and would appreciate ideas on how to move forward.

2 Answers

I suspect that your problem is a missing user gesture, which is common when using Claimed HTTPS Schemes - eg see this Chrome browser requirement.

There is a similar problem when using OAuth flows and the AppAuth pattern with HTTPS redirect URIs, which occurs for both iOS and Android. See the sections titled Problems Receiving Redirect Responses in my iOS and Android blog posts.

The solution for my mobile samples was to add an interstitial web page and if you do a view source you will see that it has an onclick handler that invokes a deep link after the user gesture:

document.getElementById('continueButton').onclick = () => {
    const redirectUri = 'https://mobile.authsamples.com/basicmobileapp/oauth/callback';
    window.location.href = redirectUri;
};

You won't need to go to these lengths of course, but I think you will need a user gesture to invoke the BankID app and do an external login reliably. In some ways this is a reasonable UX also, since you are keeping the user informed before you switch apps, rather than doing so abruptly. I would put a positive spin on it like this:

You will now be redirected to the BankID app to perform strong authentication and to provide consent. Please click Next to proceed.

Option 1:

Use window.location.href instead of window.location

const openAuthApp = () =>
(window.location.href = "https://app.bankid.com/?autostarttoken=&redirect=");

If your web app have the same domain as bankid.com use window.location.assign instead.

const openAuthApp = () =>
(window.location.assign= "https://app.bankid.com/?autostarttoken=&redirect=");

Option 2:

this will take 5 minutes, use branch.io for links (you do not need to install the SDK)

  • signup create new app, write the name of the app
  • got to "Configuration" from left menu select "I have an Android App"
  • add the link for your app and select it then fill other options if you like
  • it will give you a link "https://[YOUR_APP_ID ].app.link"
  • use this link instead of the default link

This should work without problem

Related