1

我在 Azure Functions 中创建了一个示例函数。我已经使用 AAD 保护了它。我可以成功转到 URL,使用我的 Office 365 帐户登录,然后该功能运行。

我在 AAD 中为我的 WPF 客户端创建了另一个应用程序。我可以使用 Office 365 凭据成功登录 WPF 客户端。然后,我在 AAD 中为该应用程序创建了访问 Azure Function AAD 应用程序的权限。

这是我的问题:如何使用 WPF 应用程序中的登录令牌访问 Azure Functions?

我已经阅读了大约十几个不同的教程,展示了如何设置它,每个教程都未能真正验证对函数的调用。

我错过了什么?

4

1 回答 1

0

经过大量研究和反复试验,我终于能够使用我的 Office365 帐户登录并访问 Azure 功能。

步骤 1 - 向 Azure Active Directory 注册您的应用服务应用

  1. 登录到 Azure 门户,然后导航到您的应用服务应用。将应用 URL 复制到 Azure 函数。你将使用它来配置你的 Azure Active Directory 应用程序注册。
  2. 导航到 Active Directory,然后选择应用程序注册,然后单击顶部的新应用程序注册以开始新的应用程序注册。
  3. 在创建页面中,为您的应用注册输入名称,选择 Web 应用/API 类型,在登录 URL 框中粘贴应用程序 URL(来自步骤 1)。然后点击创建。
  4. 几秒钟后,您应该会看到刚刚创建的新应用注册。
  5. 添加应用注册后,单击应用注册名称,单击顶部的设置,然后单击属性
  6. 在 App ID URI 框中,粘贴应用程序 URL(来自步骤 1),也在主页 URL 中粘贴应用程序 URL(来自步骤 1),然后单击保存
  7. 现在单击回复 URL,编辑回复 URL,粘贴应用程序 URL(从步骤 1 开始),修改协议以确保您有 https:// 协议(不是 http://),然后附加到末尾URL,/.auth/login/aad/callback(例如,https://contoso.azurewebsites.net/.auth/login/aad/callback)。单击保存。
  8. 此时,复制应用程序的应用程序 ID。保留以备后用。您将需要它来配置您的应用服务应用。
  9. 关闭已注册的应用页面。在 App 注册页面上,单击顶部的 Endpoints 按钮,然后复制联合元数据文档 URL。
  10. 打开一个新的浏览器窗口并通过粘贴并浏览到 XML 页面来导航到 URL。文档顶部是一个 EntityDescriptor 元素。找到 entityID 属性并复制其值。它用作您的颁发者 URL。您将配置您的应用程序以供以后使用。

步骤 2 - 将 Azure Active Directory 信息添加到应用服务应用

  1. 返回 Azure 门户,导航到应用服务应用。单击身份验证/授权。如果未启用身份验证/授权功能,请将开关转到 On。单击身份验证提供程序下的 Azure Active Directory 以配置您的应用程序。(可选)默认情况下,应用服务提供身份验证,但不限制对站点内容和 API 的授权访问。您必须在您的应用代码中授权用户。将请求未通过身份验证时采取的操作设置为使用 Azure Active Directory 登录。此选项要求对所有请求进行身份验证,并将所有未经身份验证的请求重定向到 Azure Active Directory 进行身份验证。
  2. 在 Active Directory 身份验证配置中,单击管理模式下的高级。将应用程序 ID 粘贴到客户端 ID 框中(来自第 8 步),然后单击确定。
  3. 在 Active Directory 身份验证配置页面上,单击保存。

第 3 步 - 配置本机客户端应用程序

Azure Active Directory 还允许您注册本机客户端,从而更好地控制权限映射。如果您希望使用诸如 Active Directory 身份验证库之类的库执行登录,则需要此功能。

  1. 在 Azure 门户中导航到 Azure Active Directory。
  2. 在左侧导航中,选择应用注册。点击顶部的新应用注册。
  3. 在创建页面中,输入您的应用注册名称。在应用程序类型中选择本机。
  4. 在重定向 URI 框中,使用 HTTPS 方案输入您站点的 /.auth/login/done 端点。此值应类似于https://contoso.azurewebsites.net/.auth/login/done。如果创建 Windows 应用程序,请改为使用包 SID 作为 URI。
  5. 单击创建。
  6. 添加应用程序注册后,选择它以将其打开。找到应用程序 ID 并记下此值。
  7. 单击所有设置 > 所需权限 > 添加 > 选择 API。
  8. 键入您之前注册的应用服务应用程序的名称以搜索它,然后选择它并单击选择。
  9. 选择访问。然后单击选择。然后单击完成。

