예제 #1
0
        IJwt IJwtParser.Parse(string jwt)
        {
            if (string.IsNullOrEmpty(jwt))
            {
                throw new ArgumentNullException("JWT string cannot be null or empty.");
            }

            var parts = jwt.Split(DefaultJwt.Separator);

            if (parts.Length != 3)
            {
                throw new MalformedJwtException("Token must consist of exactly 3 delimited parts.");
            }

            var base64UrlEncodedHeader  = parts[0];
            var base64UrlEncodedPayload = parts[1];
            var base64UrlEncodedDigest  = parts[2];

            if (string.IsNullOrEmpty(base64UrlEncodedPayload))
            {
                throw new MalformedJwtException("JWT string is missing a body/payload.");
            }

            Map header  = null;
            Map payload = null;

            try
            {
                header = this.serializer.Deserialize(Base64.Decode(base64UrlEncodedHeader, Encoding.UTF8));
            }
            catch (Exception e)
            {
                throw new MalformedJwtException("Could not decode JWT header.", e);
            }

            try
            {
                payload = this.serializer.Deserialize(Base64.Decode(base64UrlEncodedPayload, Encoding.UTF8));
            }
            catch (Exception e)
            {
                throw new MalformedJwtException("Could not decode JWT payload.", e);
            }

            IJwtClaims claims = new DefaultJwtClaims(payload);

            // Validate signing algorithm. Currently only HS256 is supported
            string algorithm = null;

            if (!header.TryGetValueAsString(JwtHeaderParameters.Algorithm, out algorithm) ||
                !algorithm.Equals("HS256", StringComparison.OrdinalIgnoreCase))
            {
                throw new MalformedJwtException($"JWT uses unsupported signing algorithm '{algorithm}'. Only HS256 is supported.");
            }

            // Validate the signature
            if (this.keyBytes != null)
            {
                var signatureValidator = new JwtSignatureValidator(this.keyBytes);
                if (!signatureValidator.IsValid(
                        base64UrlEncodedHeader,
                        base64UrlEncodedPayload,
                        base64UrlEncodedDigest))
                {
                    throw new JwtSignatureException("JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.");
                }
            }

            IJwt jwtInstance = new DefaultJwt(header, claims, base64UrlEncodedHeader, base64UrlEncodedPayload, base64UrlEncodedDigest);

            // Validate lifetime (exp, iat, nbf claims)
            var lifetimeValidator = new JwtLifetimeValidator(DateTimeOffset.Now);

            lifetimeValidator.Validate(jwtInstance.Body);

            // Validate expected claims
            this.ValidateExpectedClaims(jwtInstance);

            return(jwtInstance);
        }
        IJwt IJwtParser.Parse(string jwt)
        {
            if (string.IsNullOrEmpty(jwt))
            {
                throw new ArgumentNullException("JWT string cannot be null or empty.");
            }

            var parts = jwt.Split(DefaultJwt.Separator);
            if (parts.Length != 3)
            {
                throw new MalformedJwtException("Token must consist of exactly 3 delimited parts.");
            }

            var base64UrlEncodedHeader = parts[0];
            var base64UrlEncodedPayload = parts[1];
            var base64UrlEncodedDigest = parts[2];

            if (string.IsNullOrEmpty(base64UrlEncodedPayload))
            {
                throw new MalformedJwtException("JWT string is missing a body/payload.");
            }

            Map header = null;
            Map payload = null;
            try
            {
                header = this.serializer.Deserialize(Base64.Decode(base64UrlEncodedHeader, Encoding.UTF8));
            }
            catch (Exception e)
            {
                throw new MalformedJwtException("Could not decode JWT header.", e);
            }

            try
            {
                payload = this.serializer.Deserialize(Base64.Decode(base64UrlEncodedPayload, Encoding.UTF8));
            }
            catch (Exception e)
            {
                throw new MalformedJwtException("Could not decode JWT payload.", e);
            }

            IJwtClaims claims = new DefaultJwtClaims(payload);

            // Validate signing algorithm. Currently only HS256 is supported
            string algorithm = null;
            if (!header.TryGetValueAsString(JwtHeaderParameters.Algorithm, out algorithm)
                || !algorithm.Equals("HS256", StringComparison.OrdinalIgnoreCase))
            {
                throw new MalformedJwtException($"JWT uses unsupported signing algorithm '{algorithm}'. Only HS256 is supported.");
            }

            // Validate the signature
            if (this.keyBytes != null)
            {
                var signatureValidator = new JwtSignatureValidator(this.keyBytes);
                if (!signatureValidator.IsValid(
                    base64UrlEncodedHeader,
                    base64UrlEncodedPayload,
                    base64UrlEncodedDigest))
                {
                    throw new JwtSignatureException("JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.");
                }
            }

            IJwt jwtInstance = new DefaultJwt(header, claims, base64UrlEncodedHeader, base64UrlEncodedPayload, base64UrlEncodedDigest);

            // Validate lifetime (exp, iat, nbf claims)
            var lifetimeValidator = new JwtLifetimeValidator(DateTimeOffset.Now);
            lifetimeValidator.Validate(jwtInstance.Body);

            // Validate expected claims
            this.ValidateExpectedClaims(jwtInstance);

            return jwtInstance;
        }