public async Task <bool> IsValidAsync( TokenValidationArgs args, string schemeOwnerAccessToken, CancellationToken token = default) { if (!_decodedJwtValidator.IsIShareCompliant(args)) { return(false); } try { var validationArgs = new CertificateValidationArgs( CertificateUtilities.FromBase64Der(args.AssertionModel.Certificates.First()), args.Issuer, args.AssertionModel.Certificates.Skip(1).Select(CertificateUtilities.FromBase64Der)); return(await _jwtCertificateValidator.IsValidAsync(validationArgs, schemeOwnerAccessToken, token)); } catch (Exception e) { _logger.LogError(e, "Couldn't create proper CertificateValidationArgs. Certificates are corrupted."); return(false); } }
public void IsIShareCompliant_HeaderHasNoAlg_ReturnsFalse() { var now = DateTime.UtcNow; var jwtContent = $@"{{ ""typ"": ""JWT"", ""x5c"": [""{ Constants.AbcParty.PublicKeyBase64Der }""] }} . {{ ""iss"": ""{Constants.SchemeOwner.ClientId}"", ""sub"": ""{Constants.SchemeOwner.ClientId}"", ""aud"": ""{Constants.AbcParty.ClientId}"", ""jti"": ""{Guid.NewGuid()}"", ""exp"": ""{JwtUtilities.DateTimeToEpoch(now.AddSeconds(30))}"", ""iat"": ""{JwtUtilities.DateTimeToEpoch(now)}"" }}"; var jwtToken = JwtUtilities.SignJwt(jwtContent, Constants.AbcParty.PrivateKey); var assertionModel = CreateValidAssertionModel(jwtToken); var args = new TokenValidationArgs( assertionModel, Constants.SchemeOwner.ClientId, Constants.AbcParty.ClientId); var result = _sut.IsIShareCompliant(args); result.Should().BeFalse(); }
public void IsIShareCompliant_KeysNotFound_ReturnsFalse() { var assertionModel = new AssertionModel(new string[0], null, null); var args = new TokenValidationArgs(assertionModel, "issuer", "audience"); var result = _sut.IsIShareCompliant(args); result.Should().BeFalse(); }
IsIShareCompliant_JwtSecurityTokenHandlerValidationFailsDueToInvalidAudienceAndIssuerParams_ReturnsFalse() { var assertionModel = CreateValidAssertionModel(); var args = new TokenValidationArgs(assertionModel, Constants.AbcParty.ClientId, Constants.SchemeOwner.ClientId); var result = _sut.IsIShareCompliant(args); result.Should().BeFalse("JwtSecurityTokenHandler.ValidateToken throws exception which is handled."); }
public void IsIShareCompliant_ValidClientAssertionPassed_ReturnsTrue() { var assertionModel = CreateValidAssertionModel(); var args = new TokenValidationArgs( assertionModel, Constants.SchemeOwner.ClientId, Constants.AbcParty.ClientId); var result = _sut.IsIShareCompliant(args); result.Should().BeTrue(); }
public bool IsIShareCompliant(TokenValidationArgs args) { var keys = SecurityKeysExtractor.Extract(args.AssertionModel.Certificates); if (keys.Count == 0) { return(false); } try { var handler = new JwtSecurityTokenHandler(); var validationParameters = CreateTokenValidationParameters(args.Issuer, args.Audience, keys); handler.ValidateToken(args.AssertionModel.JwtToken, validationParameters, out var securityToken); var jwtSecurityToken = (JwtSecurityToken)securityToken; if (jwtSecurityToken.RawData != args.AssertionModel.JwtSecurityToken.RawData) { _logger.LogWarning("Keys that were used to verify this token might not be a part of this JWT."); return(false); } if (IsHeaderInvalid(jwtSecurityToken.Header)) { _logger.LogWarning($"Invalid JWT header. Jwt issued by {args.Issuer}."); return(false); } if (IsPayloadInvalid(jwtSecurityToken.Payload)) { _logger.LogWarning($"Invalid JWT payload. Jwt issued by {args.Issuer}."); return(false); } return(true); } catch (Exception e) { _logger.LogError(e, "JWT token is not iSHARE compliant, validation failed."); return(false); } }
public async Task IsValidAsync_EverythingValid_ReturnsTrue() { const string accessToken = "this_time_needed"; SetupDecodedJwtValidatorMock(); _jwtCertificateValidatorMock .Setup(x => x.IsValidAsync( It.IsAny <CertificateValidationArgs>(), accessToken, It.IsAny <CancellationToken>())) .ReturnsAsync(true); var args = new TokenValidationArgs( CreateValidAssertionModel(), Constants.SchemeOwner.ClientId, Constants.AbcParty.ClientId); var result = await _sut.IsValidAsync(args, accessToken, CancellationToken.None); result.Should().BeTrue(); }
public void IsIShareCompliant_HeaderAlgNeqRS256_ReturnsFalse() { var signingAlgorithm = JwtUtilities.CreateSigningCredentials( Constants.AbcParty.PrivateKey, SecurityAlgorithms.RsaSsaPssSha512); var jwtSecurityToken = JwtUtilities.CreateToken( Constants.SchemeOwner.ClientId, Constants.AbcParty.ClientId, Constants.AbcParty.PublicKeyBase64Der, signingAlgorithm); var jwtToken = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken); var assertionModel = CreateValidAssertionModel(jwtToken); var args = new TokenValidationArgs( assertionModel, Constants.SchemeOwner.ClientId, Constants.AbcParty.ClientId); var result = _sut.IsIShareCompliant(args); result.Should().BeFalse("Only RS256 should be supported."); }
public void IsIShareCompliant_AssertionModelContainsDifferentJwtSecurityTokenThanItsString_ReturnsFalse() { var jwtToken = CreateValidJwtToken(); var handler = new JwtSecurityTokenHandler(); var jwtSecurityToken = handler.ReadJwtToken(jwtToken); var assertionModel = new AssertionModel( new[] { Constants.AbcParty.PublicKeyBase64Der }, jwtSecurityToken, CreateValidJwtToken()); var args = new TokenValidationArgs( assertionModel, Constants.SchemeOwner.ClientId, Constants.AbcParty.ClientId); var result = _sut.IsIShareCompliant(args); const string reason = "JWT is valid because assertion model contains its public keys which were extracted " + "from JwtSecurityToken. Those public keys applies for JwtToken (string). However, " + "those public keys were not extracted from the token which is being validated, so " + "validation should fail."; result.Should().BeFalse(reason); }
public void Constructor_ValidArguments_CreatesObject() { var result = new TokenValidationArgs(new AssertionModel(null, null, null), "valid", null); result.Should().NotBeNull(); }