【问题标题】:Use MSAL Angular to access protected Azure Function使用 MSAL Angular 访问受保护的 Azure 函数
【发布时间】:2020-02-29 18:48:43
【问题描述】:

本题基于微软提供的示例代码:
https://docs.microsoft.com/en-us/samples/azure-samples/active-directory-javascript-singlepageapp-angular/active-directory-javascript-singlepageapp-angular/

app.module.ts已经配置好,应用可以通过Azure B2C登录界面成功登录。

还有一个 Azure 函数,它通过 HTTP GET 请求简单地返回一个带有一个字符串属性“text”的 JSON 对象。该函数已配置为使用 Azure B2C 进行身份验证。这已通过在浏览器中访问函数 URL、通过 B2C 登录屏幕登录并从函数返回 JSON 对象来确认。

调用受保护 api 的组件如下所示:

import { Component, OnInit } from '@angular/core';
import { MsalService } from '@azure/msal-angular';
import { HttpClient } from '@angular/common/http';

const FUNCTION_ENDPOINT = 'function-url-here';

export interface MyInterface {
  text: string;
}

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {

  value: MyInterface;

  constructor(private authService: MsalService, private http: HttpClient) { }

  ngOnInit() {
    this.getValue();
  }

  getValue() {
    this.http.get<MyInterface>(FUNCTION_ENDPOINT).toPromise()
      .then(value => {
          this.value = value;
      });
  }

}

关闭函数身份验证后,函数中的 JSON 将返回给 Angular 应用程序。开启功能认证后,浏览器控制台打印如下错误:

从源“null”访问“https://mytenant.b2clogin.com/mytenant.onmicrosoft.com/oauth2/v2.0/authorize?response_type=id_token&redirect_uri=https%3A%2F%functionname.azurewebsites.net%2F.auth%2Flogin%2Faad%2Fcallback&client_id=SAMPLE-STRING&scope=openid+profile+email&response_mode=form_post&p=b2c_1_signupsignin1&nonce=SAMPLE-STRING&state=redir%3D%252Fapi%252FHttpTrigger2%253Fcode%SAMPLE-STRING”处的 XMLHttpRequest(从“https://functionname.azurewebsites.net/api/HttpTrigger2?code=SAMPLE-STRING”重定向)已被 CORS 策略阻止:请求的资源上不存在“Access-Control-Allow-Origin”标头.

第二个错误:

core.js:4002 ERROR 错误:未捕获(承诺中):HttpErrorResponse: {"headers":{"normalizedNames":{},"lazyUpdate":null,"headers":{}},"status": 0,"statusText":"未知错误","url":"https://functionname.azurewebsites.net/api/HttpTrigger2?code=SAMPLE-STRING","ok":false,"name":"HttpErrorResponse","message":"https://functionname.azurewebsites.net/api/HttpTrigger2?code=SAMPLE-STRING 的 Http 失败响应:0 未知错误","错误":{"isTrusted":true}}

控制台也有警告:

跨域读取阻止 (CORB) 阻止了 MIME 类型为 text/html 的跨域响应 https://mytenant.b2clogin.com/mytenant.onmicrosoft.com/oauth2/v2.0/authorize?response_type=id_token&redirect_uri=https%3A%2F%2Ffunctionname.azurewebsites.net%2F.auth%2Flogin%2Faad%2Fcallback&client_id=SAMPLE-STRING&scope=openid+profile+email&response_mode=form_post&p=b2c_1_signupsignin1&nonce=SAMPLE-STRING&state=redir%3D%252Fapi%252FHttpTrigger2%253Fcode%SAMPLE-STRING。详情请见https://www.chromestatus.com/feature/5629709824032768

Angular 应用程序的 URL 是 http://localhost:4200/。这是 Azure 函数的 CORS 配置:

可以做些什么来让 Angular 应用程序向 Azure Function 发出经过身份验证的请求?

【问题讨论】:

  • 嗨@craydon。您可能需要为此检查 Enable Access-Control-Allow-Credentials
  • 有什么区别?那安全吗?如果这不起作用,还有其他建议吗?
  • 要访问已启用身份验证的应用服务,您需要在标头中传递访问令牌。 codemilltech.com/…
  • 能够将 B2C 添加到函数应用中,但使用 MSAL 从 Angular 调用并不简单。

标签: angular typescript azure-functions azure-ad-b2c msal


【解决方案1】:

AAD 和 AAD B2C 不支持 MSDN 文档中所述的 CORS。这意味着当您的 Angular 应用程序在没有令牌的情况下调用 Function API 并因此被重定向到 AAD B2C 端点进行身份验证时,您将遇到无法解决的问题。所谓的“隐式流”的技巧是通过确保您首先在从 Angular 应用程序到 B2C 端点的直接调用中发出一个令牌来防止这种情况发生。并且由于分配此令牌的应用程序注册具有访问 Function API 的权限,因此可以隐式生成令牌并将其转发给然后接受它的 Function API。然后不会发生重定向,因此也不会出现 CORS 问题。

通常 - 至少根据我的经验 - 您遇到的 CORS 问题有点误导,因为它掩盖了真正的问题,可能是 1) 用户根本没有经过身份验证(令牌完全丢失)或 2) API 调用不会隐式生成并注入到 HTTP 调用中。我建议进行以下检查:

  1. MsalModule 正确配置(注意:MsalModule.forRoot(&lt;config&gt;) 不支持动态配置)
  2. 用户令牌在 SessionStorage 或 LocalStorage 中可用且没有错误
  3. 隐式流配置正确:
    • MsalInterceptor注册为提供者
    • protectedResourceMap 为函数的 URL 配置

我最近创建并记录了一个将 Angular 和 Azure 函数连接到 AAD B2C 的参考解决方案。您可以在此处找到源代码和自述文件:https://github.com/garaio/DevCamp-AzureServerless/tree/master/Solutions/D04-AAD-B2C-multi-tenancy#client-app-deployment

【讨论】:

    【解决方案2】:

    您可以参考this document获取访问令牌。请记住将 protectedResourceMap 更新为您的值。对于 B2C,应该是这样的

    protectedResourceMap: {"https://tonyb2ctest.onmicrosoft.com/test", ["user_impersonation"]}
    

    然后就可以使用访问令牌调用函数api了。

    【讨论】:

    • 感谢您的回复。我试过了,但仍然收到上面提到的 CORS 错误。尝试了 localhost 和从 Azure blob 存储容器提供服务。两者都有 CORS 问题。甚至在函数 CORS 配置中勾选了 Enable Access-Control-Allow-Credentials
    • 在问题底部添加了一个屏幕抓取,显示 Azure 功能的 AD 身份验证配置。这可能是问题吗?
    • @crayden 使用 msal 时出现此问题?用弹窗获取令牌应该没问题。
    • 尝试了一个更简单的示例,但仍然无法正常工作。 stackoverflow.com/questions/60682584/…
    猜你喜欢
    • 2020-04-03
    • 2011-05-02
    • 2020-05-22
    • 2021-07-13
    • 2021-01-01
    • 2011-03-19
    • 2014-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多