Как интегрировать azure ad в веб-приложение react, которое также использует REST API в azure

у меня есть одно веб-приложение React, и я уже настроил проверку подлинности Azure AD для самого веб-приложения. Его 100% клиентское приложение сайта, без серверных компонентов.

я использовал этот компонент: https://github.com/salvoravida/react-adal

мой код выглядит следующим образом: adalconfig.js

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

export const adalConfig = {
  tenant: 'mytenantguid',
  clientId: 'myappguid',
  endpoints: {
    api: '14d71d65-f596-4eae-be30-27f079bf8d4b',
  },
  cacheLocation: 'localStorage',
};

export const authContext = new AuthenticationContext(adalConfig);

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

export const withAdalLoginApi = withAdalLogin(authContext, adalConfig.endpoints.api);
.js
import React from 'react';
import ReactDOM from 'react-dom';
import DashApp from './dashApp';
import registerServiceWorker from './registerServiceWorker';
import 'antd/dist/antd.css';

import { runWithAdal } from 'react-adal';
import { authContext } from './adalConfig';

const DO_NOT_LOGIN = false;

runWithAdal(authContext, () => {

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

  // Hot Module Replacement API
  if (module.hot) {
    module.hot.accept('./dashApp.js', () => {
      const NextApp = require('./dashApp').default;
      ReactDOM.render(<NextApp />, document.getElementById('root'));
    });
  }

},DO_NOT_LOGIN);


registerServiceWorker();

dashapp.js

import React from "react";
import { Provider } from "react-redux";
import { store, history } from "./redux/store";
import PublicRoutes from "./router";
import { ThemeProvider } from "styled-components";
import { LocaleProvider } from "antd";
import { IntlProvider } from "react-intl";
import themes from "./settings/themes";
import AppLocale from "./languageProvider";
import config, {
  getCurrentLanguage
} from "./containers/LanguageSwitcher/config";
import { themeConfig } from "./settings";
import DashAppHolder from "./dashAppStyle";
import Boot from "./redux/boot";

const currentAppLocale =
  AppLocale[getCurrentLanguage(config.defaultLanguage || "english").locale];


const DashApp = () => (
  <LocaleProvider locale={currentAppLocale.antd}>
    <IntlProvider
      locale={currentAppLocale.locale}
      messages={currentAppLocale.messages}
    >
      <ThemeProvider theme={themes[themeConfig.theme]}>
        <DashAppHolder>
          <Provider store={store}>
            <PublicRoutes history={history} />
          </Provider>
        </DashAppHolder>
      </ThemeProvider>
    </IntlProvider>
  </LocaleProvider>
);
Boot()
  .then(() => DashApp())
  .catch(error => console.error(error));

export default DashApp;
export { AppLocale };

до этого момента все работает нормально, когда пользователь не аутентифицировано его перенаправлено на login.live.com для аутентификации, а затем перенаправляется обратно.

однако я также создал еще один azure webapp для размещения REST API, который REST API уже настроен в Azure AD, так что пользователи, которые пытаются использовать rest, должны будут пройти проверку подлинности.

Теперь возникает вопрос: Как настроить приложение на стороне клиента для использования REST API, защищенного Azure AD.?

Я нашел это и выглядит то, что я ищу, но я не уверен, как интегрировать это в мой существующий код выше

https://github.com/AzureAD/azure-activedirectory-library-for-js/issues/481

обновление: Для потенциальных читателей

этот ответ плюс инструкции по этому url-адресу для настройки регистрации приложений помогли мне решить проблему: https://blog.ithinksharepoint.com/2016/05/16/dev-diary-s01e06-azure-mvc-web-api-angular-and-adal-js-and-401s/

1 ответов


ключ здесь adalApiFetch, определена в adalConfig.js. Как вы можете видеть, это простая обертка вокруг adalFetch. Этот метод (определяется в react-adal) получает экземпляр ADAL (authContext), идентификатор ресурса (resourceGuiId), метод (fetch), URL (url) и объекта (options). Метод делает следующее:

  1. используйте экземпляр ADAL (authContext) для получения маркера доступа к ресурсу, определенному resourceGuiId.
  2. добавить этот доступ маркер .js обертывания indexApp.js С runWithAdal способ от react-adal, который гарантирует, что пользователь подписан с Azure AD перед загрузкой indexApp.js:
    import { runWithAdal } from 'react-adal';
    import { authContext } from './adalConfig';
    
    const DO_NOT_LOGIN = false;
    
    runWithAdal(authContext, () => {
    
    // eslint-disable-next-line
    require('./indexApp.js');
    
    },DO_NOT_LOGIN);
    

    indexApp.js просто загружает и отображает экземпляр App, ничего особенного здесь:

    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
    import registerServiceWorker from './registerServiceWorker';
    
    ReactDOM.render(<App />, document.getElementById('root'));
    registerServiceWorker();
    

    App.js - это простой компонент, где происходит волшебство:

    • мы определяем state значение. В этом случае он называется apiResponse поскольку мы просто показываем необработанный ответ API, но, конечно, вы можете назвать это государство, что вы хотели (или несколько значений).
    • во время componentDidMount (который запускается после того, как элемент доступен в DOM), мы делаем вызов adalApiFetch. Проходим в fetch (от Fetch API как fetch параметр и конечная точка для запроса REST, который мы хотим сделать (/me конечная точка в Microsoft Graph, в этом случае):
    • на render метод, мы просто выводим это значение в тег <pre> элемент.
    import React, { Component } from 'react';
    import { adalApiFetch } from './adalConfig';
    
    class App extends Component {
    
      state = {
        apiResponse: ''
      };
    
      componentDidMount() {
    
        // We're using Fetch as the method to be called, and the /me endpoint 
        // from Microsoft Graph as the REST API request to make.
        adalApiFetch(fetch, 'https://graph.microsoft.com/v1.0/me', {})
          .then((response) => {
    
            // This is where you deal with your API response. In this case, we            
            // interpret the response as JSON, and then call `setState` with the
            // pretty-printed JSON-stringified object.
            response.json()
              .then((responseJson) => {
                this.setState({ apiResponse: JSON.stringify(responseJson, null, 2) })
              });
          })
          .catch((error) => {
    
            // Don't forget to handle errors!
            console.error(error);
          })
      }
    
      render() {
        return (
          <div>
            <p>API response:</p>
            <pre>{ this.state.apiResponse }</pre>
          </div>
        );
      }
    }
    
    export default App;