From 061f03fc9dd47484fa9dae9ab129dae2eeb3e05c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Mon, 23 Jul 2018 16:24:17 +0200 Subject: [PATCH] Update the validation handler to validate the token status in DecryptToken() --- .../Internal/OpenIddictValidationProvider.cs | 8 +++ .../OpenIddictValidationProviderTests.cs | 51 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/src/OpenIddict.Validation/Internal/OpenIddictValidationProvider.cs b/src/OpenIddict.Validation/Internal/OpenIddictValidationProvider.cs index 82abc0f1..d3f6571b 100644 --- a/src/OpenIddict.Validation/Internal/OpenIddictValidationProvider.cs +++ b/src/OpenIddict.Validation/Internal/OpenIddictValidationProvider.cs @@ -68,6 +68,14 @@ namespace OpenIddict.Validation return; } + // Ensure the access token is still valid (i.e was not marked as revoked). + if (!await manager.IsValidAsync(token)) + { + context.Fail("Authentication failed because the access token was no longer valid."); + + return; + } + var ticket = context.DataFormat.Unprotect(payload); if (ticket == null) { diff --git a/test/OpenIddict.Validation.Tests/Internal/OpenIddictValidationProviderTests.cs b/test/OpenIddict.Validation.Tests/Internal/OpenIddictValidationProviderTests.cs index def6689d..db5299d5 100644 --- a/test/OpenIddict.Validation.Tests/Internal/OpenIddictValidationProviderTests.cs +++ b/test/OpenIddict.Validation.Tests/Internal/OpenIddictValidationProviderTests.cs @@ -127,6 +127,50 @@ namespace OpenIddict.Validation.Tests Mock.Get(manager).Verify(mock => mock.GetPayloadAsync(token, It.IsAny()), Times.Once()); } + [Fact] + public async Task DecryptToken_ReturnsFailedResultForReferenceTokenWithInvalidStatus() + { + // Arrange + var token = new OpenIddictToken(); + + var format = new Mock>(); + format.Setup(mock => mock.Unprotect("valid-reference-token-payload")) + .Returns(value: null); + + var manager = CreateTokenManager(instance => + { + instance.Setup(mock => mock.FindByReferenceIdAsync("valid-reference-token-id", It.IsAny())) + .ReturnsAsync(token); + + instance.Setup(mock => mock.GetPayloadAsync(token, It.IsAny())) + .Returns(new ValueTask("valid-reference-token-payload")); + + instance.Setup(mock => mock.IsValidAsync(token, It.IsAny())) + .ReturnsAsync(false); + }); + + var server = CreateResourceServer(builder => + { + builder.Services.AddSingleton(manager); + }); + + var client = server.CreateClient(); + + var request = new HttpRequestMessage(HttpMethod.Get, "/"); + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "valid-reference-token-id"); + + // Act + var response = await client.SendAsync(request); + + // Assert + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + + Mock.Get(manager).Verify(mock => mock.FindByReferenceIdAsync("valid-reference-token-id", It.IsAny()), Times.Once()); + Mock.Get(manager).Verify(mock => mock.GetPayloadAsync(token, It.IsAny()), Times.Once()); + Mock.Get(manager).Verify(mock => mock.IsValidAsync(token, It.IsAny()), Times.Once()); + format.Verify(mock => mock.Unprotect("valid-reference-token-payload"), Times.Never()); + } + [Fact] public async Task DecryptToken_ReturnsFailedResultForInvalidReferenceTokenPayload() { @@ -144,6 +188,9 @@ namespace OpenIddict.Validation.Tests instance.Setup(mock => mock.GetPayloadAsync(token, It.IsAny())) .Returns(new ValueTask("invalid-reference-token-payload")); + + instance.Setup(mock => mock.IsValidAsync(token, It.IsAny())) + .ReturnsAsync(true); }); var server = CreateResourceServer(builder => @@ -165,6 +212,7 @@ namespace OpenIddict.Validation.Tests Mock.Get(manager).Verify(mock => mock.FindByReferenceIdAsync("valid-reference-token-id", It.IsAny()), Times.Once()); Mock.Get(manager).Verify(mock => mock.GetPayloadAsync(token, It.IsAny()), Times.Once()); + Mock.Get(manager).Verify(mock => mock.IsValidAsync(token, It.IsAny()), Times.Once()); format.Verify(mock => mock.Unprotect("invalid-reference-token-payload"), Times.Once()); } @@ -194,6 +242,9 @@ namespace OpenIddict.Validation.Tests instance.Setup(mock => mock.GetPayloadAsync(token, It.IsAny())) .Returns(new ValueTask("valid-reference-token-payload")); + instance.Setup(mock => mock.IsValidAsync(token, It.IsAny())) + .ReturnsAsync(true); + instance.Setup(mock => mock.GetCreationDateAsync(token, It.IsAny())) .Returns(new ValueTask(new DateTimeOffset(2018, 01, 01, 00, 00, 00, TimeSpan.Zero)));