public void OpenIdConnectProtocolValidationContext_GetSets() { OpenIdConnectProtocolValidationContext validationContext = new OpenIdConnectProtocolValidationContext(); Type type = typeof(OpenIdConnectProtocolValidationContext); PropertyInfo[] properties = type.GetProperties(); if (properties.Length != 3) Assert.Fail("Number of properties has changed from 3 to: " + properties.Length + ", adjust tests"); GetSetContext context = new GetSetContext { PropertyNamesAndSetGetValue = new List<KeyValuePair<string, List<object>>> { new KeyValuePair<string, List<object>>("AuthorizationCode", new List<object>{(string)null, "AuthorizationCode", "AuthorizationCode_AuthorizationCode"}), new KeyValuePair<string, List<object>>("Nonce", new List<object>{(string)null, "Nonce", "Nonce_Nonce"}), }, Object = validationContext, }; TestUtilities.GetSet(context); if (context.Errors.Count != 0) { StringBuilder sb = new StringBuilder(); sb.AppendLine(Environment.NewLine); foreach(string str in context.Errors) sb.AppendLine(str); Assert.Fail(sb.ToString()); } Assert.IsNotNull(validationContext.OpenIdConnectProtocolValidationParameters); TestUtilities.SetGet(validationContext, "OpenIdConnectProtocolValidationParameters", (OpenIdConnectProtocolValidationParameters)null, ExpectedException.ArgumentNullException()); TestUtilities.SetGet(validationContext, "OpenIdConnectProtocolValidationParameters", new OpenIdConnectProtocolValidationParameters(), ExpectedException.NoExceptionExpected); }
/// <summary> /// Validates that a <see cref="JwtSecurityToken"/> is valid as per http://openid.net/specs/openid-connect-core-1_0.html /// </summary> /// <param name="jwt">the <see cref="JwtSecurityToken"/>to validate.</param> /// <param name="validationContext">the <see cref="OpenIdConnectProtocolValidationContext"/> to use for validating.</param> /// <exception cref="ArgumentNullException">if 'jwt' is null.</exception> /// <exception cref="ArgumentNullException">if 'validationContext' is null.</exception> /// <exception cref="OpenIdConnectProtocolException">if the <see cref="JwtSecurityToken"/> is missing any required claims as per: http://openid.net/specs/openid-connect-core-1_0.html#IDToken </exception> /// <remarks><see cref="OpenIdConnectProtocolValidationContext.Nonce"/> and <see cref="OpenIdConnectProtocolValidationContext.AuthorizationCode"/> will be validated if they are not 'null' or 'whitespace'.</remarks> public static void Validate(JwtSecurityToken jwt, OpenIdConnectProtocolValidationContext validationContext) { if (jwt == null) throw new ArgumentNullException("jwt"); if (validationContext == null) throw new ArgumentNullException("validationContext"); // required claims if (jwt.Payload.Aud.Count == 0) throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10309, JwtRegisteredClaimNames.Aud.ToLowerInvariant(), jwt)); if (!jwt.Payload.Exp.HasValue) throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10309, JwtRegisteredClaimNames.Exp.ToLowerInvariant(), jwt)); if (!jwt.Payload.Iat.HasValue) throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10309, JwtRegisteredClaimNames.Iat.ToLowerInvariant(), jwt)); if (jwt.Payload.Iss == null) throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10309, JwtRegisteredClaimNames.Iss.ToLowerInvariant(), jwt)); OpenIdConnectProtocolValidationParameters validationParameters = validationContext.OpenIdConnectProtocolValidationParameters; // sub is optional in RC2 if (validationParameters.RequireSub && (string.IsNullOrWhiteSpace(jwt.Payload.Sub))) throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10309, JwtRegisteredClaimNames.Sub.ToLowerInvariant(), jwt)); // optional claims if (validationParameters.RequireAcr && string.IsNullOrWhiteSpace(jwt.Payload.Acr)) throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10312, jwt)); if (validationParameters.RequireAmr && string.IsNullOrWhiteSpace(jwt.Payload.Amr)) throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10313, jwt)); if (validationParameters.RequireAuthTime && string.IsNullOrWhiteSpace(jwt.Payload.AuthTime)) throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10314, jwt)); if (validationParameters.RequireAzp && string.IsNullOrWhiteSpace(jwt.Payload.Azp)) throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10315, jwt)); if (validationParameters.RequireNonce && string.IsNullOrWhiteSpace(validationContext.Nonce)) throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10311, jwt)); if (!string.IsNullOrWhiteSpace(validationContext.Nonce)) ValidateNonce(jwt, validationContext.Nonce); if (!string.IsNullOrWhiteSpace(validationContext.AuthorizationCode)) ValidateCHash(jwt, validationContext.AuthorizationCode, validationParameters.AlgorithmMap); }
public void OpenIdConnectProtocolValidationContext_GetSets() { OpenIdConnectProtocolValidationContext validationContext = new OpenIdConnectProtocolValidationContext(); Type type = typeof(OpenIdConnectProtocolValidationContext); PropertyInfo[] properties = type.GetProperties(); if (properties.Length != 2) Assert.Fail("Number of properties has changed from 2 to: " + properties.Length + ", adjust tests"); GetSetContext context = new GetSetContext { PropertyNamesAndSetGetValue = new List<KeyValuePair<string, List<object>>> { new KeyValuePair<string, List<object>>("AuthorizationCode", new List<object>{(string)null, "AuthorizationCode", "AuthorizationCode_AuthorizationCode"}), new KeyValuePair<string, List<object>>("Nonce", new List<object>{(string)null, "Nonce", "Nonce_Nonce"}), }, Object = validationContext, }; TestUtilities.GetSet(context); TestUtilities.AssertFailIfErrors(MethodInfo.GetCurrentMethod().Name, context.Errors); }
/// <summary> /// Validates that the <see cref="JwtSecurityToken"/> contains the nonce. /// </summary> /// <param name="jwt">a <see cref="JwtSecurityToken"/> with a 'nonce' claim that must match <see cref="OpenIdConnectProtocolValidationContext.Nonce"/>.</param> /// <param name="validationContext">a <see cref="OpenIdConnectProtocolValidationContext"/> that contains the 'nonce' to validate.</param> /// <exception cref="ArgumentNullException">if 'jwt' is null.</exception> /// <exception cref="ArgumentNullException">if 'validationContext' is null.</exception> /// <exception cref="OpenIdConnectProtocolInvalidNonceException">if a'nonce' is not found in the <see cref="JwtSecurityToken"/> and RequireNonce is true.</exception> /// <exception cref="OpenIdConnectProtocolInvalidNonceException">if <see cref="OpenIdConnectProtocolValidationContext.Nonce"/> is null and RequireNonce is true.</exception> /// <exception cref="OpenIdConnectProtocolInvalidNonceException">if the 'nonce' found in the <see cref="JwtSecurityToken"/> doesn't match <see cref="OpenIdConnectProtocolValidationContext.Nonce"/>.</exception> /// <exception cref="OpenIdConnectProtocolInvalidNonceException">if <see cref="RequireTimeStampInNonce"/> is true and a timestamp is not: found, well formed, negatire or expired.</exception> /// <remarks>The timestamp is only validated if <see cref="RequireTimeStampInNonce"/> is true. /// <para>If <see cref="OpenIdConnectProtocolValidationContext.Nonce"/> is not-null, then a matching 'nonce' must exist in the <see cref="JwtSecurityToken"/>.</para></remarks> protected virtual void ValidateNonce(JwtSecurityToken jwt, OpenIdConnectProtocolValidationContext validationContext) { if (jwt == null) { throw new ArgumentNullException("jwt"); } if (validationContext == null) { throw new ArgumentNullException("validationContext"); } string nonceFoundInJwt = jwt.Payload.Nonce; if (RequireNonce) { if (validationContext.Nonce == null) { throw new OpenIdConnectProtocolInvalidNonceException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10311)); } if (nonceFoundInJwt == null) { throw new OpenIdConnectProtocolInvalidNonceException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10322, jwt.ToString())); } } else if ((validationContext.Nonce != null) && (nonceFoundInJwt == null)) { throw new OpenIdConnectProtocolInvalidNonceException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10323, validationContext.Nonce, jwt.ToString())); } else if (validationContext.Nonce == null) { return; } if (!(StringComparer.Ordinal.Equals(nonceFoundInJwt, validationContext.Nonce))) { throw new OpenIdConnectProtocolInvalidNonceException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10301, validationContext.Nonce, nonceFoundInJwt, jwt.ToString())); } if (RequireTimeStampInNonce) { int endOfTimestamp = nonceFoundInJwt.IndexOf('.'); if (endOfTimestamp == -1) { throw new OpenIdConnectProtocolInvalidNonceException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10317, validationContext.Nonce)); } string timestamp = nonceFoundInJwt.Substring(0, endOfTimestamp); DateTime nonceTime; long ticks; try { ticks = Convert.ToInt64(timestamp, CultureInfo.InvariantCulture); } catch (Exception ex) { throw new OpenIdConnectProtocolInvalidNonceException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10318, timestamp, validationContext.Nonce), ex); } if (ticks <= 0) { throw new OpenIdConnectProtocolInvalidNonceException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10318, timestamp, validationContext.Nonce)); } try { nonceTime = DateTime.FromBinary(ticks); } catch(Exception ex) { throw new OpenIdConnectProtocolInvalidNonceException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10320, timestamp, System.DateTime.MinValue.Ticks.ToString(CultureInfo.InvariantCulture), System.DateTime.MaxValue.Ticks.ToString(CultureInfo.InvariantCulture)), ex); } DateTime utcNow = DateTime.UtcNow; if (nonceTime + NonceLifetime < utcNow) { throw new OpenIdConnectProtocolInvalidNonceException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10316, validationContext.Nonce, nonceTime.ToString(), utcNow.ToString(), NonceLifetime.ToString())); } } }
/// <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(); } } }
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync() { if (Options.CallbackPath.HasValue && Options.CallbackPath != (Request.PathBase + Request.Path)) { return null; } OpenIdConnectMessage openIdConnectMessage = null; if (string.Equals(Request.Method, "POST", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(Request.ContentType) && Request.ContentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase) && Request.Body.CanRead) { if (!Request.Body.CanSeek) { _logger.WriteVerbose("Buffering request body"); MemoryStream memoryStream = new MemoryStream(); await Request.Body.CopyToAsync(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); Request.Body = memoryStream; } IFormCollection form = await Request.ReadFormAsync(); Request.Body.Seek(0, SeekOrigin.Begin); openIdConnectMessage = new OpenIdConnectMessage(form); } if (openIdConnectMessage == null) { return null; } ExceptionDispatchInfo authFailedEx = null; string policy = string.Empty; try { var messageReceivedNotification = new MessageReceivedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options) { ProtocolMessage = openIdConnectMessage }; await Options.Notifications.MessageReceived(messageReceivedNotification); if (messageReceivedNotification.HandledResponse) { return GetHandledResponseTicket(); } if (messageReceivedNotification.Skipped) { return null; } AuthenticationProperties properties = GetPropertiesFromState(openIdConnectMessage.State); if (properties == null) { _logger.WriteWarning("The state field is missing or invalid."); return null; } string nonce = null; if (Options.ProtocolValidator.RequireNonce) { nonce = RetrieveNonce(openIdConnectMessage); } if (!string.IsNullOrWhiteSpace(openIdConnectMessage.Error)) { throw new OpenIdConnectProtocolException( string.Format(CultureInfo.InvariantCulture, openIdConnectMessage.Error, "", openIdConnectMessage.ErrorDescription ?? string.Empty, openIdConnectMessage.ErrorUri ?? string.Empty)); } if (string.IsNullOrWhiteSpace(openIdConnectMessage.IdToken)) { _logger.WriteWarning("The id_token is missing."); return null; } var securityTokenReceivedNotification = new SecurityTokenReceivedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options) { ProtocolMessage = openIdConnectMessage, }; await Options.Notifications.SecurityTokenReceived(securityTokenReceivedNotification); if (securityTokenReceivedNotification.HandledResponse) { return GetHandledResponseTicket(); } if (securityTokenReceivedNotification.Skipped) { return null; } // Enable Per-Policy Metadata Retreival if (properties.Dictionary.TryGetValue(PolicyParameter, out policy)) { B2CConfigurationManager mgr = Options.ConfigurationManager as B2CConfigurationManager; _configuration = await mgr.GetConfigurationAsync(Context.Request.CallCancelled, policy); } else { _logger.WriteWarning("No policy identifier was found in the Authentication Properties of the request."); return null; } TokenValidationParameters tvp = Options.TokenValidationParameters.Clone(); IEnumerable<string> issuers = new[] { _configuration.Issuer }; tvp.ValidIssuers = (tvp.ValidIssuers == null ? issuers : tvp.ValidIssuers.Concat(issuers)); tvp.IssuerSigningTokens = (tvp.IssuerSigningTokens == null ? _configuration.SigningTokens : tvp.IssuerSigningTokens.Concat(_configuration.SigningTokens)); SecurityToken validatedToken; ClaimsPrincipal principal = Options.SecurityTokenHandlers.ValidateToken(openIdConnectMessage.IdToken, tvp, out validatedToken); ClaimsIdentity claimsIdentity = principal.Identity as ClaimsIdentity; JwtSecurityToken jwt = validatedToken as JwtSecurityToken; AuthenticationTicket ticket = new AuthenticationTicket(claimsIdentity, properties); if (!string.IsNullOrWhiteSpace(openIdConnectMessage.SessionState)) { ticket.Properties.Dictionary[OpenIdConnectSessionProperties.SessionState] = openIdConnectMessage.SessionState; } if (!string.IsNullOrWhiteSpace(_configuration.CheckSessionIframe)) { ticket.Properties.Dictionary[OpenIdConnectSessionProperties.CheckSessionIFrame] = _configuration.CheckSessionIframe; } if (Options.UseTokenLifetime) { DateTime issued = jwt.ValidFrom; if (issued != DateTime.MinValue) { ticket.Properties.IssuedUtc = issued.ToUniversalTime(); } DateTime expires = jwt.ValidTo; if (expires != DateTime.MinValue) { ticket.Properties.ExpiresUtc = expires.ToUniversalTime(); } ticket.Properties.AllowRefresh = false; } var securityTokenValidatedNotification = new SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options) { AuthenticationTicket = ticket, ProtocolMessage = openIdConnectMessage, }; await Options.Notifications.SecurityTokenValidated(securityTokenValidatedNotification); if (securityTokenValidatedNotification.HandledResponse) { return GetHandledResponseTicket(); } if (securityTokenValidatedNotification.Skipped) { return null; } ticket = securityTokenValidatedNotification.AuthenticationTicket; var protocolValidationContext = new OpenIdConnectProtocolValidationContext { AuthorizationCode = openIdConnectMessage.Code, Nonce = nonce, }; Options.ProtocolValidator.Validate(jwt, protocolValidationContext); if (openIdConnectMessage.Code != null) { var authorizationCodeReceivedNotification = new AuthorizationCodeReceivedNotification(Context, Options) { AuthenticationTicket = ticket, Code = openIdConnectMessage.Code, JwtSecurityToken = jwt, ProtocolMessage = openIdConnectMessage, RedirectUri = ticket.Properties.Dictionary.ContainsKey(OpenIdConnectAuthenticationDefaults.RedirectUriUsedForCodeKey) ? ticket.Properties.Dictionary[OpenIdConnectAuthenticationDefaults.RedirectUriUsedForCodeKey] : string.Empty, }; await Options.Notifications.AuthorizationCodeReceived(authorizationCodeReceivedNotification); if (authorizationCodeReceivedNotification.HandledResponse) { return GetHandledResponseTicket(); } if (authorizationCodeReceivedNotification.Skipped) { return null; } ticket = authorizationCodeReceivedNotification.AuthenticationTicket; } return ticket; } catch (Exception exception) { authFailedEx = ExceptionDispatchInfo.Capture(exception); } if (authFailedEx != null) { _logger.WriteError("Exception occurred while processing message: '" + authFailedEx.ToString()); if (Options.RefreshOnIssuerKeyNotFound && authFailedEx.SourceException.GetType().Equals(typeof(SecurityTokenSignatureKeyNotFoundException))) { B2CConfigurationManager mgr = Options.ConfigurationManager as B2CConfigurationManager; mgr.RequestRefresh(policy); } var authenticationFailedNotification = new AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options) { ProtocolMessage = openIdConnectMessage, Exception = authFailedEx.SourceException }; await Options.Notifications.AuthenticationFailed(authenticationFailedNotification); if (authenticationFailedNotification.HandledResponse) { return GetHandledResponseTicket(); } if (authenticationFailedNotification.Skipped) { return null; } authFailedEx.Throw(); } return null; }
/// <summary> /// Validates that the <see cref="JwtSecurityToken"/> contains the nonce. /// </summary> /// <param name="jwt">a <see cref="JwtSecurityToken"/> with a 'nonce' claim that must match <see cref="OpenIdConnectProtocolValidationContext.Nonce"/>.</param> /// <param name="validationContext">a <see cref="OpenIdConnectProtocolValidationContext"/> that contains the 'nonce' to validate.</param> /// <exception cref="ArgumentNullException">if 'jwt' is null.</exception> /// <exception cref="ArgumentNullException">if 'validationContext' is null.</exception> /// <exception cref="OpenIdConnectProtocolInvalidNonceException">if a'nonce' is not found in the <see cref="JwtSecurityToken"/> and RequireNonce is true.</exception> /// <exception cref="OpenIdConnectProtocolInvalidNonceException">if <see cref="OpenIdConnectProtocolValidationContext.Nonce"/> is null and RequireNonce is true.</exception> /// <exception cref="OpenIdConnectProtocolInvalidNonceException">if the 'nonce' found in the <see cref="JwtSecurityToken"/> doesn't match <see cref="OpenIdConnectProtocolValidationContext.Nonce"/>.</exception> /// <exception cref="OpenIdConnectProtocolInvalidNonceException">if <see cref="RequireTimeStampInNonce"/> is true and a timestamp is not: found, well formed, negatire or expired.</exception> /// <remarks>The timestamp is only validated if <see cref="RequireTimeStampInNonce"/> is true. /// <para>If <see cref="OpenIdConnectProtocolValidationContext.Nonce"/> is not-null, then a matching 'nonce' must exist in the <see cref="JwtSecurityToken"/>.</para></remarks> protected virtual void ValidateNonce(JwtSecurityToken jwt, OpenIdConnectProtocolValidationContext validationContext) { if (jwt == null) { throw new ArgumentNullException("jwt"); } if (validationContext == null) { throw new ArgumentNullException("validationContext"); } string nonceFoundInJwt = jwt.Payload.Nonce; if (RequireNonce) { if (validationContext.Nonce == null) { throw new OpenIdConnectProtocolInvalidNonceException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10311)); } if (nonceFoundInJwt == null) { throw new OpenIdConnectProtocolInvalidNonceException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10322, jwt.ToString())); } } else if ((validationContext.Nonce != null) && (nonceFoundInJwt == null)) { throw new OpenIdConnectProtocolInvalidNonceException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10323, validationContext.Nonce, jwt.ToString())); } else if (validationContext.Nonce == null) { return; } if (!(StringComparer.Ordinal.Equals(nonceFoundInJwt, validationContext.Nonce))) { throw new OpenIdConnectProtocolInvalidNonceException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10301, validationContext.Nonce, nonceFoundInJwt, jwt.ToString())); } if (RequireTimeStampInNonce) { int endOfTimestamp = nonceFoundInJwt.IndexOf('.'); if (endOfTimestamp == -1) { throw new OpenIdConnectProtocolInvalidNonceException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10317, validationContext.Nonce)); } string timestamp = nonceFoundInJwt.Substring(0, endOfTimestamp); DateTime nonceTime; long ticks; try { ticks = Convert.ToInt64(timestamp, CultureInfo.InvariantCulture); } catch (Exception ex) { throw new OpenIdConnectProtocolInvalidNonceException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10318, timestamp, validationContext.Nonce), ex); } if (ticks <= 0) { throw new OpenIdConnectProtocolInvalidNonceException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10318, timestamp, validationContext.Nonce)); } try { nonceTime = DateTime.FromBinary(ticks); } catch (Exception ex) { throw new OpenIdConnectProtocolInvalidNonceException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10320, timestamp, System.DateTime.MinValue.Ticks.ToString(CultureInfo.InvariantCulture), System.DateTime.MaxValue.Ticks.ToString(CultureInfo.InvariantCulture)), ex); } DateTime utcNow = DateTime.UtcNow; if (nonceTime + NonceLifetime < utcNow) { throw new OpenIdConnectProtocolInvalidNonceException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10316, validationContext.Nonce, nonceTime.ToString(), utcNow.ToString(), NonceLifetime.ToString())); } } }
/// <summary> /// Validates that a <see cref="JwtSecurityToken"/> is valid as per http://openid.net/specs/openid-connect-core-1_0.html /// </summary> /// <param name="jwt">the <see cref="JwtSecurityToken"/>to validate.</param> /// <param name="validationContext">the <see cref="OpenIdConnectProtocolValidationContext"/> that contains expected values.</param> /// <exception cref="ArgumentNullException">if 'jwt' is null.</exception> /// <exception cref="ArgumentNullException">if 'validationContext' is null.</exception> /// <exception cref="OpenIdConnectProtocolException">if the <see cref="JwtSecurityToken"/> is missing any required claims as per: http://openid.net/specs/openid-connect-core-1_0.html#IDToken </exception> /// <remarks><see cref="OpenIdConnectProtocolValidationContext.Nonce"/> and <see cref="OpenIdConnectProtocolValidationContext.AuthorizationCode"/> will be validated if they are non-null.</remarks> public virtual void Validate(JwtSecurityToken jwt, OpenIdConnectProtocolValidationContext validationContext) { if (jwt == null) { throw new ArgumentNullException("jwt"); } if (validationContext == null) { throw new ArgumentNullException("validationContext"); } // required claims if (jwt.Payload.Aud.Count == 0) { throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10309, JwtRegisteredClaimNames.Aud.ToLowerInvariant(), jwt)); } if (!jwt.Payload.Exp.HasValue) { throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10309, JwtRegisteredClaimNames.Exp.ToLowerInvariant(), jwt)); } if (!jwt.Payload.Iat.HasValue) { throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10309, JwtRegisteredClaimNames.Iat.ToLowerInvariant(), jwt)); } if (jwt.Payload.Iss == null) { throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10309, JwtRegisteredClaimNames.Iss.ToLowerInvariant(), jwt)); } // sub is optional by default if (RequireSub && (string.IsNullOrWhiteSpace(jwt.Payload.Sub))) { throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10309, JwtRegisteredClaimNames.Sub.ToLowerInvariant(), jwt)); } // optional claims if (RequireAcr && string.IsNullOrWhiteSpace(jwt.Payload.Acr)) { throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10312, jwt)); } if (RequireAmr && string.IsNullOrWhiteSpace(jwt.Payload.Amr)) { throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10313, jwt)); } if (RequireAuthTime && string.IsNullOrWhiteSpace(jwt.Payload.AuthTime)) { throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10314, jwt)); } if (RequireAzp && string.IsNullOrWhiteSpace(jwt.Payload.Azp)) { throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10315, jwt)); } ValidateNonce(jwt, validationContext); ValidateCHash(jwt, validationContext); }
public void PublicValidateNonce(JwtSecurityToken jwt, OpenIdConnectProtocolValidationContext context) { base.ValidateNonce(jwt, context); }
private void ValidateNonce(JwtSecurityToken jwt, PublicOpenIdConnectProtocolValidator protocolValidator, OpenIdConnectProtocolValidationContext validationContext, ExpectedException ee) { try { protocolValidator.PublicValidateNonce(jwt, validationContext); ee.ProcessNoException(); } catch(Exception ex) { ee.ProcessException(ex); } }
public void OpenIdConnectProtocolValidator_ValidateNonce() { PublicOpenIdConnectProtocolValidator protocolValidatorRequiresTimeStamp = new PublicOpenIdConnectProtocolValidator(); string nonceWithTimeStamp = protocolValidatorRequiresTimeStamp.GenerateNonce(); PublicOpenIdConnectProtocolValidator protocolValidatorDoesNotRequireTimeStamp = new PublicOpenIdConnectProtocolValidator { RequireTimeStampInNonce = false, }; PublicOpenIdConnectProtocolValidator protocolValidatorDoesNotRequireNonce = new PublicOpenIdConnectProtocolValidator { RequireNonce = false, }; string nonceWithoutTimeStamp = protocolValidatorDoesNotRequireTimeStamp.GenerateNonce(); string nonceBadTimeStamp = "abc.abc"; string nonceTicksTooLarge = Int64.MaxValue.ToString() + "." + nonceWithoutTimeStamp; string nonceTicksTooSmall = Int64.MinValue.ToString() + "." + nonceWithoutTimeStamp; string nonceTicksNegative = ((Int64)(-1)).ToString() + "." + nonceWithoutTimeStamp; string nonceTicksZero = ((Int64)(0)).ToString() + "." + nonceWithoutTimeStamp; JwtSecurityToken jwtWithNonceWithTimeStamp = new JwtSecurityToken ( claims: new List<Claim> { new Claim(JwtRegisteredClaimNames.Nonce, nonceWithTimeStamp) }); JwtSecurityToken jwtWithNonceWithoutTimeStamp = new JwtSecurityToken(claims: new List<Claim> { new Claim(JwtRegisteredClaimNames.Nonce, nonceWithoutTimeStamp) }); JwtSecurityToken jwtWithNonceWithBadTimeStamp = new JwtSecurityToken(claims: new List<Claim> { new Claim(JwtRegisteredClaimNames.Nonce, nonceBadTimeStamp) }); JwtSecurityToken jwtWithNonceTicksTooLarge = new JwtSecurityToken(claims: new List<Claim> { new Claim(JwtRegisteredClaimNames.Nonce, nonceTicksTooLarge) }); JwtSecurityToken jwtWithNonceTicksTooSmall = new JwtSecurityToken(claims: new List<Claim> { new Claim(JwtRegisteredClaimNames.Nonce, nonceTicksTooSmall) }); JwtSecurityToken jwtWithNonceTicksNegative = new JwtSecurityToken(claims: new List<Claim> { new Claim(JwtRegisteredClaimNames.Nonce, nonceTicksNegative) }); JwtSecurityToken jwtWithNonceZero = new JwtSecurityToken(claims: new List<Claim> { new Claim(JwtRegisteredClaimNames.Nonce, nonceTicksZero) }); JwtSecurityToken jwtWithoutNonce = new JwtSecurityToken(claims: new List<Claim> { new Claim(JwtRegisteredClaimNames.NameId, nonceWithTimeStamp) }); JwtSecurityToken jwtWithNonceWhitespace = new JwtSecurityToken(claims: new List<Claim> { new Claim(JwtRegisteredClaimNames.Nonce, "") }); OpenIdConnectProtocolValidationContext validationContext = new OpenIdConnectProtocolValidationContext(); validationContext.Nonce = null; ValidateNonce(jwt: null, protocolValidator: protocolValidatorRequiresTimeStamp, validationContext: validationContext, ee: ExpectedException.ArgumentNullException()); ValidateNonce(jwt: jwtWithNonceWithTimeStamp, protocolValidator: protocolValidatorRequiresTimeStamp, validationContext: null, ee: ExpectedException.ArgumentNullException()); // nonce is null, RequireNonce is true. ValidateNonce(jwt: jwtWithNonceWithTimeStamp, protocolValidator: protocolValidatorRequiresTimeStamp, validationContext: validationContext, ee: new ExpectedException(typeof(OpenIdConnectProtocolInvalidNonceException), substringExpected: "IDX10311:")); validationContext.Nonce = nonceWithoutTimeStamp; ValidateNonce(jwt: jwtWithoutNonce, protocolValidator: protocolValidatorRequiresTimeStamp, validationContext: validationContext, ee: new ExpectedException(typeof(OpenIdConnectProtocolInvalidNonceException), substringExpected: "IDX10322:")); ValidateNonce(jwt: jwtWithNonceWhitespace, protocolValidator: protocolValidatorRequiresTimeStamp, validationContext: validationContext, ee: new ExpectedException(typeof(OpenIdConnectProtocolInvalidNonceException), substringExpected: "IDX10301:")); ValidateNonce(jwt: jwtWithNonceWithTimeStamp, protocolValidator: protocolValidatorRequiresTimeStamp, validationContext: validationContext, ee: new ExpectedException(typeof(OpenIdConnectProtocolInvalidNonceException), substringExpected: "IDX10301:")); validationContext.Nonce = nonceWithTimeStamp; ValidateNonce(jwt: jwtWithNonceWithTimeStamp, protocolValidator: protocolValidatorRequiresTimeStamp, validationContext: validationContext, ee: ExpectedException.NoExceptionExpected); // nonce expired validationContext.Nonce = nonceWithTimeStamp; protocolValidatorRequiresTimeStamp.NonceLifetime = TimeSpan.FromMilliseconds(10); Thread.Sleep(100); ValidateNonce(jwt: jwtWithNonceWithTimeStamp, protocolValidator: protocolValidatorRequiresTimeStamp, validationContext: validationContext, ee: new ExpectedException(typeof(OpenIdConnectProtocolInvalidNonceException))); // nonce missing timestamp, validator requires time stamp // 1. not well formed, no '.' validationContext.Nonce = nonceWithoutTimeStamp; protocolValidatorRequiresTimeStamp.NonceLifetime = TimeSpan.FromMinutes(10); ValidateNonce(jwt: jwtWithNonceWithoutTimeStamp, protocolValidator: protocolValidatorRequiresTimeStamp, validationContext: validationContext, ee: new ExpectedException(typeof(OpenIdConnectProtocolInvalidNonceException), substringExpected: "IDX10317:")); // 2. timestamp not well formed validationContext.Nonce = nonceBadTimeStamp; ValidateNonce(jwt: jwtWithNonceWithBadTimeStamp, protocolValidator: protocolValidatorRequiresTimeStamp, validationContext: validationContext, ee: new ExpectedException( typeExpected: typeof(OpenIdConnectProtocolInvalidNonceException), innerTypeExpected: typeof(FormatException), substringExpected: "IDX10318:")); // 3. timestamp not required validationContext.Nonce = nonceBadTimeStamp; ValidateNonce(jwt: jwtWithNonceWithBadTimeStamp, protocolValidator: protocolValidatorDoesNotRequireTimeStamp, validationContext: validationContext, ee: ExpectedException.NoExceptionExpected); // 4. ticks max value validationContext.Nonce = nonceTicksTooLarge; ValidateNonce(jwt: jwtWithNonceTicksTooLarge, protocolValidator: protocolValidatorRequiresTimeStamp, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolInvalidNonceException), innerTypeExpected: typeof(ArgumentException), substringExpected: "IDX10320:")); // 5. ticks min value small validationContext.Nonce = nonceTicksTooSmall; ValidateNonce(jwt: jwtWithNonceTicksTooSmall, protocolValidator: protocolValidatorRequiresTimeStamp, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolInvalidNonceException), substringExpected: "IDX10318:")); // 6. ticks negative validationContext.Nonce = nonceTicksNegative; ValidateNonce(jwt: jwtWithNonceTicksNegative, protocolValidator: protocolValidatorRequiresTimeStamp, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolInvalidNonceException), substringExpected: "IDX10318:")); // 7. ticks zero validationContext.Nonce = nonceTicksZero; ValidateNonce(jwt: jwtWithNonceZero, protocolValidator: protocolValidatorRequiresTimeStamp, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolInvalidNonceException), substringExpected: "IDX10318:")); // require nonce false validationContext.Nonce = null; ValidateNonce(jwt: jwtWithNonceWithoutTimeStamp, protocolValidator: protocolValidatorDoesNotRequireNonce, validationContext: validationContext, ee: ExpectedException.NoExceptionExpected); // validationContext has nonce validationContext.Nonce = nonceWithTimeStamp; ValidateNonce(jwt: jwtWithoutNonce, protocolValidator: protocolValidatorDoesNotRequireNonce, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolInvalidNonceException), substringExpected: "IDX10323:")); }
public void OpenIdConnectProtocolValidator_CHash() { PublicOpenIdConnectProtocolValidator protocolValidator = new PublicOpenIdConnectProtocolValidator(); string authorizationCode1 = protocolValidator.GenerateNonce(); string authorizationCode2 = protocolValidator.GenerateNonce(); string chash1 = IdentityUtilities.CreateCHash(authorizationCode1, "SHA256"); string chash2 = IdentityUtilities.CreateCHash(authorizationCode2, "SHA256"); Dictionary<string, string> emptyDictionary = new Dictionary<string, string>(); Dictionary<string, string> mappedDictionary = new Dictionary<string, string>(protocolValidator.HashAlgorithmMap); JwtSecurityToken jwtWithCHash1 = new JwtSecurityToken ( audience: IdentityUtilities.DefaultAudience, claims: new List<Claim> { new Claim(JwtRegisteredClaimNames.CHash, chash1) }, issuer: IdentityUtilities.DefaultIssuer ); JwtSecurityToken jwtWithEmptyCHash = new JwtSecurityToken ( audience: IdentityUtilities.DefaultAudience, claims: new List<Claim> { new Claim(JwtRegisteredClaimNames.CHash, string.Empty) }, issuer: IdentityUtilities.DefaultIssuer, signingCredentials: IdentityUtilities.DefaultAsymmetricSigningCredentials ); JwtSecurityToken jwtWithoutCHash = new JwtSecurityToken ( audience: IdentityUtilities.DefaultAudience, claims: new List<Claim> { new Claim(JwtRegisteredClaimNames.Nonce, chash2) }, issuer: IdentityUtilities.DefaultIssuer ); JwtSecurityToken jwtWithSignatureChash1 = new JwtSecurityToken ( audience : IdentityUtilities.DefaultAudience, claims: new List<Claim> { new Claim(JwtRegisteredClaimNames.CHash, chash1) }, issuer: IdentityUtilities.DefaultIssuer, signingCredentials : IdentityUtilities.DefaultAsymmetricSigningCredentials ); JwtSecurityToken jwtWithSignatureMultipleChashes = new JwtSecurityToken ( audience: IdentityUtilities.DefaultAudience, claims: new List<Claim> { new Claim(JwtRegisteredClaimNames.CHash, chash1), new Claim(JwtRegisteredClaimNames.CHash, chash2) }, issuer: IdentityUtilities.DefaultIssuer, signingCredentials: IdentityUtilities.DefaultAsymmetricSigningCredentials ); OpenIdConnectProtocolValidationContext validationContext = new OpenIdConnectProtocolValidationContext(); validationContext.AuthorizationCode = authorizationCode2; // chash is not a string, but array ValidateCHash(jwt: jwtWithSignatureMultipleChashes, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolInvalidCHashException), substringExpected: "IDX10304:")); // chash doesn't match ValidateCHash(jwt: jwtWithSignatureChash1, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolInvalidCHashException), substringExpected: "IDX10304:")); // use algorithm map validationContext.AuthorizationCode = authorizationCode1; ValidateCHash(jwt: jwtWithSignatureChash1, protocolValidator: protocolValidator, validationContext: validationContext, ee: ExpectedException.NoExceptionExpected); // Creation of algorithm failed, need to map. protocolValidator.SetHashAlgorithmMap(emptyDictionary); ValidateCHash(jwt: jwtWithSignatureChash1, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolInvalidCHashException), substringExpected: "IDX10307:")); protocolValidator.SetHashAlgorithmMap(mappedDictionary); ValidateCHash(jwt: null, protocolValidator: protocolValidator, validationContext: validationContext, ee: ExpectedException.ArgumentNullException()); ValidateCHash(jwt: jwtWithoutCHash, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolInvalidCHashException), substringExpected: "IDX10308:")); ValidateCHash(jwt: jwtWithEmptyCHash, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolInvalidCHashException), substringExpected: "IDX10304:")); ValidateCHash(jwt: jwtWithCHash1, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolInvalidCHashException), substringExpected: "IDX10307:")); ValidateCHash(jwt: jwtWithoutCHash, protocolValidator: protocolValidator, validationContext: null, ee: ExpectedException.ArgumentNullException()); // make sure default alg works. validationContext.AuthorizationCode = authorizationCode1; jwtWithCHash1.Header.Remove("alg"); ValidateCHash(jwt: jwtWithCHash1, protocolValidator: protocolValidator, validationContext: validationContext, ee: ExpectedException.NoExceptionExpected); }
public void OpenIdConnectProtocolValidator_Validate() { JwtSecurityToken jwt = new JwtSecurityToken(); OpenIdConnectProtocolValidationContext validationContext = new OpenIdConnectProtocolValidationContext(); OpenIdConnectProtocolValidator protocolValidator = new OpenIdConnectProtocolValidator(); // jwt null Validate(jwt: null, protocolValidator: protocolValidator, validationContext: null, ee: ExpectedException.ArgumentNullException()); // validationContext null Validate(jwt: jwt, protocolValidator: protocolValidator, validationContext: null, ee: ExpectedException.ArgumentNullException()); // aud missing Validate(jwt: jwt, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolException), substringExpected: "IDX10309:")); // exp missing jwt.Payload.AddClaim(new Claim(JwtRegisteredClaimNames.Aud, IdentityUtilities.DefaultAudience)); Validate(jwt: jwt, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolException), substringExpected: "IDX10309:")); // iat missing jwt.Payload.AddClaim(new Claim(JwtRegisteredClaimNames.Exp, EpochTime.GetIntDate(DateTime.UtcNow).ToString())); Validate(jwt: jwt, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolException), substringExpected: "IDX10309:")); // iss missing jwt.Payload.AddClaim(new Claim(JwtRegisteredClaimNames.Iat, EpochTime.GetIntDate(DateTime.UtcNow).ToString())); Validate(jwt: jwt, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolException), substringExpected: "IDX10309:")); // add iis, nonce is not retuired. protocolValidator.RequireNonce = false; jwt.Payload.AddClaim(new Claim(JwtRegisteredClaimNames.Iss, IdentityUtilities.DefaultIssuer)); Validate(jwt: jwt, protocolValidator: protocolValidator, validationContext: validationContext, ee: ExpectedException.NoExceptionExpected); // nonce invalid string validNonce = protocolValidator.GenerateNonce(); // add the valid 'nonce' but set validationContext.Nonce to a different 'nonce'. protocolValidator.RequireNonce = true; jwt.Payload.AddClaim(new Claim(JwtRegisteredClaimNames.Nonce, validNonce)); validationContext.Nonce = protocolValidator.GenerateNonce(); Validate(jwt: jwt, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolInvalidNonceException), substringExpected: "IDX10301:")); // sub missing, default not required validationContext.Nonce = validNonce; Validate(jwt: jwt, protocolValidator: protocolValidator, validationContext: validationContext, ee: ExpectedException.NoExceptionExpected); protocolValidator.RequireSub = true; Validate(jwt: jwt, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolException), substringExpected: "IDX10309:")); // authorizationCode invalid string validAuthorizationCode = protocolValidator.GenerateNonce(); string validChash = IdentityUtilities.CreateCHash(validAuthorizationCode, "SHA256"); JwtSecurityToken jwtWithSignatureChash = new JwtSecurityToken ( audience: IdentityUtilities.DefaultAudience, claims: new List<Claim> { new Claim(JwtRegisteredClaimNames.CHash, validChash), new Claim(JwtRegisteredClaimNames.Iat, EpochTime.GetIntDate(DateTime.UtcNow).ToString()), new Claim(JwtRegisteredClaimNames.Nonce, validNonce), new Claim(JwtRegisteredClaimNames.Sub, "sub"), }, expires: DateTime.UtcNow + TimeSpan.FromHours(1), issuer: IdentityUtilities.DefaultIssuer, signingCredentials: IdentityUtilities.DefaultAsymmetricSigningCredentials ); Dictionary<string,string> algmap = new Dictionary<string,string>(protocolValidator.HashAlgorithmMap); protocolValidator.HashAlgorithmMap.Clear(); protocolValidator.HashAlgorithmMap.Add(JwtAlgorithms.RSA_SHA256, "SHA256"); validationContext.Nonce = validNonce; validationContext.AuthorizationCode = validNonce; Validate(jwt: jwtWithSignatureChash, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolInvalidCHashException), substringExpected: "IDX10304:")); // nonce and authorizationCode valid validationContext.AuthorizationCode = validAuthorizationCode; Validate(jwt: jwtWithSignatureChash, protocolValidator: protocolValidator, validationContext: validationContext, ee: ExpectedException.NoExceptionExpected); // validate optional claims protocolValidator.RequireAcr = true; Validate(jwt: jwtWithSignatureChash, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolException), substringExpected: "IDX10312:")); jwtWithSignatureChash.Payload.AddClaim(new Claim(JwtRegisteredClaimNames.Acr, "acr")); protocolValidator.RequireAmr = true; Validate(jwt: jwtWithSignatureChash, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolException), substringExpected: "IDX10313:")); jwtWithSignatureChash.Payload.AddClaim(new Claim(JwtRegisteredClaimNames.Amr, "amr")); protocolValidator.RequireAuthTime = true; Validate(jwt: jwtWithSignatureChash, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolException), substringExpected: "IDX10314:")); jwtWithSignatureChash.Payload.AddClaim(new Claim(JwtRegisteredClaimNames.AuthTime, "authTime")); protocolValidator.RequireAzp = true; Validate(jwt: jwtWithSignatureChash, protocolValidator: protocolValidator, validationContext: validationContext, ee: new ExpectedException(typeExpected: typeof(OpenIdConnectProtocolException), substringExpected: "IDX10315:")); jwtWithSignatureChash.Payload.AddClaim(new Claim(JwtRegisteredClaimNames.Azp, "azp")); Validate(jwt: jwtWithSignatureChash, protocolValidator: protocolValidator, validationContext: validationContext, ee: ExpectedException.NoExceptionExpected); }
public void Validate(JwtSecurityToken jwt, OpenIdConnectProtocolValidationContext validationContext, ExpectedException ee) { try { OpenIdConnectProtocolValidator.Validate(jwt, validationContext); ee.ProcessNoException(); } catch (Exception ex) { ee.ProcessException(ex); } }