Search code examples
reactjsoauth-2.0azure-ad-msalmicrosoft-identity-platform

Get access tokens with react-aad-msal for two different resources and scopes


Developed one React app which needs to call two different APIs with access tokens. The application's code uses for authentication the react-aad-msal library. Originally the application has built to call only one API where I have requested the necessary access token which works like charm.

As per Microsoft documentation about using permissions which states:

An access token can be used only for a single resource, but encoded inside the access token is every permission that your app has been granted for that resource.

Based on that I need to request two different access tokens because the resources are different, that's clear.

Working solution with only one resource and scope:

Creating the necessary provider for <AzureAD> wrapper:

const config = {
   auth: {
      authority: process.env.REACT_APP_AUTH_AUTHORITY,
      clientId: process.env.REACT_APP_AUTH_CLIENT_ID,
      redirectUri: process.env.REACT_APP_AUTH_REDIRECT_URI
   },
   cache: {
      cacheLocation: 'localStorage',
      storeAuthStateInCookie: true
   }
};

const authenticationParameters = {
   scopes: ['https://<our-api-name>.azurewebsites.net/user_impersonation'],
};

// saved to AuthenticationService.provider - logic removed
new MsalAuthProvider(config, authenticationParameters, LoginType.Redirect);

Then passing it to <AzureAD> wrapper:

<AzureAD provider={AuthenticationService.provider}
         forceLogin={true}>

No issues here.

Questions:

So I am a bit confused how should I handle the scenario if I need two access tokens from different resources and scopes.

Once I try to add to scopes array the other resource and scope as the following:

const authenticationParameters = {
    scopes: [
       'https://<our-app-name>.azurewebsites.net/user_impersonation',
       'https://<tenant-name>.onmicrosoft.com/<api-guid>/access_as_user'
    ],
};

It gives obviously the following error message:

AADSTS28000: Provided value for the input parameter scope is not valid because it contains more than one resource.

Interested in the following:

  1. How should I get the other access token properly to send to the other API?
  2. Shouldn't the user will be redirected two times to login page?
  3. Can the situation be handled in one request somehow?

Any clarification or idea is appreciated, thank you!


Solution

  • As an aside, an architecture where there are 2 levels of API is often the preferred option, though of course this is likely to be out of scope for your immediate problem:

    • An entry point API is focused on serving your React app and similar consumers - this might be branded the User Experience API
    • Entry point APIs call core services to do the real work - these might be the Products, Users, Stock APIs

    In this setup each UI only ever needs to call a Single API and the OAuth work related to getting data from multiple sources is simpler