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.

AADSTS90009 (I think) due to no scope form parameter on refresh

See original GitHub issue

Core Library

MSAL.js v2 (@azure/msal-browser)

Core Library Version

2.28.1

Wrapper Library

MSAL React (@azure/msal-react)

Wrapper Library Version

1.4.0

Public or Confidential Client?

Public

Description

When the library makes a refresh request (using aquireTokenSilent) I get a 400 error back from the /token endpoint. Initially obtaining the token works fine with these code samples, and when I refresh local storage I can get a token again.

When the library makes a refresh request (e.g. when I invoke getServiceToken [see code samples] after initial token has expired) I can see following network request in dev tools:

POST https://login.microsoftonline.com/bbbbbbbb-663d-4ae5-9253-cb7d2aac234e/oauth2/v2.0/token Payload (form data): client_id: aaaaaaaa-663d-4ae5-9253-cb7d2aac234e scope: openid profile offline_access grant_type: refresh_token client_info: 1 refresh_token: 0.ABC…

Which gives the following response 400 { "error" : "invalid_request", "error_description": "AADSTS90009: Application 'aaaaaaaa-663d-4ae5-9253-cb7d2aac234e' (aaaaaaaa-663d-4ae5-9253-cb7d2aac234e) is requesting a token for itself. This scenario is supported only if resource is specified using the GUID based App Identifier. ..." ... }

Now if I make the same request using postman, but replace the scope form parameter with

scope: https://back-end-service.com/FRONT-END

I get a 200 OK response containing a token & new refresh token as expected.

When getServiceToken is invoked, I can not only see the POST returning a 400 error, but there is an uncaught console error. If I add an ErrorBoundary type component, it catches the error… but the try… catch inside getServiceToken never catches an error.

I suppose my question are is it possible to

  • Stop this 400 error from happening by passing the ‘correct’ scope to the resfresh_token request
  • Supressing the error somehow? Or is the error a symptom and not a root cause?

N.b. the initial POST looks like this: POST https://login.microsoftonline.com/bbbbbbbb-663d-4ae5-9253-cb7d2aac234e/oauth/v2.0/token?resource=aaaaaaaa-663d-4ae5-9253-cb7d2aac234e&scope=https://back-end-service.com/FRONT-END

Which returns 200OK and a token.

MSAL Configuration

// n.b. this is hand-typed as I can't copy + paste off corporate network
{
    auth: {
        // Not the real clientId
        clientId: "aaaaaaaa-663d-4ae5-9253-cb7d2aac234e",
        // not real tenantId appended to the end
        authority: "https://login.microsoftonline.com/bbbbbbbb-663d-4ae5-9253-cb7d2aac234e",
        redirectUri: window.location.origin
    },
    cache: "localStorage"

}

Relevant Code Snippets

// msalConfig.js:

// exported for use in react app in MsalProvider
// _.once ensures the function only runs once
export const getMsalInstance = _.once(() => {
    const msalInstance = new PublicClientApplication(msalConfig) //see MSAL Configuration section
    
    msalIntance.addEventCallback(event => {
        if(event.eventType === EventType.LOGIN_SUCCESS)
            msalInstance.setActiveACcount(event.payload.account)
    })
})

// n.b. httpRequestService.js is used OUTSIDE of hooks, so never uses @azure/msal-react
export async function getServiceToken() {
    const request = {
        scopes: ["https://back-end-service.com/FRONT-END"],
        account: getMsalInstance().getActiveAccount()
    }

    try {
        console.log(reqeust) //can always see initialized account
        const result = await getMsalInstance().aquireTokenSilent(request)
        console.log(result) // can always see a result, even with a new token (e.g. exp is set in the future here)
        return result.accessToken
    } catch (err) {
        // this catch handler never gets hit!!!
    }
}

// httpRequestService.js:
export async function(url) {
    let authHeader = "Bearer " + (await getServiceToken())
    console.log(authHeader) // I can even see the authHeader here with the new token!!
    return axios.get(url, { headers: { Authorization: authHeader } })
}

Identity Provider

Azure AD / MSA

Source

External (Customer)

Issue Analytics

  • State:open
  • Created a year ago
  • Comments:14 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
nedgradycommented, Oct 8, 2022

@nedgrady Apologies for the delay, can you resend the logs to my email? I could not find them and not sure if I ever received them.

No probs no rush, not like our current auth solution is going to stop working. Have resent the email from my gmail account

0reactions
hada79commented, Nov 2, 2022

@sameerag The refresh token acquisition never succeeds.

Read more comments on GitHub >

github_iconTop Results From Across the Web

AADSTS90009 : Issue in connecting Azure Active Directory
This error is saying that the field you provided in the resource parameter is requesting tokens for itself. Alternatively, ...
Read more >
Azure AD authentication & authorization error codes
The refresh token isn't valid. Error may be due to the following reasons: Token binding header is empty; Token binding hash does not...
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