AppAuth-Android icon indicating copy to clipboard operation
AppAuth-Android copied to clipboard

Redirect URI is not been handled by the app and therefore getting page not found

Open waldjdida opened this issue 3 years ago • 5 comments

Configuration

  • "react-native-app-auth": 6.4.0
  • Integration: ReactNative
  • Identity provider: IdentityServer 4

Description

Android app is unable to catch the redirect Uri and therefore unable to complete authentication.

I don't seem to see where the issue is

I am running the app in Android Simulator

This is my configuration

AndroidManifest.xml

Added this in the application tag

<activity
	android:name="net.openid.appauth.RedirectUriReceiverActivity"
	android:theme="@style/Theme.AppCompat.NoActionBar">
		<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="https"
              android:host="sub.company.com"
              android:path="/oauthredirect"/>
		</intent-filter>
</activity>

The config used in the react native app:

const configs = {
  identityserver: {
    issuer: 'https://sub.company.com',
    clientId: 'company_react_mobile',
    redirectUrl: 'https://sub.company.com/oauthredirect',
    scopes: ['openid', 'profile', 'email', 'offline_access'],
  }
};

add this in build.gradle

android {
   ....
    defaultConfig {
        ....
        manifestPlaceholders = [
            appAuthRedirectScheme: 'https://sub.company.com' // I have used sub.company.com by itself here but no luck
            ]
        
    }

image

waldjdida avatar Nov 17 '21 21:11 waldjdida

Couple of different things:

  • using appAuthRedirectScheme:sub.company.com means you expect a redirect uri of the form sub.company.com://some-auth-path . Judging by the https config you want the activity declaration which seems correct not the manifestPlaceholder.
  • when intercepting https redirects you want to configure https://developer.android.com/training/app-links/index.html otherwise users may never get redirected to your app after the first disambiguation dialog
  • you can try testing your redirect config with adb shell am start -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "https://sub.company.com/path" which could open: the browser, a disambiguation dialog or your app depending on the state of the app link
  • if you're using https redirect try to have the website responding at the link in case the app doesn't intercept the redirect. there have been cases where browsers would precheck the url and not redirect it if ends up in 404
  • remember you need user interaction during the flow (the user needs to tap something in the browser) or the flow will most likely end up never redirecting back to the app

agologan avatar Nov 19 '21 18:11 agologan

@agologan I made a progress in this.

After a thorough investigation, I realised and using that command that the redirect actually work.

So let me elaborate...

When the user first logs in, the app opens an in-app browser page to the auth server login page. Once the login is validated, the user is redirected to the app using the redirect URI and everything works as expected.

The issue lays when the user logs out the app or when revoke function is called. Apparently,the user is still logged in the browser used in the initial authentication.

But when I manually logs the user out in the browser and try log in through the app, I'm able to log in and the redirect works just fine.

It looks like I only get (see the screenshot in my previous post) the not found error page, when the user is already logged-in in the browser.

waldjdida avatar Nov 19 '21 18:11 waldjdida

Token revocation in react-native-app-auth is not the same as logout done by calling EndSession with this lib which will open a browser window and invalidate your cookies also.

Due to the session being active per my last comment:

remember you need user interaction during the flow (the user needs to tap something in the browser) or the flow will most likely end up never redirecting back to the app

I fully expect your described behavior and encourage you to add an account confirmation step for the user to tap (something like, you're logged in as X tap here to continue) which would alleviate the problem since this is an SSO scenario and not logging out is not the only way to end up in this situation.

With everything said some developers have opted into using prompt=login during authentication which would ask the user to always relogin in case the flow is initiated in the app.

agologan avatar Nov 22 '21 08:11 agologan

I'm experiencing a similar issue now.

main/AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          package="com.monarchmoney.mobile">
        ...
        <application
            android:name=".MainApplication"
            android:label="@string/app_name"
            android:icon="@mipmap/ic_launcher"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:allowBackup="false"
            android:usesCleartextTraffic="true"
            android:theme="@style/AppTheme">
            ...

            <activity
                android:name="net.openid.appauth.RedirectUriReceiverActivity"
                tools:node="replace">
                 <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="https"/>
                    <data android:scheme="http"/>
                    <data android:host="app.monarchmoney.com"/>
                    <data android:pathPrefix="/oauth"/>                
                </intent-filter>
            </activity>
        </application>
        ...
</manifest>

and config:

const COINBASE_OAUTH_CONFIG = {
  clientId: COINBASE_CLIENT_ID,
  redirectUrl: https://app.monarchmoney.com/oauth,
  scopes: COINBASE_SCOPES,
  serviceConfiguration: {
    authorizationEndpoint: COINBASE_AUTH_URL,
    tokenEndpoint: '',
  },
  skipCodeExchange: true,
  additionalParameters: { account: 'all' },
};

we're NOT setting appAuthRedirectScheme since it's my understanding that using the RedirectUriReceiverActivity is what you do instead of that if you want to use https app-links.

We go through the authorization flow, the user hits "Authorize" on the Coinbase site, then it just redirects to the app.monarchmoney.com website. BUT doing the same thing via adb adb shell am start -a android.intent.action.VIEW -d "https://app.monarchmoney.com/oauth?code=597&state=foo" appears to successfully redirect to the app for some reason.

If it helps, we also have a prod AndriodManifest override for our other app-links:

prod/AndriodManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.monarchmoney.mobile">
    <application
            android:name=".MainApplication"
            android:label="@string/app_name"
            android:icon="@mipmap/ic_launcher"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:allowBackup="false"
            android:theme="@style/AppTheme">
        <activity
                android:name=".MainActivity"
                android:label="@string/app_name"
                android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
                android:launchMode="singleTask"
                android:windowSoftInputMode="adjustResize">

            <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>

                <data android:scheme="https"/>
                <data android:scheme="http"/>
                <data android:host="app.monarchmoney.com"/>
                <data android:pathPrefix="/links"/>
            </intent-filter>
        </activity>
    </application>
</manifest>

Any guidance here would be appreciated @agologan

Maushundb avatar Nov 22 '21 19:11 Maushundb

Opened my own issue over at https://github.com/openid/AppAuth-Android/issues/766 since they may be different.

Maushundb avatar Nov 23 '21 01:11 Maushundb