private async Task AddToCache(string url, JWKeyset keyset) { if (_cache == null || keyset == null) { return; } await _cache.Add(url, keyset).ConfigureAwait(false); }
/// <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); }
/// <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); }
/// <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); }