internal bool TryValidate(X509Certificate2 certificate, out Exception exception) { using (X509Chain chain = new X509Chain(this.useMachineContext)) { chain.ChainPolicy = this.chainPolicy; if (!chain.Build(certificate)) { exception = new SecurityTokenValidationException(SR.GetString(SR.X509ChainBuildFail, SecurityUtils.GetCertificateId(certificate), GetChainStatusInformation(chain.ChainStatus))); return(false); } if (chain.ChainElements.Count > 1) //is not self-signed { chain.ChainPolicy = OidChainPolicy; X509Certificate2 cert = chain.ChainElements[1].Certificate; if (!chain.Build(cert)) { exception = new SecurityTokenValidationException(SR.GetString(SR.X509ChainBuildFail, SecurityUtils.GetCertificateId(certificate), GetChainStatusInformation(chain.ChainStatus))); return(false); } } exception = null; return(true); } }
internal bool TryValidate(X509Certificate2 certificate, out Exception exception) { // Checklist // 1) time validity of cert // 2) in trusted people store // 3) not in disallowed store // The following code could be written as: // DateTime now = DateTime.UtcNow; // if (now > certificate.NotAfter.ToUniversalTime() || now < certificate.NotBefore.ToUniversalTime()) // // this is because X509Certificate2.xxx doesn't return UT. However this would be a SMALL perf hit. // I put a DebugAssert so that this will ensure that the we are compatible with the CLR we shipped with DateTime now = DateTime.Now; DiagnosticUtility.DebugAssert(now.Kind == certificate.NotAfter.Kind && now.Kind == certificate.NotBefore.Kind, ""); if (now > certificate.NotAfter || now < certificate.NotBefore) { exception = new SecurityTokenValidationException(SR.Format(SR.X509InvalidUsageTime, SecurityUtils.GetCertificateId(certificate), now, certificate.NotBefore, certificate.NotAfter)); return(false); } if (!StoreContainsCertificate(StoreName.TrustedPeople, certificate)) { exception = new SecurityTokenValidationException(SR.Format(SR.X509IsNotInTrustedStore, SecurityUtils.GetCertificateId(certificate))); return(false); } if (StoreContainsCertificate(StoreName.Disallowed, certificate)) { exception = new SecurityTokenValidationException(SR.Format(SR.X509IsInUntrustedStore, SecurityUtils.GetCertificateId(certificate))); return(false); } exception = null; return(true); }
internal bool TryValidate(X509Certificate2 certificate, out Exception exception) { DateTime now = DateTime.Now; if ((now > certificate.NotAfter) || (now < certificate.NotBefore)) { exception = new SecurityTokenValidationException(System.IdentityModel.SR.GetString("X509InvalidUsageTime", new object[] { System.IdentityModel.SecurityUtils.GetCertificateId(certificate), now, certificate.NotBefore, certificate.NotAfter })); return(false); } if (!StoreContainsCertificate(StoreName.TrustedPeople, certificate)) { exception = new SecurityTokenValidationException(System.IdentityModel.SR.GetString("X509IsNotInTrustedStore", new object[] { System.IdentityModel.SecurityUtils.GetCertificateId(certificate) })); return(false); } if (StoreContainsCertificate(StoreName.Disallowed, certificate)) { exception = new SecurityTokenValidationException(System.IdentityModel.SR.GetString("X509IsInUntrustedStore", new object[] { System.IdentityModel.SecurityUtils.GetCertificateId(certificate) })); return(false); } exception = null; return(true); }
private async Task <JwtSecurityToken> ValidateTokenAsync( string token, string issuer, string audience, ILogger log, IConfigurationManager <OpenIdConnectConfiguration> configurationManager, CancellationToken ct = default(CancellationToken)) { JwtSecurityToken result = null; if (string.IsNullOrEmpty(token)) { log.LogError(new ArgumentNullException(nameof(token)), "ERROR: ValidateToken: token input value is missing."); } if (string.IsNullOrEmpty(issuer)) { log.LogError(new ArgumentNullException(nameof(issuer)), "ERROR: ValidateToken: issuer input value is missing."); } if (string.IsNullOrEmpty(audience)) { log.LogError(new ArgumentNullException(nameof(audience)), "ERROR: ValidateToken: audience input value is missing."); } var discoveryDocument = await configurationManager.GetConfigurationAsync(ct); var signingKeys = discoveryDocument.SigningKeys; var validationParameters = new TokenValidationParameters { RequireExpirationTime = true, RequireSignedTokens = true, ValidAudience = audience, ValidateAudience = true, ValidIssuer = issuer, ValidateIssuer = true, ValidateIssuerSigningKey = true, IssuerSigningKeys = signingKeys, ValidateLifetime = true, // Allow for some drift in server time // (a lower value is better; we recommend two minutes or less) ClockSkew = TimeSpan.FromMinutes(2), }; var tries = 0; while (result == null && tries <= 1) { try { var principal = new JwtSecurityTokenHandler() .ValidateToken(token, validationParameters, out var rawValidatedToken); if (rawValidatedToken != null) { var validatedToken = (JwtSecurityToken)rawValidatedToken; var expectedAlg = SecurityAlgorithms.RsaSha256; //Okta uses RS256 if (validatedToken.Header?.Alg == null || validatedToken.Header?.Alg != expectedAlg) { var tokvalex = new SecurityTokenValidationException("The alg must be RS256."); log.LogError(tokvalex, "ERROR: ValidateToken: SecurityTokenValidationException Ocurred"); } else { result = validatedToken; } } } catch (SecurityTokenSignatureKeyNotFoundException) { // This exception is thrown if the signature key of the JWT could not be found. // This could be the case when the issuer changed its signing keys, so we trigger a // refresh and retry validation. _configurationManager.RequestRefresh(); tries++; } catch (SecurityTokenValidationException stvex) { log.LogError(stvex, "ERROR: ValidateToken: Token failed validation."); } catch (ArgumentException argex) { log.LogError(argex, "ERROR: ValidateToken: Token was not well-formed or was invalid for some other reason."); } } return(result); }
private async Task <ClaimsPrincipal> ValidateTokenAsync(AuthenticationHeaderValue value, ILogger log) { ClaimsPrincipal result = null; if (value?.Scheme != "Bearer") { return(null); } var discoveryDocument = await _configurationManager.GetConfigurationAsync(CancellationToken.None); var signingKeys = discoveryDocument.SigningKeys; var issuer = Environment.GetEnvironmentVariable("ISSUER"); var audience = Environment.GetEnvironmentVariable("AUDIENCE"); var validationParameters = new TokenValidationParameters() { RequireExpirationTime = true, RequireSignedTokens = true, ValidAudience = audience, ValidateAudience = true, ValidIssuer = issuer, ValidateIssuer = true, ValidateIssuerSigningKey = true, IssuerSigningKeys = signingKeys, ValidateLifetime = true, // Allow for some drift in server time // (a lower value is better; recommend two minutes or less) ClockSkew = TimeSpan.FromMinutes(2), }; var tries = 0; while (result == null && tries <= 1) { try { var handler = new JwtSecurityTokenHandler(); result = handler.ValidateToken(value.Parameter, validationParameters, out var token); if (token != null) { var validatedToken = (JwtSecurityToken)token; var expectedAlg = SecurityAlgorithms.RsaSha256; //Okta uses RS256 if (validatedToken.Header?.Alg == null || validatedToken.Header?.Alg != expectedAlg) { var tokenValidationEx = new SecurityTokenValidationException("The alg must be RS256."); log.LogError(tokenValidationEx, "ERROR: SecurityTokenValidationException Ocurred"); return(null); } } } catch (SecurityTokenSignatureKeyNotFoundException) { // This exception is thrown if the signature key of the JWT could not be found. // This could be the case when the issuer changed its signing keys, so we trigger a // refresh and retry validation. _configurationManager.RequestRefresh(); tries++; } catch (SecurityTokenValidationException stvex) { log.LogError(stvex, "ERROR: ValidateToken: Token failed validation."); } catch (ArgumentException argex) { log.LogError(argex, "ERROR: ValidateToken: Token was not well-formed or was invalid for some other reason."); } } return(result); }