I am calling a protected web api from react SPA web app. Both spa and the web api have been registered with AzureAD and each registered for each other via "Expose API" and "API permissions".
After the client is authenticated then before calling the web api, call to (await this.props.provider.getAccessToken()) is made to get the access token. The auth provider is configured as:
export const authProvider = new MsalAuthProvider(
{
auth: {
authority: "https://login.microsoftonline.com/common",
clientId: "xxxx-xxxx-xxxxx",
postLogoutRedirectUri: window.location.origin,
redirectUri: window.location.origin,
validateAuthority: true,
navigateToLoginRequestUrl: false
},
system: {
logger: logger as any
},
cache: {
cacheLocation: "sessionStorage",
storeAuthStateInCookie: false
}
},
{
scopes: ["openid", "user.read", "api://xxxx-xxxxx-xxxxx/user_impersonation"]
},
{
loginType: LoginType.Redirect,
tokenRefreshUri: window.location.origin + "/auth.html"
}
);
Where the "api://xxxx-xxxxx-xxxxx/user_impersonation" is the web api scope request. Authorization against the web api fails with 401 because when inspected the access token returned is missing the web api scope in the claims.
An AAD access token is only valid for one API, so make sure that when you ask for a token, you only specify the scope for your API. AAD will then give your app a token for your API. It should be okay to specify scopes for more than one API in the authentication request, but when you ask for tokens, specify only scopes for one API.
In the scopes array you have user.read which is for MS Graph API.