public async Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret) { var success = new SecretValidationResult { Success = true }; var fail = new SecretValidationResult { Success = false }; var issuer = GetIssuer(parsedSecret); if (string.IsNullOrEmpty(issuer) || issuer == "NULL") { _logger.LogInformation("Issuer is not present"); return(fail); } var isValid = await _partiesValidation.IsValidParty(issuer); if (!isValid) { _logger.LogInformation("{Issuer} is not a valid party", issuer); return(fail); } return(success); }
public Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret) { if (secrets.Any()) { if (secrets.First().Type == "confirmation.test") { var cnf = new Dictionary <string, string> { { "x5t#S256", "foo" } }; var result = new SecretValidationResult { Success = true, Confirmation = JsonConvert.SerializeObject(cnf) }; return(Task.FromResult(result)); } } return(Task.FromResult(new SecretValidationResult { Success = false })); }
/// <summary> /// Validate api secrets /// </summary> /// <param name="secrets"></param> /// <param name="parsedSecret"></param> /// <returns></returns> public async Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret) { SecretValidationResult validationResult; // Impersonation. If the current user is an admin, we allow any password to be used for the token if (_contextAccessor.HttpContext.User.Identity.IsAuthenticated) { if (_contextAccessor.HttpContext.User.HasClaim(tbl => tbl.Type == ClaimTypes.Role && (tbl.Value.ToLower() == "root" || tbl.Value.ToLower() == "moderator"))) { validationResult = new SecretValidationResult() { IsError = false, Success = true }; return(await Task.FromResult(validationResult)); } } // Owner's credentials var result = _passwordHasher.VerifyHashedPassword( parsedSecret.Id, secrets?.FirstOrDefault()?.Value, parsedSecret.Credential.ToString()); validationResult = new SecretValidationResult { IsError = result == PasswordVerificationResult.Failed, Success = result == PasswordVerificationResult.Success }; return(await Task.FromResult(validationResult)); }
/// <summary> /// 设置秘钥类型后会触发该实现进行验证秘钥 /// ClientSecrets = new[] { /// new Secret() /// { /// Value = client.ClientSecrets, /// Type = IdentityServerConstants.SecretTypes.SharedSecret /// } /// } /// </summary> /// <param name="secrets"></param> /// <param name="parsedSecret"></param> /// <returns></returns> public Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret) { SecretValidationResult secretValidationResult = new SecretValidationResult(); secretValidationResult.Success = true; secretValidationResult.IsError = false; return(Task.FromResult(secretValidationResult)); }
public Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret) { var result = new SecretValidationResult { Success = true }; return(Task.FromResult(result)); }
public Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret) { //parsedSecret. //IdentityServer4.Validation.ClientSecretValidator var result = new SecretValidationResult { Success = false }; return(Task.FromResult(result)); }
public Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret) { // this is just for demo var success = new SecretValidationResult { IsError = false, Success = true }; return(Task.FromResult(success)); }
public async Task <ClientSecretValidationResult> ValidateAsync(HttpContext context) { var fail = new ClientSecretValidationResult { IsError = true }; var parsedSecret = await ParseAsync(context); if (parsedSecret == null) { await RaiseFailureEventAsync("unknown", "No client id found"); return(fail); } var client = await _clients.FindEnabledClientByIdAsync(parsedSecret.Id); if (client == null) { await RaiseFailureEventAsync(parsedSecret.Id, "Unknown client"); return(fail); } SecretValidationResult secretValidationResult = null; if (client.RequireClientSecret || !client.IsImplicitOnly()) { secretValidationResult = await _validator.ValidateAsync(client.ClientSecrets, parsedSecret); if (secretValidationResult.Success == false) { await RaiseFailureEventAsync(client.ClientId, "Invalid client secret"); return(fail); } } var success = new ClientSecretValidationResult { IsError = false, Client = client, Secret = parsedSecret, Confirmation = secretValidationResult?.Confirmation }; await RaiseSuccessEventAsync(client.ClientId, parsedSecret.Type); return(success); }
/// <inheritdoc/> public Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret) { var fail = Task.FromResult(new SecretValidationResult { Success = false }); if (parsedSecret.Type != IdentityServerConstants.ParsedSecretTypes.X509Certificate) { _logger.LogDebug("X509 name secret validator cannot process {type}", parsedSecret.Type ?? "null"); return(fail); } if (!(parsedSecret.Credential is X509Certificate2 cert)) { throw new InvalidOperationException("Credential is not a x509 certificate."); } var name = cert.Subject; if (name == null) { _logger.LogWarning("No subject/name found in X509 certificate."); return(fail); } var nameSecrets = secrets.Where(s => s.Type == IdentityServerConstants.SecretTypes.X509CertificateName); if (!nameSecrets.Any()) { _logger.LogDebug("No x509 name secrets configured for client."); return(fail); } foreach (var nameSecret in nameSecrets) { if (name.Equals(nameSecret.Value, StringComparison.Ordinal)) { var result = new SecretValidationResult { Success = true, Confirmation = cert.CreateThumbprintCnf() }; return(Task.FromResult(result)); } } _logger.LogDebug("No matching x509 name secret found."); return(fail); }
public async Task <SecretValidationResult> ValidateAsync(AssertionModel assertion) { var fail = new SecretValidationResult { Success = false }; if (assertion == null) { _logger.LogInformation("The client assertion is not provided."); return(fail); } if (assertion.Typ == null || !assertion.Typ.Equals("jwt", StringComparison.InvariantCultureIgnoreCase)) { _logger.LogError("Client assertion \"typ\" header is not \"JWT\"."); return(fail); } if (assertion.Exp - assertion.Iat != 30) { _logger.LogError("Client assertion validity should be exactly 30 seconds."); return(fail); } if (!assertion.Certificates.Any()) { _logger.LogInformation("The x5c certificates chain is not provided."); return(fail); } try { if (!await _certificateValidator.IsValid(DateTime.UtcNow, assertion.Certificates.ToArray())) { _logger.LogInformation("Certificate chain is not valid"); return(fail); } } catch (Exception ex) { _logger.LogWarning(ex, "Could not load certificate from x5C header."); return(fail); } return(await Task.FromResult(new SecretValidationResult { Success = true })); }
public async Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret) { _logger.LogDebug("Validate client assertion started"); var fail = new SecretValidationResult { Success = false }; if (parsedSecret.Type != IdentityServerConstants.ParsedSecretTypes.JwtBearer) { _logger.LogDebug($"Secret type is not a JwtBearer, instead it was {parsedSecret.Type}"); return(fail); } if (!(parsedSecret.Credential is string jwtTokenString)) { _logger.LogDebug("Secret is not like a JWT string"); return(fail); } return(await _assertionManager.ValidateAsync(jwtTokenString)); }
public async Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret) { var fail = new SecretValidationResult { Success = false }; var assertion = parsedSecret.Credential as string; if (assertion == null) { _logger.LogInformation("The client assertion is not provided."); return(fail); } var certificates = _assertionParser.GetCertificatesData(assertion); if (!certificates.Any()) { _logger.LogInformation("The x5c certificates chain is not provided."); return(fail); } var validateCertificateResult = await _schemeOwnerClient.ValidateCertificate(new ClientAssertion(), certificates.ToArray()).ConfigureAwait(false); if (!validateCertificateResult.Validity) { _logger.LogError("Scheme Owner didn't validate the certificates."); return(fail); } var secretsIncludingCertificates = secrets.ToList(); secretsIncludingCertificates.AddRange(certificates.Select(c => new Secret { Type = IdentityServerConstants.SecretTypes.X509CertificateBase64, Value = c })); var result = await _innerValidator.Instance.ValidateAsync(secretsIncludingCertificates, parsedSecret); return(result); }
async public Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret) { foreach (var secret in secrets .Where(s => "SecretsVault-Secret".Equals(s.Type, StringComparison.CurrentCultureIgnoreCase))) { var secretsVersion = await _secretsVaultManager.GetSecretVersion(secret.Value); if (parsedSecret.Credential?.ToString() == secretsVersion.Secret) { return(new SecretValidationResult() { Success = true }); } } var result = new SecretValidationResult() { Success = false }; return(result); }
public virtual Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret) { var fail = Task.FromResult(new SecretValidationResult { Success = false }); if (parsedSecret == null || parsedSecret.Type != IdentityServerConstants.ParsedSecretTypes.X509Certificate) { this.Logger.LogDebugIfEnabled($"{this.SecretType} secret validator cannot process {parsedSecret?.Type ?? "null"}."); return(fail); } if (!(parsedSecret.Credential is X509Certificate2 certificate)) { throw new InvalidOperationException("Credential is not a x509 certificate."); } var issuer = certificate.Issuer; if (issuer == null) { this.Logger.LogWarningIfEnabled("The certificate-issuer is null."); return(fail); } var issuerSecrets = secrets.Where(secret => string.Equals(secret.Type, this.SecretType, StringComparison.Ordinal)).ToArray(); if (!issuerSecrets.Any()) { this.Logger.LogDebugIfEnabled($"No {this.SecretType} secrets configured for client."); return(fail); } // ReSharper disable All foreach (var secret in issuerSecrets) { var secretDescription = string.IsNullOrEmpty(secret.Description) ? "no description" : secret.Description; if (issuer.Equals(secret.Value, StringComparison.OrdinalIgnoreCase)) { var values = new Dictionary <string, string> { { "x5t#S256", certificate.Thumbprint } }; var confirmation = JsonConvert.SerializeObject(values); var result = new SecretValidationResult { Success = true, Confirmation = confirmation }; return(Task.FromResult(result)); } } // ReSharper restore All this.Logger.LogDebugIfEnabled($"No matching {this.SecretType} secret found."); return(fail); }
/// <summary> /// Validates the current request. /// </summary> /// <param name="context">The context.</param> /// <returns></returns> public async Task <ClientSecretValidationResult> ValidateAsync(HttpContext context) { _logger.LogDebug("Start client validation"); var fail = new ClientSecretValidationResult { IsError = true }; var parsedSecret = await _parser.ParseAsync(context); if (parsedSecret == null) { await RaiseFailureEventAsync("unknown", "No client id found"); _logger.LogError("No client identifier found"); return(fail); } // load client var client = await _clients.FindEnabledClientByIdAsync(parsedSecret.Id) as ClientExtra; if (client == null) { await RaiseFailureEventAsync(parsedSecret.Id, $"Unknown client for tenant: '{_scopedTenantRequestContext.Context.TenantName}'"); _logger.LogError($"No client with id '{parsedSecret.Id}' for tenant: '{_scopedTenantRequestContext.Context.TenantName}' found. aborting"); return(fail); } SecretValidationResult secretValidationResult = null; if (!client.RequireClientSecret || client.IsImplicitOnly()) { _logger.LogDebug("Public Client - skipping secret validation success"); } else { //////////////////////////////////////// // Check if this is a refresh_token //////////////////////////////////////// bool continueValidation = true; if (!client.RequireRefreshClientSecret) { try { var parameters = (await context.Request.ReadFormAsync()).AsNameValueCollection(); var grantType = parameters.Get(OidcConstants.TokenRequest.GrantType); if (!string.IsNullOrWhiteSpace(grantType) && grantType == OidcConstants.GrantTypes.RefreshToken) { // let it through _logger.LogDebug("RequireRefreshClientSecret == false - skipping secret validation success"); continueValidation = false; } } catch (Exception ex) { // let it through _logger.LogDebug("RequireRefreshClientSecret == false - skipping secret validation success"); continueValidation = false; } } if (continueValidation) { secretValidationResult = await _validator.ValidateAsync(client.ClientSecrets, parsedSecret); if (secretValidationResult.Success == false) { await RaiseFailureEventAsync(client.ClientId, "Invalid client secret"); _logger.LogError("Client secret validation failed for client: {clientId}.", client.ClientId); return(fail); } } } _logger.LogDebug("Client validation success"); var success = new ClientSecretValidationResult { IsError = false, Client = client, Secret = parsedSecret, Confirmation = secretValidationResult?.Confirmation }; await RaiseSuccessEventAsync(client.ClientId, parsedSecret.Type); return(success); }
/// <summary> /// Validates a secret /// </summary> /// <param name="secrets">The stored secrets.</param> /// <param name="parsedSecret">The received secret.</param> /// <returns> /// A validation result /// </returns> /// <exception cref="System.ArgumentException">ParsedSecret.Credential is not a JWT token</exception> public async Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret) { var fail = new SecretValidationResult { Success = false }; var success = new SecretValidationResult { Success = true }; if (parsedSecret.Type != IdentityServerConstants.ParsedSecretTypes.JwtBearer) { return(fail); } if (!(parsedSecret.Credential is string jwtTokenString)) { _logger.LogError("ParsedSecret.Credential is not a string."); return(fail); } List <SecurityKey> trustedKeys; try { trustedKeys = await secrets.GetKeysAsync(); } catch (Exception e) { _logger.LogError(e, "Could not parse secrets"); return(fail); } if (!trustedKeys.Any()) { _logger.LogError("There are no keys available to validate client assertion."); return(fail); } var validAudiences = new[] { // token endpoint URL string.Concat(_urls.BaseUrl.EnsureTrailingSlash(), Constants.ProtocolRoutePaths.Token), // TODO: remove the issuer URL in a future major release? // issuer URL string.Concat((await _issuerNameService.GetCurrentAsync()).EnsureTrailingSlash(), Constants.ProtocolRoutePaths.Token) }.Distinct(); var tokenValidationParameters = new TokenValidationParameters { IssuerSigningKeys = trustedKeys, ValidateIssuerSigningKey = true, ValidIssuer = parsedSecret.Id, ValidateIssuer = true, ValidAudiences = validAudiences, ValidateAudience = true, RequireSignedTokens = true, RequireExpirationTime = true, ClockSkew = TimeSpan.FromMinutes(5) }; var handler = new JsonWebTokenHandler() { MaximumTokenSizeInBytes = _options.InputLengthRestrictions.Jwt }; var result = handler.ValidateToken(jwtTokenString, tokenValidationParameters); if (!result.IsValid) { _logger.LogError(result.Exception, "JWT token validation error"); return(fail); } var jwtToken = (JsonWebToken)result.SecurityToken; if (jwtToken.Subject != jwtToken.Issuer) { _logger.LogError("Both 'sub' and 'iss' in the client assertion token must have a value of client_id."); return(fail); } var exp = jwtToken.ValidTo; if (exp == DateTime.MinValue) { _logger.LogError("exp is missing."); return(fail); } var jti = jwtToken.Id; if (jti.IsMissing()) { _logger.LogError("jti is missing."); return(fail); } if (await _replayCache.ExistsAsync(Purpose, jti)) { _logger.LogError("jti is found in replay cache. Possible replay attack."); return(fail); } else { await _replayCache.AddAsync(Purpose, jti, exp.AddMinutes(5)); } return(success); }
/// <summary> /// 登录校验密钥 /// </summary> /// <param name="context"></param> /// <returns></returns> public async Task <ClientSecretValidationResult> ValidateAsync(HttpContext context) { var _signInManager = (SignInManager <ApplicationUser>)context.RequestServices.GetService(typeof(SignInManager <ApplicationUser>)); _logger.LogDebug("Start client validation"); //错误返回 var fail = new ClientSecretValidationResult { IsError = true }; //根据上下文查找密钥 var parsedSecret = await _parser.ParseAsync(context); if (parsedSecret == null) { await RaiseFailureEventAsync("unknown", "No client id found"); _logger.LogError("No client identifier found"); return(fail); } // 加载客户端配置 var client = await _clients.FindEnabledClientByIdAsync(parsedSecret.Id); if (client == null) { await RaiseFailureEventAsync(parsedSecret.Id, "Unknown client"); _logger.LogError("No client with id '{clientId}' found. aborting", parsedSecret.Id); return(fail); } SecretValidationResult secretValidationResult = null; if (!client.RequireClientSecret || client.IsImplicitOnly()) { _logger.LogDebug("Public Client - skipping secret validation success"); } else { //验证客户端密钥 secretValidationResult = await _validator.ValidateAsync(parsedSecret, client.ClientSecrets); if (secretValidationResult.Success == false) { await RaiseFailureEventAsync(client.ClientId, "Invalid client secret"); _logger.LogError("Client secret validation failed for client: {clientId}.", client.ClientId); return(fail); } } _logger.LogDebug("Client validation success"); //var user = await _signInManager.UserManager.FindByNameAsync(context.User.Identity.Name); //var claimsPrincipal = await _signInManager.ClaimsFactory.CreateAsync(user); var success = new ClientSecretValidationResult { IsError = false, Client = client, Secret = parsedSecret, Confirmation = secretValidationResult?.Confirmation }; await RaiseSuccessEventAsync(client.ClientId, parsedSecret.Type); return(success); }
/// <summary> /// Validates the current request. /// </summary> /// <param name="context">The context.</param> /// <returns></returns> public async Task <ClientSecretValidationResult> ValidateAsync(HttpContext context) { using var activity = Tracing.ValidationActivitySource.StartActivity("ClientSecretValidator.Validate"); _logger.LogDebug("Start client validation"); var fail = new ClientSecretValidationResult { IsError = true }; var parsedSecret = await _parser.ParseAsync(context); if (parsedSecret == null) { await RaiseFailureEventAsync("unknown", "No client id found"); _logger.LogError("No client identifier found"); return(fail); } // load client var client = await _clients.FindEnabledClientByIdAsync(parsedSecret.Id); if (client == null) { await RaiseFailureEventAsync(parsedSecret.Id, "Unknown client"); _logger.LogError("No client with id '{clientId}' found. aborting", parsedSecret.Id); return(fail); } SecretValidationResult secretValidationResult = null; if (!client.RequireClientSecret || client.IsImplicitOnly()) { _logger.LogDebug("Public Client - skipping secret validation success"); } else { secretValidationResult = await _validator.ValidateAsync(client.ClientSecrets, parsedSecret); if (secretValidationResult.Success == false) { await RaiseFailureEventAsync(client.ClientId, "Invalid client secret"); _logger.LogError("Client secret validation failed for client: {clientId}.", client.ClientId); return(fail); } } _logger.LogDebug("Client validation success"); var success = new ClientSecretValidationResult { IsError = false, Client = client, Secret = parsedSecret, Confirmation = secretValidationResult?.Confirmation }; await RaiseSuccessEventAsync(client.ClientId, parsedSecret.Type); return(success); }
/// <summary> /// Validates a secret /// </summary> /// <param name="secrets">The stored secrets.</param> /// <param name="parsedSecret">The received secret.</param> /// <returns> /// A validation result /// </returns> /// <exception cref="System.ArgumentException">ParsedSecret.Credential is not a JWT token</exception> public async Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret) { var fail = new SecretValidationResult { Success = false }; var success = new SecretValidationResult { Success = true }; if (parsedSecret.Type != IdentityServerConstants.ParsedSecretTypes.JwtBearer) { return(fail); } if (!(parsedSecret.Credential is string jwtTokenString)) { _logger.LogError("ParsedSecret.Credential is not a string."); return(fail); } List <SecurityKey> trustedKeys; try { trustedKeys = await secrets.GetKeysAsync(); } catch (Exception e) { _logger.LogError(e, "Could not parse secrets"); return(fail); } if (!trustedKeys.Any()) { _logger.LogError("There are no keys available to validate client assertion."); return(fail); } var tokenValidationParameters = new TokenValidationParameters { IssuerSigningKeys = trustedKeys, ValidateIssuerSigningKey = true, ValidIssuer = parsedSecret.Id, ValidateIssuer = true, ValidAudience = _audienceUri, ValidateAudience = true, RequireSignedTokens = true, RequireExpirationTime = true }; try { var handler = new JwtSecurityTokenHandler(); handler.ValidateToken(jwtTokenString, tokenValidationParameters, out var token); var jwtToken = (JwtSecurityToken)token; if (jwtToken.Subject != jwtToken.Issuer) { _logger.LogError("Both 'sub' and 'iss' in the client assertion token must have a value of client_id."); return(fail); } return(success); } catch (Exception e) { _logger.LogError(e, "JWT token validation error"); return(fail); } }