使用adalFetch从API调用返回的“ AADSTS500011”错误消息

时间:2019-06-05 15:48:11

标签: reactjs rest azure-active-directory adal

我有一个在Azure Active Directory中注册的React应用程序。在“ API权限”部分中,我添加了访问我尝试访问的API的权限。

当用户进入应用程序时,我正在使用react-adal包来处理访问令牌的登录和存储。我的理解是,API的访问令牌已在此时创建,而adalFetch在调用API时负责物流。

API的响应是一个错误对象(我替换了实际的id;是的,它们完全匹配并且在AAD中是正确的):

{
message: "AADSTS500011: The resource principal named https://EMCloudAD.onmicrosoft.com/APP_ID/access_as_user was not found in the tenant named TENANT. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant."
msg: "invalid_resource"
}

我搜寻了很多内容,以找到解决方案,以解决此问题。该API上有文档,但没有指定资源或超出各种端点(即http://thing-api.azurewebsites.net/api/endpointGoesHere

)的任何内容

API页面指出:

要使用该API,应用程序需要使用AzureAD(AAD)实现现代身份验证(OIDC),然后向AAD请求该API的令牌。

Azure中的应用程序ID为https://EMCloudAD.onmicrosoft.com/APP_ID,并且需要“ access_as_user”范围。

adalConfig.js

import { AuthenticationContext, adalFetch, withAdalLogin } from 'react-adal';

export const adalConfig = {
  clientId: CLIENT_ID,
  tenant: TENANT,
  endpoints: {
    thingApi: 'https://EMCloudAD.onmicrosoft.com/APP_ID/access_as_user',
    graphApi: 'https://graph.microsoft.com',
  },
  cacheLocation: 'localStorage',
};

export const authContext = new AuthenticationContext(adalConfig);

export const adalApiFetch = (fetch, url, options) =>
  adalFetch(authContext, adalConfig.endpoints.thingApi, fetch, url, options);

export const adalGraphFetch = (fetch, url, options) =>
  adalFetch(authContext, adalConfig.endpoints.graphApi, fetch, url, options);

API调用的功能。在componentDidMount中执行。

TrainLanding.jsx

//Returns error
fetchData = () => {
    adalApiFetch(fetch, 'http://thing-api.azurewebsites.net/api/EventGet', {})
      .then((response) => {
        response.json()
          .then((responseJson) => {
            this.setState({ apiResponse: JSON.stringify(responseJson, null, 2) }, () => {
              console.log(this.state.apiResponse)
            })
          });
      })
      .catch((error) => {
        console.error(error);
      })
  }

//works perfectly fine
fetchGraph = () => {
    adalGraphFetch(fetch, 'https://graph.microsoft.com/v1.0/me', {})
      .then((response) => {
        response.json()
          .then((responseJson) => {
            this.setState({ apiResponse: JSON.stringify(responseJson, null, 2) }, () => {
              console.log(this.state.apiResponse)
            })
          });
      })
      .catch((error) => {
        console.error(error);
      })
  }

我以完全相同的方式设置了一个图形API调用来测试该方法,并且效果很好。所以我知道adal的设置正确,我只是不了解错误以及我要去哪里。我的谷歌搜索没有产生任何有用的结果。

1 个答案:

答案 0 :(得分:0)

好吧,如果您在这里,请注意以下几点:

  1. 请勿使用ADAL。使用MSAL。 ADAL为v1,无法正常工作。请阅读此处的示例:https://www.npmjs.com/package/react-aad-msal
  2. 您应该将整个应用程序包装在从上面获得的组件中。我将在下面显示我的操作方式。
  3. 您必须已经在Azure Active Directory中注册了您的应用程序,已配置的重定向URL并包括API权限。

index.js

import { AzureAD, MsalAuthProviderFactory, LoginType } from 'react-aad-msal';
import { msalConfig, authParams } from './msalConfig';

class Index extends Component {
  state = {
    userInfo: null,
  }

  userJustLoggedIn = (accInfo) => {
    this.setState({
      userInfo: accInfo
    })
  }

  render() {
    return(
      <AzureAD
      provider={
        new MsalAuthProviderFactory(msalConfig, authParams, LoginType.Redirect)
      }
      forceLogin={true}
      accountInfoCallback={this.userJustLoggedIn}
        >
        <HashRouter>
          <App userInfo={this.state.userInfo}/>
        </HashRouter>
      </AzureAD>
    );
  }
}


  ReactDOM.render(
    <Index/>, document.getElementById('root')
  );

如果您使用的是最新版本的Create React App,则索引可能不会如此。我出于几个原因将Index转换为组件。首先,对我而言,身份验证循环在重定向时卡住了1次刷新。其次,这样我就可以将已登录用户的信息存储为状态,使用setState更新(这将强制另一个渲染),然后将其作为道具传递给我的应用程序的其余部分。

msalConfig.js

export const msalConfig = {
  auth: {
    authority: process.env.REACT_APP_AUTHORITY, //this should be "https://login.microsoftonline.com/<your-tenant-id>"
    clientId: process.env.REACT_APP_CLIENT_ID, //just "<your-client-id>"
    redirectUri: process.env.REACT_APP_REDIRECT //"<url of your app or localhost port you dev on>"
  },
  cache: {
    cacheLocation: "localStorage",
    storeAuthStateInCookie: true
  }
};

export const authParams = {
//can be whatever api scopes you need here **as long as they are from the same API address**
  scopes: [
    'https://graph.microsoft.com/User.ReadBasic.All',
    'https://graph.microsoft.com/email',
    'https://graph.microsoft.com/profile',
    'https://graph.microsoft.com/User.Read'
  ],
  extraScopesToConsent: [
    //any non Microsoft Graph API scopes go here for this example
    'any extra strings of APIs to consent to'
  ]
}

在此处阅读上述环境文件和变量:https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables#what-other-env-files-can-be-used

我有一个.env.development和.env.production,每个都有正确的重定向URL。


对用户进行身份验证之后,就可以访问API。

您需要在每次API调用之前静默获取令牌,然后在请求中使用该令牌。对我来说看起来像这样:

const authProvider = new MsalAuthProviderFactory(msalConfig, authParams);
    console.log(authProvider)
    authProvider.getAuthProvider().UserAgentApplication.acquireTokenSilent(authParams)
    .then((res) => {
      axios({
        headers: {
          'Authorization': 'Bearer ' + res.accessToken
        },
        method: 'GET',
        url: "api address"
      })
      .then((response) => {
        //do stuff with response
        console.log(response)
      })
      .catch((error) => {
        console.log('axios fail: ' + error)
      })
    })
    .catch((error) => {
      console.log('token fail: ' + error)
    })

我将其放入函数中,并在componentDidMount期间调用。

如有任何更改,我将进行更新。我希望这对某人有帮助。