web
You’re offline. This is a read only version of the page.
close
Skip to main content

Announcements

News and Announcements icon
Community site session details

Community site session details

Session Id :
Power Platform Community / Forums / Power Pages / Access token generated...
Power Pages
Answered

Access token generated using MSAL in Power Pages SPA does not work

(0) ShareShare
ReportReport
Posted on by 10
I have an SPA hosted on Power Pages in React + TypeScript. I have used MSAL.js to authenticate users with Entra ID, and I am using `acquireTokenSilent()` of MSAL.js to get an access token to make external API calls. I need to make Graph API calls as well as API calls to an Azure Function.

I have granted admin consent permissions to my app registration for MS Graph as well as the custom Azure Function scope. And I have outlined them in my React code in an array of scopes to pass as parameter for `acquireTokenSilent()`.

The issue is, the token generated allows me to make API calls to MS Graph, but it does not let me call the Azure Function. It keeps saying invalid JWT token. I know the custom Azure Function scope works because I generated a token using that scope in Postman and it worked. But for some reason, it does not work when I generate the token in my SPA.
Categories:
I have the same question (0)
  • Verified answer
    DP_Prabh Profile Picture
    315 on at

    First, do not mix scopes from different APIs in a single request. MSAL issues an access token for only one resource at a time, so combining scopes results in a token that works for one API but causes an “invalid JWT” error for others. To verify you can also check by decoding the JWT token "aud" will give you message for Azure function that might audience mismatch something like that error if you decode the JWT token. 
    To fix this, request separate tokens for each API, with scopes specific to that resource.

    //MS graph token
    await acquireTokenSilent({ scopes: ["", ""] });
     
    //azure token call
    await acquireTokenSilent({scopes: ["api://"] });
     
    //if you have additional APIs, request tokens for them separately as well.
     
    So, this will make one token per resource, and which is the right way when using MSAL or ADAL. 
    I hope this works for you!
  • Verified answer
    deepakmehta13a Profile Picture
    200 on at
    Hi @CU19031015-0,
     

    The behavior comes from how scopes and resources work in MSAL and the Microsoft identity platform.

     

    acquireTokenSilent can only return a token for one resource (audience) at a time. When multiple scopes for different resources are passed in a single call, the token is issued only for the first resource in the scopes list. That token will work for Microsoft Graph if the first scope is a Graph scope (for example User.Read), but it will be invalid for the Azure Function, which expects a token whose aud matches the Function’s app ID URI.

     

    To call both Microsoft Graph and the Azure Function from the SPA, request separate tokens, one per resource.

    1. Request a token for Microsoft Graph only:

    TypeScript

     

    const graphTokenResponse = await msalInstance.acquireTokenSilent({
      scopes: ["User.Read", "Mail.Read"] // Graph-only scopes});
    const graphAccessToken = graphTokenResponse.accessToken;
    // Use graphAccessToken in Authorization: Bearer when calling Graph
    1. Request a token for the Azure Function only:

    Use the app ID URI and scope name configured on the Azure Function’s app registration, for example:

    TypeScript

     

    const functionTokenResponse = await msalInstance.acquireTokenSilent({
      scopes: ["api://<your-function-app-client-id>/your.scope"]
    });
    const functionAccessToken = functionTokenResponse.accessToken;
    // Use functionAccessToken in Authorization: Bearer when calling the Function
    1. Do not mix resources in a single scopes array:

    TypeScript

     

    // ❌ Wrong: mixed resourcesawait msalInstance.acquireTokenSilent({
      scopes: [    "User.Read",                               // Microsoft Graph"api://<your-function-app-client-id>/your.scope" // Azure Function
      ]
    });
    // This returns a token only for the first resource (Graph),// so the Function sees an invalid JWT (wrong audience).
    1. Verify the scope format for the Azure Function:

    The scope must match the Function’s API configuration, typically:

    • api://<your-function-app-client-id>/<scopeName>

    If the Function is fronted by another service or expects a different audience format, use the exact app ID URI and scope format that worked in Postman.

    1. Use the token correctly when calling the Function:

    TypeScript

     

    const headers = new Headers();
    headers.append("Authorization", `Bearer ${functionAccessToken}`);
    const response = await fetch("https://<your-function-app>.azurewebsites.net/api/endpoint", {
      method: "GET",
      headers
    });
     

    If the Function still reports an invalid JWT, inspect the token’s aud claim and compare it to what the Function expects. If the aud does not match, adjust the scope value (for example, with or without scheme/host) to align with the Function’s configuration.

    Hope this helps.

    If this helps resolve your issue, please consider marking the response as Verified so it can help others facing a similar scenario. 

    If you found this helpful, you can also click “Yes” on “Was this reply helpful?” or give it a Like. 

     
  • rezarizvii Profile Picture
    10 on at
    Thank you @deepakmehta13a and @DP_Prabh. I was trying to get a single token to use with both Graph API and Azure Function API. That fixes it. Thank you again.

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Introducing the 2026 Season 1 community Super Users

Congratulations to our 2026 Super Users!

Kudos to our 2025 Community Spotlight Honorees

Congratulations to our 2025 community superstars!

Leaderboard > Power Pages

#1
Hammed Profile Picture

Hammed 22

#2
Lucas001 Profile Picture

Lucas001 21 Super User 2026 Season 1

#2
DP_Prabh Profile Picture

DP_Prabh 21

Last 30 days Overall leaderboard