问题描述
IdentityServer 客户端已注册
new Client
{
ClientId = "mtls",ClientSecrets =
{
new Secret("157F807EC5A592201C2B502CEB5934DEF645D6F5","w.test")
{
Type = IdentityServerConstants.SecretTypes.X509CertificateThumbprint
},},AccesstokenType = AccesstokenType.Jwt,AllowedGrantTypes = GrantTypes.ClientCredentials,AllowedScopes = { "resource1.scope1","resource2.scope1" }
},
和 Samples ConsoleMTLSClient 使用相同的证书。
我解决了 IdentityServer->Kestrel->certificate for sub-domain mtls.* registering 的问题,所以我继续前进,但我陷入了新问题
> [15:21:20 Debug] IdentityServer4.Endpoints.discoveryKeyEndpoint Start
> key discovery request
>
> [15:21:20 @R_46_4045@ion] Serilog.AspNetCore.RequestLoggingMiddleware
> HTTP GET /.well-kNown/openid-configuration/jwks responded 200 in
> 64.3172 ms
>
> [15:21:41 Debug] IdentityServer4.Hosting.MutualTlsEndpointMiddleware
> MTLS authentication Failed,error: null.
>
> [15:21:41 @R_46_4045@ion]
> Microsoft.AspNetCore.Authentication.Certificate.CertificateAuthenticationHandler
> AuthenticationScheme: Certificate was forbidden.
>
> [15:21:41 @R_46_4045@ion] Serilog.AspNetCore.RequestLoggingMiddleware
> HTTP POST /connect/token responded 403 in 19.5811 ms
解决方法
我成功了
首先使用powershell创建合适的证书(以管理员身份运行) 步骤一:与IDS4服务器一起使用-需要注册DNS localhost和mtls.localhost
New-SelfSignedCertificate -Subject "CN=localhost" -DnsName "localhost","mtls.localhost" -CertStoreLocation cert:\CurrentUser\My -Provider "Microsoft Strong Cryptographic Provider" -FriendlyName "AAABBBIds4mtls test" -NotAfter (Get-Date).AddYears(1)
它是自签名所以复制并粘贴(使用 Windows certmgr.exe)到“受信任的根证书颁发机构”
第 2 步:为客户端创建证书
$cert = New-SelfSignedCertificate -Subject "CN=aaabbb" -DnsName "localhost" -CertStoreLocation cert:\CurrentUser\My -Provider "Microsoft Strong Cryptographic Provider" -FriendlyName "aaabbb20210125" -NotAfter (Get-Date).AddYears(1)
$cred = Get-Credential
Export-PfxCertificate -Cert $cert -Password $cred.Password -FilePath "./aaabbb20210125.pfx"
然后我使用来自 Scoot Braddy 示例 Scott Brady blog
的客户端代码检查它如何与 Microsoft.AspNetCore.Authentication.Certificate 配合使用
接下来您需要设置托管在 Kestrel 上的 IdentityServer4 项目
程序.cs
BuildWebHost(args).Run();
.......
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseSerilog()
.UseStartup<Startup>()
.UseKestrel(options =>
{
options.Listen(IPAddress.Loopback,5001,listenOptions =>
{
listenOptions.UseHttps(new HttpsConnectionAdapterOptions
{
ServerCertificate = **get cert from step 1**
from file or windows cert store ///X509.GetCertificate("a9dfaac956575d850f718dde03c9e86a6eb15984",StoreLocation.CurrentUser),///RequireCertificate is important switch it off -to get error with client mtls validation
ClientCertificateMode = ClientCertificateMode.RequireCertificate,ClientCertificateValidation = CertificateValidator.DisableChannelValidation
});
});
options.Listen(IPAddress.Loopback,5000);
})
.Build();
检查您是否添加了 nuget 包 Microsoft.AspNetCore.Authentication.Certificate
Startup.cs
var builder = services.AddIdentityServer(options =>
{
options.Events.RaiseSuccessEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.EmitScopesAsSpaceDelimitedStringInJwt = true;
options.MutualTls.Enabled = true;
options.MutualTls.DomainName = "mtls";
options.MutualTls.ClientCertificateAuthenticationScheme = "Certificate";
//options.MutualTls.AlwaysEmitConfirmationClaim = true;
})
.AddInMemoryApiScopes(Configuration.GetApiScopes())
.AddInMemoryApiResources(Configuration.GetApiResources())
.AddInMemoryIdentityResources(Configuration.GetIdentityResources())
.AddInMemoryClients(Configuration.GetClients())
.AddMutualTlsSecretValidators()
.AddSigningCredential(X509.GetCertificate("88D603D7F65B07109E4D0FFBECCCD70881F902F8",StoreLocation.CurrentUser));//add your certificate
services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(options =>
{
options.AllowedCertificateTypes = CertificateTypes.All; //selfsigned too
options.RevocationMode = X509RevocationMode.NoCheck;//for development/testing
options.Events = new CertificateAuthenticationEvents
{
OnCertificateValidated = context =>
{
var claims = new[]
{
new Claim(ClaimTypes.NameIdentifier,context.ClientCertificate.Subject,ClaimValueTypes.String,context.Options.ClaimsIssuer),new Claim(ClaimTypes.Name,context.Options.ClaimsIssuer)
};
context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims,context.Scheme.Name));
context.Success();
return Task.CompletedTask;
}
};
});
设置 mtlsclient mtlsclient
....
static async Task<TokenResponse> RequestTokenAsync()
{
var client = new HttpClient(GetHandler());
var disco = await client.GetDiscoveryDocumentAsync("https://localhost:5001"); "https://identityserver.local");
............
static SocketsHttpHandler GetHandler()
{
var handler = new SocketsHttpHandler();
var cert = new X509Certificate2("client.p12","changeit");///**get cert from step 2**
handler.SslOptions.ClientCertificates = new X509CertificateCollection { cert };
return handler;
}
设置你的主机文件 C:\Windows\System32\drivers\etc
# To allow the MTLS for identityServer4
127.0.0.1 mtls.localhost
127.0.0.1 identityserver.local
# End of section
最后运行IDS4,运行mtlsclient
[19:36:48 Debug] IdentityServer4.Endpoints.TokenEndpoint
Start token request.
[19:36:48 Debug] IdentityServer4.Validation.ClientSecretValidator
Start client validation
[19:36:48 Debug] IdentityServer4.Validation.BasicAuthenticationSecretParser
Start parsing Basic Authentication secret
[19:36:48 Debug] IdentityServer4.Validation.PostBodySecretParser
Start parsing for secret in post body
[19:36:48 Debug] IdentityServer4.Validation.PostBodySecretParser
client id without secret found
[19:36:48 Debug] IdentityServer4.Validation.ISecretsListParser
Parser found secret: PostBodySecretParser
[19:36:48 Debug] IdentityServer4.Validation.MutualTlsSecretParser
Start parsing for client id in post body
[19:36:48 Debug] IdentityServer4.Validation.ISecretsListParser
Parser found secret: MutualTlsSecretParser
[19:36:48 Debug] IdentityServer4.Validation.ISecretsListParser
Secret id found: mtls
[19:36:48 Debug] IdentityServer4.Stores.ValidatingClientStore
client configuration validation for client mtls succeeded.
[19:36:48 Debug] IdentityServer4.Validation.HashedSharedSecretValidator
Hashed shared secret validator cannot process X509Certificate
[19:36:48 Debug] IdentityServer4.Validation.ISecretsListValidator
Secret validator success: X509ThumbprintSecretValidator
[19:36:48 Debug] IdentityServer4.Validation.ClientSecretValidator
Client validation success
[19:36:48 Information] IdentityServer4.Events.DefaultEventService
{"ClientId": "mtls","AuthenticationMethod": "X509Certificate","Category": "Authentication","Name": "Client Authentication Success","EventType": "Success","Id": 1010,"Message": null,"ActivityId": "0HM62U8QNJK8Q:00000001","TimeStamp": "2021-01-27T18:36:48.0000000Z","ProcessId": 27900,"LocalIpAddress": "127.0.0.1:5001","RemoteIpAddress": "127.0.0.1","$type": "ClientAuthenticationSuccessEvent"}
[19:36:48 Debug] IdentityServer4.Validation.TokenRequestValidator
Start token request validation
[19:36:48 Debug] IdentityServer4.Validation.TokenRequestValidator
Start client credentials token request validation
[19:36:48 Debug] IdentityServer4.Validation.TokenRequestValidator
mtls credentials token request validation success
[19:36:48 Information] IdentityServer4.Validation.TokenRequestValidator
Token request validation success,{"ClientId": "mtls","ClientName": null,"GrantType": "client_credentials","Scopes": "AconsApi ApiTwo","AuthorizationCode": "********","RefreshToken": "********","UserName": null,"AuthenticationContextReferenceClasses": null,"Tenant": null,"IdP": null,"Raw": {"grant_type": "client_credentials","scope": "AconsApi ApiTwo","client_id": "mtls"},"$type": "TokenRequestValidationLog"}
[19:36:48 Debug] IdentityServer4.Services.DefaultClaimsService
Getting claims for access token for client: mtls
[19:36:49 Information] IdentityServer4.Events.DefaultEventService
{"ClientId": "mtls","RedirectUri": null,"Endpoint": "Token","SubjectId": null,"Tokens": [{"TokenType": "access_token","TokenValue": "****hTTg","$type": "Token"}],"Category": "Token","Name": "Token Issued Success","Id": 2000,"TimeStamp": "2021-01-27T18:36:49.0000000Z","$type": "TokenIssuedSuccessEvent"}
[19:36:49 Debug] IdentityServer4.Endpoints.TokenEndpoint
Token request success.
MTLS 客户端
Access Token (decoded):
{
"alg": "RS256","kid": "88D603D7F65B07109E4D0FFBECCCD70881F902F8RS256","typ": "at+jwt","x5t": "iNYD1_ZbBxCeTQ_77MzXCIH5Avg"
}
{
"nbf": 1611772608,"exp": 1611776208,"iss": "https://localhost:5001","aud": [
"Api","ApiTwo"
],"client_id": "mtls","jti": "447F97582B1C1ADDABB237B7E36C4F32","iat": 1611772608,"cnf": {
"x5t#S256": "1F9sG7CCC77SL9LI9edhus9Ga8AKJgfE5eraKvrv438"
}
}
总结
- 1.setup ...\ets\hosts
- 2.准备证书 step1 step2(makecert.exe 不适用于 SAN(主题备用名称))
- 3.setup IDS4 Program.cs Startup.cs
- 4. 使用第 2 步中的 mtlsclient 证书