Glitch - loop to redirect to login popup, not redirect to app
I have implemented an azure login button, the flow is working well on iOS, but on Android there is a glitch that I don’t manage to fix, maybe you have already faced this issue so i take my shot
The button trigger the login popup from Microsoft as expected, but once logged in, instead of redirecting to the app it just bring me to the same page in a loop.. (Again this is not happening on IOS)
Here is a video screen of the glitch.
My manifest is the basic showed in the doc.
<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:host="{applicationId}"
android:pathPrefix="/android/callback"
android:scheme="{applicationId}" />
</intent-filter>
And my code is very basic, i create new AzureAuth instance and pass my client id. On the login button i call the authorize method with the most basic scope.
const azureAuth = new AzureAuth({
clientId: azureGoogleEnvConfig.azure.clientId,
});
const tokens = await azureAuth.webAuth.authorize({
scope: 'openid profile User.Read',
});
console.log(tokens)
Another weird behavior:
I tried to add the .staging suffix to the intent-filter on AndroidManifest.xml (as we append it when testing our app locally) , and added the new redirect uri in the Azure portal (com.ourApp.staging://com.ourApp.staging/android/callback)
I got to two apps options in the "open the link with" to redirect to the app, both called the same:
- If i click on the first, it does the same behavior (loop to the same page)
- If i click on the second to redirect to the app but cancel the login request (and receive
{error_description: "User cancelled the Auth", error: "aa.session.user_cancelled"})
Try to replace {applicationId} in your manifest with a string literal and check if it helps.
what do you mean ? In my code this is not applicationId, it is literally com.myApp.staging
If you don't have any variable or placeholder and just string there, double check the app registration - you should have the same scheme/pathPrefix in you callback URI.
I tried to create a sample app and it is working as expected on both os. It seems that the app we created in our company cause the glitch but i can't seem to figure what/where... Here are some details about our config:
android/build.gradle
...
ext {
compileSdkVersion = 33
targetSdkVersion = 31
minSdkVersion = 26
buildToolsVersion = "29.0.2"
supportLibVersion = buildToolsVersion
playServicesVersion= "18.0.0"
androidMapsUtilsVersion = "2.3.0"
}
...
gradle-wrapper.properties
#Tue Mar 10 17:31:53 EDT 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.3-all.zip
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.OUR_APP_NAME.android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<supports-screens
android:anyDensity="true"
android:largeScreens="true"
android:normalScreens="true"
android:resizeable="true"
android:smallScreens="true"
android:xlargeScreens="true" />
<!-- maps -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<!-- push -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!-- OpenGL ES version 2 -->
<uses-feature
android:glEsVersion="0x00020000"
android:required="true" />
<application
android:name=".Application"
android:allowBackup="true"
android:largeHeap="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name_key"
android:theme="@style/AppTheme"
android:networkSecurityConfig="@xml/network_security_config">
<activity android:exported="true" android:name=".MainActivity" android:theme="@style/AppTheme.SplashScreen" android:launchMode="singleTask">
<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:host="com.OUR_APP_NAME.android"
android:pathPrefix="/android/callback"
android:scheme="com.OUR_APP_NAME.android" />
</intent-filter>
</activity>
<receiver android:name=".push.ActionReceiver"></receiver>
<service
android:name="com.OUR_APP_NAME.android.push.ListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service
android:name="com.OUR_APP_NAME.android.push.RegistrationIntentService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false" />
<uses-library
android:name="com.google.android.maps"
android:required="false" />
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_api_key" />
<activity
android:exported="true"
android:name=".controllers.dashboard.DashboardActivity"
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTop"
android:screenOrientation="portrait"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".controllers.login.ReactLoginActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait"
android:label="@string/title_activity_login"
/>
<activity
android:name=".controllers.alertdetail.ACADetailActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait"
android:label="">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".controllers.dashboard.DashboardActivity" />
</activity>
<activity
android:name=".controllers.alertdetail.AlertDetailActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait"
android:label="">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".controllers.dashboard.DashboardActivity" />
</activity>
<activity
android:name=".controllers.alertdetail.NotificationACADetailActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait"
android:label="">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".controllers.dashboard.DashboardActivity" />
</activity>
<activity
android:name=".controllers.alertdetail.NotificationAlertDetailActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait"
android:label="">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".controllers.dashboard.DashboardActivity" />
</activity>
<activity android:exported="true" android:name=".controllers.shared.DeepLinkActivity" android:launchMode="singleTask" android:noHistory="true">
<intent-filter android:label="@string/app_name" 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:host="app.OUR_APP_NAME.com" />
<data android:host="corp.OUR_APP_NAME.com" />
<data android:host="ps.OUR_APP_NAME.com" />
<data android:host="gov.OUR_APP_NAME.com" />
<data android:host="firstalert.OUR_APP_NAME.com" />
<data android:host="news.OUR_APP_NAME.com" />
<data android:host="stage.OUR_APP_NAME.com" />
<data android:host="r-stage.OUR_APP_NAME.com" />
<data android:host="redirect-stage.OUR_APP_NAME.com" />
<data android:host="redirect.OUR_APP_NAME.com" />
</intent-filter>
</activity>
<activity
android:name=".controllers.settings.AccountSettingsActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait"
android:label="@string/title_activity_account_settings"
android:parentActivityName=".controllers.dashboard.DashboardActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".controllers.dashboard.DashboardActivity" />
</activity>
<activity
android:name=".controllers.search.SearchActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait"
android:label="" />
<activity
android:name=".controllers.settings.SettingsActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait"
android:label="@string/title_activity_settings" />
<activity
android:name=".controllers.messages.MessageDetailActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait"
android:label="" />
<activity
android:name=".controllers.settings.DashboardSettingsActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait"
android:label="@string/title_activity_dashboard_settings" />
<activity
android:name=".controllers.settings.CustomDashboardSettingsActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait" />
<activity
android:name=".controllers.twitterUser.TwitterUserDetailActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait" />
<activity
android:name=".controllers.map.ReactMapActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait" />
<activity
android:exported="true"
android:name=".controllers.login.ReactTermsOfUseActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="com.intent.action.TERMS.${termsOfUseTarget}" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".controllers.settings.ResetPasswordActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"/>
<activity
android:name=".controllers.settings.ReactWatchlistEditActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait" />
<activity
android:name=".controllers.settings.ContrastSettingsActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait" />
<activity
android:name=".controllers.settings.BetaFeaturesActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait" />
<activity
android:name=".controllers.settings.LocalizationSettingsActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait" />
<activity
android:name=".controllers.settings.ReactNotificationSettingActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait" />
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
<activity
android:name=".controllers.map.ProximitySelectionActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize" />
<activity
android:name=".controllers.login.OnboardingActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize" />
</application>
<queries>
<intent>
<action android:name="android.support.customtabs.action.CustomTabsService" />
</intent>
</queries>
</manifest>
I mention that when i console.log azure.auth.redirectUri i got the same as the one in app registration and the same as what is in the intent-filter, meaning that the redirectUris matches
Please check the answer below. I suppose it is your case too:
https://github.com/vmurin/react-native-azure-auth/issues/94#issuecomment-656315746
I am not sure, because in my case the redirect uri match the one in the app registration
Just try to use the additional parameter redirectUri in the initialization:
const azureAuth = new AzureAuth({
clientId: 'YOUR_CLIENT_ID',
redirectUri: 'your redirect URI here'
});
i tried to use the redirectUri param in the initialization, and it did help returning to the app, but it gives the
"User cancelled the auth" error now..
I don't understand what could cause this trouble, since i just did a test by creating a new react-native app, and the flow work perfectly. Feel like something is wrong in our existing app..
@vmurin Do you think it's ok to delete the <intent-filter> if I use the redirectUri parameter in the AzureAuth initialization ?
@vmurin Do you think it's ok to delete the
<intent-filter>if I use theredirectUriparameter in theAzureAuthinitialization ?
no, without intent the android OS will not know which app should be called upon callback. It is your connection between URI and the app.
remove android:pathPrefix from intent-filter and update your intent filter to the following it will fix your issue
<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:host='${applicationid}'
android:scheme="msauth" />
</intent-filter>
anyone figured out how to fix it? For me there is also two apps options in the "open the link with" to redirect to the app, both called the same:
- If i click on the first, it works correctly
- if I click on the second, it loops
I suspect that such behavior is due to having two intent-filters which are both catching redirect, but no, for my application there are only two intent filters: main one, and the one which is explained in readme for this library.
I suspect that indeed my main intent filter is somehow catching the redirect, even though in no way it should be able to catch it. It's looking like this:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
But why it's happening for my app and not for others?
what worked for me is to use custom redirect uri, different to default one (your app's package name). Then two redirect options disappear.