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 阅读(1326) 评论(0) 编辑 收藏 举报