/// <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 the <see cref="JwtSecurityToken"/> contains the nonce. /// </summary> /// <param name="jwt">the <see cref="JwtSecurityToken"/>that must contain the nonce.</param> /// <param name="nonce">the 'nonce' to match.</param> /// <exception cref="ArgumentNullException">if 'jwt' is null.</exception> /// <exception cref="ArgumentNullException">if 'nonce' is null or whitespace.</exception> /// <exception cref="OpenIdConnectProtocolInvalidNonceException">if a'nonce' is not found in the <see cref="JwtSecurityToken"/>.</exception> /// <exception cref="OpenIdConnectProtocolInvalidNonceException">if the 'nonce' found in the <see cref="JwtSecurityToken"/> is null or whitespace.</exception> /// <exception cref="OpenIdConnectProtocolInvalidNonceException">if the 'nonce' found in the <see cref="JwtSecurityToken"/> doesn't match the 'nonce' passed to routine.</exception> public static void ValidateNonce(JwtSecurityToken jwt, string nonce) { if (jwt == null) { throw new ArgumentNullException("jwt"); } if (string.IsNullOrWhiteSpace(nonce)) { throw new ArgumentNullException("nonce"); } string nonceFoundInJwt = jwt.Payload.Nonce; if (nonceFoundInJwt == null || string.IsNullOrWhiteSpace(nonceFoundInJwt)) { throw new OpenIdConnectProtocolInvalidNonceException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10300, JwtRegisteredClaimNames.Nonce, jwt.ToString())); } if (!(StringComparer.Ordinal.Equals(nonceFoundInJwt, nonce))) { throw new OpenIdConnectProtocolInvalidNonceException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10301, nonceFoundInJwt, nonce, jwt.ToString())); } }