AzureAD / microsoft-authentication-library-for-android

Microsoft Authentication Library (MSAL) for Android
http://aka.ms/aadv2
MIT License
214 stars 125 forks source link

acquireTokenSilent fails to return or throw an exception. (when used in Coil's ImageRequest). #1898

Open Innova133 opened 1 year ago

Innova133 commented 1 year ago

Describe the bug I need to load an image that requires a Bearer token as a request header. When I try to retrieve the token from MSAL, the call never returns, and does not throw an exception either. This forces me to cache the token in my app, and used a cached, possibly expired token when I request the image.

Smartphone (please complete the following information):

I don't think any of these parameters matter, but I tested on:

Stacktrace Application Not Responding error happens.

To Reproduce Steps to reproduce the behavior:

Have an AsyncImage in your Jetpack Compose layout:

                AsyncImage(
                    model = ImageRequest.Builder(LocalContext.current)
                        .data(imageUrl)
                        .crossfade(true)
                        .setHeader("authorization", "Bearer ${MSALAuth.getToken(LocalContext.current)}")    //If you delete this line, the call will complete successfully.
                        .build(),
                    contentDescription = "Test",
                    contentScale = ContentScale.Crop,
                    modifier = Modifier.clip(CircleShape)
                )

The MSALAuth.getToken() method is:

fun getToken(context: Context): String {
            try {
                println("Getting Token from MSAL")
                if (account == null) {
                    singleAccountApp =
                        PublicClientApplication.createSingleAccountPublicClientApplication(
                            context,
                            R.raw.msal
                        )
                    val acctResult = singleAccountApp.currentAccount
                    account = acctResult?.currentAccount
                }
                println("About to get token silently.") //. This is the last line that prints out, then application hangs here.
                val authResult = singleAccountApp.acquireTokenSilent(
                    getTokenParams(TOKEN_SCOPE)
                )!!
                println("MSAL Token retrieved.")
                return authResult.accessToken
            } catch (exception: Exception) {
                println(exception.localizedMessage)
                exception.printStackTrace()
                return ""
            }
        }

If related to user experience, use the format:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

If related to development, please provide relevant configuration details necessary to understand your problem including any relevant traces, logs, or otherwise.

Expected behavior A token should be returned, or exception thrown if interactive auth is required.

Actual Behavior The application will get a not responding error.

Screenshots If applicable, add screenshots to help explain your problem.

Additional context

I have created a simple project that can reproduce this (with proper Azure setup), and attached. In order to finish configuring, add the correct values in:

  1. app/src/main/res/raw/msal.json (client_id, redirect_uri, tenant_id)
  2. app/src/main/AndroidManifest.xml (android:host, android:path in the BrowserTabActivity)
  3. app/src/main/authentication/MSALAuth.kt (Token Scope) SilentTokenHang.zip

Please note: Do not include sensitive information like PII, OII, credentials, secrets, and tokens.

For privacy/security issues please see instructions here

sam-innes commented 11 months ago

@Innova133 I've been having this issue too and I've found that running the method in a new thread resolved it - could you try and make the request to getToken in a new thread and see if that fixed the issue?

For @negoe this appears to be an issue either in the way that the method is called in a way that's unexpected (i.e. from the main thread, in which case it's probably worth a documentation update) or a threading issue where the PublicClientApplication is using a promise that's blocking the main thread (line 1816 will hang forever if run in the main thread - gets stuck at the red line): image