首页 > 解决方案 > 代表授权用户从浏览器中的客户端应用程序调用 azure 函数

问题描述

我的目标是让 Angular 8 SPA 具有一个无服务器后端,该后端由多个使用来自 Facebook、Google 的 OAuth 的 azure 函数应用程序表示。

我在代表授权用户调用 azure 函数时遇到问题。函数将这些调用视为匿名用户。

从浏览器,函数返回授权用户名,从浏览器应用程序调用它返回“无名称”,表示用户未授权。

我的猜测是来自myapp.azurewebsites.net的会话在本地主机中的我的应用程序中不可见(它可以是任何其他域)。此外,我无法在功能端点的请求中提供会话。

那么,授权用户并从其他域的客户端应用程序调用 azure 函数的方式是什么?还是只能手动实现 JWT 令牌,并在所有功能中扩展逻辑? 另外,我不想向 Auth0 甚至 AAD 等第三方服务付费。

Jim Xu,提出了一种可行的方法,但不适用于我的情况。我看到的缺点:

我正在寻找这些问题的答案:

  1. 我的案例是否有后端驱动的身份验证?
  2. 是否有能力设置 post_login_redirect_url 来接收服务令牌?
  3. 也许可以通过https://resources.azure.com/进行设置 ?
  4. 是否可以为多个功能应用共享访问令牌?(通过这种方式,UI 逻辑将被简化为 get 到 app/.auth/login/provider 然后保存一个服务令牌。)

我的代码示例和配置:

这是我用来调用的客户端应用程序主要部分:

<button (click)="call('https://myapp.azurewebsites.net/Function1')">CallWithoutAuth</button>
<button (click)="call('https://myapp.azurewebsites.net/Function2')">CallWithAuth</button>

<a href="https://myapp.azurewebsites.net/.auth/login/facebook?post_login_redirect_url=http%3A%2F%2Flocalhost%3A5000" target="_blank">Log in with Facebook</a>

调用函数体:

var url = 'my azure func url with auth via facebook';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
  if (this.readyState == 4 && this.status == 200) {
    console.log(this.responseText);
  }
};
xhttp.onerror = function(e){console.log(e, this)};
xhttp.open("GET", url, true);
xhttp.send();

功能代码:

public static async Task<IActionResult> Run(
 [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "Func2")] HttpRequest req, 
 ClaimsPrincipal claimsPrincipal)
{
    var name = claimsPrincipal?.Identity?.Name;
    return (ActionResult)new OkObjectResult($"Hello, {name ?? "no name"}");
}

以下是函数应用配置:

在此处输入图像描述

CORS 配置:

在此处输入图像描述

通讯录配置:

在此处输入图像描述

标签: azureazure-active-directoryazure-functionssession-cookiesazure-authentication

解决方案


根据我的测试,我们可以通过以下步骤调用facebook投影的Azure函数

  1. 将 Facebook 集成到您的 Angular 应用程序中。完成后,我们可以登录 facebook 并获得一个accessToken. 有关如何实现它的更多详细信息,请参阅文章

    例如

    一个。将应用程序 URL 添加到Valid OAuth Redirect URIs

    湾。添加以下代码app.component.ts

    
    export class AppComponent {
      title = 'web';
      fbLibrary() {
    
        (window as any).fbAsyncInit = function() {
          window['FB'].init({
            appId      : '<app id you use to project azure function>',
            cookie     : true,
            xfbml      : true,
            version    : 'v3.1'
          });
          window['FB'].AppEvents.logPageView();
        };
    
        (function(d, s, id){
           var js, fjs = d.getElementsByTagName(s)[0];
           if (d.getElementById(id)) {return;}
           js = d.createElement(s); js.id = id;
           js.src = "https://connect.facebook.net/en_US/sdk.js";
           fjs.parentNode.insertBefore(js, fjs);
         }(document, 'script', 'facebook-jssdk'));
    
    }
    ngOnInit() {
      this.fbLibrary();
    }
      login() {
    
        window['FB'].login((response) => {
    
    
            if (response.authResponse) {
             //get access token
              var accessToken=response.authResponse.accessToken;
              console.log('login response',accessToken);
              window['FB'].api('/me', {
                fields: 'last_name, first_name, email'
              }, (userInfo) => {
    
                console.log("user information");
                console.log(userInfo);
              });
    
            } else {
              console.log('User login failed');
            }
        }, {scope: 'email'});
    }
    }
    
    
    

    C。将登录按钮添加到 html

  2. 调用以下请求以将此 accessToken 交换为“应用服务令牌”

要求

   POST https://<appname>.azurewebsites.net/.auth/login/aad HTTP/1.1
  Content-Type: application/json

  {"access_token":"<token>"}

回复

{
    "authenticationToken": "...",
    "user": {
        "userId": "sid:..."
    }
}

在此处输入图像描述

  1. 调用天蓝色函数
Get https://myapp.azurewebsites.net/Function1
X-ZUMO-AUTH: <authenticationToken_value>

在此处输入图像描述 有关详细信息,请参阅https://docs.microsoft.com/en-us/azure/app-service/app-service-authentication-how-to


推荐阅读