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

Posted

技术标签:

【中文标题】如何将 azure 广告集成到在 azure 中也使用 REST API 的 React Web 应用程序【英文标题】:How to integrate azure ad into a react web app that consumes a REST API in azure too 【发布时间】:2018-10-22 15:40:05 【问题描述】:

我有一个 Web 应用程序,它是 React,并且我已经为 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);

index.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/

【问题讨论】:

检查这可能会帮助你azure.microsoft.com/en-in/resources/videos/… 【参考方案1】:

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

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

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

好的,那么您如何使用所有这些来发出 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.js 使用来自react-adalrunWithAdal 方法包装indexApp.js,确保用户在加载indexApp.js 之前使用Azure AD 进行签名:

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 请求的端点(在本例中为Microsoft Graph 中的/me 端点): 在render 方法中,我们只是在&lt;pre&gt; 元素中显示此状态值。
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;

【讨论】:

我收到此错误 Unhandled Rejection (SyntaxError): Unexpected token 我无法评论我看不到的代码。可以分享一下出错的代码吗? 哦,实际上,我可以看到足够多的错误来猜测问题所在。您的 API (/values) 是否返回 JSON? response.json() 假设它是,并试图反序列化它,但找到一个 &lt; 字符。也许/values 正在返回 html 或 XML? 是的,这也是我的想法,我只是将格式化程序更改为 json 而不是 xml,测试 react 应用程序 这是问题所在,非常感谢,经过 1 周的努力,终于可以正常工作了。【参考方案2】:

上面给出的配置仍然存在问题。我在上面添加了更多配置并且它有效。希望对您有所帮助。

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);

【讨论】:

【参考方案3】:

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

aadsTS700051:没有为应用启用 response_type 'token'。

要解决这个问题,我需要进入我的应用注册 > manifest 并将 oauth2AllowImplicitFlow 设置为 true:

    "oauth2AllowImplicitFlow": true,

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

【讨论】:

以上是关于如何将 azure 广告集成到在 azure 中也使用 REST API 的 React Web 应用程序的主要内容,如果未能解决你的问题,请参考以下文章

如何将标签添加到在 Microsoft Azure 中创建的文件存储、队列存储和表存储

如何将 Azure Policy 与 Azure DevOps 集成?

正在修改或添加应用程序设置到在 linux 容器上运行的 azure 应用程序服务将回收站点

如何在 Azure 广告 B2C 上使用自定义角色?

如何将 Pycharm 和 git 与 azure 机器学习服务(工作区)集成

如何将 sonarqube 集成到 azure CI