private async Task AddToCache(string url, JWKeyset keyset)
        {
            if (_cache == null || keyset == null)
            {
                return;
            }

            await _cache.Add(url, keyset).ConfigureAwait(false);
        }
Пример #2
0
        /// <summary>
        /// Validates an id token signature by signing the id token payload and comparing the result with the signature
        /// </summary>
        /// <param name="idToken">IDToken to validate</param>
        /// <param name="keyset">
        /// Keyset retrieved from the jwks url, used to validate the token signature.
        /// If null the token will not be validated and <see cref="TokenValidationResult.JWKSError"/> will be returned
        /// </param>
        /// <returns>TokenValidationResult that specifies if the token signature is valid, or if not why it is not valid</returns>
        public static TokenValidationResult ValidateIdTokenSignature(string idToken, JWKeyset keyset)
        {
            if (keyset == null)
            {
                return(TokenValidationResult.JWKSError);
            }

            JObject header = JObject.Parse(JsonWebToken.DecodePart(idToken, JWTPart.Header));
            string  alg    = (string)header["alg"];

            string keyid = (string)header["kid"];
            var    key   = keyset.GetMatching(x => x.KeyID == keyid && (string.IsNullOrEmpty(x.Algorithm) || x.Algorithm == alg)).FirstOrDefault();

            if (key == null)
            {
                return(TokenValidationResult.NoMatchingKey);
            }

            int lastSplitIndex = idToken.LastIndexOf('.');

            if (lastSplitIndex < 0 || lastSplitIndex == idToken.Length - 1)
            {
                return(TokenValidationResult.InvalidSignature);
            }

            var dataToSign = idToken.Substring(0, lastSplitIndex);
            var signature  = idToken.Substring(lastSplitIndex + 1);

            bool isValid;

            try
            {
                isValid = key.Verify(dataToSign, signature, alg);
            }
            catch (MobileConnectUnsupportedJWKException)
            {
                return(TokenValidationResult.UnsupportedAlgorithm);
            }
            catch (MobileConnectInvalidJWKException)
            {
                return(TokenValidationResult.KeyMisformed);
            }

            return(isValid ? TokenValidationResult.Valid : TokenValidationResult.InvalidSignature);
        }
Пример #3
0
        /// <summary>
        /// Validates an id token against the mobile connect validation requirements, this includes validation of some claims and validation of the signature
        /// </summary>
        /// <param name="idToken">IDToken to validate</param>
        /// <param name="clientId">ClientId that is validated against the aud and azp claims</param>
        /// <param name="issuer">Issuer that is validated against the iss claim</param>
        /// <param name="nonce">Nonce that is validated against the nonce claim</param>
        /// <param name="maxAge">MaxAge that is used to validate the auth_time claim (if supplied)</param>
        /// <param name="keyset">Keyset retrieved from the jwks url, used to validate the token signature</param>
        /// <param name="version">Version of MobileConnect services supported by current provider</param>
        /// <returns>TokenValidationResult that sepcfies if the token is valid, or if not why it is not valid</returns>
        public static TokenValidationResult ValidateIdToken(string idToken, string clientId, string issuer, string nonce, int?maxAge, JWKeyset keyset, string version)
        {
            if (string.IsNullOrEmpty(idToken))
            {
                return(TokenValidationResult.IdTokenMissing);
            }

            bool isR1Source = version == Discovery.SupportedVersions.R1Version;
            TokenValidationResult result = ValidateIdTokenClaims(idToken, clientId, issuer, nonce, maxAge, version);

            if (isR1Source)
            {
                return(TokenValidationResult.IdTokenValidationSkipped);
            }
            if (result != TokenValidationResult.Valid)
            {
                return(result);
            }

            result = ValidateIdTokenSignature(idToken, keyset);
            return(result != TokenValidationResult.Valid ? TokenValidationResult.IdTokenValidationSkipped : result);
        }
Пример #4
0
        /// <inheritdoc/>
        public TokenValidationResult ValidateTokenResponse(RequestTokenResponse tokenResponse, string clientId, string issuer, string nonce, int?maxAge, JWKeyset keyset, string version)
        {
            if (tokenResponse?.ResponseData == null)
            {
                Log.Warning(() => $"Token was incomplete from issuer={issuer}");
                return(TokenValidationResult.IncompleteTokenResponse);
            }

            TokenValidationResult result = TokenValidation.ValidateAccessToken(tokenResponse.ResponseData);

            if (result != TokenValidationResult.Valid)
            {
                Log.Warning(() => $"Access token was invalid from issuer={issuer}");
                return(result);
            }

            result = TokenValidation.ValidateIdToken(tokenResponse.ResponseData.IdToken, clientId, issuer, nonce, maxAge, keyset, version);
            if (result != TokenValidationResult.Valid)
            {
                Log.Warning(() => $"IDToken was invalid from issuer={issuer} for reason={result}");
            }

            return(result);
        }