我正在开发一个带有 React 的 SPA,它作为 Azure 静态 Web 应用程序托管。该应用程序受到 Azure AD 身份验证的保护,效果很好,我已经构建了一个运行良好的登录,我可以使用我获得的令牌调用 Azure (Graph) API 并检索授予范围的信息(例如用户个人资料图片)。为此,我使用了一个名为React AAD MSAL的包装器,它巧妙地包装了 Microsoft 身份验证库 (msal@1.4.0)。
到目前为止一切顺利,这里没有问题。但我当然需要一个后端。我决定使用 Azure Functions,因为无服务器对我来说是最好的方式。因此,我制作了一个快速 HTTP 触发原型,该原型在 Azure 中运行,当我使用正确的参数调用 URL 时,Azure Function und 可以正常工作。
但是当然 Azure Function 需要被保护,所以只有我的 React App 可以调用这个函数。所以我认为应该有办法通过 Azure AD 来做到这一点,因为我的用户已经这样登录了。
我尝试并尝试了我在网上找到的不同方法,但它们似乎都不起作用,或者我做错了什么。
我尝试遵循的一般教程是来自MS 本身的教程。我尝试使用“Express”设置,这当然不起作用。我尝试了高级配置,但也没有用。高级教程说您需要为该服务注册一个应用程序,我什至不确定这是否可以是我的静态 Web 应用程序或新的(我都尝试过但没有成功)。告诉 Azure 函数它现在受 AAD 保护并且只能接受来自由包含我的应用程序的应用程序 ID(在设置中提供)的访问令牌保护的源的调用还不够吗?您可以轻松提供所有这些设置,但它似乎不起作用。
所以我很早就在这里停滞不前。要调用函数本身,我首先需要获取一个授权令牌。根据MS 的本教程(请参阅“验证来自提供商的令牌”),我需要将登录到我的 SPA Web 应用程序时获得的访问令牌发送到以.auth/login/aad
. 获取这个令牌很容易,因为 React AAD MSAL 提供了一种authProvider.getAccessToken()
我可以用来提取它的方法。https://<My Azure Function URI>/.auth/login/aad
然后,我使用正文中的访问令牌作为 JSON发出 POST 请求{ 'access_token': authToken.accessToken }
。我应该得到一个身份验证令牌,然后我可以用它来调用实际的函数,但无论我尝试什么,我总是得到相同的响应:You do not have permission to view this directory or page.
所以这就是我所在的地方。我尝试了不同的方法和解决方案,但发现无济于事。也许我从头开始做错了什么,也许我使用了错误的方法,我现在真的不知道。这个事情谁有经验?我的一般方法有问题吗,我需要做其他事情吗?还是只是我需要更改的配置中的某些内容?
编辑
既然有人问了,这就是我检索令牌的方式。这背后的概念是使用 aredux-thunk
将异步操作分派到 react-redux 存储。我不仅在这里简化了这个问题,还简化了我的测试。现在我只是想获取身份验证令牌并记录 POST 请求给我的答案:
import { authProvider } from '../../Authentication/AuthProvider';
//Fetch
async function getAccessToken(authToken) {
const body = { 'access_token': authToken.accessToken };
fetch('https://<My Azure function URL>/.auth/login/aad', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body)
},
).then(response => {
console.log(response);
});
}
export const fetchAddressData = () => async dispatch => {
const token = await authProvider.getAccessToken();
await getAccessToken(token);
// The actual call to the Azure function will go here once we have an Authentication Token
}
这authProvider
是一个组件,react-aad msal
配置如下所示:
import { MsalAuthProvider, LoginType } from 'react-aad-msal';
//MSAL Config
const config = {
auth: {
authority: '<Tenant ID>',
clientId: '<Client ID from App registration (Azure Static Web App)>',
redirectUri: window.location.origin
},
cache: {
cacheLocation: "localStorage",
storeAuthStateInCookie: true
}
};
// Authentication Parameters
const authenticationParameters = {
scopes: [
'openid',
'user.read',
'https://<Azure Function URI>/user_impersonation'
],
forceRefresh: true
}
// Options
const options = {
loginType: LoginType.Redirect,
tokenRefreshUri: window.location.origin
}
export const authProvider = new MsalAuthProvider(config, authenticationParameters, options)
编辑 2
我调整了一些额外的设置,试图与用户模拟一起工作,但仍然没有成功。下面是对我当前重要的 Azure 设置的概述(我忘记了吗?)。
蔚蓝功能:
Azure 功能 - 应用注册:
公开 API - 公开 user_impersonation API,以便 Web 应用可以使用它:
Azure 静态 Web 应用 (React SPA) - 应用注册:
在 Azure 函数中用作令牌受众的应用程序 URI ID(高级身份验证设置):
API 权限 - 使用 Azure Function App Registration 公开的 user_impersonation API:
这个配置有什么问题吗?很可能是,但我不知道是什么,因为我按照 MSDN 上的教程进行操作。之后我只添加了 user_impersonation,因为它不起作用。