Select to view content in your preferred language

OAuth window appears circularly on Android emulator

117
8
Thursday
Labels (1)
EgorFedorov
Emerging Contributor

I have configured my app to sign in to ArcGIS online via OAuth according to sample. When I try to access portal (namely, get token) on Android emulator, I experience the following behaviour.

  1. Window with standard ArcGIS web view asking for username/password appears
  2. I fill required info and click "Sign In" button
  3. Window disappears but immediately appears again with empty UN/PW fields and without any errors
  4. If I fill UN/PW fields and click "Sign In" again, I see step #3 repeated again
  5. If I click "Cancel", I see step #3 repeated again
  6. If I click "X" button in top left, it returns back to my application without any error in log

This is very confusing behaviour. Nevertheless, token in received correctly and is available in my code.

Here is what I see in Flutter log:

Launching lib/main.dart on sdk gphone64 x86 64 in debug mode...
Running Gradle task 'assembleDebug'...
✓ Built build/app/outputs/flutter-apk/app-debug.apk
D/FlutterLocationService(25127): Creating service.
D/FlutterLocationService(25127): Binding to location service.
Debug service listening on ws://127.0.0.1:54747/7nhbvLo_1Ck=/ws
Syncing files to device sdk gphone64 x86 64...
D/ProfileInstaller(25127): Installing profile for com.esri.[my-app-id]
I/PlatformViewsController(25127): Using hybrid composition for platform view: 0
D/CompatibilityChangeReporter(25127): Compat change id reported: 236825255; UID 10191; state: ENABLED
E/EGL_emulation(25127): eglQueryContext 32c0 EGL_BAD_ATTRIBUTE
E/EGL_emulation(25127): tid 25127: eglQueryContext(2146): error 0x3004 (EGL_BAD_ATTRIBUTE)
I/MapViewRenderer(25127): Starting pulse
I/flutter (25127): Getting token
I/flutter (25127): Creating OAuthUserCredential
D/EGL_emulation(25127): app_time_stats: avg=3309.65ms min=164.96ms max=6454.35ms count=2
D/EGL_emulation(25127): app_time_stats: avg=3305.84ms min=166.88ms max=6444.81ms count=2
D/EGL_emulation(25127): app_time_stats: avg=1767.54ms min=59.52ms max=6441.73ms count=4
I/MapViewRenderer(25127): Stopping pulse
D/EGL_emulation(25127): app_time_stats: avg=243.07ms min=17.80ms max=1832.81ms count=9
D/EGL_emulation(25127): app_time_stats: avg=243.33ms min=14.82ms max=1836.10ms count=9
D/EGL_emulation(25127): app_time_stats: avg=242.64ms min=19.78ms max=1825.41ms count=9
I/flutter (25127): Getting token info
I/flutter (25127): accessToken: 3NKHt6...
I/MapViewRenderer(25127): Resumed by user. Texture view available: true
W/OpenGLRenderer(25127): Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
W/OpenGLRenderer(25127): Failed to initialize 101010-2 format, error = EGL_SUCCESS
E/OpenGLRenderer(25127): Unable to match the desired swap behavior.
D/EGL_emulation(25127): app_time_stats: avg=24751.84ms min=24751.84ms max=24751.84ms count=1
D/EGL_emulation(25127): app_time_stats: avg=24763.88ms min=24763.88ms max=24763.88ms count=1
I/MapViewRenderer(25127): Starting pulse
D/EGL_emulation(25127): app_time_stats: avg=27904.54ms min=157.61ms max=55651.45ms count=2
D/EGL_emulation(25127): app_time_stats: avg=27900.98ms min=150.63ms max=55651.33ms count=2
D/EGL_emulation(25127): app_time_stats: avg=18624.16ms min=93.41ms max=55642.82ms count=3

 

Notes:

  1. OAuth credentials are valid and works well with ArcGIS Maps SDK for Kotlin/Swift.
  2. I use currently released version of ArcGIS SDK for Flutter (200.6.0+4426), the latest Flutter SDK (3.27.0), and the latest Dart version (3.6.0).
  3. This workflow works correctly for iOS
  4. Android simulator versions are 12 and 14

Here is the video describing what's happening.

 

 

 

0 Kudos
8 Replies
PaulSturm
Esri Contributor

My first guess is that there is a mismatch with the "redirect url", described in the "Redirect URL" section on this page: https://developers.arcgis.com/documentation/security-and-authentication/user-authentication/oauth-cr...

That needs to be configured properly on the server side, and it needs to match two places in your client code. It needs to match the "redirectUri" parameter to your "OAuthUserConfiguration" object, and it needs to be set up properly in your "AndroidManifest.xml". It needs to be an "<activity>" tag under your "<application>" tag, like this:

 

<activity android:name="com.linusu.flutter_web_auth_2.CallbackActivity"
android:exported="true">
  <intent-filter android:label="flutter_web_auth_2">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="my-ags-app" />
  </intent-filter>
</activity>
​

 

