/// <summary> /// Validates that the <see cref="JwtSecurityToken"/> contains the nonce. /// </summary> /// <param name="validationContext">A <see cref="OpenIdConnectProtocolValidationContext"/> that contains the 'nonce' to validate.</param> /// <exception cref="ArgumentNullException">If 'validationContext' is null.</exception> /// <exception cref="ArgumentNullException">If 'validationContext.ValidatedIdToken' is null.</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 'id_token' does not 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 'id_token'.</para></remarks> protected virtual void ValidateNonce(OpenIdConnectProtocolValidationContext validationContext) { IdentityModelEventSource.Logger.WriteVerbose(LogMessages.IDX10319); if (validationContext == null) { throw LogHelper.LogArgumentNullException("validationContext"); } if (validationContext.ValidatedIdToken == null) { throw LogHelper.LogArgumentNullException("validationContext.ValidatedIdToken"); } string nonceFoundInJwt = validationContext.ValidatedIdToken.Payload.Nonce; if (!RequireNonce && string.IsNullOrEmpty(validationContext.Nonce) && string.IsNullOrEmpty(nonceFoundInJwt)) { IdentityModelEventSource.Logger.WriteInformation(LogMessages.IDX10322); return; } else if (string.IsNullOrEmpty(validationContext.Nonce)) { throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolInvalidNonceException(String.Format(CultureInfo.InvariantCulture, LogMessages.IDX10320, RequireNonce.ToString()))); } else if (string.IsNullOrEmpty(nonceFoundInJwt)) { throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolInvalidNonceException(String.Format(CultureInfo.InvariantCulture, LogMessages.IDX10323, RequireNonce.ToString(), validationContext.ValidatedIdToken))); } if (!string.Equals(nonceFoundInJwt, validationContext.Nonce, StringComparison.Ordinal)) { throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolInvalidNonceException(String.Format(CultureInfo.InvariantCulture, LogMessages.IDX10321, validationContext.Nonce, nonceFoundInJwt, validationContext.ValidatedIdToken))); } if (RequireTimeStampInNonce) { int endOfTimestamp = nonceFoundInJwt.IndexOf('.'); if (endOfTimestamp == -1) { throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolInvalidNonceException(String.Format(CultureInfo.InvariantCulture, LogMessages.IDX10325, validationContext.Nonce))); } string timestamp = nonceFoundInJwt.Substring(0, endOfTimestamp); DateTime nonceTime = new DateTime(1979, 1, 1); // initializing to some value otherwise it gives an error long ticks = -1; try { ticks = Convert.ToInt64(timestamp, CultureInfo.InvariantCulture); } catch (Exception ex) { throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolInvalidNonceException(String.Format(CultureInfo.InvariantCulture, LogMessages.IDX10326, timestamp, validationContext.Nonce), ex)); } if (ticks <= 0) { throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolInvalidNonceException(String.Format(CultureInfo.InvariantCulture, LogMessages.IDX10326, timestamp, validationContext.Nonce))); } try { nonceTime = DateTime.FromBinary(ticks); } catch (Exception ex) { throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolInvalidNonceException(String.Format(CultureInfo.InvariantCulture, LogMessages.IDX10327, timestamp, DateTime.MinValue.Ticks.ToString(CultureInfo.InvariantCulture), DateTime.MaxValue.Ticks.ToString(CultureInfo.InvariantCulture)), ex)); } DateTime utcNow = DateTime.UtcNow; if (nonceTime + NonceLifetime < utcNow) { throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolInvalidNonceException(String.Format(CultureInfo.InvariantCulture, LogMessages.IDX10324, validationContext.Nonce, nonceTime.ToString(), utcNow.ToString(), NonceLifetime.ToString()))); } } }
/// <summary> /// Validates that the <see cref="JwtSecurityToken"/> contains the nonce. /// </summary> /// <param name="validationContext">A <see cref="OpenIdConnectProtocolValidationContext"/> that contains the 'nonce' to validate.</param> /// <exception cref="ArgumentNullException">If 'validationContext' is null.</exception> /// <exception cref="ArgumentNullException">If 'validationContext.ValidatedIdToken' is null.</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 'id_token' does not 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 'id_token'.</para></remarks> protected virtual void ValidateNonce(OpenIdConnectProtocolValidationContext validationContext) { LogHelper.LogVerbose(LogMessages.IDX21319); if (validationContext == null) { throw LogHelper.LogArgumentNullException(nameof(validationContext)); } if (validationContext.ValidatedIdToken == null) { throw LogHelper.LogArgumentNullException(nameof(validationContext.ValidatedIdToken)); } string nonceFoundInJwt = validationContext.ValidatedIdToken.Payload.Nonce; // if a nonce is not required AND there is no nonce in the context (which represents what was returned from the IDP) and the token log and return if (!RequireNonce && string.IsNullOrEmpty(validationContext.Nonce) && string.IsNullOrEmpty(nonceFoundInJwt)) { LogHelper.LogInformation(LogMessages.IDX21322); return; } // if we get here then RequireNonce == true || validationContext.None != null || nonceFoundInJwt != null if (string.IsNullOrEmpty(validationContext.Nonce) && string.IsNullOrEmpty(nonceFoundInJwt)) { throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolInvalidNonceException(LogHelper.FormatInvariant(LogMessages.IDX21320, RequireNonce))); } else if (string.IsNullOrEmpty(validationContext.Nonce)) { throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolInvalidNonceException(LogHelper.FormatInvariant(LogMessages.IDX21323, RequireNonce))); } else if (string.IsNullOrEmpty(nonceFoundInJwt)) { throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolInvalidNonceException(LogHelper.FormatInvariant(LogMessages.IDX21349, RequireNonce))); } if (!string.Equals(nonceFoundInJwt, validationContext.Nonce, StringComparison.Ordinal)) { throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolInvalidNonceException(LogHelper.FormatInvariant(LogMessages.IDX21321, validationContext.Nonce, nonceFoundInJwt, validationContext.ValidatedIdToken))); } if (RequireTimeStampInNonce) { int endOfTimestamp = nonceFoundInJwt.IndexOf('.'); if (endOfTimestamp == -1) { throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolInvalidNonceException(LogHelper.FormatInvariant(LogMessages.IDX21325, nonceFoundInJwt))); } string timestamp = nonceFoundInJwt.Substring(0, endOfTimestamp); DateTime nonceTime = new DateTime(1979, 1, 1); // initializing to some value otherwise it gives an error long ticks = -1; try { ticks = Convert.ToInt64(timestamp, CultureInfo.InvariantCulture); } catch (Exception ex) { throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolInvalidNonceException(LogHelper.FormatInvariant(LogMessages.IDX21326, timestamp, nonceFoundInJwt), ex)); } if (ticks <= 0) { throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolInvalidNonceException(LogHelper.FormatInvariant(LogMessages.IDX21326, timestamp, nonceFoundInJwt))); } try { nonceTime = DateTime.FromBinary(ticks); } catch (Exception ex) { throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolInvalidNonceException(LogHelper.FormatInvariant(LogMessages.IDX21327, timestamp, DateTime.MinValue.Ticks.ToString(CultureInfo.InvariantCulture), DateTime.MaxValue.Ticks.ToString(CultureInfo.InvariantCulture)), ex)); } DateTime utcNow = DateTime.UtcNow; if (nonceTime + NonceLifetime < utcNow) { throw LogHelper.LogExceptionMessage(new OpenIdConnectProtocolInvalidNonceException(LogHelper.FormatInvariant(LogMessages.IDX21324, nonceFoundInJwt, nonceTime.ToString(CultureInfo.InvariantCulture), utcNow.ToString(CultureInfo.InvariantCulture), NonceLifetime.ToString("c", CultureInfo.InvariantCulture)))); } } }
/// <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())); } } }