public bool TryValidate(JwtHeaderDocument header, JwtPayloadDocument payload, [NotNullWhen(false)] out TokenValidationError?error) { if (payload is null) { error = TokenValidationError.MalformedToken(); return(false); } if (!payload.TryGetClaim(_claim, out var claim)) { error = TokenValidationError.MissingClaim(_claim); return(false); } if (!claim.TryGetDouble(out var value) || _value != value) { error = TokenValidationError.InvalidClaim(_claim); return(false); } #if NET5_0_OR_GREATER Unsafe.SkipInit(out error); #else error = default; #endif return(true); }
public bool TryValidate(JwtHeaderDocument header, JwtPayloadDocument payload, [NotNullWhen(false)] out TokenValidationError?error) { if (payload is null) { error = TokenValidationError.MalformedToken(); return(false); } if (payload.ContainsClaim(_claim)) { error = null; return(true); } error = TokenValidationError.MissingClaim(_claim); return(false); }
public bool TryValidate(JwtHeaderDocument header, JwtPayloadDocument payload, [NotNullWhen(false)] out TokenValidationError?error) { if (payload is null) { error = TokenValidationError.MalformedToken(); return(false); } if (payload.ContainsClaim(OAuth2Claims.AuthTime.EncodedUtf8Bytes)) { error = null; return(true); } error = TokenValidationError.MissingClaim(OAuth2Claims.AuthTime.ToString()); return(false); }
/// <summary>Parses and validates a JWT encoded as a JWS or JWE in compact serialized format.</summary> /// <param name="token">The JWT encoded as JWE or JWS</param> /// <param name="policy">The validation policy.</param> /// <param name="jwt">The resulting <see cref="Jwt"/>.</param> public static bool TryParse(string token, TokenValidationPolicy policy, out Jwt jwt) { if (token is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.token); } if (policy is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.policy); } if (token.Length == 0) { jwt = new Jwt(TokenValidationError.MalformedToken()); return(false); } int length = Utf8.GetMaxByteCount(token.Length); if (length > policy.MaximumTokenSizeInBytes) { jwt = new Jwt(TokenValidationError.MalformedToken()); return(false); } byte[]? utf8ArrayToReturnToPool = null; var utf8Token = length <= Constants.MaxStackallocBytes ? stackalloc byte[length] : (utf8ArrayToReturnToPool = ArrayPool <byte> .Shared.Rent(length)); try { int bytesWritten = Utf8.GetBytes(token, utf8Token); return(TryParse(utf8Token.Slice(0, bytesWritten), policy, out jwt)); } finally { if (utf8ArrayToReturnToPool != null) { ArrayPool <byte> .Shared.Return(utf8ArrayToReturnToPool); } } }
public bool TryValidate(JwtHeaderDocument header, JwtPayloadDocument payload, [NotNullWhen(false)] out TokenValidationError?error) { if (payload is null) { error = TokenValidationError.MalformedToken(); return(false); } if (payload.ContainsClaim(_claim)) { #if NET5_0_OR_GREATER Unsafe.SkipInit(out error); #else error = default; #endif return(true); } error = TokenValidationError.MissingClaim(_claim); return(false); }
public bool TryValidate(JwtHeaderDocument header, JwtPayloadDocument payload, [NotNullWhen(false)] out TokenValidationError?error) { if (payload is null) { error = TokenValidationError.MalformedToken(); return(false); } if (!payload.TryGetClaim(_claim, out var claim)) { error = TokenValidationError.MissingClaim(_claim); return(false); } if (!claim.TryGetDouble(out var value) || _value != value) { error = TokenValidationError.InvalidClaim(_claim); return(false); } error = null; return(true); }
public bool TryValidate(JwtHeaderDocument header, JwtPayloadDocument payload, [NotNullWhen(false)] out TokenValidationError?error) { if (payload is null) { error = TokenValidationError.MalformedToken(); return(false); } if (!payload.TryGetClaim(OAuth2Claims.Acr.EncodedUtf8Bytes, out var property)) { error = TokenValidationError.MissingClaim(OAuth2Claims.Acr.ToString()); return(false); } if (!property.ValueEquals(_requiredAcr)) { error = TokenValidationError.InvalidClaim(OAuth2Claims.Acr.ToString()); return(false); } error = null; return(true); }
/// <summary>Parses and validates a JWT encoded as a JWS or JWE in compact serialized format.</summary> /// <param name="utf8Token">The JWT encoded as JWE or JWS</param> /// <param name="policy">The validation policy.</param> /// <param name="jwt">The resulting <see cref="Jwt"/>.</param> public static bool TryParse(ReadOnlySpan <byte> utf8Token, TokenValidationPolicy policy, out Jwt jwt) { if (policy is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.policy); } TokenValidationError?error; if (utf8Token.IsEmpty) { error = TokenValidationError.MalformedToken(); goto TokenError; } if (utf8Token.Length > policy.MaximumTokenSizeInBytes) { error = TokenValidationError.MalformedToken(); goto TokenError; } Span <TokenSegment> segments = stackalloc TokenSegment[Constants.JweSegmentCount]; ref TokenSegment segmentsRef = ref MemoryMarshal.GetReference(segments);
internal static bool TryParseHeader(ReadOnlyMemory <byte> utf8Payload, byte[]?buffer, TokenValidationPolicy policy, [NotNullWhen(true)] out JwtHeaderDocument?header, [NotNullWhen(false)] out TokenValidationError?error) { ReadOnlySpan <byte> utf8JsonSpan = utf8Payload.Span; var database = new JsonMetadata(utf8Payload.Length); int algIdx = -1; int encIdx = -1; int kidIdx = -1; int critIdx = -1; var reader = new Utf8JsonReader(utf8JsonSpan); if (reader.Read()) { JsonTokenType tokenType = reader.TokenType; if (tokenType == JsonTokenType.StartObject) { while (reader.Read()) { tokenType = reader.TokenType; int tokenStart = (int)reader.TokenStartIndex; if (tokenType == JsonTokenType.EndObject) { break; } else if (tokenType != JsonTokenType.PropertyName) { error = TokenValidationError.MalformedToken(); goto Error; } // Adding 1 to skip the start quote will never overflow Debug.Assert(tokenStart < int.MaxValue); database.Append(JsonTokenType.PropertyName, tokenStart + 1, reader.ValueSpan.Length); if (reader.ValueSpan.IndexOf((byte)'\\') != -1) { database.SetNeedUnescaping(database.Length - JsonRow.Size); } ReadOnlySpan <byte> memberName = reader.ValueSpan; reader.Read(); tokenType = reader.TokenType; tokenStart = (int)reader.TokenStartIndex; // Since the input payload is contained within a Span, // token start index can never be larger than int.MaxValue (i.e. utf8JsonSpan.Length). Debug.Assert(reader.TokenStartIndex <= int.MaxValue); if (tokenType == JsonTokenType.String) { if (memberName.Length == 3) { switch ((JwtHeaderParameters)IntegerMarshal.ReadUInt24(memberName)) { case JwtHeaderParameters.Alg: algIdx = database.Length; break; case JwtHeaderParameters.Enc: encIdx = database.Length; break; case JwtHeaderParameters.Kid: kidIdx = database.Length; break; } } // Adding 1 to skip the start quote will never overflow Debug.Assert(tokenStart < int.MaxValue); database.Append(JsonTokenType.String, tokenStart + 1, reader.ValueSpan.Length); } else if (tokenType == JsonTokenType.StartObject) { int count = Utf8JsonReaderHelper.SkipObject(ref reader); int index = database.Length; int tokenEnd = (int)reader.TokenStartIndex; database.Append(JsonTokenType.StartObject, tokenStart, tokenEnd - tokenStart + 1); database.SetNumberOfRows(index, count); } else if (tokenType == JsonTokenType.StartArray) { int count; if (memberName.Length == 4 && (JwtHeaderParameters)IntegerMarshal.ReadUInt32(memberName) == JwtHeaderParameters.Crit && !policy.IgnoreCriticalHeader) { critIdx = database.Length; if (!TryCheckCrit(ref reader, out count)) { error = TokenValidationError.MalformedToken("The 'crit' header parameter must be an array of string."); goto Error; } } else { count = Utf8JsonReaderHelper.SkipArray(ref reader); } int index = database.Length; int tokenEnd = (int)reader.TokenStartIndex; database.Append(JsonTokenType.StartArray, tokenStart, tokenEnd - tokenStart + 1); database.SetNumberOfRows(index, count); } else { Debug.Assert(tokenType >= JsonTokenType.Number && tokenType <= JsonTokenType.Null); database.Append(tokenType, tokenStart, reader.ValueSpan.Length); } } } } Debug.Assert(reader.BytesConsumed == utf8JsonSpan.Length); database.CompleteAllocations(); header = new JwtHeaderDocument(new JwtDocument(utf8Payload, database, buffer), algIdx, encIdx, kidIdx, critIdx); #if NET5_0_OR_GREATER Unsafe.SkipInit(out error); #else error = default; #endif return(true); Error: #if NET5_0_OR_GREATER Unsafe.SkipInit(out header); #else header = default; #endif return(false); }
internal static bool TryParsePayload(ReadOnlyMemory <byte> utf8Payload, byte[]?buffer, TokenValidationPolicy policy, [NotNullWhen(true)] out JwtPayloadDocument?payload, [NotNullWhen(false)] out TokenValidationError?error) { ReadOnlySpan <byte> utf8JsonSpan = utf8Payload.Span; var database = new JsonMetadata(utf8Payload.Length); byte control = policy.Control; int issIdx = -1; var reader = new Utf8JsonReader(utf8JsonSpan); if (reader.Read()) { JsonTokenType tokenType = reader.TokenType; if (tokenType == JsonTokenType.StartObject) { while (reader.Read()) { tokenType = reader.TokenType; int tokenStart = (int)reader.TokenStartIndex; if (tokenType == JsonTokenType.EndObject) { break; } else if (tokenType != JsonTokenType.PropertyName) { error = TokenValidationError.MalformedToken(); goto Error; } Debug.Assert(tokenStart < int.MaxValue); database.Append(JsonTokenType.PropertyName, tokenStart + 1, reader.ValueSpan.Length); ReadOnlySpan <byte> memberName = reader.ValueSpan; if (memberName.IndexOf((byte)'\\') != -1) { database.SetNeedUnescaping(database.Length - JsonRow.Size); } reader.Read(); tokenType = reader.TokenType; tokenStart = (int)reader.TokenStartIndex; Debug.Assert(reader.TokenStartIndex <= int.MaxValue); if (tokenType == JsonTokenType.String) { if (memberName.Length == 3) { switch ((JwtClaims)IntegerMarshal.ReadUInt24(memberName)) { case JwtClaims.Aud: CheckStringAudience(ref reader, ref control, policy); break; case JwtClaims.Iss: issIdx = database.Length; CheckIssuer(ref reader, ref control, policy); break; } } Debug.Assert(tokenStart < int.MaxValue); database.Append(JsonTokenType.String, tokenStart + 1, reader.ValueSpan.Length); } else if (tokenType == JsonTokenType.Number) { if (memberName.Length == 3) { switch ((JwtClaims)IntegerMarshal.ReadUInt24(memberName)) { case JwtClaims.Exp: if (!TryCheckExpirationTime(ref reader, ref control, policy)) { error = TokenValidationError.MalformedToken("The claim 'exp' must be an integral number."); goto Error; } break; case JwtClaims.Nbf: if (!TryCheckNotBefore(ref reader, ref control, policy)) { error = TokenValidationError.MalformedToken("The claim 'nbf' must be an integral number."); goto Error; } break; } } database.Append(JsonTokenType.Number, tokenStart, reader.ValueSpan.Length); } else if (tokenType == JsonTokenType.StartObject) { int itemCount = Utf8JsonReaderHelper.SkipObject(ref reader); int tokenEnd = (int)reader.TokenStartIndex; int index = database.Length; database.Append(JsonTokenType.StartObject, tokenStart, tokenEnd - tokenStart + 1); database.SetNumberOfRows(index, itemCount); } else if (tokenType == JsonTokenType.StartArray) { int itemCount; if (memberName.Length == 3 && (JwtClaims)IntegerMarshal.ReadUInt24(memberName) == JwtClaims.Aud) { itemCount = CheckArrayAudience(ref reader, ref control, policy); } else { itemCount = Utf8JsonReaderHelper.SkipArray(ref reader); } int index = database.Length; int tokenEnd = (int)reader.TokenStartIndex; database.Append(JsonTokenType.StartArray, tokenStart, tokenEnd - tokenStart + 1); database.SetNumberOfRows(index, itemCount); } else { Debug.Assert(tokenType >= JsonTokenType.True && tokenType <= JsonTokenType.Null); database.Append(tokenType, tokenStart, reader.ValueSpan.Length); } } } } Debug.Assert(reader.BytesConsumed == utf8JsonSpan.Length); database.CompleteAllocations(); payload = new JwtPayloadDocument(new JwtDocument(utf8Payload, database, buffer), control, issIdx); #if NET5_0_OR_GREATER Unsafe.SkipInit(out error); #else error = default; #endif return(true); Error: #if NET5_0_OR_GREATER Unsafe.SkipInit(out payload); #else payload = default; #endif return(false); }