In this example, my redirect url is "my-ags-app://auth", and the "scheme" setting in AndroidManifest.xml is just the "my-ags-app" part.
 
This configuration is necessary so that Android can move the user from the browser login page back to your application. Also note that you should have a unique redirect uri for each app installed on a single device -- if you have multiple apps with the same redirect uri, Android won't be able to navigate back to the proper app.
0 Kudos
PaulSturm
Esri Contributor

For comparison, here is how OAuth is configured in our Sample Viewer's "Authenticate with OAuth" sample:

https://github.com/Esri/arcgis-maps-sdk-flutter-samples/blob/main/lib/samples/authenticate_with_oaut...

https://github.com/Esri/arcgis-maps-sdk-flutter-samples/blob/main/android/app/src/main/AndroidManife...

(Note that your "clientId" and "redirectUri" will be unique to your application.)

0 Kudos
EgorFedorov
Emerging Contributor

 

Thanks for answer, but looks like this is not the case. I have configured AndroidManifest.xml according to sample, it has the following lines:

 

<activity
    android:name="com.linusu.flutter_web_auth_2.CallbackActivity"
    android:exported="true">
    <intent-filter android:label="flutter_web_auth_2">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="rn-ags-examples" />
    </intent-filter>
</activity>

 

 

And here are redirect URLs configured on portal:

Screenshot 2025-01-09 at 23.38.56.png

 

Also, I use correct clientId and redirectUri when creating OAuthUserConfiguration instance (just double-checked it).

 

 

 

 

0 Kudos
PaulSturm
Esri Contributor

I wonder if the "/" (slash) at the end matters? The sample code uses "my-ags-app://auth", without the trailing slash. I see that your portal configuration uses a trailing slash in two cases, but not the third. I'm not sure if that matters, but it might.

Another thought is this: does the device you're testing on have more than one installed app using the same redirectUri (or perhaps just the same "scheme" in the Android.xml)? We've run into problems when that happens. Perhaps to test this theory you could try running on a second Android device. If the problem only occurs on some but not all Android devices, then that would indicate there's something unique to the device.

And then lastly, does the "Authenticate with OAuth" sample work on this particular device?

0 Kudos
EgorFedorov
Emerging Contributor

I've removed trailing slash in all cases, removed all my apps from emulator and re-installed the app I test. I've even created a new simulator w/ Android 14. No success for any try: oauth window still appears circularly.

 

Running the latest sample from GH has the following results (checked both with my own oAuth configuration and one provided with sample).

  1. Open "Authenticate with OAuth" sample.
  2. It loads basemap automatically and opens web view for UN/PW after some delay
  3. I fill UN/PW fields and click "Sign In". App returns to the map and displays webmap layer as expected
  4. If I click Android hardware Back button, it goes to the list of samples, and, with another Back button click, to web view with UN/PW
  5. If I fill UN/PW in window appeared in step 4, it goes back to the list of samples or (observed several times) become appearing circularly again

 

Please take a look at video attached.

 

Note: I have Android API 35 installed, so I had to update Gradle to 8.3 and AGP to 8.1.4 so that I can build and run samples.

 

 

0 Kudos
PaulSturm
Esri Contributor

Hmm that's very confusing. Can you post the code for your app from the very first screen recording? The one with the "Get token" button. And drop in the OAuth configuration from the "Authenticate with OAuth" sample (so you don't have to post your own OAuth configuration).

From the new video, it looks like the Sample Viewer is behaving a little better than your example app. I'm not sure why that is. Possibly because the Sample Viewer navigates to a separate page when you select it from the list. Or there might be some other relevant difference in how the challenge handler is set up.

It looks like the Sample Viewer only gets into trouble when you use the hardware back button to return to the login view. I'm going to look for a way to close the login view after a successful login. The implementation on iOS doesn't behave like that, so maybe there's something Android-specific we should be doing.

0 Kudos
PaulSturm
Esri Contributor

I found another thing to try. In your call to the OAuthUserConfiguration constructor, add the flag "preferPrivateWebBrowserSession: true". For example, here's adding this flag in the Sample Viewer:

  final _oauthUserConfiguration = OAuthUserConfiguration(
    portalUri: Uri.parse('https://www.arcgis.com'),
    clientId: 'T0A3SudETrIQndd2',
    redirectUri: Uri.parse('my-ags-flutter-app://auth'),
    preferPrivateWebBrowserSession: true,
  );

With a private browser session, the web view gets closed after you log in successfully (or cancel). That keeps it from getting in the way. I'm sure this will solve the odd behaviour from your video with the Sample Viewer, but I'm not certain it will solve the problem with your test app. 

0 Kudos
EgorFedorov
Emerging Contributor

Tried to use 'preferPrivateWebBrowserSession: true' param. Results are the following:

  • "Authenticate with OAuth" sample works well: OAuth window does not appear anymore when I click Back button
  • My app still works as previously, with no changes.

I've removed both apps before testing, just in case.

0 Kudos