Azure AAD 验证方式

总结一下最近项目上使用azure 遇到的问题。

azure functions 使用 aad auoth 2.0 身份证书身份认证。从国外一个博客上学到的知识。信息量非常大,博客中介绍了如何使用key vault 创建证书。

 

 

先简单介绍一下原理,然后再讲一下容易出错的细节

azure funcation: funcApi; 对应的 app叫 funApiApp ,配置一个客户端app 叫 clientApp.

我们把前期工作先做好:

1 创建azure funcation funcAPI

2.在azure activity directory 中注册两个APP。funApiApp 和clientApp。

3.在key vault 中创建证书。并将CER格式的证书下载。

1 配置 azure function 使用 AAD身份认证,使用Express模式,选择前期工作中创建的APP:funApiApp 

2 配置APP:funApiApp ,编辑mainfest: 添加appRoles 将保存

"appRoles": [
		{
			"allowedMemberTypes": [
				"Application"
			],
			"description": "Accesss the service-api",
			"displayName": "service-api",
			"id": "d5deb0a5-0d04-4740-a48d-d6b92c3578db",
			"isEnabled": true,
			"lang": null,
			"origin": "Application",
			"value": "service-api"
		},
		{
			"allowedMemberTypes": [
				"Application"
			],
			"description": "Accesss the access_as_applicaton",
			"displayName": "access_as_application",
			"id": "d3deb0a5-0d04-4740-a48d-d6b92c3578db",
			"isEnabled": true,
			"lang": null,
			"origin": "Application",
			"value": "access_as_application"
		}
	],

  

3 配置clientAPP,上传在前期工作中3步的证书上传

 

 

 

 4 添加权限,添加对funcApiApp的权限

 

 

 

 

 

 5。获取funapiApp的 appid.及刚才的URL

6.获取clientapp的clientid

7。配置key vault的访问权限,可以在代码获取证书文件。

Get started with Key Vault certificates | Microsoft Docs

 

 

 

 

 

 8 获取证书,获取token,调用API代码如下 

 public static async Task Test()
        {

            
            // Use Key Vault to get certificate
            var azureServiceTokenProvider = new AzureServiceTokenProvider();

            // Get the certificate from Key Vault
            var identifier = Environment.GetEnvironmentVariable("KeyVaultCertificateName");//Environment.GetEnvironmentVariable("ClientCertificates:0:KeyVaultCertificateName"];
            var cert = await GetCertificateAsync(identifier);

            var scope =Environment.GetEnvironmentVariable("ScopeForAccessToken");
            var authority = $"{Environment.GetEnvironmentVariable("Instance")}{Environment.GetEnvironmentVariable("TenantId")}";

            // client credentials flows, get access token
            IConfidentialClientApplication app = ConfidentialClientApplicationBuilder
                     .Create(Environment.GetEnvironmentVariable("ClientId"))
                     .WithAuthority(new Uri(authority))
                     .WithCertificate(cert)
                     .WithLogging(MyLoggingMethod, Microsoft.Identity.Client.LogLevel.Verbose,
                         enablePiiLogging: true, enableDefaultPlatformLogging: true)
                     .Build();

            var accessToken = await app.AcquireTokenForClient(new[] { scope }).ExecuteAsync();


            HttpClient client = new HttpClient();

            client.BaseAddress = new Uri(Environment.GetEnvironmentVariable("ApiBaseAddress"));
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.AccessToken);
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            // use access token and get payload
            var content = new StringContent("", Encoding.UTF8, "application/json");

            var response = await client.PostAsync(Environment.GetEnvironmentVariable("TargetURL"), content); ;
            if (response.IsSuccessStatusCode)
            {
                var responseContent = await response.Content.ReadAsStringAsync();
                var data = JArray.Parse(responseContent);

               //eturn data;
            }
        }

        private static async Task<X509Certificate2> GetCertificateAsync(string identitifier)
        {
            var vaultBaseUrl =Environment.GetEnvironmentVariable("KeyVaultUrl");

            // including AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, and AZURE_TENANT_ID.
            var secretClient = new SecretClient(vaultUri: new Uri(vaultBaseUrl),
                   credential: new DefaultAzureCredential());
           

            // Create a new secret using the secret client.
            var secretName = identitifier;
            //var secretVersion = "";
            KeyVaultSecret secret = await secretClient.GetSecretAsync(secretName);

            var privateKeyBytes = Convert.FromBase64String(secret.Value);

            var certificateWithPrivateKey = new X509Certificate2(privateKeyBytes,
                (string)null,
                X509KeyStorageFlags.MachineKeySet);

            return certificateWithPrivateKey;
        }

        static void MyLoggingMethod(Microsoft.Identity.Client.LogLevel level, string message, bool containsPii)
        {
            _log.LogInformation($"MSAL {level} {containsPii} {message}");
        }

 

PS:获取key vault 的配置需要配置环境变量

 

 

在项目中设置环境变量,
// Create a new certificate client using the default credential from Azure.Identity using environment variables previously set, // including AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, and AZURE_TENANT_ID. var client = new CertificateClient(vaultUri: new Uri(keyVaultUrl), credential: new DefaultAzureCredential());
 

其它配置文件:

 

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet",
    "ScopeForAccessToken": "http://XXXXX/.default",
    "ApiBaseAddress": "https://localhost:44390",
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "damienbodhotmail.onmicrosoft.com",
    "TenantId": "XXXXX,
    "ClientId": "XXXXX",


    "SourceType": "KeyVault",
    "KeyVaultUrl": "https://XXX.vault.azure.net/",
    "KeyVaultCertificateName": "XXXX"
  }
}

  

 原理图

 

posted on 2021-02-09 18:00  HelloHongfu  阅读(1121)  评论(0编辑  收藏  举报

导航