コード例 #1
0
        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);
        }
コード例 #2
0
        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);
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        /// <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);
                }
            }
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        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);
        }
コード例 #7
0
        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);
        }
コード例 #8
0
        /// <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);
コード例 #9
0
ファイル: JwtHeaderDocument.cs プロジェクト: uruk-project/Jwt
        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);
        }
コード例 #10
0
        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);
        }