gpt4 book ai didi

c# - 我的 ASP.NET Core 应用服务 Web API 如何支持 AAD 承载 token 和客户端证书身份验证?

转载 作者:行者123 更新时间:2023-12-03 02:39:54 25 4
gpt4 key购买 nike

我有一个应用服务 Web API,我想支持 Azure Active Directory 身份验证以及客户端证书身份验证。

我按照这些指南到达了现在的位置:

这是我到目前为止的设置:

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
services
.AddAuthentication()
.AddAzureADBearer(options => Configuration.Bind("AzureAd", options))
.AddCertificate();

services.Configure<JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationScheme, options =>
{
options.TokenValidationParameters.ValidAudiences = new[]
{
options.Audience,
};
});

services
.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddAuthenticationSchemes(
CertificateAuthenticationDefaults.AuthenticationScheme,
AzureADDefaults.JwtBearerAuthenticationScheme)
.Build();
});

services.AddSingleton<IAuthorizationHandler, MyAuthorizationHandler>();

services.AddControllers().AddControllersAsServices();
}

public static void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseAuthentication();
app.UseAuthorization();
...

MyAuthorizationHandler.cs

public class MyAuthorizationHandler : IAuthorizationHandler
{
private const string AppIdClaimType = "appid";
private const string AppIdACRClaimType = "appidacr";

private readonly HashSet<string> allowedCertificateSubjects;
private readonly HashSet<string> allowedAadClients;

private readonly IWebHostEnvironment env;
private readonly IHttpContextAccessor httpContextAccessor;
public MyAuthorizationHandler(
IWebHostEnvironment env,
IHttpContextAccessor httpContextAccessor,
IUnityContainer unityContainer)
{
this.env = env;
this.httpContextAccessor = httpContextAccessor;
allowedCertificateSubjects = // Get from DI;
allowedAadClients = // Get from DI;
}

public Task HandleAsync(AuthorizationHandlerContext context)
{
bool isAuthorized = false;

// Check for Certificate First
string certificateSubjectName = null;
if (env.IsDevelopment())
{
// Is Local environment, the cert is pasded through the Claims
Claim subjectNameClaim = context.User.Claims.FirstOrDefault(claim => claim.Type == ClaimTypes.Name);

if (subjectNameClaim != null)
{
certificateSubjectName = subjectNameClaim.Value;
}
}
else
{
// https://learn.microsoft.com/en-us/azure/app-service/app-service-web-configure-tls-mutual-auth
// App Service by default captures the client certificate, and passes it through
// in the Header X-ARR-ClientCert. We have to read it from there to verify.
string certHeader = httpContextAccessor.HttpContext.Request.Headers["X-ARR-ClientCert"];
if (!string.IsNullOrEmpty(certHeader))
{
try
{
var certificate = new X509Certificate2(Convert.FromBase64String(certHeader));
certificateSubjectName = certificate.GetNameInfo(X509NameType.SimpleName, forIssuer: false);
}
catch (Exception)
{
// If there is an error parsing the value (e.g. fake value passed in header),
// we should not error, but just ignore the header value.
}
}
}

// Validate Certificate
if (allowedCertificateSubjects.Contains(certificateSubjectName, StringComparer.OrdinalIgnoreCase))
{
isAuthorized = true;
}
else
{
// If no cert found or not valid, check for AAD Bearer Token
Claim authTypeClaim = context.User.Claims.FirstOrDefault(claim => claim.Type == AppIdACRClaimType);
Claim claimAppId = context.User.Claims.FirstOrDefault(claim => claim.Type == AppIdClaimType);

if (authTypeClaim != null && claimAppId != null)
{
// We only support Client/Secret and Cert AAD auth, not user auth.
bool isValidAuthType = authTypeClaim.Value == "1" || authTypeClaim.Value == "2";
bool isValidAppId = allowedAadClients.Contains(claimAppId.Value, StringComparer.OrdinalIgnoreCase);

if (isValidAuthType && isValidAppId)
{
isAuthorized = true;
}
}
}

if (!isAuthorized)
{
context.Fail();
}

return Task.CompletedTask;
}
}

应用程序设置已将 WEBSITE_LOAD_CERTIFICATES 设置为 *

应用服务需要客户端证书设置:

enter image description here

我已从“需要传入证书”中排除了所有路径,因为我希望 Aad 或 Cert 身份验证可用。

注释:

  • 在本地运行我的 API 时,会正确获取证书并通过声明。在我的应用服务中运行时,证书似乎被应用服务删除了。这就是为什么我有 if (env.IsDevelopment()) 语句来在 Claims 和 X-ARR-ClientCert header 之间进行选择。
  • 当我排除“传入客户端证书”中的所有路径时,X-ARR-ClientCert header 不会被传递。当我删除排除项时,它会正确传递 header 。

我有什么办法可以:

  1. 获取要通过我的产品应用服务应用中的用户声明传递的客户端证书吗?
  2. 让应用服务传递 X-ARR-ClientCert header 而不强制提供客户端证书?
  3. 有什么我遗漏的/更好的方法吗?

最佳答案

正如您已经发现的,Azure 应用服务不会设置 X-ARR-ClientCert由于已禁用(服务器级)身份验证,因此已排除路径的请求 header 。

禁用Web app client certificates并附上并从 a custom header using options.CertificateHeader = "value" 获取证书.

关于c# - 我的 ASP.NET Core 应用服务 Web API 如何支持 AAD 承载 token 和客户端证书身份验证?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61646162/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com