Unable to authenticate against azure fhir api from msal-react

222 Views Asked by At

I am trying to access the azure api for fhir from a react application. I am using msal-react 2.x. I get a 401 error when I try to access the "/Patient" rest endpoint. I have created a Azure AD application (SPA). The app has FHIR Data Reader access to the fhir api service. Api permissions are Azure Healthcare Apis (patient.all.read, user_impersonation). Graph (User.Read, profile, openid).
CORS is enabled on the FHIR api.

React code. index.js

      <MsalProvider instance={msalInstance}>
        <App />
      </MsalProvider>

App.js

    <MsalAuthenticationTemplate
      interactionType={InteractionType.Popup}
      authenticationRequest={authRequest}
      errorComponent={ErrorComponent}
      loadingComponent={LoadingComponent}
    >
      <App />
    </MsalAuthenticationTemplate>

msalConfig.js

const msalConfig = {
    auth: {
        clientId: "{clientid}",
        authority: 'https://login.microsoftonline.com/{tenantid}',
    },
};

export const msalInstance = new PublicClientApplication(msalConfig);

export const authRequest = {
    scopes: [
        "https://{myserver}.azurehealthcareapis.com/.default"
    ]
};

export const acquireAccessToken = async () => {
    const activeAccount = msalInstance.getActiveAccount(); 
    const accounts = msalInstance.getAllAccounts();

    const request = {
        scopes: [
            "https://{myserver}.azurehealthcareapis.com/.default"
        ],
        account: activeAccount || accounts[0]
    };

    const authResult = await msalInstance.acquireTokenSilent(request);

    return authResult.accessToken    
};

I am probably missing something with the scopes.

Decoded token attachedenter image description here

1

There are 1 best solutions below

7
Sridevi On

I registered one Azure AD application and added API permissions as below:

enter image description here

When I tried to access the "/Patient" rest endpoint with token generated with User.Read scope, I too got 401 Unauthorized error as below:

GET https://demofhir20.azurehealthcareapis.com/Patient

Response:

enter image description here

The error 401 Unauthorized usually occurs if you make calls to the Azure Healthcare API with invalid audience(Microsoft Graph).

To confirm that, you can decode the access token by pasting it in jwt.ms and check aud & scp claims:

enter image description here

To resolve the error, make sure to pass only Azure Healthcare API in scope parameter while generating access token.

In my case, I generated access token using authorization code flow via Postman with below parameters:

POST https://login.microsoftonline.com/<tenantID>/oauth2/v2.0/token
grant_type:authorization_code
client_id: <appID>
scope: https://demofhir20.azurehealthcareapis.com/.default
code:code
redirect_uri:https://jwt.ms

Response:

enter image description here

To check aud and scp claims, you can decode above token by pasting it in jwt.ms website:

enter image description here

When I used this token to access the "/Patient" rest endpoint, I got response successfully as below:

GET https://demofhir20.azurehealthcareapis.com/Patient

Response:

enter image description here

In your code, remove all Microsoft Graph permissions like User.Read, openid, profile from scope parameter and pass only Azure Healthcare API scope like this:

const msalConfig = {
    auth: {
        clientId: "{clientid}",
        authority: 'https://login.microsoftonline.com/{tenantid}',
    },
};

export const msalInstance = new PublicClientApplication(msalConfig);

export const authRequest = {
    scopes: [
        "https://{your_fhir}.azurehealthcareapis.com/.default"
    ]
};

export const acquireAccessToken = async () => {
    const activeAccount = msalInstance.getActiveAccount(); 
    const accounts = msalInstance.getAllAccounts();

    const request = {
        scopes: [
            "https://{your_fhir}.azurehealthcareapis.com/user_impersonation",
            "https://{your_fhir}.azurehealthcareapis.com/patient.all.read",
        ],
        account: activeAccount || accounts[0]
    };

    const authResult = await msalInstance.acquireTokenSilent(request);

    return authResult.accessToken    
};

If you are generating access token by authenticating as user, make sure to assign FHIR Data Reader role to user account under FHIR API service like this:

enter image description here