javascript - 使用 Azure Active Directory 授权从 Angular 静态网页前端调用 Azure Functions API
问题描述
我的前端和后端(Azure Functions)都由 Azure Active Directory(AAD)保护。
前端:我已经按照此处描述的方式在 Angular 中实现了 MSAL:(https://www.pshul.com/2020/02/07/azure-ad-authentication-from-angular-to-azure-functions/)。现在,当打开我的 Angular 网页时,我被重定向到 Microsoft 登录,它只接受正确的用户和帐户,这似乎可以工作。
后端:我的后端端点不允许来自已注册帐户的没有有效 id_token 的请求。所有带有无效令牌的请求都将导致 401(未经授权)错误,这似乎也有效。
问题在于从我的前端调用后端函数,或者更确切地说是获取一个 id_token:当我像上面描述的那样登录到前端时,我想存储 id_token 并让我的拦截器在每个请求中发送它,所以我每个请求都不需要额外登录。在我提到的链接中,这似乎是由 MSAL 和 MSALInterceptor 处理的,这对我不起作用(它没有向后端发送任何承载令牌),所以我有自己的拦截器从 localStorage 中获取令牌。问题是,来自 localStorage 的令牌也会导致 401 错误,因此它似乎无效。当我没有误解时,登录时,它会调用登录名并从 https://MyAzureWebPage/.auth/me 获取一个 id-token,它存储在本地存储中,但该令牌不起作用。调用 https://MyAzureWebPage/ 时。手动 auth/me 并将该 id_token 与邮递员一起使用,它可以工作。有谁知道我做错了什么或者我在哪里可以获得正确的 id_token?
这是我的 MSAL 配置,也许我在那里做错了什么:
MsalModule.forRoot({
auth: {
clientId: 'myCliendAdd',
authority: "https://login.microsoftonline.com/myTenantID",
},
cache: {
cacheLocation: 'localStorage',
storeAuthStateInCookie: isIE, // Set to true for Internet Explorer 11
},
},
{
popUp: !isIE,
consentScopes: [
'user.read',
'openid',
'profile',
],
unprotectedResources: [],
protectedResourceMap: [
['https://MyAzureWebPage/.auth/me', ['user.read']]
],
extraQueryParameters: {}
}),
providers: [
AuthGuard,
RoleGuard,
{ provide: HTTP_INTERCEPTORS, useClass: MsalInterceptor, multi: true }
],
bootstrap: [AppComponent],
})
出于某种原因,我从 msal 获得的令牌(例如:
this.broadcastService.subscribe("msal:acquireTokenSuccess", payload => {
console.log(payload)
});
并且从 localStorage 与我调用 https://MyAzureWebPage/.auth/me 时获得的令牌不同,这是唯一一个似乎有效的令牌
如果您需要任何进一步的信息,我会在此处添加
解决方案
如果要在 Angular 应用程序中调用 Azure AD 投影的 Azure 函数,请参考以下代码
创建 Azure AD 应用程序以保护功能
在应用服务应用中启用 Azure Active Directory
创建客户端 AD 应用程序以访问功能
- 注册申请
- 启用 隐式授权流
- 配置 API 权限。让您的客户端应用程序具有访问功能的权限
代码
MsalModule.forRoot(
{
auth: {
clientId: '232a1406-b27b-4667-b8c2-3a865c42b79c',
authority:
'https://login.microsoftonline.com/e4c9ab4e-bd27-40d5-8459-230ba2a757fb',
redirectUri: 'http://localhost:4200/',
},
cache: {
cacheLocation: 'localStorage',
storeAuthStateInCookie: isIE, // set to true for IE 11
},
},
{
popUp: !isIE,
consentScopes: [
'user.read',
'openid',
'profile',
'<your function app scope your define>',
],
unprotectedResources: [],
protectedResourceMap: [
[
'<your function app url>',
[<your function app scope you define>],
]
],
extraQueryParameters: {},
}
),
],
推荐阅读
- regex - Perl 正则表达式将多行转换为单行
- flutter - 在堆栈中覆盖一个小部件并更改其可见性 n 按钮单击
- html - 如何以不同的顺序显示css网格?
- youtube - 用于 YouTube 评论的 Webhook(推送通知)作为推送通知
- android - MIUI 10.3.7 版本未运行后台服务
- android - 使用相同的应用签名密钥签名的 3 种不同风格的应用(应用包)显示相同的语言内容
- jquery - HTML - 使用内部 CSS
- node.js - 微服务架构中服务之间通信的最佳方式?
- android - 不希望底部导航抽屉上的 android-studios 默认动画
- flutter - FlatButton onPressed 在定位的小部件中不起作用