如何将 azure 广告集成到使用 azure 中的 REST API 的 React Web 应用程序中

IT技术 javascript reactjs azure-active-directory adal adal.js
2021-04-20 18:28:56

我有一个名为 React 的 Web 应用程序,并且我已经为 Web 应用程序本身配置了 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 进行身份验证,然后重定向回来。

但是,我还创建了另一个用于托管 REST API 的 azure webapp,该 REST API 已在 Azure AD 中配置,因此尝试使用其余 API 的用户需要进行身份验证。

现在的问题是:如何设置我的客户端 APP 以使用受 Azure AD 保护的 REST API。?

我找到了这个并寻找我正在寻找的东西,但我不确定如何将它集成到我上面的现有代码中

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/

3个回答

这里的关键是adalApiFetch,定义在adalConfig.js. 如您所见,它是一个简单的adalFetch. 该方法(在 中定义react-adal)接收 ADAL 实例 ( authContext)、资源标识符 ( resourceGuiId)、方法 ( fetch)、 URL ( url) 和对象 ( options)。该方法执行以下操作:

  1. 使用 ADAL 实例 ( authContext) 获取由 标识的资源的访问令牌resourceGuiId
  2. 将此访问令牌添加到对象headers字段options(如果未提供,则创建一个)。
  3. 调用传入的给定“fetch”方法urloptions对象作为参数。

adalApiFetch方法(您已在 中定义adalConfig.js)仅adalFetch使用 中标识的资源进行调用adalConfig.endpoints.api

好的,那么您如何使用所有这些来发出 REST 请求,并在您的 React 应用程序中使用响应?让我们举一个例子。在以下示例中,我们将使用 Microsoft Graph API 作为 Azure AD 保护的 REST API。我们将通过它的友好标识符 URI(“ https://graph.microsoft.com ”)来识别它,但请记住,这也可能是 Guid 应用程序 ID。

adalConfig.js定义了 ADAL 配置,并导出了几个辅助方法:

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

export const adalConfig = {
tenant: '{tenant-id-or-domain-name}',
clientId: '{app-id-of-native-client-app}',
endpoints: {
    api: 'https://graph.microsoft.com' // <-- The Azure AD-protected API
},
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);

index.jsindexApp.js使用runWithAdalfrom 方法包装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;
我无法真正评论我看不到的代码。你能分享错误的代码吗?
2021-05-22 18:28:56
这就是问题所在,非常感谢,经过 1 周的努力,终于可以正常工作了。
2021-05-26 18:28:56
是的,这也是我的想法,我只是将格式化程序更改为 json 而不是 xml,测试 react 应用程序
2021-05-30 18:28:56
我收到此错误 Unhandled Rejection (SyntaxError): Unexpected token < in JSON at position 0 (anonymous function) src/containers/testREST.js:28
2021-06-04 18:28:56
哦,实际上,我可以看到足够多的错误来猜测问题所在。您的 API ( /values) 是否返回 JSON?response.json()假设它是,并试图反序列化它,但找到一个<字符。也许/values是返回 HTML 或 XML?
2021-06-14 18:28:56

我仍然遇到上面给出的配置问题。我在上面添加了更多配置并且它起作用了。希望能帮助到你。

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

export const adalConfig = {
tenant: '{tenant-id-or-domain-name}',
clientId: '{app-id-of-native-client-app}',
endpoints: {
    api: 'https://graph.microsoft.com'
},
cacheLocation: 'localStorage',
extraQueryParameter: 'prompt=admin_consent'
};

export const authContext = new AuthenticationContext(adalConfig);

Phillipe 的回应让我走上了正确的道路,但我仍然遇到了我的令牌不被接受的问题。

aadsTS700051:应用程序未启用 response_type 'token'。

要解决此问题,我需要进入我的应用程序的注册 > 清单并将 oauth2AllowImplicitFlow 设置为 true:

    "oauth2AllowImplicitFlow": true,

注销您的 Azure 帐户,重新登录,您应该会收到用户的详细信息。