/// <summary> /// Returns all <see cref="SecurityKey"/> to use when validating the signature of a token. /// </summary> /// <param name="token">The <see cref="string"/> representation of the token that is being validated.</param> /// <param name="samlToken">The <see cref="SecurityToken"/> that is being validated.</param> /// <param name="tokenKeyInfo">The <see cref="KeyInfo"/> field of the token being validated</param> /// <param name="validationParameters">A <see cref="TokenValidationParameters"/> required for validation.</param> /// <param name="keyMatched">A <see cref="bool"/> to represent if a a issuer signing key matched with token kid or x5t</param> /// <returns>Returns all <see cref="SecurityKey"/> to use for signature validation.</returns> internal static IEnumerable <SecurityKey> GetKeysForTokenSignatureValidation(string token, SecurityToken samlToken, KeyInfo tokenKeyInfo, TokenValidationParameters validationParameters, out bool keyMatched) { keyMatched = false; if (validationParameters.IssuerSigningKeyResolver != null) { return(validationParameters.IssuerSigningKeyResolver(token, samlToken, tokenKeyInfo?.Id, validationParameters)); } else { SecurityKey key = ResolveTokenSigningKey(tokenKeyInfo, validationParameters); if (key != null) { keyMatched = true; return(new List <SecurityKey> { key }); } else { keyMatched = false; if (validationParameters.TryAllIssuerSigningKeys) { return(TokenUtilities.GetAllSigningKeys(validationParameters)); } } } return(null); }
protected virtual IEnumerable <SecurityKey> GetSigningKeys(string token, TokenValidationParameters validationParameters) { List <SecurityKey> keys = null; if (validationParameters.IssuerSigningKeyResolver != null) { keys = validationParameters.IssuerSigningKeyResolver(token, null, null, validationParameters)?.ToList(); } if (keys == null || !keys.Any()) { keys = new List <SecurityKey>(); if (validationParameters.IssuerSigningKey != null) { keys.Add(validationParameters.IssuerSigningKey); } if (validationParameters.IssuerSigningKeys != null && validationParameters.IssuerSigningKeys.Any()) { keys.AddRange(validationParameters.IssuerSigningKeys); } } return(keys); }
/// <summary> /// Validates the JWT signature. /// </summary> private JsonWebToken ValidateSignature(string token, TokenValidationParameters validationParameters) { if (string.IsNullOrWhiteSpace(token)) { throw LogHelper.LogArgumentNullException(nameof(token)); } if (validationParameters == null) { throw LogHelper.LogArgumentNullException(nameof(validationParameters)); } if (validationParameters.SignatureValidator != null) { var validatedToken = validationParameters.SignatureValidator(token, validationParameters); if (validatedToken == null) { throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidSignatureException(LogHelper.FormatInvariant(TokenLogMessages.IDX10505, token))); } var validatedJsonWebToken = validatedToken as JsonWebToken; if (validatedJsonWebToken == null) { throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidSignatureException(LogHelper.FormatInvariant(TokenLogMessages.IDX10506, typeof(JsonWebToken), validatedJsonWebToken.GetType(), token))); } return(validatedJsonWebToken); } JsonWebToken jwtToken = null; if (validationParameters.TokenReader != null) { var securityToken = validationParameters.TokenReader(token, validationParameters); if (securityToken == null) { throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidSignatureException(LogHelper.FormatInvariant(TokenLogMessages.IDX10510, token))); } jwtToken = securityToken as JsonWebToken; if (jwtToken == null) { throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidSignatureException(LogHelper.FormatInvariant(TokenLogMessages.IDX10509, typeof(JsonWebToken), securityToken.GetType(), token))); } } else { jwtToken = new JsonWebToken(token); } string[] tokenParts = jwtToken.EncodedToken.Split(new char[] { '.' }, JwtConstants.MaxJwtSegmentCount + 1); byte[] encodedBytes = Encoding.UTF8.GetBytes(tokenParts[0] + "." + tokenParts[1]); if (string.IsNullOrEmpty(tokenParts[2])) { if (validationParameters.RequireSignedTokens) { throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidSignatureException(LogHelper.FormatInvariant(TokenLogMessages.IDX10504, token))); } else { return(jwtToken); } } bool kidMatched = false; IEnumerable <SecurityKey> keys = null; if (validationParameters.IssuerSigningKeyResolver != null) { keys = validationParameters.IssuerSigningKeyResolver(token, jwtToken, jwtToken.Kid, validationParameters); } else { var key = ResolveIssuerSigningKey(jwtToken, validationParameters); if (key != null) { kidMatched = true; keys = new List <SecurityKey> { key }; } } if (keys == null) { // control gets here if: // 1. User specified delegate: IssuerSigningKeyResolver returned null // 2. ResolveIssuerSigningKey returned null // Try all the keys. This is the degenerate case, not concerned about perf. keys = GetAllSigningKeys(token, validationParameters); } // keep track of exceptions thrown, keys that were tried var exceptionStrings = new StringBuilder(); var keysAttempted = new StringBuilder(); bool kidExists = !string.IsNullOrEmpty(jwtToken.Kid); byte[] signatureBytes; try { signatureBytes = Base64UrlEncoder.DecodeBytes(tokenParts[2]); } catch (FormatException e) { throw new SecurityTokenInvalidSignatureException(TokenLogMessages.IDX10508, e); } foreach (var key in keys) { try { if (ValidateSignature(encodedBytes, signatureBytes, key, jwtToken.Alg, validationParameters)) { LogHelper.LogInformation(TokenLogMessages.IDX10242, token); jwtToken.SigningKey = key; return(jwtToken); } ; } catch (Exception ex) { exceptionStrings.AppendLine(ex.ToString()); } if (key != null) { keysAttempted.AppendLine(key.ToString() + " , KeyId: " + key.KeyId); if (kidExists && !kidMatched && key.KeyId != null) { kidMatched = jwtToken.Kid.Equals(key.KeyId, key is X509SecurityKey ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal); } } } if (kidExists) { if (kidMatched) { throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidSignatureException(LogHelper.FormatInvariant(TokenLogMessages.IDX10511, keysAttempted, jwtToken.Kid, exceptionStrings, jwtToken))); } else { throw LogHelper.LogExceptionMessage(new SecurityTokenSignatureKeyNotFoundException(LogHelper.FormatInvariant(TokenLogMessages.IDX10501, jwtToken.Kid, jwtToken))); } } else { if (keysAttempted.Length > 0) { throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidSignatureException(LogHelper.FormatInvariant(TokenLogMessages.IDX10503, keysAttempted, exceptionStrings, jwtToken))); } else { throw LogHelper.LogExceptionMessage(new SecurityTokenSignatureKeyNotFoundException(TokenLogMessages.IDX10500)); } } }
private bool ResolvesToSigningToken(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityKey key, out SecurityToken token) { token = null; key = null; CertMatcher certMatcher = null; // for SAML tokens the highest probability are certs, with RawData first X509RawDataKeyIdentifierClause rawCertKeyIdentifierClause = keyIdentifierClause as X509RawDataKeyIdentifierClause; if (rawCertKeyIdentifierClause != null) { certMatcher = rawCertKeyIdentifierClause.Matches; } else { X509SubjectKeyIdentifierClause subjectKeyIdentifierClause = keyIdentifierClause as X509SubjectKeyIdentifierClause; if (subjectKeyIdentifierClause != null) { certMatcher = subjectKeyIdentifierClause.Matches; } else { X509ThumbprintKeyIdentifierClause thumbprintKeyIdentifierClause = keyIdentifierClause as X509ThumbprintKeyIdentifierClause; if (thumbprintKeyIdentifierClause != null) { certMatcher = thumbprintKeyIdentifierClause.Matches; } else { X509IssuerSerialKeyIdentifierClause issuerKeyIdentifierClause = keyIdentifierClause as X509IssuerSerialKeyIdentifierClause; if (issuerKeyIdentifierClause != null) { certMatcher = issuerKeyIdentifierClause.Matches; } } } } if (_validationParameters.IssuerSigningKeyResolver != null) { key = _validationParameters.IssuerSigningKeyResolver(token: _securityToken, securityToken: null, keyIdentifier: new SecurityKeyIdentifier(keyIdentifierClause), validationParameters: _validationParameters); if (key != null) { this.IsKeyMatched = true; } } if (_validationParameters.IssuerSigningKey != null) { if (Matches(keyIdentifierClause, _validationParameters.IssuerSigningKey, certMatcher, out token)) { key = _validationParameters.IssuerSigningKey; this.IsKeyMatched = true; } } if (_validationParameters.IssuerSigningKeys != null) { foreach (SecurityKey securityKey in _validationParameters.IssuerSigningKeys) { if (Matches(keyIdentifierClause, securityKey, certMatcher, out token)) { key = securityKey; this.IsKeyMatched = true; break; } } } if (_validationParameters.IssuerSigningToken != null) { if (_validationParameters.IssuerSigningToken.MatchesKeyIdentifierClause(keyIdentifierClause)) { token = _validationParameters.IssuerSigningToken; key = token.SecurityKeys[0]; this.IsKeyMatched = true; } } if (_validationParameters.IssuerSigningTokens != null) { foreach (SecurityToken issuerToken in _validationParameters.IssuerSigningTokens) { if (_validationParameters.IssuerSigningToken.MatchesKeyIdentifierClause(keyIdentifierClause)) { token = issuerToken; key = token.SecurityKeys[0]; this.IsKeyMatched = true; break; } } } return(this.IsKeyMatched); }