Сообщение об ошибке «AADSTS500011» возвращается из вызова API с использованием adalFetch - PullRequest
1 голос
/ 05 июня 2019

У меня есть приложение React, зарегистрированное в Azure Active Directory. В разделе Разрешения API я добавил разрешения для доступа к API, к которому я пытаюсь получить доступ.

Я использую пакет Reaction-Adal для обработки входа и хранения токенов доступа, когда пользователь входит в приложение. Насколько я понимаю, на этом этапе создается токен доступа для API, и adalFetch обрабатывает логистику во время вызова API.

Ответ от API - это объект ошибки (я заменил действительные идентификаторы; да, они точно совпадают и верны в 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, приложения должны реализовать современную аутентификацию (OIDC) с использованием AzureAD (AAD), а затем запросить токен у AAD для API.

Идентификатор приложения в Azure - 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 API для тестирования метода, и он отлично работает. Так что я знаю, что adal настроен правильно, я просто не понимаю, в чем ошибка и где я ошибаюсь. Мой поиск в Google не дал никаких полезных результатов.

1 Ответ

0 голосов
/ 11 июня 2019

Хорошо, поэтому, если вы здесь, обратите внимание на некоторые вещи:

  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.Я преобразовал Индекс в компонент по нескольким причинам.Во-первых, цикл аутентификации для меня застрял 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'
  ]
}

Прочитайте приведенные выше env-файлы и переменные здесь: 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.

Я обновлю, если что-то изменится.Надеюсь, это кому-нибудь поможет.

...