如何将 azure 广告集成到也在 azure 中使用 REST API 的 React Web 应用程序中
How to integrate azure ad into a react web app that consumes a REST API in azure too
我有一个 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);
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 中配置,因此尝试使用其余部分的用户将需要进行身份验证.
现在的问题是:如何设置我的客户端应用程序以使用受 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/
这里的关键是adalApiFetch
,在adalConfig.js
中定义。如您所见,它是 adalFetch
的简单包装器。此方法(在 react-adal
中定义)接收一个 ADAL 实例 (authContext
)、一个资源标识符 (resourceGuiId
)、一个方法 (fetch
)、一个 URL (url
) 和一个对象 (options
)。该方法执行以下操作:
- 使用 ADAL 实例 (
authContext
) 获取由 resourceGuiId
标识的资源的访问令牌。
- 将此访问令牌添加到
options
对象的 headers
字段(如果未提供,则创建一个)。
- 调用给定的 "fetch" 方法,传入
url
和 options
对象作为参数。
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-adal
中的 runWithAdal
方法包装 indexApp.js
,确保用户使用 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 请求的端点(Microsoft Graph 中的 /me
端点,在此案例):
- 在
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;
上面给出的配置仍然存在问题。我在上面添加了更多配置并且它有效。希望对你有帮助。
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 帐户,重新登录,您应该会收到用户的详细信息。
我有一个 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);
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 中配置,因此尝试使用其余部分的用户将需要进行身份验证.
现在的问题是:如何设置我的客户端应用程序以使用受 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/
这里的关键是adalApiFetch
,在adalConfig.js
中定义。如您所见,它是 adalFetch
的简单包装器。此方法(在 react-adal
中定义)接收一个 ADAL 实例 (authContext
)、一个资源标识符 (resourceGuiId
)、一个方法 (fetch
)、一个 URL (url
) 和一个对象 (options
)。该方法执行以下操作:
- 使用 ADAL 实例 (
authContext
) 获取由resourceGuiId
标识的资源的访问令牌。 - 将此访问令牌添加到
options
对象的headers
字段(如果未提供,则创建一个)。 - 调用给定的 "fetch" 方法,传入
url
和options
对象作为参数。
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-adal
中的 runWithAdal
方法包装 indexApp.js
,确保用户使用 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 请求的端点(Microsoft Graph 中的/me
端点,在此案例): - 在
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;
上面给出的配置仍然存在问题。我在上面添加了更多配置并且它有效。希望对你有帮助。
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 帐户,重新登录,您应该会收到用户的详细信息。