question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

The acquireToken method doesn't work if you uses "withFragmemt"

See original GitHub issue

Details We are going to make b2c authorization in our Android app and we faced with issue with “IMultipleAccountPublicClientApplication.acquireToken” method and fragment.

Smartphone (please complete the following information):

  • Device: Samsun M51
  • Android Version: 12,
  • MSAL Version: 4.0.5

Config { "broker_redirect_uri_registered": false, "client_id" : "****", "authorization_user_agent" : "WEBVIEW", "redirect_uri" : "****", "authorities" : [ { "type": "B2C", "authority_url": "https://schcoad.b2clogin.com/schcoad.onmicrosoft.com/.......", "default": true } ] }

Stacktrace W/MSALLogger: AuthorizationFragment:onCreate | [2022-11-11 13:11:47 - thread_name: main, correlation_id: UNSET - Android 31] No stored state. Unable to handle response W/AuthorizationFragment:onCreate: [2022-11-11 13:11:47 - thread_name: main, correlation_id: UNSET - Android 31] No stored state. Unable to handle response E/MSALLogger: AuthorizationFragment#finish | [2022-11-11 13:11:47 - thread_name: main, correlation_id: UNSET - Android 31] Logged as error to capture 'cause'; Exception occurred when removing ourselves from provided FragmentManager java.lang.IllegalStateException: FragmentManager is already executing transactions at androidx.fragment.app.FragmentManager.ensureExecReady(FragmentManager.java:1636) at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1666) at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:317) at com.microsoft.identity.common.internal.providers.oauth2.AuthorizationFragment.finish(AuthorizationFragment.java:136) at com.microsoft.identity.common.internal.providers.oauth2.AuthorizationFragment.onCreate(AuthorizationFragment.java:94) at com.microsoft.identity.common.internal.providers.oauth2.WebViewAuthorizationFragment.onCreate(WebViewAuthorizationFragment.java:104) at androidx.fragment.app.Fragment.performCreate(Fragment.java:2981) at androidx.fragment.app.FragmentStateManager.create(FragmentStateManager.java:474) at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:257) at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1840) at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1758) at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1701) at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:488) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:226) at android.os.Looper.loop(Looper.java:313) at android.app.ActivityThread.main(ActivityThread.java:8663) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:567) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)

To Reproduce

  1. Create the fragment where you would like to have the WebView. As example, in sample app. it can be “MultipleAccountModeFragment” from the sample app.

  2. Set the WebView client for “authorization_user_agent” : “WEBVIEW”,

  3. Add the “withFragment” to val parameters: AcquireTokenParameters = AcquireTokenParameters.Builder() .withScopes(AzureUserAuthorizationApi.SCOPES) .startAuthorizationFromActivity(requireActivity())// we are inside fragment .withCallback(b2cAuthenticationCallback) *.withFragment(*this*)// this equals MultipleAccountModeFragment* .withPrompt(Prompt.LOGIN) .build()

  4. call IMultipleAccountPublicClientApplication.acquireToken(parameters)

Expected behavior I would like to have the WebView is run inside the fragment/over MultipleAccountModeFragment. Also, I checked all the provided documentation, samples and I’ve not found anything how to use “withFragment” method correctly. I kindly ask to document it and it can save a lot of time for developers. Right know it doesn’t work.

Actual Behavior The error log message is observed, the spinner is running. 2022-11-11 15 13 24

I found that it by some reasons “savedInstanceState” and “mInstanceState” is null and it closes itself onCreate. AuthorizationFragment.java if (savedInstanceState == null && mInstanceState == null) { Logger.warn(methodTag, "No stored state. Unable to handle response"); **finish();** return; }

Issue Analytics

  • State:open
  • Created 10 months ago
  • Comments:14

github_iconTop GitHub Comments

3reactions
VolodaUacommented, Nov 21, 2022

+1 on this

I found the workaround. Just create the same class in your project with the same package and Java runtime will use your class instead. Please take the fix here: https://github.com/AzureAD/microsoft-authentication-library-common-for-android/pull/1704

I still see the error about fragment transaction, but it works.

2reactions
RileyGBcommented, Dec 17, 2022

I was able to get this working in release. TLDR; it takes some work.

For my purposes, I wanted to replace both AndroidAuthorizationStrategy.java(this bug) and WebViewAuthorizationFragment.java(I needed access to the webview) with my own implementations.

You may want to get a coffee (or beverage of your choice) before attempting the following:

Removing the necessary files from the library

  • I acquired the AAR for https://github.com/AzureAD/microsoft-authentication-library-common-for-android from my local gradle cache (find an aar in a sub directory of .gradle/caches/modules-2/files-2.1/com.microsoft.identity/common/9.0.0)
  • Since an AAR is just a zip, I renamed its extension to a .zip and unzipped its contents.
  • Within its contents, classes.jar exists. I renamed its extension to a .zip and unzipped its contents.
  • I found and deleted all of the .class files for both AndroidAuthorizationStrategy and WebViewAuthorizationFragment
  • To convert my classes folder to a .jar I ran jar cvf classes.jar classes
  • I took my new classes.jar and put it back in the decompiled aar folder
  • To convert my aar folder to a .aar I ran jar cvf microsoft-common.aar common-9.0.0

Importing the AAR in your project successfully

I added microsoft-common.aar to app/libs/ in my project (libs may be a new directory that you need to create).

In the dependencies section of my app build.gradle:

    implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
    
    // Microsoft MSAL (need to exclude all transitive dependencies or the commons lib will cause a duplicate class error)
    implementation('com.microsoft.identity.client:msal:4.1.0') {
        transitive = false
    }
    
    // Import my modified AAR 
    implementation files('libs/microsoft-common.aar')
    
    // Import required dependencies for common library (excluded by transitive = false above)
    implementation("androidx.constraintlayout:constraintlayout:2.1.4")
    implementation 'com.microsoft.identity:common4j:6.0.0'
    implementation 'com.yubico.yubikit:android:2.1.0'

Result

Now I can build a release build with both com.microsoft.identity.common.internal.providers.oauth2.AndroidAuthorizationStrategy.java and com.microsoft.identity.common.internal.providers.oauth2.WebViewAuthorizationFragment.java existing in my project. You can grab these classes from https://github.com/AzureAD/microsoft-authentication-library-common-for-android/tree/dev/common/src/main/java/com/microsoft/identity/common/internal/providers/oauth2

For those who trust a random on GitHub providing them with a modified AAR, I have attached mine below. For those who don’t, just follow the Removing the necessary files from the library steps above.

microsoft-common.aar.zip

Read more comments on GitHub >

github_iconTop Results From Across the Web

PublicClientApplication.acquireToken calls should allow an ...
In our App we are making the acquireToken call from a Fragment. When we do so, we have to pass in the parent...
Read more >
ADAL AcquireToken with ClientCredential fails with ... - MSDN
AcquireToken method with ClientCredential. I am trying to use ... My code works if I use the details of the Azure application that...
Read more >
ADAL.js - acquire token for Graph API resources
To call the Microsoft Graph, we need to get the specific token for this resource. Based on the code you were acquire the...
Read more >
Using OAuth 2.0 for Web Server Applications | YouTube Data ...
This document explains how web server applications use Google API Client Libraries or Google OAuth 2.0 endpoints to implement OAuth 2.0 ...
Read more >
Index (msal 2.2.3 API) - javadoc.io
The audiences that can be used for Authority when making token requests in MSAL. ... Encapsulates the parameters passed to the acquireToken methods...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found