以上说明取自https://docs.microsoft.com/en-us/azure/app-service/configure-authentication-provider-aad?toc=%2fazure%2fazure-functions%2ftoc.json

以下是我的更改,以使其与调用 Azure 函数的 WPF 应用程序一起使用

第 4 步 - 在服务应用程序中授权客户端应用程序

  1. 从第 3 步复制客户端应用程序 ID:
  2. 打开 Azure 活动目录
  3. 点击应用注册(预览)
  4. 点击第 1 步中注册的 Service App
  5. 单击公开 API
  6. 在授权的客户端应用程序下,单击添加客户端应用程序。
  7. 粘贴客户端 ID 并单击范围 https://{您的租户名称}.onmicrosoft.com/{您的服务应用 ID}/user_impersonation
  8. 单击添加应用程序

第 5 步 - 使服务应用程序多租户

  1. 打开 Azure 活动目录
  2. 点击应用注册(预览)
  3. 点击第 1 步中注册的 Service App
  4. 点击身份验证
  5. 在支持的帐户类型下选择“任何组织目录中的帐户”
  6. 您将收到一个错误。这是因为步骤 1 子步骤 6。我们需要根据租户域 {tenantname}.onmicrosoft.com 创建一个 App URI
  7. 导航到旧的应用注册(因为这在应用注册(预览版)中不可用,除非您编辑清单)
  8. 选择您的服务应用程序(您可能需要单击查看所有应用程序)
  9. 点击设置。然后单击属性。
  10. 在 App ID URI 下将其更改为 https://{ad tenant name}.onmicrosoft.com/{Service App ID}
  11. 确保 Multi-tenanted 设置为 Yes(应该是因为 Step 5 sub step 6.)

第 6 步 - 将范围添加到功能 APP

  1. 在 Azure 门户中打开函数应用并导航到 Authenticaiton
  2. 将 Active Directory 设置更改为具有来自服务 APP IE 的 API 范围权限的全部值的 Allowed Token Audiences

https://{AD TENANT}.onmicrosoft.com/{SERVICE APP ID}/user_impersonation

现在看代码

从您的客户端应用程序。安装 nuget Microsoft.Identity.Client

using Microsoft.Identity.Client;
using Newtonsoft.Json.Linq;
using System;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;

namespace TestAzureFunctionLogin
{
public class ManualTestApp
{
    static string ClientId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; //replace with AppID from Client App Azure AD registration
    static string ServiceId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; //replace with AppID from Service App Azure AD registration
    static string Scope = $"{ServiceId}/user_impersonation";
    static string Authority = "https://login.microsoftonline.com/organizations";

    string[] _scopes => new string[] { Scope };
    private PublicClientApplication _clientApp = new PublicClientApplication(ClientId, Authority);

    private AuthenticationResult authResult;
    public PublicClientApplication ClientApp => _clientApp;

    public async Task LoginAsync()
    {
        var user = (await ClientApp.GetAccountsAsync()).FirstOrDefault();
        authResult = await ClientApp.AcquireTokenAsync(_scopes, user);
    }

    public async Task<string> CallAzureFunction(string url)
    {
        return await GetHttpContentWithToken(url, authResult.AccessToken);
    }

    //Code taken from somewhere on the Microsoft Website
    public async Task<string> GetHttpContentWithToken(string url, string token)
    {
        var httpClient = new System.Net.Http.HttpClient();
        System.Net.Http.HttpResponseMessage response;
        try
        {
            var request = new System.Net.Http.HttpRequestMessage(System.Net.Http.HttpMethod.Get, url);
            //Add the token in Authorization header
            request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
            response = await httpClient.SendAsync(request);

            var content = await response.Content.ReadAsStringAsync();
            return content;
        }
        catch (Exception ex)
        {
            return ex.ToString();
        }
    }
}

}

于 2019-01-13T02:02:32.180 回答