2
votes

I'm creating a node web app that needs to integrate with some azure services using Azure REST API. I'm using the node MSAL library for user login and retrieving an access token for making requests to the Azure REST api. I'm able to login a user successfully and retrieve an access token. However, when I try to make a request to Azure's REST api I am receiving a 401 error that says error="invalid_token", error_description="The access token is from wrong audience or resource."

The web app itself is built with Node LTS and React v16.8.6. It has been deployed in Azure and registered with active directory. I'm using MSAL v1.0.1 to login a user and retrieve a token when the user lands on the login page.

login.js

import React, { Component } from 'react';
import * as Msal from 'msal';

let msalConfig = {
  auth: {
    clientId: process.env.REACT_APP_CLIENT_ID,
    authority: `https://login.microsoftonline.com/process.env.REACT_APP_TENANT_ID'`,
    navigateToLoginRequestUrl: false,
    redirect_uri: 'http://localhost:3000/newEntry',
    resource: 'https://management.azure.com/'
  },
  cache: {
    cacheLocation: "localStorage",
    storeAuthStateInCookie: true
  }
};

var msalInstance = new Msal.UserAgentApplication(msalConfig);

var tokenRequest = {
  scopes: ['https://management.azure.com/']
}

class Login extends Component {
  constructor(props) {
    super(props);
    this.state = {
      response: null,
    };
  }

  componentWillMount() {
    // prevent login loop by checking for logged in user and then acquire a token if logged in
    if (!msalInstance.getAccount() && !msalInstance.isCallback(window.location.hash)) {
      this.login();
    } else {
      msalInstance.acquireTokenSilent(tokenRequest)
        .then(res => localStorage.setItem('access_token', res.accessToken))
        .catch(err => console.error(err))
    }
  }

  login = () => {  
    msalInstance.handleRedirectCallback((error, response) => {
      if (error) console.error(error);
      console.log(response);
    })
    msalInstance.loginRedirect(tokenRequest);
  }

  render() {
    return (
      <div>
        <h2>Login</h2>
      </div>
    )
  }
}

export default Login;

I am successfully returning an access token and putting it in local storage.

On a separate page I am retrieving the MSAL access token from local storage and using it to make a request to retrieve all resources associated with my Azure subscription.

  componentWillMount() {
    let token = localStorage.getItem('access_token');
    let url = 'https://management.azure.com/subscriptions/process.env.REACT_APP_SUBSCRIPTION_ID/resource?api-version=2018-02-14'

    fetch(url, {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${token}`
      }
    })
    .then(response => console.log(response))
    .catch(err => console.error(err));
  }

I suspect I'm getting the error because there is some discrepancy between the resource value sent with the login request and the scope value sent with the token request.

I've attempted changing the resource value to 'resource': 'https://management.core.windows.net/' per Azure: The access token has been obtained from wrong audience or resource but that didn't change anything.

I've also attempted various scopes including https://management.azure.com/user_impersonation and https://management.azure.com//user_impersonation following this example Access Token do not include access for API with MSAL

3

3 Answers

0
votes

The get method is default, and the problem might be in 'Authorization': `Bearer ${token}`. Sometimes people use different rules, like 'Authorization': token, or 'Token': `Bearer ${token}`. I see some API using 'S-token': token. try that. I thinkit is because the token did get there.

0
votes

You are using msal, so resource parameter is not needed in your msalConfig. You can remove it.

Change the scopes to scopes: ['https://management.azure.com/.default'].

0
votes

So I ended up switching to the ADAL library to see if I would get the same error and I did. I did however realize the resource request URL wasn't correct. The api-version wasn't an accepted version. Once I switched it to 2018-02-01 the request returned 200.