使用MSAL Angular访问受保护的Azure函数

时间:2020-02-29 18:48:43

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

此问题基于Microsoft提供的示例代码:
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”(从“ https://functionname.azurewebsites.net/api/HttpTrigger2?code=SAMPLE-STRING”重定向)对XMLHttpRequest的访问已被CORS策略阻止:不存在“ Access-Control-Allow-Origin”头在请求的资源上。

第二个错误:

core.js:4002错误错误:未捕获(已承诺):HttpErrorResponse:{“ headers”:{“ normalizedNames”:{},“ lazyUpdate”:null,“ headers”:{}},“状态”: 0,“ statusText”:“未知错误”,“ url”:“ https://functionname.azurewebsites.net/api/HttpTrigger2?code=SAMPLE-STRING”,“ ok”:false,“名称”:“ HttpErrorResponse”,“消息”:“对{{3} }:0未知错误“,”错误“:{” isTrusted“:true}}

控制台中还警告:

跨域读取阻止(CORB)阻止了MIME类型为text / html的跨域响应https://functionname.azurewebsites.net/api/HttpTrigger2?code=SAMPLE-STRING。有关更多详细信息,请参见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

Angular应用程序的URL为https://www.chromestatus.com/feature/5629709824032768。这是Azure功能的CORS配置:

http://localhost:4200/

enter image description here

如何允许Angular应用程序对Azure函数发出经过身份验证的请求?

2 个答案:

答案 0 :(得分:1)

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

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

  1. MsalModule正确配置(注意:MsalModule.forRoot(<config>)不支持动态配置)
  2. 用户令牌在SessionStorage或LocalStorage中可用,没有错误
  3. 使用以下命令正确配置隐式流:
    • MsalInterceptor已注册为提供商
    • 为功能的URL配置了
    • protectedResourceMap

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

答案 1 :(得分:0)

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

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

然后,您可以使用访问令牌调用函数api。

enter image description here