WPF 应用程序使用 AAD 访问 Azure Function

3
我已经在Azure Functions中创建了一个示例函数,并使用AAD进行了安全保护。我可以成功访问URL,使用我的Office 365帐户登录,然后运行该函数。
我在AAD中为我的WPF客户端创建了另一个应用程序。我可以使用我的Office 365凭据成功登录WPF客户端。然后,我在AAD中为此应用程序创建了一个权限,以便访问Azure Function AAD应用程序。
这是我的问题: 如何使用我的WPF应用程序的登录令牌来访问Azure Functions?
我已经阅读了大约十几个不同的教程,展示了如何设置这个过程,但每个教程都无法实际验证对函数的调用身份验证。
我缺少什么?

我还可以成功使用我的WPF令牌调用Microsoft Graph。 - undefined
使用WPF令牌作为Bearer令牌在授权头上不起作用。 - undefined
你给WPF客户端应用程序授予了什么样的权限?是委派权限还是应用程序权限?能否分享一下你的AAD应用程序注册详细信息? - undefined
你是否为具有委派权限的功能AD应用程序提供了WPF AD应用程序?如果是,请展示授予访问令牌的代码。 - undefined
在“公开一个API”中,我应该从Functions API授权客户端WPF应用程序吗?还是反过来? - undefined
1个回答

0

经过大量的研究和试错,我终于成功使用我的Office365账户登录并访问Azure函数。

步骤1 - 将您的应用服务应用程序注册到Azure Active Directory

  1. 登录Azure门户,并导航到您的应用服务应用程序。将应用程序URL复制到Azure函数中。您将使用此URL来配置Azure Active Directory应用注册。
  2. 导航到Active Directory,然后选择应用注册,然后点击顶部的新建应用注册以开始新的应用注册。
  3. 在创建页面中,为您的应用注册输入一个名称,选择Web应用/ API类型,在登录URL框中粘贴应用程序URL(来自步骤1)。然后点击创建。
  4. 几秒钟后,您应该会看到刚刚创建的新应用注册。
  5. 添加了应用注册后,点击应用注册名称,点击顶部的设置,然后点击属性
  6. 在应用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. 关闭注册应用页面。在应用注册页面,点击顶部的终结点按钮,然后复制联合元数据文档URL。
  10. 打开一个新的浏览器窗口,并通过粘贴和浏览到XML页面的URL进行导航。在文档的顶部是一个EntityDescriptor元素。找到entityID属性并复制其值。它将作为您的发行者URL。您将稍后配置您的应用程序使用它。

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

  1. 返回Azure门户,在应用服务中导航到您的应用程序。点击“身份验证/授权”。如果未启用“身份验证/授权”功能,请将开关打开。在“身份验证提供程序”下方,点击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. 输入您之前注册的App Service应用的名称进行搜索,然后选择它并点击选择。
  9. 选择访问权限。然后点击选择。然后点击完成。

上述指示来自https://learn.microsoft.com/en-us/azure/app-service/configure-authentication-provider-aad?toc=%2fazure%2fazure-functions%2ftoc.json

以下是我对其进行的修改,以使其与调用 Azure Function 的 WPF 应用程序配合使用

第四步 - 在服务应用中授权客户端应用

  1. 复制第三步中的客户端应用程序 ID:
  2. 打开 Azure Active Directory
  3. 点击“应用注册(预览)”
  4. 点击在第一步中注册的服务应用
  5. 点击“公开 API”
  6. 在“已授权的客户端应用程序”下点击“添加客户端应用程序”
  7. 粘贴客户端 ID,并点击范围 https://{your tenant name}.onmicrosoft.com/{Your Service App ID}/user_impersonation
  8. 点击“添加应用程序”

第五步 - 将服务应用设置为多租户

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

步骤6 - 向函数应用添加范围

  1. 在 Azure 门户中打开您的函数应用并导航到身份验证
  2. 将 Active Directory 设置更改为允许令牌受众为来自服务应用的 API 范围权限的完整值

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();
        }
    }
}

}


这对我来说还是不起作用,即使从http://myfuntionsapp.host/.auth/me获取令牌似乎也无法在httpclient中使用。 - undefined
我在处理一个全新的应用程序时仍然遇到困难。而且我认为我上面的示例已经过时了,不符合现在的做法。 - undefined
我发现问题是因为在函数应用中使用了错误的令牌授权 - 它应该是https://login.microsoftonline.com/{Tenant_Id}/v2.0。虽然上述授权在Web浏览器中进行身份验证时有效,但如果您从ADAL/MSAL请求令牌,则不起作用。您可以通过使用jwt.io网站解码您的JWT来验证应该使用的授权。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接