public void SetHashAlgorithmMap(Dictionary <string, string> hashAlgorithmMap) { HashAlgorithmMap.Clear(); foreach (var key in hashAlgorithmMap.Keys) { HashAlgorithmMap.Add(key, hashAlgorithmMap[key]); } }
/// <summary> /// Returns a <see cref="HashAlgorithm"/> corresponding to string 'algorithm' after translation using <see cref="HashAlgorithmMap"/>. /// </summary> /// <param name="algorithm">string representing the hash algorithm</param> /// <returns>A <see cref="HashAlgorithm"/>.</returns> public virtual HashAlgorithm GetHashAlgorithm(string algorithm) { if (string.IsNullOrEmpty(algorithm)) { throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolException(LogMessages.IDX21350)); } try { if (!HashAlgorithmMap.TryGetValue(algorithm, out string hashAlgorithm)) { hashAlgorithm = algorithm; } return(CryptoProviderFactory.CreateHashAlgorithm(hashAlgorithm)); } catch (Exception ex) { throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolException(LogHelper.FormatInvariant(LogMessages.IDX21301, algorithm, typeof(HashAlgorithm)), ex)); } throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolException(LogHelper.FormatInvariant(LogMessages.IDX21302, algorithm))); }
/// <summary> /// Returns a <see cref="HashAlgorithm"/> corresponding to string 'algorithm' after translation using <see cref="HashAlgorithmMap"/>. /// </summary> /// <param name="algorithm">string representing the hash algorithm</param> /// <returns>A <see cref="HashAlgorithm"/>.</returns> public virtual HashAlgorithm GetHashAlgorithm(string algorithm) { if (algorithm == null) { algorithm = SecurityAlgorithms.RsaSha256; } try { string hashAlgorithm; if (!HashAlgorithmMap.TryGetValue(algorithm, out hashAlgorithm)) { hashAlgorithm = algorithm; } return(CryptoProviderFactory.CreateHashAlgorithm(hashAlgorithm)); } catch (Exception ex) { throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolException(String.Format(CultureInfo.InvariantCulture, LogMessages.IDX10301, algorithm, typeof(HashAlgorithm)), ex)); } throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolException(String.Format(CultureInfo.InvariantCulture, LogMessages.IDX10302, algorithm))); }
/// <summary> /// Validates the 'authorizationCode' according to http://openid.net/specs/openid-connect-core-1_0.html section 3.3.2.10. /// </summary> /// <param name="jwt">a <see cref="JwtSecurityToken"/> with a 'c_hash' claim that must match <see cref="OpenIdConnectProtocolValidationContext.AuthorizationCode"/>. If <see cref="OpenIdConnectProtocolValidationContext.AuthorizationCode"/> is null, the check is not made.</param> /// <param name="validationContext">a <see cref="OpenIdConnectProtocolValidationContext"/> that contains 'c_hash' to validate.</param> /// <exception cref="ArgumentNullException">if 'jwt' is null.</exception> /// <exception cref="ArgumentNullException">if 'validationContext' is null.</exception> /// <exception cref="OpenIdConnectProtocolInvalidCHashException">if the <see cref="JwtSecurityToken"/> 'c_hash' claim does not match <see cref="OpenIdConnectProtocolValidationContext.AuthorizationCode"/> as per http://openid.net/specs/openid-connect-core-1_0.html#CodeValidation .</exception> /// <exception cref="OpenIdConnectProtocolInvalidCHashException">if the hash algorithm defined in <see cref="JwtHeader"/> (default is JwtAlgorithms.RSA_SHA256) was unable to be created.</exception> /// <exception cref="OpenIdConnectProtocolInvalidCHashException">if the creation of the hash algorithm return a null instance.</exception> /// <remarks>if <see cref="OpenIdConnectProtocolValidationContext.AuthorizationCode"/> is null, then the <see cref="JwtSecurityToken"/> 'c_hash' will not be validated.</remarks> protected virtual void ValidateCHash(JwtSecurityToken jwt, OpenIdConnectProtocolValidationContext validationContext) { if (jwt == null) { throw new ArgumentNullException("jwt"); } if (validationContext == null) { throw new ArgumentNullException("validationContext"); } // this handles the case the code is not expected if (validationContext.AuthorizationCode == null) { return; } if (!jwt.Payload.ContainsKey(JwtRegisteredClaimNames.CHash)) { throw new OpenIdConnectProtocolInvalidCHashException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10308, jwt)); } HashAlgorithm hashAlgorithm = null; string algorithm = jwt.Header.Alg; if (algorithm == null) { algorithm = JwtAlgorithms.RSA_SHA256; } string alg = string.Empty; if (HashAlgorithmMap.TryGetValue(algorithm, out alg)) { algorithm = alg; } try { try { hashAlgorithm = HashAlgorithm.Create(algorithm); } catch (Exception ex) { throw new OpenIdConnectProtocolInvalidCHashException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10306, algorithm, jwt), ex); } if (hashAlgorithm == null) { throw new OpenIdConnectProtocolInvalidCHashException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10307, algorithm, jwt)); } byte[] hashBytes = hashAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(validationContext.AuthorizationCode)); string hashString = Base64UrlEncoder.Encode(hashBytes, 0, hashBytes.Length / 2); if (!StringComparer.Ordinal.Equals(jwt.Payload.CHash, hashString)) { throw new OpenIdConnectProtocolInvalidCHashException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10304, jwt.Payload.CHash, validationContext.AuthorizationCode, algorithm, jwt)); } } finally { if (hashAlgorithm != null) { hashAlgorithm.Dispose(); } } }