WPF应用使用AAD访问Azure功能

时间:2018-12-29 02:53:46

标签: c# wpf azure azure-active-directory azure-functions

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

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

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

我遍历了大约十二个不同的教程,展示了如何进行设置,但每个教程都未能真正验证对函数的调用。

我想念什么?

1 个答案:

答案 0 :(得分:0)

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

步骤1-向Azure Active Directory注册您的App Service应用

  1. 登录到Azure门户,然后导航到您的App Service应用程序。将应用程序URL复制到Azure函数。您将使用它来配置Azure Active Directory应用程序注册。
  2. 导航到Active Directory,然后选择应用程序注册,然后单击顶部的“新建应用程序注册”以开始新的应用程序注册。
  3. 在“创建”页面中,为您的应用程序注册输入名称,选择Web App / 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。保留以备后用。您将需要它来配置您的App Service应用。
  9. 关闭“已注册的应用”页面。在“应用程序注册”页面上,单击顶部的“端点”按钮,然后复制联合身份验证元数据文档URL。
  10. 打开一个新的浏览器窗口,并通过粘贴并浏览到XML页面来导航到URL。文档顶部是EntityDescriptor元素。查找entityID属性并复制其值。它用作您的发行者URL。您将配置您的应用程序以供以后使用。

步骤2-将Azure Active Directory信息添加到您的App Service应用程序

  1. 返回Azure门户,导航至您的App Service应用程序。单击身份验证/授权。如果未启用身份验证/授权功能,则将开关转到On。单击身份验证提供程序下的Azure Active Directory,以配置您的应用程序。 (可选)默认情况下,App Service提供身份验证,但不限制对您的网站内容和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://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 Active Directory
  3. 点击应用程序注册(预览)
  4. 单击在步骤1中注册的Service App
  5. 点击公开API
  6. 在“授权的客户端应用程序”下,单击“添加客户端应用程序”。
  7. 粘贴客户端ID,然后单击范围https:// {您的租户名称} .onmicrosoft.com / {您的服务应用程序ID} / user_impersonation
  8. 点击添加应用

步骤5-使Service App多租户

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

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

  1. 在Azure门户中打开您的功能应用,然后导航到Authenticaiton
  2. 更改Active Directory设置,以使“服务应用程序IE”中的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();
        }
    }
}

}