From e9d5a1c64f69384e23d5592c5d92b638c8c8593c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Mon, 27 Jul 2026 17:44:19 +0200 Subject: [PATCH] Update the client/server/validation stacks to always use the CancellationToken attached to the context --- .../Controllers/HomeController.cs | 2 +- .../Controllers/HomeController.cs | 2 +- .../OpenIddictClientAspNetCoreHandler.cs | 28 +++-- .../OpenIddictClientOwinHandler.cs | 28 +++-- ...ystemIntegrationHandlers.Authentication.cs | 4 +- ...ClientSystemIntegrationHandlers.Session.cs | 4 +- ...enIddictClientSystemIntegrationHandlers.cs | 2 +- ...penIddictClientSystemIntegrationService.cs | 9 +- ...ictClientSystemNetHttpHandlers.Userinfo.cs | 2 +- .../OpenIddictClientSystemNetHttpHandlers.cs | 14 +-- .../IOpenIddictClientFactory.cs | 6 +- .../OpenIddictClientConfiguration.cs | 16 +-- .../OpenIddictClientDispatcher.cs | 2 + .../OpenIddictClientEvents.cs | 14 +-- .../OpenIddictClientFactory.cs | 12 +- .../OpenIddictClientHandlers.Protection.cs | 40 +++---- .../OpenIddictClientHandlers.cs | 8 +- .../OpenIddictClientService.cs | 84 ++++---------- .../OpenIddictClientTransaction.cs | 8 +- .../OpenIddictServerAspNetCoreHandler.cs | 29 +++-- .../OpenIddictServerAspNetCoreHandlers.cs | 2 +- .../OpenIddictServerOwinHandler.cs | 30 +++-- .../OpenIddictServerOwinHandlers.cs | 8 +- .../IOpenIddictServerFactory.cs | 6 +- .../OpenIddictServerConfiguration.cs | 6 +- .../OpenIddictServerDispatcher.cs | 2 + .../OpenIddictServerEvents.cs | 14 +-- .../OpenIddictServerFactory.cs | 12 +- ...OpenIddictServerHandlers.Authentication.cs | 104 +++++++++--------- .../OpenIddictServerHandlers.Device.cs | 20 ++-- .../OpenIddictServerHandlers.Exchange.cs | 34 +++--- .../OpenIddictServerHandlers.Introspection.cs | 8 +- .../OpenIddictServerHandlers.Protection.cs | 64 +++++------ .../OpenIddictServerHandlers.Revocation.cs | 8 +- .../OpenIddictServerHandlers.Session.cs | 36 +++--- .../OpenIddictServerHandlers.cs | 98 ++++++++--------- .../OpenIddictServerTransaction.cs | 8 +- .../OpenIddictValidationAspNetCoreHandler.cs | 26 ++--- .../OpenIddictValidationAspNetCoreHandlers.cs | 2 +- .../OpenIddictValidationOwinHandler.cs | 26 ++--- .../OpenIddictValidationOwinHandlers.cs | 8 +- ...enIddictValidationSystemNetHttpHandlers.cs | 14 +-- .../IOpenIddictValidationFactory.cs | 6 +- .../OpenIddictValidationDispatcher.cs | 2 + .../OpenIddictValidationEvents.cs | 14 +-- .../OpenIddictValidationFactory.cs | 12 +- ...OpenIddictValidationHandlers.Protection.cs | 34 +++--- .../OpenIddictValidationService.cs | 12 +- .../OpenIddictValidationTransaction.cs | 8 +- 49 files changed, 436 insertions(+), 502 deletions(-) diff --git a/sandbox/OpenIddict.Sandbox.AspNet.Client/Controllers/HomeController.cs b/sandbox/OpenIddict.Sandbox.AspNet.Client/Controllers/HomeController.cs index bc6fc812..291a291c 100644 --- a/sandbox/OpenIddict.Sandbox.AspNet.Client/Controllers/HomeController.cs +++ b/sandbox/OpenIddict.Sandbox.AspNet.Client/Controllers/HomeController.cs @@ -43,7 +43,7 @@ public class HomeController([FromKeyedServices("ApiClient")] HttpClient client, return View("Index", new IndexViewModel { - Message = await response.Content.ReadAsStringAsync(), + Message = await response.Content.ReadAsStringAsync(cancellationToken), Providers = from registration in await service.GetClientRegistrationsAsync(cancellationToken) where !string.IsNullOrEmpty(registration.ProviderName) where !string.IsNullOrEmpty(registration.ProviderDisplayName) diff --git a/sandbox/OpenIddict.Sandbox.AspNetCore.Client/Controllers/HomeController.cs b/sandbox/OpenIddict.Sandbox.AspNetCore.Client/Controllers/HomeController.cs index 715be7a3..351874d4 100644 --- a/sandbox/OpenIddict.Sandbox.AspNetCore.Client/Controllers/HomeController.cs +++ b/sandbox/OpenIddict.Sandbox.AspNetCore.Client/Controllers/HomeController.cs @@ -35,7 +35,7 @@ public class HomeController([FromKeyedServices("ApiClient")] HttpClient client, return View("Index", new IndexViewModel { - Message = await response.Content.ReadAsStringAsync(), + Message = await response.Content.ReadAsStringAsync(cancellationToken), Providers = from registration in await service.GetClientRegistrationsAsync(cancellationToken) where !string.IsNullOrEmpty(registration.ProviderName) where !string.IsNullOrEmpty(registration.ProviderDisplayName) diff --git a/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandler.cs b/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandler.cs index bff91682..f704f287 100644 --- a/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandler.cs +++ b/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandler.cs @@ -44,13 +44,23 @@ public sealed class OpenIddictClientAspNetCoreHandler : AuthenticationHandler public async Task HandleRequestAsync() { + // Note: to ensure internal operations are not immediately cancelled when the request is aborted + // (which may represent a security risk if sensitive operations are in progress), an ad-hoc token + // source is always created and configured to be triggered 5 seconds after the request is aborted. + var source = new CancellationTokenSource(); + var registration = Context.RequestAborted.Register(static state => + ((CancellationTokenSource) state!).CancelAfter(TimeSpan.FromSeconds(5)), source); + + Response.RegisterForDispose(source); + Response.RegisterForDispose(registration); + // Note: the transaction may be already attached when replaying an ASP.NET Core request // (e.g when using the built-in status code pages middleware with the re-execute mode). var transaction = Context.Features.Get()?.Transaction; if (transaction is null) { // Create a new transaction and attach the HTTP request to make it available to the ASP.NET Core handlers. - transaction = await _factory.CreateTransactionAsync(); + transaction = await _factory.CreateTransactionAsync(source.Token); transaction.Properties[typeof(HttpRequest).FullName!] = new WeakReference(Request); // Attach the OpenIddict client transaction to the ASP.NET Core features @@ -58,11 +68,7 @@ public sealed class OpenIddictClientAspNetCoreHandler : AuthenticationHandler(typeof(ProcessAuthenticationContext).FullName!); if (context is null) { - await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction) - { - CancellationToken = Context.RequestAborted - }); + await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction)); // Store the context object in the transaction so it can be later retrieved by handlers // that want to access the authentication result without triggering a new authentication flow. @@ -377,7 +379,6 @@ public sealed class OpenIddictClientAspNetCoreHandler : AuthenticationHandler protected override async Task InitializeCoreAsync() { + // Note: to ensure internal operations are not immediately cancelled when the request is aborted + // (which may represent a security risk if sensitive operations are in progress), an ad-hoc token + // source is always created and configured to be triggered 5 seconds after the request is aborted. + var source = new CancellationTokenSource(); + var registration = Request.CallCancelled.Register(static state => + ((CancellationTokenSource) state!).CancelAfter(TimeSpan.FromSeconds(5)), source); + + Response.OnSendingHeaders(static state => ((CancellationTokenSource) state!).Dispose(), source); + Response.OnSendingHeaders(static state => ((CancellationTokenRegistration) state!).Dispose(), registration); + // Note: the transaction may be already attached when replaying an OWIN request // (e.g when using a status code pages middleware re-invoking the OWIN pipeline). var transaction = Context.Get(typeof(OpenIddictClientTransaction).FullName); if (transaction is null) { // Create a new transaction and attach the OWIN request to make it available to the OWIN handlers. - transaction = await _factory.CreateTransactionAsync(); + transaction = await _factory.CreateTransactionAsync(source.Token); transaction.Properties[typeof(IOwinRequest).FullName!] = new WeakReference(Request); // Attach the OpenIddict client transaction to the OWIN shared dictionary @@ -60,11 +70,7 @@ public sealed class OpenIddictClientOwinHandler : AuthenticationHandler(typeof(ProcessAuthenticationContext).FullName!); if (context is null) { - await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction) - { - CancellationToken = Request.CallCancelled - }); + await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction)); // Store the context object in the transaction so it can be later retrieved by handlers // that want to access the authentication result without triggering a new authentication flow. @@ -302,7 +304,6 @@ public sealed class OpenIddictClientOwinHandler : AuthenticationHandler "Authentication failed. Please return to the application." }); - await response.OutputStream.WriteAsync(buffer); - await response.OutputStream.FlushAsync(); + await response.OutputStream.WriteAsync(buffer.AsMemory(), context.CancellationToken); + await response.OutputStream.FlushAsync(context.CancellationToken); context.HandleRequest(); } diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Session.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Session.cs index 1551a2f6..85950f40 100644 --- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Session.cs +++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Session.cs @@ -646,8 +646,8 @@ public static partial class OpenIddictClientSystemIntegrationHandlers _ => "Logout failed. Please return to the application." }); - await response.OutputStream.WriteAsync(buffer); - await response.OutputStream.FlushAsync(); + await response.OutputStream.WriteAsync(buffer.AsMemory(), context.CancellationToken); + await response.OutputStream.FlushAsync(context.CancellationToken); context.HandleRequest(); } diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs index 23fefd7d..138e4bd6 100644 --- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs +++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs @@ -457,7 +457,7 @@ public static partial class OpenIddictClientSystemIntegrationHandlers context.Transaction.Request = new OpenIddictRequest(await OpenIddictHelpers.ParseFormAsync( stream : request.InputStream, encoding : GetEncoding(type) is { CodePage: not 65000 } encoding ? encoding : Encoding.UTF8, - cancellationToken: CancellationToken.None)); + cancellationToken: context.CancellationToken)); } else diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationService.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationService.cs index a4a8d6a5..ff628085 100644 --- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationService.cs +++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationService.cs @@ -147,21 +147,16 @@ public sealed class OpenIddictClientSystemIntegrationService // Create a client transaction and store the specified instance so // it can be retrieved by the event handlers that need to access it. - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(cancellationToken); transaction.SetProperty(typeof(TProperty).FullName!, property); - var context = new ProcessRequestContext(transaction) - { - CancellationToken = cancellationToken - }; - + var context = new ProcessRequestContext(transaction); await dispatcher.DispatchAsync(context); if (context.IsRejected) { await dispatcher.DispatchAsync(new ProcessErrorContext(transaction) { - CancellationToken = cancellationToken, Error = context.Error ?? Errors.InvalidRequest, ErrorDescription = context.ErrorDescription, ErrorUri = context.ErrorUri, diff --git a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Userinfo.cs b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Userinfo.cs index 41b34fcb..482ea91b 100644 --- a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Userinfo.cs +++ b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Userinfo.cs @@ -127,7 +127,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers MediaTypes.JsonWebToken, StringComparison.OrdinalIgnoreCase)) { context.Response = new OpenIddictResponse(); - context.UserInfoToken = await response.Content.ReadAsStringAsync(); + context.UserInfoToken = await response.Content.ReadAsStringAsync(context.CancellationToken); return; } diff --git a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs index b5036220..8819d0ec 100644 --- a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs +++ b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs @@ -611,7 +611,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers else if (string.Equals(encoding, ContentEncodings.Gzip, StringComparison.OrdinalIgnoreCase)) { - stream ??= await response.Content.ReadAsStreamAsync(); + stream ??= await response.Content.ReadAsStreamAsync().WaitAsync(context.CancellationToken); stream = new GZipStream(stream, CompressionMode.Decompress); } @@ -625,13 +625,13 @@ public static partial class OpenIddictClientSystemNetHttpHandlers // For more information, read https://www.rfc-editor.org/rfc/rfc9110.html#name-deflate-coding. else if (string.Equals(encoding, ContentEncodings.Deflate, StringComparison.OrdinalIgnoreCase)) { - stream ??= await response.Content.ReadAsStreamAsync(); + stream ??= await response.Content.ReadAsStreamAsync().WaitAsync(context.CancellationToken); stream = new ZLibStream(stream, CompressionMode.Decompress); } else if (string.Equals(encoding, ContentEncodings.Brotli, StringComparison.OrdinalIgnoreCase)) { - stream ??= await response.Content.ReadAsStreamAsync(); + stream ??= await response.Content.ReadAsStreamAsync().WaitAsync(context.CancellationToken); stream = new BrotliStream(stream, CompressionMode.Decompress); } #endif @@ -655,7 +655,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers // (e.g if the JSON deserialization process fails, the stream is read as a string // during a second pass a second time for logging/debuggability purposes). var content = new StreamContent(stream); - await content.LoadIntoBufferAsync(); + await content.LoadIntoBufferAsync(context.CancellationToken); // Copy the headers from the original content to the new instance. foreach (var header in response.Content.Headers) @@ -728,7 +728,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception)) { context.Logger.LogError(6183, exception, SR.GetResourceString(SR.ID6183), - await response.Content.ReadAsStringAsync()); + await response.Content.ReadAsStringAsync(context.CancellationToken)); context.Reject( error: Errors.ServerError, @@ -949,7 +949,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers if (!response.IsSuccessStatusCode && string.IsNullOrEmpty(context.Transaction.Response?.Error)) { context.Logger.LogError(6184, SR.GetResourceString(SR.ID6184), response.StatusCode, - await response.Content.ReadAsStringAsync()); + await response.Content.ReadAsStringAsync(context.CancellationToken)); context.Reject( error: (int) response.StatusCode switch @@ -973,7 +973,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers if (context.Transaction.Response is null) { context.Logger.LogError(6185, SR.GetResourceString(SR.ID6185), response.StatusCode, - response.Content.Headers.ContentType, await response.Content.ReadAsStringAsync()); + response.Content.Headers.ContentType, await response.Content.ReadAsStringAsync(context.CancellationToken)); context.Reject( error: Errors.ServerError, diff --git a/src/OpenIddict.Client/IOpenIddictClientFactory.cs b/src/OpenIddict.Client/IOpenIddictClientFactory.cs index 24e1dfd2..91713f97 100644 --- a/src/OpenIddict.Client/IOpenIddictClientFactory.cs +++ b/src/OpenIddict.Client/IOpenIddictClientFactory.cs @@ -18,9 +18,13 @@ public interface IOpenIddictClientFactory /// Creates a new that is used as a /// way to store per-request data needed to process the requested operation. /// + /// The that can be used to abort the operation. + /// + /// Note: the specified is automatically attached to the returned transaction. + /// /// /// A that can be used to monitor the asynchronous /// operation, whose result returns the created transaction. /// - ValueTask CreateTransactionAsync(); + ValueTask CreateTransactionAsync(CancellationToken cancellationToken); } diff --git a/src/OpenIddict.Client/OpenIddictClientConfiguration.cs b/src/OpenIddict.Client/OpenIddictClientConfiguration.cs index 0d5e9a66..a92e7165 100644 --- a/src/OpenIddict.Client/OpenIddictClientConfiguration.cs +++ b/src/OpenIddict.Client/OpenIddictClientConfiguration.cs @@ -88,8 +88,8 @@ public sealed class OpenIddictClientConfiguration : IPostConfigureOptions registration.RedirectUri is not null) - .Select(registration => registration.RedirectUri!) + .Where(static registration => registration.RedirectUri is not null) + .Select(static registration => registration.RedirectUri!) .Where(uri => !options.RedirectionEndpointUris.Contains(uri)) .Distinct() .ToList()); @@ -97,8 +97,8 @@ public sealed class OpenIddictClientConfiguration : IPostConfigureOptions registration.PostLogoutRedirectUri is not null) - .Select(registration => registration.PostLogoutRedirectUri!) + .Where(static registration => registration.PostLogoutRedirectUri is not null) + .Select(static registration => registration.PostLogoutRedirectUri!) .Where(uri => !options.PostLogoutRedirectionEndpointUris.Contains(uri)) .Distinct() .ToList()); @@ -113,9 +113,9 @@ public sealed class OpenIddictClientConfiguration : IPostConfigureOptions Compare(left.Key, right.Key, now)); // Generate a key identifier for the encryption/signing keys that don't already have one. - foreach (var key in options.EncryptionCredentials.Select(credentials => credentials.Key) - .Concat(options.SigningCredentials.Select(credentials => credentials.Key)) - .Where(key => string.IsNullOrEmpty(key.KeyId))) + foreach (var key in options.EncryptionCredentials.Select(static credentials => credentials.Key) + .Concat(options.SigningCredentials.Select(static credentials => credentials.Key)) + .Where(static key => string.IsNullOrEmpty(key.KeyId))) { key.KeyId = GetKeyIdentifier(key); } @@ -354,7 +354,7 @@ public sealed class OpenIddictClientConfiguration : IPostConfigureOptions registration.RegistrationId) + if (options.Registrations.Count != options.Registrations.Select(static registration => registration.RegistrationId) .Distinct(StringComparer.OrdinalIgnoreCase) .Count()) { diff --git a/src/OpenIddict.Client/OpenIddictClientDispatcher.cs b/src/OpenIddict.Client/OpenIddictClientDispatcher.cs index e0373ba6..5e7dae63 100644 --- a/src/OpenIddict.Client/OpenIddictClientDispatcher.cs +++ b/src/OpenIddict.Client/OpenIddictClientDispatcher.cs @@ -40,6 +40,8 @@ public sealed class OpenIddictClientDispatcher : IOpenIddictClientDispatcher await foreach (var handler in GetHandlersAsync()) { + context.CancellationToken.ThrowIfCancellationRequested(); + try { await handler.HandleAsync(context); diff --git a/src/OpenIddict.Client/OpenIddictClientEvents.cs b/src/OpenIddict.Client/OpenIddictClientEvents.cs index c7cd6d47..4f11e13f 100644 --- a/src/OpenIddict.Client/OpenIddictClientEvents.cs +++ b/src/OpenIddict.Client/OpenIddictClientEvents.cs @@ -32,19 +32,9 @@ public static partial class OpenIddictClientEvents public OpenIddictClientTransaction Transaction { get; } /// - /// Gets or sets the cancellation token that will be - /// used to determine if the operation was aborted. + /// Gets the cancellation token used to determine if the operation was aborted. /// - /// - /// Note: for security reasons, this property shouldn't be used by event - /// handlers to abort security-sensitive operations. As such, it is - /// recommended to use this property only for user-dependent operations. - /// - public CancellationToken CancellationToken - { - get => Transaction.CancellationToken; - set => Transaction.CancellationToken = value; - } + public CancellationToken CancellationToken => Transaction.CancellationToken; /// /// Gets or sets the endpoint type that handled the request, if applicable. diff --git a/src/OpenIddict.Client/OpenIddictClientFactory.cs b/src/OpenIddict.Client/OpenIddictClientFactory.cs index 59cf992d..1ae7a02f 100644 --- a/src/OpenIddict.Client/OpenIddictClientFactory.cs +++ b/src/OpenIddict.Client/OpenIddictClientFactory.cs @@ -31,10 +31,18 @@ public sealed class OpenIddictClientFactory : IOpenIddictClientFactory } /// - public ValueTask CreateTransactionAsync() - => new(new OpenIddictClientTransaction + public ValueTask CreateTransactionAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return new(Task.FromCanceled(cancellationToken)); + } + + return new(new OpenIddictClientTransaction { + CancellationToken = cancellationToken, Logger = _logger, Options = _options.CurrentValue }); + } } diff --git a/src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs b/src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs index f0396abb..aba7b694 100644 --- a/src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs +++ b/src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs @@ -274,7 +274,7 @@ public static partial class OpenIddictClientHandlers } // If the reference token cannot be found, don't return an error to allow another handler to validate it. - var token = await _tokenManager.FindByReferenceIdAsync(context.Token); + var token = await _tokenManager.FindByReferenceIdAsync(context.Token, context.CancellationToken); if (token is null) { return; @@ -284,8 +284,8 @@ public static partial class OpenIddictClientHandlers if (!(context.ValidTokenTypes.Count switch { 0 => true, // If no specific token type is expected, accept all token types at this stage. - 1 => await _tokenManager.HasTypeAsync(token, context.ValidTokenTypes.ElementAt(0)), - _ => await _tokenManager.HasTypeAsync(token, [.. context.ValidTokenTypes]) + 1 => await _tokenManager.HasTypeAsync(token, context.ValidTokenTypes.ElementAt(0), context.CancellationToken), + _ => await _tokenManager.HasTypeAsync(token, [.. context.ValidTokenTypes], context.CancellationToken) })) { context.Reject( @@ -296,7 +296,7 @@ public static partial class OpenIddictClientHandlers return; } - var payload = await _tokenManager.GetPayloadAsync(token); + var payload = await _tokenManager.GetPayloadAsync(token, context.CancellationToken); if (string.IsNullOrEmpty(payload)) { throw new InvalidOperationException(SR.GetResourceString(SR.ID0026)); @@ -307,7 +307,7 @@ public static partial class OpenIddictClientHandlers // used to restore the properties associated with the token. context.IsReferenceToken = true; context.Token = payload; - context.TokenId = await _tokenManager.GetIdAsync(token); + context.TokenId = await _tokenManager.GetIdAsync(token, context.CancellationToken); } } @@ -575,7 +575,7 @@ public static partial class OpenIddictClientHandlers } // If the token entry cannot be found, return a generic error. - var token = await _tokenManager.FindByIdAsync(identifier); + var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken); if (token is null) { context.Reject( @@ -589,9 +589,9 @@ public static partial class OpenIddictClientHandlers // If the token was not validated as a reference token but has a reference identifier attached, this // may indicate that the payload stored in the database has leaked and is being used as a regular, // non-reference token. To prevent this, reject the token if the reference identifier is not null. - if (!context.IsReferenceToken && !string.IsNullOrEmpty(await _tokenManager.GetReferenceIdAsync(token))) + if (!context.IsReferenceToken && !string.IsNullOrEmpty(await _tokenManager.GetReferenceIdAsync(token, context.CancellationToken))) { - context.Logger.LogWarning(6292, SR.GetResourceString(SR.ID6292), await _tokenManager.GetIdAsync(token)); + context.Logger.LogWarning(6292, SR.GetResourceString(SR.ID6292), await _tokenManager.GetIdAsync(token, context.CancellationToken)); context.Reject( error: Errors.InvalidToken, @@ -603,10 +603,10 @@ public static partial class OpenIddictClientHandlers // Restore the creation/expiration dates/identifiers from the token entry metadata. context.Principal - .SetCreationDate(await _tokenManager.GetCreationDateAsync(token)) - .SetExpirationDate(await _tokenManager.GetExpirationDateAsync(token)) - .SetTokenId(context.TokenId = await _tokenManager.GetIdAsync(token)) - .SetTokenType(await _tokenManager.GetTypeAsync(token)); + .SetCreationDate(await _tokenManager.GetCreationDateAsync(token, context.CancellationToken)) + .SetExpirationDate(await _tokenManager.GetExpirationDateAsync(token, context.CancellationToken)) + .SetTokenId(context.TokenId = await _tokenManager.GetIdAsync(token, context.CancellationToken)) + .SetTokenType(await _tokenManager.GetTypeAsync(token, context.CancellationToken)); } } @@ -851,10 +851,10 @@ public static partial class OpenIddictClientHandlers Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); Debug.Assert(!string.IsNullOrEmpty(context.TokenId), SR.GetResourceString(SR.ID4017)); - var token = await _tokenManager.FindByIdAsync(context.TokenId) + var token = await _tokenManager.FindByIdAsync(context.TokenId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0021)); - if (await _tokenManager.HasStatusAsync(token, Statuses.Redeemed)) + if (await _tokenManager.HasStatusAsync(token, Statuses.Redeemed, context.CancellationToken)) { context.Logger.LogInformation(6002, SR.GetResourceString(SR.ID6002), context.TokenId); @@ -876,7 +876,7 @@ public static partial class OpenIddictClientHandlers return; } - if (!await _tokenManager.HasStatusAsync(token, Statuses.Valid)) + if (!await _tokenManager.HasStatusAsync(token, Statuses.Valid, context.CancellationToken)) { context.Logger.LogInformation(6005, SR.GetResourceString(SR.ID6005), context.TokenId); @@ -980,10 +980,10 @@ public static partial class OpenIddictClientHandlers // Tokens produced by the client stack cannot have an application attached. - var token = await _tokenManager.CreateAsync(descriptor) + var token = await _tokenManager.CreateAsync(descriptor, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0019)); - var identifier = await _tokenManager.GetIdAsync(token); + var identifier = await _tokenManager.GetIdAsync(token, context.CancellationToken); // Attach the token identifier to the principal so that it can be stored in the token. context.Principal.SetTokenId(identifier); @@ -1172,11 +1172,11 @@ public static partial class OpenIddictClientHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0009)); } - var token = await _tokenManager.FindByIdAsync(identifier) + var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0021)); var descriptor = new OpenIddictTokenDescriptor(); - await _tokenManager.PopulateAsync(descriptor, token); + await _tokenManager.PopulateAsync(descriptor, token, context.CancellationToken); // Attach the generated token to the token entry. descriptor.Payload = context.Token; @@ -1187,7 +1187,7 @@ public static partial class OpenIddictClientHandlers descriptor.ReferenceId = Base64Url.EncodeToString(RandomNumberGenerator.GetBytes(count: 256 / 8)); } - await _tokenManager.UpdateAsync(token, descriptor); + await _tokenManager.UpdateAsync(token, descriptor, context.CancellationToken); context.Logger.LogTrace(6014, SR.GetResourceString(SR.ID6014), context.Token, identifier, context.TokenType); diff --git a/src/OpenIddict.Client/OpenIddictClientHandlers.cs b/src/OpenIddict.Client/OpenIddictClientHandlers.cs index 0acac21c..9fbb27fd 100644 --- a/src/OpenIddict.Client/OpenIddictClientHandlers.cs +++ b/src/OpenIddict.Client/OpenIddictClientHandlers.cs @@ -7,7 +7,9 @@ using System.Collections.Immutable; using System.ComponentModel; using System.Diagnostics; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Buffers.Text; using System.Security.Claims; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; @@ -18,8 +20,6 @@ using Microsoft.Extensions.Primitives; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; using static OpenIddict.Abstractions.OpenIddictExceptions; -using System.Runtime.CompilerServices; -using System.Buffers.Text; #if !NET using Org.BouncyCastle.Crypto.Digests; @@ -857,8 +857,8 @@ public static partial class OpenIddictClientHandlers } // Mark the token as redeemed to prevent future reuses. - var token = await _tokenManager.FindByIdAsync(identifier); - if (token is not null && !await _tokenManager.TryRedeemAsync(token)) + var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken); + if (token is not null && !await _tokenManager.TryRedeemAsync(token, context.CancellationToken)) { context.Reject( error: Errors.InvalidToken, diff --git a/src/OpenIddict.Client/OpenIddictClientService.cs b/src/OpenIddict.Client/OpenIddictClientService.cs index 0d04fbfe..34bcb79d 100644 --- a/src/OpenIddict.Client/OpenIddictClientService.cs +++ b/src/OpenIddict.Client/OpenIddictClientService.cs @@ -266,11 +266,10 @@ public class OpenIddictClientService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(request.CancellationToken); var context = new ProcessAuthenticationContext(transaction) { - CancellationToken = request.CancellationToken, Nonce = request.Nonce, Request = new(), TokenEndpointClientCertificate = request.TokenBindingCertificate, @@ -340,11 +339,10 @@ public class OpenIddictClientService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(request.CancellationToken); var context = new ProcessChallengeContext(transaction) { - CancellationToken = request.CancellationToken, CodeChallengeMethod = request.CodeChallengeMethod, GrantType = request.GrantType, IdentityTokenHint = request.IdentityTokenHint, @@ -422,11 +420,10 @@ public class OpenIddictClientService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(request.CancellationToken); var context = new ProcessAuthenticationContext(transaction) { - CancellationToken = request.CancellationToken, GrantType = GrantTypes.ClientCredentials, Issuer = request.Issuer, ProviderName = request.ProviderName, @@ -513,11 +510,10 @@ public class OpenIddictClientService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(request.CancellationToken); var context = new ProcessAuthenticationContext(transaction) { - CancellationToken = request.CancellationToken, DisableUserInfoRetrieval = request.DisableUserInfo, DisableUserInfoValidation = request.DisableUserInfo, GrantType = request.GrantType, @@ -607,11 +603,10 @@ public class OpenIddictClientService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(request.CancellationToken); var context = new ProcessAuthenticationContext(transaction) { - CancellationToken = source.Token, DeviceCode = request.DeviceCode, DisableUserInfoRetrieval = request.DisableUserInfo, DisableUserInfoValidation = request.DisableUserInfo, @@ -714,11 +709,10 @@ public class OpenIddictClientService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(request.CancellationToken); var context = new ProcessChallengeContext(transaction) { - CancellationToken = request.CancellationToken, DeviceAuthorizationRequest = request.AdditionalDeviceAuthorizationRequestParameters is Dictionary parameters ? new(parameters) : new(), GrantType = GrantTypes.DeviceCode, @@ -793,11 +787,10 @@ public class OpenIddictClientService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(request.CancellationToken); var context = new ProcessAuthenticationContext(transaction) { - CancellationToken = request.CancellationToken, DisableUserInfoRetrieval = request.DisableUserInfo, DisableUserInfoValidation = request.DisableUserInfo, GrantType = GrantTypes.Password, @@ -881,13 +874,12 @@ public class OpenIddictClientService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(request.CancellationToken); var context = new ProcessAuthenticationContext(transaction) { ActorToken = request.ActorToken, ActorTokenType = request.ActorTokenType, - CancellationToken = request.CancellationToken, DisableUserInfoRetrieval = request.DisableUserInfo, DisableUserInfoValidation = request.DisableUserInfo, GrantType = GrantTypes.TokenExchange, @@ -969,11 +961,10 @@ public class OpenIddictClientService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(request.CancellationToken); var context = new ProcessAuthenticationContext(transaction) { - CancellationToken = request.CancellationToken, DisableUserInfoRetrieval = request.DisableUserInfo, DisableUserInfoValidation = request.DisableUserInfo, GrantType = GrantTypes.RefreshToken, @@ -1055,11 +1046,10 @@ public class OpenIddictClientService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(request.CancellationToken); var context = new ProcessIntrospectionContext(transaction) { - CancellationToken = request.CancellationToken, IntrospectionRequest = request.AdditionalIntrospectionRequestParameters is Dictionary parameters ? new(parameters) : new(), Issuer = request.Issuer, @@ -1115,11 +1105,10 @@ public class OpenIddictClientService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(request.CancellationToken); var context = new ProcessRevocationContext(transaction) { - CancellationToken = request.CancellationToken, Issuer = request.Issuer, ProviderName = request.ProviderName, RegistrationId = request.RegistrationId, @@ -1183,7 +1172,7 @@ public class OpenIddictClientService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(cancellationToken); var request = new OpenIddictRequest(); request = await PrepareConfigurationRequestAsync(); @@ -1197,7 +1186,6 @@ public class OpenIddictClientService { var context = new PrepareConfigurationRequestContext(transaction) { - CancellationToken = cancellationToken, RemoteUri = uri, Registration = registration, Request = request @@ -1219,7 +1207,6 @@ public class OpenIddictClientService { var context = new ApplyConfigurationRequestContext(transaction) { - CancellationToken = cancellationToken, RemoteUri = uri, Registration = registration, Request = request @@ -1243,7 +1230,6 @@ public class OpenIddictClientService { var context = new ExtractConfigurationResponseContext(transaction) { - CancellationToken = cancellationToken, RemoteUri = uri, Registration = registration, Request = request @@ -1269,7 +1255,6 @@ public class OpenIddictClientService { var context = new HandleConfigurationResponseContext(transaction) { - CancellationToken = cancellationToken, RemoteUri = uri, Registration = registration, Request = request, @@ -1308,11 +1293,10 @@ public class OpenIddictClientService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(request.CancellationToken); var context = new ProcessSignOutContext(transaction) { - CancellationToken = request.CancellationToken, IdentityTokenHint = request.IdentityTokenHint, Issuer = request.Issuer, LoginHint = request.LoginHint, @@ -1379,7 +1363,7 @@ public class OpenIddictClientService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(cancellationToken); var request = new OpenIddictRequest(); request = await PrepareJsonWebKeySetRequestAsync(); @@ -1394,7 +1378,6 @@ public class OpenIddictClientService { var context = new PrepareJsonWebKeySetRequestContext(transaction) { - CancellationToken = cancellationToken, RemoteUri = uri, Registration = registration, Request = request @@ -1416,7 +1399,6 @@ public class OpenIddictClientService { var context = new ApplyJsonWebKeySetRequestContext(transaction) { - CancellationToken = cancellationToken, RemoteUri = uri, Registration = registration, Request = request @@ -1440,7 +1422,6 @@ public class OpenIddictClientService { var context = new ExtractJsonWebKeySetResponseContext(transaction) { - CancellationToken = cancellationToken, RemoteUri = uri, Registration = registration, Request = request @@ -1466,7 +1447,6 @@ public class OpenIddictClientService { var context = new HandleJsonWebKeySetResponseContext(transaction) { - CancellationToken = cancellationToken, RemoteUri = uri, Registration = registration, Request = request, @@ -1521,7 +1501,7 @@ public class OpenIddictClientService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(cancellationToken); request = await PrepareDeviceAuthorizationRequestAsync(); request = await ApplyDeviceAuthorizationRequestAsync(); @@ -1534,7 +1514,6 @@ public class OpenIddictClientService { var context = new PrepareDeviceAuthorizationRequestContext(transaction) { - CancellationToken = cancellationToken, ClientAuthenticationMethod = method, Configuration = configuration, RemoteUri = uri, @@ -1559,7 +1538,6 @@ public class OpenIddictClientService { var context = new ApplyDeviceAuthorizationRequestContext(transaction) { - CancellationToken = cancellationToken, RemoteUri = uri, Configuration = configuration, Registration = registration, @@ -1584,7 +1562,6 @@ public class OpenIddictClientService { var context = new ExtractDeviceAuthorizationResponseContext(transaction) { - CancellationToken = cancellationToken, RemoteUri = uri, Configuration = configuration, Registration = registration, @@ -1611,7 +1588,6 @@ public class OpenIddictClientService { var context = new HandleDeviceAuthorizationResponseContext(transaction) { - CancellationToken = cancellationToken, RemoteUri = uri, Configuration = configuration, Registration = registration, @@ -1666,7 +1642,7 @@ public class OpenIddictClientService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(cancellationToken); request = await PrepareIntrospectionRequestAsync(); request = await ApplyIntrospectionRequestAsync(); @@ -1679,7 +1655,6 @@ public class OpenIddictClientService { var context = new PrepareIntrospectionRequestContext(transaction) { - CancellationToken = cancellationToken, ClientAuthenticationMethod = method, Configuration = configuration, Registration = registration, @@ -1704,7 +1679,6 @@ public class OpenIddictClientService { var context = new ApplyIntrospectionRequestContext(transaction) { - CancellationToken = cancellationToken, Configuration = configuration, Registration = registration, RemoteUri = uri, @@ -1729,7 +1703,6 @@ public class OpenIddictClientService { var context = new ExtractIntrospectionResponseContext(transaction) { - CancellationToken = cancellationToken, Configuration = configuration, Registration = registration, RemoteUri = uri, @@ -1756,7 +1729,6 @@ public class OpenIddictClientService { var context = new HandleIntrospectionResponseContext(transaction) { - CancellationToken = cancellationToken, Configuration = configuration, Registration = registration, RemoteUri = uri, @@ -1814,7 +1786,7 @@ public class OpenIddictClientService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(cancellationToken); request = await PreparePushedAuthorizationRequestAsync(); request = await ApplyPushedAuthorizationRequestAsync(); @@ -1827,7 +1799,6 @@ public class OpenIddictClientService { var context = new PreparePushedAuthorizationRequestContext(transaction) { - CancellationToken = cancellationToken, ClientAuthenticationMethod = method, RemoteUri = uri, Configuration = configuration, @@ -1852,7 +1823,6 @@ public class OpenIddictClientService { var context = new ApplyPushedAuthorizationRequestContext(transaction) { - CancellationToken = cancellationToken, RemoteUri = uri, Configuration = configuration, Registration = registration, @@ -1877,7 +1847,6 @@ public class OpenIddictClientService { var context = new ExtractPushedAuthorizationResponseContext(transaction) { - CancellationToken = cancellationToken, RemoteUri = uri, Configuration = configuration, Registration = registration, @@ -1904,7 +1873,6 @@ public class OpenIddictClientService { var context = new HandlePushedAuthorizationResponseContext(transaction) { - CancellationToken = cancellationToken, RemoteUri = uri, Configuration = configuration, Registration = registration, @@ -1959,7 +1927,7 @@ public class OpenIddictClientService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(cancellationToken); request = await PrepareRevocationRequestAsync(); request = await ApplyRevocationRequestAsync(); @@ -1972,7 +1940,6 @@ public class OpenIddictClientService { var context = new PrepareRevocationRequestContext(transaction) { - CancellationToken = cancellationToken, ClientAuthenticationMethod = method, Configuration = configuration, Registration = registration, @@ -1997,7 +1964,6 @@ public class OpenIddictClientService { var context = new ApplyRevocationRequestContext(transaction) { - CancellationToken = cancellationToken, Configuration = configuration, Registration = registration, RemoteUri = uri, @@ -2022,7 +1988,6 @@ public class OpenIddictClientService { var context = new ExtractRevocationResponseContext(transaction) { - CancellationToken = cancellationToken, Configuration = configuration, Registration = registration, RemoteUri = uri, @@ -2049,7 +2014,6 @@ public class OpenIddictClientService { var context = new HandleRevocationResponseContext(transaction) { - CancellationToken = cancellationToken, Configuration = configuration, Registration = registration, RemoteUri = uri, @@ -2105,7 +2069,7 @@ public class OpenIddictClientService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(cancellationToken); request = await PrepareTokenRequestAsync(); request = await ApplyTokenRequestAsync(); @@ -2118,7 +2082,6 @@ public class OpenIddictClientService { var context = new PrepareTokenRequestContext(transaction) { - CancellationToken = cancellationToken, ClientAuthenticationMethod = method, Configuration = configuration, Registration = registration, @@ -2143,7 +2106,6 @@ public class OpenIddictClientService { var context = new ApplyTokenRequestContext(transaction) { - CancellationToken = cancellationToken, Configuration = configuration, Registration = registration, RemoteUri = uri, @@ -2169,7 +2131,6 @@ public class OpenIddictClientService { var context = new ExtractTokenResponseContext(transaction) { - CancellationToken = cancellationToken, Configuration = configuration, Registration = registration, RemoteUri = uri, @@ -2197,7 +2158,6 @@ public class OpenIddictClientService { var context = new HandleTokenResponseContext(transaction) { - CancellationToken = cancellationToken, Configuration = configuration, Registration = registration, RemoteUri = uri, @@ -2252,7 +2212,7 @@ public class OpenIddictClientService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(cancellationToken); request = await PrepareUserInfoRequestAsync(); request = await ApplyUserInfoRequestAsync(); @@ -2265,7 +2225,6 @@ public class OpenIddictClientService { var context = new PrepareUserInfoRequestContext(transaction) { - CancellationToken = cancellationToken, Configuration = configuration, RemoteUri = uri, Registration = registration, @@ -2289,7 +2248,6 @@ public class OpenIddictClientService { var context = new ApplyUserInfoRequestContext(transaction) { - CancellationToken = cancellationToken, Configuration = configuration, RemoteUri = uri, Registration = registration, @@ -2314,7 +2272,6 @@ public class OpenIddictClientService { var context = new ExtractUserInfoResponseContext(transaction) { - CancellationToken = cancellationToken, Configuration = configuration, RemoteUri = uri, Registration = registration, @@ -2341,7 +2298,6 @@ public class OpenIddictClientService { var context = new HandleUserInfoResponseContext(transaction) { - CancellationToken = cancellationToken, Configuration = configuration, Registration = registration, RemoteUri = uri, diff --git a/src/OpenIddict.Client/OpenIddictClientTransaction.cs b/src/OpenIddict.Client/OpenIddictClientTransaction.cs index cdc15db4..88a46d20 100644 --- a/src/OpenIddict.Client/OpenIddictClientTransaction.cs +++ b/src/OpenIddict.Client/OpenIddictClientTransaction.cs @@ -16,14 +16,8 @@ namespace OpenIddict.Client; public sealed class OpenIddictClientTransaction { /// - /// Gets or sets the cancellation token that will be - /// used to determine if the operation was aborted. + /// Gets or sets the cancellation token used to determine if the operation was aborted. /// - /// - /// Note: for security reasons, this property shouldn't be used by event - /// handlers to abort security-sensitive operations. As such, it is - /// recommended to use this property only for user-dependent operations. - /// public CancellationToken CancellationToken { get; set; } /// diff --git a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandler.cs b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandler.cs index 15cc58aa..ef08d9f7 100644 --- a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandler.cs +++ b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandler.cs @@ -44,13 +44,23 @@ public sealed class OpenIddictServerAspNetCoreHandler : AuthenticationHandler public async Task HandleRequestAsync() { + // Note: to ensure internal operations are not immediately cancelled when the request is aborted + // (which may represent a security risk if sensitive operations are in progress), an ad-hoc token + // source is always created and configured to be triggered 5 seconds after the request is aborted. + var source = new CancellationTokenSource(); + var registration = Context.RequestAborted.Register(static state => + ((CancellationTokenSource) state!).CancelAfter(TimeSpan.FromSeconds(5)), source); + + Response.RegisterForDispose(source); + Response.RegisterForDispose(registration); + // Note: the transaction may be already attached when replaying an ASP.NET Core request // (e.g when using the built-in status code pages middleware with the re-execute mode). var transaction = Context.Features.Get()?.Transaction; if (transaction is null) { // Create a new transaction and attach the HTTP request to make it available to the ASP.NET Core handlers. - transaction = await _factory.CreateTransactionAsync(); + transaction = await _factory.CreateTransactionAsync(source.Token); transaction.Properties[typeof(HttpRequest).FullName!] = new WeakReference(Request); // Attach the OpenIddict server transaction to the ASP.NET Core features @@ -58,11 +68,7 @@ public sealed class OpenIddictServerAspNetCoreHandler : AuthenticationHandler(typeof(ProcessAuthenticationContext).FullName!); if (context is null) { - await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction) - { - CancellationToken = Context.RequestAborted - }); + await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction)); // Store the context object in the transaction so it can be later retrieved by handlers // that want to access the authentication result without triggering a new authentication flow. @@ -393,7 +395,6 @@ public sealed class OpenIddictServerAspNetCoreHandler : AuthenticationHandler protected override async Task InitializeCoreAsync() { + // Note: to ensure internal operations are not immediately cancelled when the request is aborted + // (which may represent a security risk if sensitive operations are in progress), an ad-hoc token + // source is always created and configured to be triggered 5 seconds after the request is aborted. + var source = new CancellationTokenSource(); + var registration = Request.CallCancelled.Register(static state => + ((CancellationTokenSource) state!).CancelAfter(TimeSpan.FromSeconds(5)), source); + + Response.OnSendingHeaders(static state => ((CancellationTokenSource) state!).Dispose(), source); + Response.OnSendingHeaders(static state => ((CancellationTokenRegistration) state!).Dispose(), registration); + // Note: the transaction may be already attached when replaying an OWIN request // (e.g when using a status code pages middleware re-invoking the OWIN pipeline). var transaction = Context.Get(typeof(OpenIddictServerTransaction).FullName); if (transaction is null) { // Create a new transaction and attach the OWIN request to make it available to the OWIN handlers. - transaction = await _factory.CreateTransactionAsync(); + transaction = await _factory.CreateTransactionAsync(source.Token); transaction.Properties[typeof(IOwinRequest).FullName!] = new WeakReference(Request); // Attach the OpenIddict server transaction to the OWIN shared dictionary @@ -51,11 +61,7 @@ public sealed class OpenIddictServerOwinHandler : AuthenticationHandler(typeof(ProcessAuthenticationContext).FullName!); if (context is null) { - await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction) - { - CancellationToken = Request.CallCancelled - }); + await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction)); // Store the context object in the transaction so it can be later retrieved by handlers // that want to access the authentication result without triggering a new authentication flow. @@ -290,7 +292,6 @@ public sealed class OpenIddictServerOwinHandler : AuthenticationHandler GetClientCertificateAsync(IOwinContext context) + static async ValueTask GetClientCertificateAsync( + IOwinContext context, CancellationToken cancellationToken) { // If a loading function was provided by the OWIN host, always invoke it before trying // to resolve the certificate to ensure it is present in the environment dictionary. if (context.Get>("ssl.LoadClientCertAsync") is Func loader) { - await loader(); + await loader().WaitAsync(cancellationToken); } return context.Get("ssl.ClientCertificate") is X509Certificate certificate diff --git a/src/OpenIddict.Server/IOpenIddictServerFactory.cs b/src/OpenIddict.Server/IOpenIddictServerFactory.cs index 40fb02d3..695333d1 100644 --- a/src/OpenIddict.Server/IOpenIddictServerFactory.cs +++ b/src/OpenIddict.Server/IOpenIddictServerFactory.cs @@ -18,9 +18,13 @@ public interface IOpenIddictServerFactory /// Creates a new that is used as a /// way to store per-request data needed to process the requested operation. /// + /// The that can be used to abort the operation. + /// + /// Note: the specified is automatically attached to the returned transaction. + /// /// /// A that can be used to monitor the asynchronous /// operation, whose result returns the created transaction. /// - ValueTask CreateTransactionAsync(); + ValueTask CreateTransactionAsync(CancellationToken cancellationToken); } diff --git a/src/OpenIddict.Server/OpenIddictServerConfiguration.cs b/src/OpenIddict.Server/OpenIddictServerConfiguration.cs index 4930ac04..9d97f42a 100644 --- a/src/OpenIddict.Server/OpenIddictServerConfiguration.cs +++ b/src/OpenIddict.Server/OpenIddictServerConfiguration.cs @@ -77,9 +77,9 @@ public sealed class OpenIddictServerConfiguration : IPostConfigureOptions Compare(left.Key, right.Key, now)); // Generate a key identifier for the encryption/signing keys that don't already have one. - foreach (var key in options.EncryptionCredentials.Select(credentials => credentials.Key) - .Concat(options.SigningCredentials.Select(credentials => credentials.Key)) - .Where(key => string.IsNullOrEmpty(key.KeyId))) + foreach (var key in options.EncryptionCredentials.Select(static credentials => credentials.Key) + .Concat(options.SigningCredentials.Select(static credentials => credentials.Key)) + .Where(static key => string.IsNullOrEmpty(key.KeyId))) { key.KeyId = GetKeyIdentifier(key); } diff --git a/src/OpenIddict.Server/OpenIddictServerDispatcher.cs b/src/OpenIddict.Server/OpenIddictServerDispatcher.cs index c68f3b19..6edc5576 100644 --- a/src/OpenIddict.Server/OpenIddictServerDispatcher.cs +++ b/src/OpenIddict.Server/OpenIddictServerDispatcher.cs @@ -40,6 +40,8 @@ public sealed class OpenIddictServerDispatcher : IOpenIddictServerDispatcher await foreach (var handler in GetHandlersAsync()) { + context.CancellationToken.ThrowIfCancellationRequested(); + try { await handler.HandleAsync(context); diff --git a/src/OpenIddict.Server/OpenIddictServerEvents.cs b/src/OpenIddict.Server/OpenIddictServerEvents.cs index 65b12246..dce4f282 100644 --- a/src/OpenIddict.Server/OpenIddictServerEvents.cs +++ b/src/OpenIddict.Server/OpenIddictServerEvents.cs @@ -30,19 +30,9 @@ public static partial class OpenIddictServerEvents public OpenIddictServerTransaction Transaction { get; } /// - /// Gets or sets the cancellation token that will be - /// used to determine if the operation was aborted. + /// Gets the cancellation token used to determine if the operation was aborted. /// - /// - /// Note: for security reasons, this property shouldn't be used by event - /// handlers to abort security-sensitive operations. As such, it is - /// recommended to use this property only for user-dependent operations. - /// - public CancellationToken CancellationToken - { - get => Transaction.CancellationToken; - set => Transaction.CancellationToken = value; - } + public CancellationToken CancellationToken => Transaction.CancellationToken; /// /// Gets or sets the endpoint type that handled the request, if applicable. diff --git a/src/OpenIddict.Server/OpenIddictServerFactory.cs b/src/OpenIddict.Server/OpenIddictServerFactory.cs index df714124..7c0394f6 100644 --- a/src/OpenIddict.Server/OpenIddictServerFactory.cs +++ b/src/OpenIddict.Server/OpenIddictServerFactory.cs @@ -31,10 +31,18 @@ public sealed class OpenIddictServerFactory : IOpenIddictServerFactory } /// - public ValueTask CreateTransactionAsync() - => new(new OpenIddictServerTransaction + public ValueTask CreateTransactionAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return new(Task.FromCanceled(cancellationToken)); + } + + return new(new OpenIddictServerTransaction { + CancellationToken = cancellationToken, Logger = _logger, Options = _options.CurrentValue }); + } } diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs index d53813f7..5231b99f 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs @@ -1396,14 +1396,14 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // To prevent downgrade attacks, ensure that authorization requests returning // an access token directly from the authorization endpoint are rejected if // the client_id corresponds to a confidential application. if (context.Request.HasResponseType(ResponseTypes.Token) && - await _applicationManager.HasClientTypeAsync(application, ClientTypes.Confidential)) + await _applicationManager.HasClientTypeAsync(application, ClientTypes.Confidential, context.CancellationToken)) { context.Logger.LogInformation(6045, SR.GetResourceString(SR.ID6045), context.ClientId); @@ -1449,14 +1449,14 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // If no explicit redirect_uri was specified, retrieve the URI associated with the // client and ensure exactly one redirect_uri was attached to the client definition. if (string.IsNullOrEmpty(context.RedirectUri)) { - var uris = await _applicationManager.GetRedirectUrisAsync(application); + var uris = await _applicationManager.GetRedirectUrisAsync(application, context.CancellationToken); if (uris.Length is not 1) { context.Logger.LogInformation(6033, SR.GetResourceString(SR.ID6033), Parameters.RedirectUri); @@ -1475,7 +1475,7 @@ public static partial class OpenIddictServerHandlers } // Otherwise, ensure that the specified redirect_uri is valid and is associated with the client application. - if (!await _applicationManager.ValidateRedirectUriAsync(application, context.RedirectUri)) + if (!await _applicationManager.ValidateRedirectUriAsync(application, context.RedirectUri, context.CancellationToken)) { context.Logger.LogInformation(6046, SR.GetResourceString(SR.ID6046), context.RedirectUri); @@ -1540,9 +1540,9 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); } - await foreach (var scope in _scopeManager.FindByNamesAsync([.. scopes])) + await foreach (var scope in _scopeManager.FindByNamesAsync([.. scopes], context.CancellationToken)) { - var name = await _scopeManager.GetNameAsync(scope); + var name = await _scopeManager.GetNameAsync(scope, context.CancellationToken); if (!string.IsNullOrEmpty(name)) { scopes.Remove(name); @@ -1615,9 +1615,9 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); } - await foreach (var resource in _resourceManager.FindByNamesAsync([.. resources])) + await foreach (var resource in _resourceManager.FindByNamesAsync([.. resources], context.CancellationToken)) { - var name = await _resourceManager.GetNameAsync(resource); + var name = await _resourceManager.GetNameAsync(resource, context.CancellationToken); if (!string.IsNullOrEmpty(name)) { resources.Remove(name); @@ -1672,11 +1672,11 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the authorization endpoint. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.Authorization)) + if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.Authorization, context.CancellationToken)) { context.Logger.LogInformation(6048, SR.GetResourceString(SR.ID6048), context.ClientId); @@ -1722,12 +1722,12 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the authorization code grant. if (context.Request.IsAuthorizationCodeFlow() && - !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.AuthorizationCode)) + !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.AuthorizationCode, context.CancellationToken)) { context.Logger.LogInformation(6049, SR.GetResourceString(SR.ID6049), context.ClientId); @@ -1741,7 +1741,7 @@ public static partial class OpenIddictServerHandlers // Reject the request if the application is not allowed to use the implicit grant. if (context.Request.IsImplicitFlow() && - !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.Implicit)) + !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.Implicit, context.CancellationToken)) { context.Logger.LogInformation(6050, SR.GetResourceString(SR.ID6050), context.ClientId); @@ -1755,8 +1755,8 @@ public static partial class OpenIddictServerHandlers // Reject the request if the application is not allowed to use the authorization code/implicit grants. if (context.Request.IsHybridFlow() && - (!await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.AuthorizationCode) || - !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.Implicit))) + (!await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.AuthorizationCode, context.CancellationToken) || + !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.Implicit, context.CancellationToken))) { context.Logger.LogInformation(6051, SR.GetResourceString(SR.ID6051), context.ClientId); @@ -1771,7 +1771,7 @@ public static partial class OpenIddictServerHandlers // Reject the request if the offline_access scope was request and // if the application is not allowed to use the refresh token grant. if (context.Request.HasScope(Scopes.OfflineAccess) && - !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.RefreshToken)) + !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.RefreshToken, context.CancellationToken)) { context.Logger.LogInformation(6052, SR.GetResourceString(SR.ID6052), context.ClientId, Scopes.OfflineAccess); @@ -1817,7 +1817,7 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject requests that specify a response_type for which no permission was granted. @@ -1838,7 +1838,7 @@ public static partial class OpenIddictServerHandlers // Note: response type permissions are always prefixed with "rst:". const string prefix = Permissions.Prefixes.ResponseType; - foreach (var permission in await _applicationManager.GetPermissionsAsync(application)) + foreach (var permission in await _applicationManager.GetPermissionsAsync(application, context.CancellationToken)) { // Ignore permissions that are not response type permissions. if (!permission.StartsWith(prefix, StringComparison.Ordinal)) @@ -1892,7 +1892,7 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); foreach (var scope in context.Request.GetScopes()) @@ -1905,7 +1905,7 @@ public static partial class OpenIddictServerHandlers } // Reject the request if the application is not allowed to use the iterated scope. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Scope + scope)) + if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Scope + scope, context.CancellationToken)) { context.Logger.LogInformation(6052, SR.GetResourceString(SR.ID6052), context.ClientId, scope); @@ -1953,13 +1953,13 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); foreach (var resource in context.Request.GetResources()) { // Reject the request if the application is not allowed to use the iterated resource. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Resource + resource)) + if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Resource + resource, context.CancellationToken)) { context.Logger.LogInformation(6281, SR.GetResourceString(SR.ID6278), context.ClientId, resource); @@ -2014,10 +2014,10 @@ public static partial class OpenIddictServerHandlers return; } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); - if (await _applicationManager.HasRequirementAsync(application, Requirements.Features.PushedAuthorizationRequests)) + if (await _applicationManager.HasRequirementAsync(application, Requirements.Features.PushedAuthorizationRequests, context.CancellationToken)) { if (string.IsNullOrEmpty(context.Request.RequestUri)) { @@ -2080,10 +2080,10 @@ public static partial class OpenIddictServerHandlers return; } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); - if (await _applicationManager.HasRequirementAsync(application, Requirements.Features.ProofKeyForCodeExchange)) + if (await _applicationManager.HasRequirementAsync(application, Requirements.Features.ProofKeyForCodeExchange, context.CancellationToken)) { context.Logger.LogInformation(6033, SR.GetResourceString(SR.ID6033), Parameters.CodeChallenge); @@ -3483,14 +3483,14 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // To prevent downgrade attacks, ensure that pushed authorization requests returning // an access token directly from the authorization endpoint are rejected if // the client_id corresponds to a confidential application. if (context.Request.HasResponseType(ResponseTypes.Token) && - await _applicationManager.HasClientTypeAsync(application, ClientTypes.Confidential)) + await _applicationManager.HasClientTypeAsync(application, ClientTypes.Confidential, context.CancellationToken)) { context.Logger.LogInformation(6251, SR.GetResourceString(SR.ID6251), context.ClientId); @@ -3536,14 +3536,14 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // If no explicit redirect_uri was specified, retrieve the URI associated with the // client and ensure exactly one redirect_uri was attached to the client definition. if (string.IsNullOrEmpty(context.RedirectUri)) { - var uris = await _applicationManager.GetRedirectUrisAsync(application); + var uris = await _applicationManager.GetRedirectUrisAsync(application, context.CancellationToken); if (uris.Length is not 1) { context.Logger.LogInformation(6240, SR.GetResourceString(SR.ID6240), Parameters.RedirectUri); @@ -3562,7 +3562,7 @@ public static partial class OpenIddictServerHandlers } // Otherwise, ensure that the specified redirect_uri is valid and is associated with the client application. - if (!await _applicationManager.ValidateRedirectUriAsync(application, context.RedirectUri)) + if (!await _applicationManager.ValidateRedirectUriAsync(application, context.RedirectUri, context.CancellationToken)) { context.Logger.LogInformation(6252, SR.GetResourceString(SR.ID6252), context.RedirectUri); @@ -3627,9 +3627,9 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); } - await foreach (var scope in _scopeManager.FindByNamesAsync([.. scopes])) + await foreach (var scope in _scopeManager.FindByNamesAsync([.. scopes], context.CancellationToken)) { - var name = await _scopeManager.GetNameAsync(scope); + var name = await _scopeManager.GetNameAsync(scope, context.CancellationToken); if (!string.IsNullOrEmpty(name)) { scopes.Remove(name); @@ -3702,9 +3702,9 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); } - await foreach (var resource in _resourceManager.FindByNamesAsync([.. resources])) + await foreach (var resource in _resourceManager.FindByNamesAsync([.. resources], context.CancellationToken)) { - var name = await _resourceManager.GetNameAsync(resource); + var name = await _resourceManager.GetNameAsync(resource, context.CancellationToken); if (!string.IsNullOrEmpty(name)) { resources.Remove(name); @@ -3759,11 +3759,11 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the pushed authorization endpoint. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.PushedAuthorization)) + if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.PushedAuthorization, context.CancellationToken)) { context.Logger.LogInformation(6254, SR.GetResourceString(SR.ID6254), context.ClientId); @@ -3809,12 +3809,12 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the authorization code grant. if (context.Request.IsAuthorizationCodeFlow() && - !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.AuthorizationCode)) + !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.AuthorizationCode, context.CancellationToken)) { context.Logger.LogInformation(6255, SR.GetResourceString(SR.ID6255), context.ClientId); @@ -3828,7 +3828,7 @@ public static partial class OpenIddictServerHandlers // Reject the request if the application is not allowed to use the implicit grant. if (context.Request.IsImplicitFlow() && - !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.Implicit)) + !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.Implicit, context.CancellationToken)) { context.Logger.LogInformation(6256, SR.GetResourceString(SR.ID6256), context.ClientId); @@ -3842,8 +3842,8 @@ public static partial class OpenIddictServerHandlers // Reject the request if the application is not allowed to use the authorization code/implicit grants. if (context.Request.IsHybridFlow() && - (!await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.AuthorizationCode) || - !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.Implicit))) + (!await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.AuthorizationCode, context.CancellationToken) || + !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.Implicit, context.CancellationToken))) { context.Logger.LogInformation(6257, SR.GetResourceString(SR.ID6257), context.ClientId); @@ -3858,7 +3858,7 @@ public static partial class OpenIddictServerHandlers // Reject the request if the offline_access scope was request and // if the application is not allowed to use the refresh token grant. if (context.Request.HasScope(Scopes.OfflineAccess) && - !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.RefreshToken)) + !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.RefreshToken, context.CancellationToken)) { context.Logger.LogInformation(6258, SR.GetResourceString(SR.ID6258), context.ClientId, Scopes.OfflineAccess); @@ -3904,7 +3904,7 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject requests that specify a response_type for which no permission was granted. @@ -3925,7 +3925,7 @@ public static partial class OpenIddictServerHandlers // Note: response type permissions are always prefixed with "rst:". const string prefix = Permissions.Prefixes.ResponseType; - foreach (var permission in await _applicationManager.GetPermissionsAsync(application)) + foreach (var permission in await _applicationManager.GetPermissionsAsync(application, context.CancellationToken)) { // Ignore permissions that are not response type permissions. if (!permission.StartsWith(prefix, StringComparison.Ordinal)) @@ -3979,7 +3979,7 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); foreach (var scope in context.Request.GetScopes()) @@ -3992,7 +3992,7 @@ public static partial class OpenIddictServerHandlers } // Reject the request if the application is not allowed to use the iterated scope. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Scope + scope)) + if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Scope + scope, context.CancellationToken)) { context.Logger.LogInformation(6258, SR.GetResourceString(SR.ID6258), context.ClientId, scope); @@ -4040,13 +4040,13 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); foreach (var resource in context.Request.GetResources()) { // Reject the request if the application is not allowed to use the iterated resource. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Resource + resource)) + if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Resource + resource, context.CancellationToken)) { context.Logger.LogInformation(6283, SR.GetResourceString(SR.ID6279), context.ClientId, resource); @@ -4100,10 +4100,10 @@ public static partial class OpenIddictServerHandlers return; } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); - if (await _applicationManager.HasRequirementAsync(application, Requirements.Features.ProofKeyForCodeExchange)) + if (await _applicationManager.HasRequirementAsync(application, Requirements.Features.ProofKeyForCodeExchange, context.CancellationToken)) { context.Logger.LogInformation(6240, SR.GetResourceString(SR.ID6240), Parameters.CodeChallenge); diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs index 92bf129a..ca052ea4 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs @@ -481,9 +481,9 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); } - await foreach (var scope in _scopeManager.FindByNamesAsync([.. scopes])) + await foreach (var scope in _scopeManager.FindByNamesAsync([.. scopes], context.CancellationToken)) { - var name = await _scopeManager.GetNameAsync(scope); + var name = await _scopeManager.GetNameAsync(scope, context.CancellationToken); if (!string.IsNullOrEmpty(name)) { scopes.Remove(name); @@ -595,14 +595,14 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the device authorization endpoint. // // Note: the legacy "ept:device" permission is still allowed for backward compatibility. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.DeviceAuthorization) && - !await _applicationManager.HasPermissionAsync(application, "ept:device")) + if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.DeviceAuthorization, context.CancellationToken) && + !await _applicationManager.HasPermissionAsync(application, "ept:device", context.CancellationToken)) { context.Logger.LogInformation(6062, SR.GetResourceString(SR.ID6062), context.ClientId); @@ -648,11 +648,11 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the device code grant. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.DeviceCode)) + if (!await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.DeviceCode, context.CancellationToken)) { context.Logger.LogInformation(6118, SR.GetResourceString(SR.ID6118), context.ClientId); @@ -667,7 +667,7 @@ public static partial class OpenIddictServerHandlers // Reject the request if the offline_access scope was request and // if the application is not allowed to use the refresh token grant. if (context.Request.HasScope(Scopes.OfflineAccess) && - !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.RefreshToken)) + !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.RefreshToken, context.CancellationToken)) { context.Logger.LogInformation(6120, SR.GetResourceString(SR.ID6120), context.ClientId, Scopes.OfflineAccess); @@ -715,7 +715,7 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); foreach (var scope in context.Request.GetScopes()) @@ -728,7 +728,7 @@ public static partial class OpenIddictServerHandlers } // Reject the request if the application is not allowed to use the iterated scope. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Scope + scope)) + if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Scope + scope, context.CancellationToken)) { context.Logger.LogInformation(6063, SR.GetResourceString(SR.ID6063), context.ClientId, scope); diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs index 95bff8d6..6d22cf52 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs @@ -1047,9 +1047,9 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); } - await foreach (var scope in _scopeManager.FindByNamesAsync([.. scopes])) + await foreach (var scope in _scopeManager.FindByNamesAsync([.. scopes], context.CancellationToken)) { - var name = await _scopeManager.GetNameAsync(scope); + var name = await _scopeManager.GetNameAsync(scope, context.CancellationToken); if (!string.IsNullOrEmpty(name)) { scopes.Remove(name); @@ -1163,9 +1163,9 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); } - await foreach (var resource in _resourceManager.FindByNamesAsync([.. resources])) + await foreach (var resource in _resourceManager.FindByNamesAsync([.. resources], context.CancellationToken)) { - var name = await _resourceManager.GetNameAsync(resource); + var name = await _resourceManager.GetNameAsync(resource, context.CancellationToken); if (!string.IsNullOrEmpty(name)) { resources.Remove(name); @@ -1284,11 +1284,11 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the token endpoint. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.Token)) + if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.Token, context.CancellationToken)) { context.Logger.LogInformation(6086, SR.GetResourceString(SR.ID6086), context.ClientId); @@ -1336,11 +1336,11 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the specified grant type. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.GrantType + context.Request.GrantType)) + if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.GrantType + context.Request.GrantType, context.CancellationToken)) { context.Logger.LogInformation(6087, SR.GetResourceString(SR.ID6087), context.ClientId, context.Request.GrantType); @@ -1355,7 +1355,7 @@ public static partial class OpenIddictServerHandlers // Reject the request if the offline_access scope was request and if // the application is not allowed to use the refresh token grant type. if (context.Request.HasScope(Scopes.OfflineAccess) && - !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.RefreshToken)) + !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.RefreshToken, context.CancellationToken)) { context.Logger.LogInformation(6088, SR.GetResourceString(SR.ID6088), context.ClientId, Scopes.OfflineAccess); @@ -1403,7 +1403,7 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); foreach (var scope in context.Request.GetScopes()) @@ -1416,7 +1416,7 @@ public static partial class OpenIddictServerHandlers } // Reject the request if the application is not allowed to use the iterated scope. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Scope + scope)) + if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Scope + scope, context.CancellationToken)) { context.Logger.LogInformation(6089, SR.GetResourceString(SR.ID6089), context.ClientId, scope); @@ -1465,13 +1465,13 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); foreach (var audience in context.Request.GetAudiences()) { // Reject the request if the application is not allowed to use the iterated audience. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Audience + audience)) + if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Audience + audience, context.CancellationToken)) { context.Logger.LogInformation(6278, SR.GetResourceString(SR.ID6276), context.ClientId, audience); @@ -1520,13 +1520,13 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); foreach (var resource in context.Request.GetResources()) { // Reject the request if the application is not allowed to use the iterated resource. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Resource + resource)) + if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Resource + resource, context.CancellationToken)) { context.Logger.LogInformation(6279, SR.GetResourceString(SR.ID6277), context.ClientId, resource); @@ -1586,10 +1586,10 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); - if (await _applicationManager.HasRequirementAsync(application, Requirements.Features.ProofKeyForCodeExchange)) + if (await _applicationManager.HasRequirementAsync(application, Requirements.Features.ProofKeyForCodeExchange, context.CancellationToken)) { context.Logger.LogInformation(6077, SR.GetResourceString(SR.ID6077), Parameters.CodeVerifier); diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs index f96c8396..51f1eac2 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs @@ -528,11 +528,11 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the introspection endpoint. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.Introspection)) + if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.Introspection, context.CancellationToken)) { context.Logger.LogInformation(6103, SR.GetResourceString(SR.ID6103), context.ClientId); @@ -816,11 +816,11 @@ public static partial class OpenIddictServerHandlers return; } - var application = await _applicationManager.FindByClientIdAsync(context.Request.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.Request.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Public clients are not allowed to access sensitive claims as authentication cannot be enforced. - if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public)) + if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public, context.CancellationToken)) { context.Logger.LogInformation(6107, SR.GetResourceString(SR.ID6107), context.Request.ClientId); diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Protection.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Protection.cs index 0a24d124..dbbc0a8f 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Protection.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Protection.cs @@ -173,8 +173,8 @@ public static partial class OpenIddictServerHandlers // the signing keys from the JSON Web Key set attached to the client application. // // Important: at this stage, the issuer isn't guaranteed to be valid or legitimate. - var application = await _applicationManager.FindByClientIdAsync(token.Issuer); - if (application is not null && await _applicationManager.GetJsonWebKeySetAsync(application) + var application = await _applicationManager.FindByClientIdAsync(token.Issuer, context.CancellationToken); + if (application is not null && await _applicationManager.GetJsonWebKeySetAsync(application, context.CancellationToken) is JsonWebKeySet set) { return set.GetSigningKeys(); @@ -359,7 +359,7 @@ public static partial class OpenIddictServerHandlers } // If the reference token cannot be found, don't return an error to allow another handler to validate it. - var token = await _tokenManager.FindByReferenceIdAsync(context.Token); + var token = await _tokenManager.FindByReferenceIdAsync(context.Token, context.CancellationToken); if (token is null) { return; @@ -369,8 +369,8 @@ public static partial class OpenIddictServerHandlers if (!(context.ValidTokenTypes.Count switch { 0 => true, // If no specific token type is expected, accept all token types at this stage. - 1 => await _tokenManager.HasTypeAsync(token, context.ValidTokenTypes.ElementAt(0)), - _ => await _tokenManager.HasTypeAsync(token, [.. context.ValidTokenTypes]) + 1 => await _tokenManager.HasTypeAsync(token, context.ValidTokenTypes.ElementAt(0), context.CancellationToken), + _ => await _tokenManager.HasTypeAsync(token, [.. context.ValidTokenTypes], context.CancellationToken) })) { context.Reject( @@ -407,7 +407,7 @@ public static partial class OpenIddictServerHandlers return; } - var payload = await _tokenManager.GetPayloadAsync(token); + var payload = await _tokenManager.GetPayloadAsync(token, context.CancellationToken); if (string.IsNullOrEmpty(payload)) { throw new InvalidOperationException(SR.GetResourceString(SR.ID0026)); @@ -418,7 +418,7 @@ public static partial class OpenIddictServerHandlers // used to restore the properties associated with the token. context.IsReferenceToken = true; context.Token = payload; - context.TokenId = await _tokenManager.GetIdAsync(token); + context.TokenId = await _tokenManager.GetIdAsync(token, context.CancellationToken); } } @@ -799,7 +799,7 @@ public static partial class OpenIddictServerHandlers } // If the token entry cannot be found, return a generic error. - var token = await _tokenManager.FindByIdAsync(identifier); + var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken); if (token is null) { context.Reject( @@ -827,9 +827,9 @@ public static partial class OpenIddictServerHandlers // If the token was not validated as a reference token but has a reference identifier attached, this // may indicate that the payload stored in the database has leaked and is being used as a regular, // non-reference token. To prevent this, reject the token if the reference identifier is not null. - if (!context.IsReferenceToken && !string.IsNullOrEmpty(await _tokenManager.GetReferenceIdAsync(token))) + if (!context.IsReferenceToken && !string.IsNullOrEmpty(await _tokenManager.GetReferenceIdAsync(token, context.CancellationToken))) { - context.Logger.LogWarning(6292, SR.GetResourceString(SR.ID6292), await _tokenManager.GetIdAsync(token)); + context.Logger.LogWarning(6292, SR.GetResourceString(SR.ID6292), await _tokenManager.GetIdAsync(token, context.CancellationToken)); context.Reject( error: Errors.InvalidToken, @@ -855,11 +855,11 @@ public static partial class OpenIddictServerHandlers // Restore the creation/expiration dates/identifiers from the token entry metadata. context.Principal - .SetCreationDate(await _tokenManager.GetCreationDateAsync(token)) - .SetExpirationDate(await _tokenManager.GetExpirationDateAsync(token)) - .SetAuthorizationId(context.AuthorizationId = await _tokenManager.GetAuthorizationIdAsync(token)) - .SetTokenId(context.TokenId = await _tokenManager.GetIdAsync(token)) - .SetTokenType(await _tokenManager.GetTypeAsync(token)); + .SetCreationDate(await _tokenManager.GetCreationDateAsync(token, context.CancellationToken)) + .SetExpirationDate(await _tokenManager.GetExpirationDateAsync(token, context.CancellationToken)) + .SetAuthorizationId(context.AuthorizationId = await _tokenManager.GetAuthorizationIdAsync(token, context.CancellationToken)) + .SetTokenId(context.TokenId = await _tokenManager.GetIdAsync(token, context.CancellationToken)) + .SetTokenType(await _tokenManager.GetTypeAsync(token, context.CancellationToken)); } } @@ -1236,7 +1236,7 @@ public static partial class OpenIddictServerHandlers Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); Debug.Assert(!string.IsNullOrEmpty(context.TokenId), SR.GetResourceString(SR.ID4017)); - var token = await _tokenManager.FindByIdAsync(context.TokenId) + var token = await _tokenManager.FindByIdAsync(context.TokenId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0021)); // If the token is already marked as redeemed, this may indicate that it was compromised. @@ -1245,7 +1245,7 @@ public static partial class OpenIddictServerHandlers // Special logic is used to avoid revoking refresh tokens already marked as redeemed to allow for a small leeway. // Note: the authorization itself is not revoked to allow the legitimate client to start a new flow. // See https://tools.ietf.org/html/rfc6749#section-10.5 for more information. - if (await _tokenManager.HasStatusAsync(token, Statuses.Redeemed)) + if (await _tokenManager.HasStatusAsync(token, Statuses.Redeemed, context.CancellationToken)) { if (!context.Principal.HasTokenType(TokenTypeIdentifiers.RefreshToken) || !await IsReusableAsync(token)) { @@ -1255,7 +1255,7 @@ public static partial class OpenIddictServerHandlers try { - count = await _tokenManager.RevokeByAuthorizationIdAsync(context.AuthorizationId); + count = await _tokenManager.RevokeByAuthorizationIdAsync(context.AuthorizationId, context.CancellationToken); } catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception)) @@ -1302,7 +1302,7 @@ public static partial class OpenIddictServerHandlers } // If the token is not marked as valid yet, return an authorization_pending error. - if (await _tokenManager.HasStatusAsync(token, Statuses.Inactive)) + if (await _tokenManager.HasStatusAsync(token, Statuses.Inactive, context.CancellationToken)) { context.Logger.LogInformation(6003, SR.GetResourceString(SR.ID6003), context.TokenId); @@ -1315,7 +1315,7 @@ public static partial class OpenIddictServerHandlers } // If the token is marked as rejected, return an access_denied error. - if (await _tokenManager.HasStatusAsync(token, Statuses.Rejected)) + if (await _tokenManager.HasStatusAsync(token, Statuses.Rejected, context.CancellationToken)) { context.Logger.LogInformation(6004, SR.GetResourceString(SR.ID6004), context.TokenId); @@ -1327,7 +1327,7 @@ public static partial class OpenIddictServerHandlers return; } - if (!await _tokenManager.HasStatusAsync(token, Statuses.Valid)) + if (!await _tokenManager.HasStatusAsync(token, Statuses.Valid, context.CancellationToken)) { context.Logger.LogInformation(6005, SR.GetResourceString(SR.ID6005), context.TokenId); @@ -1367,7 +1367,7 @@ public static partial class OpenIddictServerHandlers return false; } - var date = await _tokenManager.GetRedemptionDateAsync(token); + var date = await _tokenManager.GetRedemptionDateAsync(token, context.CancellationToken); if (date is null || context.Options.TimeProvider.GetUtcNow() < date + context.Options.RefreshTokenReuseLeeway) { @@ -1413,8 +1413,8 @@ public static partial class OpenIddictServerHandlers Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); Debug.Assert(!string.IsNullOrEmpty(context.AuthorizationId), SR.GetResourceString(SR.ID4018)); - var authorization = await _authorizationManager.FindByIdAsync(context.AuthorizationId); - if (authorization is null || !await _authorizationManager.HasStatusAsync(authorization, Statuses.Valid)) + var authorization = await _authorizationManager.FindByIdAsync(context.AuthorizationId, context.CancellationToken); + if (authorization is null || !await _authorizationManager.HasStatusAsync(authorization, Statuses.Valid, context.CancellationToken)) { context.Logger.LogInformation(6006, SR.GetResourceString(SR.ID6006), context.AuthorizationId); @@ -1562,16 +1562,16 @@ public static partial class OpenIddictServerHandlers // If the client application is known, associate it with the token. if (!string.IsNullOrEmpty(context.ClientId)) { - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); - descriptor.ApplicationId = await _applicationManager.GetIdAsync(application); + descriptor.ApplicationId = await _applicationManager.GetIdAsync(application, context.CancellationToken); } - var token = await _tokenManager.CreateAsync(descriptor) + var token = await _tokenManager.CreateAsync(descriptor, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0019)); - var identifier = await _tokenManager.GetIdAsync(token); + var identifier = await _tokenManager.GetIdAsync(token, context.CancellationToken); // Attach the token identifier to the principal so that it can be stored in the token payload. context.Principal.SetTokenId(identifier); @@ -1815,11 +1815,11 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0009)); } - var token = await _tokenManager.FindByIdAsync(identifier) + var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0021)); var descriptor = new OpenIddictTokenDescriptor(); - await _tokenManager.PopulateAsync(descriptor, token); + await _tokenManager.PopulateAsync(descriptor, token, context.CancellationToken); // Attach the generated token to the token entry. descriptor.Payload = context.Token; @@ -1839,7 +1839,7 @@ public static partial class OpenIddictServerHandlers // User codes are generally short. To help reduce the risks of collisions with // existing entries, a database check is performed here before updating the entry. - while (await _tokenManager.FindByReferenceIdAsync(descriptor.ReferenceId) is not null); + while (await _tokenManager.FindByReferenceIdAsync(descriptor.ReferenceId, context.CancellationToken) is not null); } else @@ -1849,7 +1849,7 @@ public static partial class OpenIddictServerHandlers } } - await _tokenManager.UpdateAsync(token, descriptor); + await _tokenManager.UpdateAsync(token, descriptor, context.CancellationToken); context.Logger.LogTrace(6014, SR.GetResourceString(SR.ID6014), context.Token, identifier, context.TokenType); diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs index 5fc5f448..c08954c9 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs @@ -469,11 +469,11 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the revocation endpoint. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.Revocation)) + if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.Revocation, context.CancellationToken)) { context.Logger.LogInformation(6116, SR.GetResourceString(SR.ID6116), context.ClientId); @@ -671,7 +671,7 @@ public static partial class OpenIddictServerHandlers return; } - var token = await _tokenManager.FindByIdAsync(identifier); + var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken); if (token is null) { context.Logger.LogInformation(6123, SR.GetResourceString(SR.ID6123), identifier); @@ -685,7 +685,7 @@ public static partial class OpenIddictServerHandlers } // Try to revoke the token. If an error occurs, return an error. - if (!await _tokenManager.TryRevokeAsync(token)) + if (!await _tokenManager.TryRevokeAsync(token, context.CancellationToken)) { context.Reject( error: Errors.UnsupportedTokenType, diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs index 30cf29b3..b148823d 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs @@ -599,10 +599,10 @@ public static partial class OpenIddictServerHandlers if (!string.IsNullOrEmpty(context.ClientId)) { - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); - if (!await _applicationManager.ValidatePostLogoutRedirectUriAsync(application, context.PostLogoutRedirectUri)) + if (!await _applicationManager.ValidatePostLogoutRedirectUriAsync(application, context.PostLogoutRedirectUri, context.CancellationToken)) { context.Logger.LogInformation(6128, SR.GetResourceString(SR.ID6128), context.PostLogoutRedirectUri); @@ -634,17 +634,17 @@ public static partial class OpenIddictServerHandlers // To be considered valid, a post_logout_redirect_uri must correspond to an existing client application // that was granted the ept:logout permission, unless endpoint permissions checking was explicitly disabled. - await foreach (var application in _applicationManager.FindByPostLogoutRedirectUriAsync(uri)) + await foreach (var application in _applicationManager.FindByPostLogoutRedirectUriAsync(uri, context.CancellationToken)) { // Note: the legacy "ept:logout" permission is still allowed for backward compatibility. if (!context.Options.IgnoreEndpointPermissions && - !await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.EndSession) && - !await _applicationManager.HasPermissionAsync(application, "ept:logout")) + !await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.EndSession, context.CancellationToken) && + !await _applicationManager.HasPermissionAsync(application, "ept:logout", context.CancellationToken)) { continue; } - if (await _applicationManager.ValidatePostLogoutRedirectUriAsync(application, uri)) + if (await _applicationManager.ValidatePostLogoutRedirectUriAsync(application, uri, context.CancellationToken)) { return true; } @@ -667,18 +667,18 @@ public static partial class OpenIddictServerHandlers string.Equals(value.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase))) { await foreach (var application in _applicationManager.FindByPostLogoutRedirectUriAsync( - uri: new UriBuilder(value) { Port = -1 }.Uri.AbsoluteUri)) + uri: new UriBuilder(value) { Port = -1 }.Uri.AbsoluteUri, context.CancellationToken)) { // Note: the legacy "ept:logout" permission is still allowed for backward compatibility. if (!context.Options.IgnoreEndpointPermissions && - !await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.EndSession) && - !await _applicationManager.HasPermissionAsync(application, "ept:logout")) + !await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.EndSession, context.CancellationToken) && + !await _applicationManager.HasPermissionAsync(application, "ept:logout", context.CancellationToken)) { continue; } - if (await _applicationManager.HasApplicationTypeAsync(application, ApplicationTypes.Native) && - await _applicationManager.ValidatePostLogoutRedirectUriAsync(application, uri)) + if (await _applicationManager.HasApplicationTypeAsync(application, ApplicationTypes.Native, context.CancellationToken) && + await _applicationManager.ValidatePostLogoutRedirectUriAsync(application, uri, context.CancellationToken)) { return true; } @@ -729,14 +729,14 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the end session endpoint. // // Note: the legacy "ept:logout" permission is still allowed for backward compatibility. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.EndSession) && - !await _applicationManager.HasPermissionAsync(application, "ept:logout")) + if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.EndSession, context.CancellationToken) && + !await _applicationManager.HasPermissionAsync(application, "ept:logout", context.CancellationToken)) { context.Logger.LogInformation(6048, SR.GetResourceString(SR.ID6048), context.ClientId); @@ -858,7 +858,7 @@ public static partial class OpenIddictServerHandlers foreach (var identifier in identifiers) { - var application = await _applicationManager.FindByClientIdAsync(identifier); + var application = await _applicationManager.FindByClientIdAsync(identifier, context.CancellationToken); if (application is null) { continue; @@ -866,13 +866,13 @@ public static partial class OpenIddictServerHandlers // Note: the legacy "ept:logout" permission is still allowed for backward compatibility. if (!context.Options.IgnoreEndpointPermissions && - !await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.EndSession) && - !await _applicationManager.HasPermissionAsync(application, "ept:logout")) + !await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.EndSession, context.CancellationToken) && + !await _applicationManager.HasPermissionAsync(application, "ept:logout", context.CancellationToken)) { continue; } - if (await _applicationManager.ValidatePostLogoutRedirectUriAsync(application, uri)) + if (await _applicationManager.ValidatePostLogoutRedirectUriAsync(application, uri, context.CancellationToken)) { return true; } diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.cs index a6517294..44a1a598 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.cs @@ -1046,7 +1046,7 @@ public static partial class OpenIddictServerHandlers // Retrieve the application details corresponding to the requested client_id. // If no entity can be found, this likely indicates that the client_id is invalid. - var application = await _applicationManager.FindByClientIdAsync(context.ClientId); + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken); if (application is null) { context.Logger.LogInformation(6221, SR.GetResourceString(SR.ID6221), context.ClientId); @@ -1113,10 +1113,10 @@ public static partial class OpenIddictServerHandlers return; } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); - if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public)) + if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public, context.CancellationToken)) { // Reject grant_type=client_credentials token requests if the application is a public client. if (context.EndpointType is OpenIddictServerEndpointType.Token && @@ -1224,16 +1224,16 @@ public static partial class OpenIddictServerHandlers return; } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // If the application is a public client, don't validate the client secret. - if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public)) + if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public, context.CancellationToken)) { return; } - if (!await _applicationManager.ValidateClientSecretAsync(application, context.ClientSecret)) + if (!await _applicationManager.ValidateClientSecretAsync(application, context.ClientSecret, context.CancellationToken)) { context.Logger.LogInformation(6225, SR.GetResourceString(SR.ID6225), context.ClientId); @@ -1398,7 +1398,7 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Note: to avoid building and introspecting a X.509 certificate chain and reduce the cost @@ -1421,7 +1421,7 @@ public static partial class OpenIddictServerHandlers } if (await _applicationManager.GetSelfSignedTlsClientAuthenticationPolicyAsync( - application, context.Options.SelfSignedTlsClientAuthenticationPolicy) is not X509ChainPolicy policy) + application, context.Options.SelfSignedTlsClientAuthenticationPolicy, context.CancellationToken) is not X509ChainPolicy policy) { context.Logger.LogInformation(6283, SR.GetResourceString(SR.ID6283), context.ClientId); @@ -1442,7 +1442,7 @@ public static partial class OpenIddictServerHandlers // To allow validating such certificates, the chain policy is amended to consider the specified // self-signed certificate as a trusted root and basically disable chain validation while still // validating the other aspects of the certificate (e.g expiration date, key usage, etc). - if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public)) + if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public, context.CancellationToken)) { // Always clone the X.509 chain policy to ensure the original instance is never mutated. policy = policy.Clone(); @@ -1455,7 +1455,7 @@ public static partial class OpenIddictServerHandlers } if (!await _applicationManager.ValidateSelfSignedTlsClientCertificateAsync( - application, context.Transaction.RemoteCertificate, policy)) + application, context.Transaction.RemoteCertificate, policy, context.CancellationToken)) { context.Logger.LogInformation(6283, SR.GetResourceString(SR.ID6283), context.ClientId); @@ -1481,9 +1481,9 @@ public static partial class OpenIddictServerHandlers } if (await _applicationManager.GetPublicKeyInfrastructureTlsClientAuthenticationPolicyAsync( - application, context.Options.PublicKeyInfrastructureTlsClientAuthenticationPolicy) is not X509ChainPolicy policy || + application, context.Options.PublicKeyInfrastructureTlsClientAuthenticationPolicy, context.CancellationToken) is not X509ChainPolicy policy || !await _applicationManager.ValidatePublicKeyInfrastructureTlsClientCertificateAsync( - application, context.Transaction.RemoteCertificate, policy)) + application, context.Transaction.RemoteCertificate, policy, context.CancellationToken)) { context.Logger.LogInformation(6284, SR.GetResourceString(SR.ID6284), context.ClientId); @@ -2663,10 +2663,10 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0008)); } - var token = await _tokenManager.FindByIdAsync(identifier); + var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken); if (token is not null) { - await _tokenManager.TryRejectAsync(token); + await _tokenManager.TryRejectAsync(token, context.CancellationToken); } } } @@ -2719,10 +2719,10 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0009)); } - var token = await _tokenManager.FindByIdAsync(identifier); + var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken); if (token is not null) { - await _tokenManager.TryRejectAsync(token); + await _tokenManager.TryRejectAsync(token, context.CancellationToken); } } } @@ -2988,7 +2988,7 @@ public static partial class OpenIddictServerHandlers return; } - var token = await _tokenManager.FindByIdAsync(identifier); + var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken); if (token is null) { return; @@ -2998,10 +2998,10 @@ public static partial class OpenIddictServerHandlers // errors returned while trying to mark the entry as redeemed (that may be caused by concurrent requests). if (context.EndpointType is OpenIddictServerEndpointType.Token && context.Request.IsRefreshTokenGrantType()) { - await _tokenManager.TryRedeemAsync(token); + await _tokenManager.TryRedeemAsync(token, context.CancellationToken); } - else if (!await _tokenManager.TryRedeemAsync(token)) + else if (!await _tokenManager.TryRedeemAsync(token, context.CancellationToken)) { context.Reject( error: Errors.InvalidToken, @@ -3483,16 +3483,16 @@ public static partial class OpenIddictServerHandlers // If the client application is known, associate it to the authorization. if (!string.IsNullOrEmpty(context.Request.ClientId)) { - var application = await _applicationManager.FindByClientIdAsync(context.Request.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.Request.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); - descriptor.ApplicationId = await _applicationManager.GetIdAsync(application); + descriptor.ApplicationId = await _applicationManager.GetIdAsync(application, context.CancellationToken); } - var authorization = await _authorizationManager.CreateAsync(descriptor) + var authorization = await _authorizationManager.CreateAsync(descriptor, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0018)); - var identifier = await _authorizationManager.GetIdAsync(authorization); + var identifier = await _authorizationManager.GetIdAsync(authorization, context.CancellationToken); if (string.IsNullOrEmpty(context.Request.ClientId)) { @@ -3610,10 +3610,10 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); - var settings = await _applicationManager.GetSettingsAsync(application); + var settings = await _applicationManager.GetSettingsAsync(application, context.CancellationToken); if (settings.TryGetValue(Settings.TokenLifetimes.AccessToken, out string? setting) && TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) { @@ -3744,10 +3744,10 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); - var settings = await _applicationManager.GetSettingsAsync(application); + var settings = await _applicationManager.GetSettingsAsync(application, context.CancellationToken); if (settings.TryGetValue(Settings.TokenLifetimes.AuthorizationCode, out string? setting) && TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) { @@ -3868,10 +3868,10 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); - var settings = await _applicationManager.GetSettingsAsync(application); + var settings = await _applicationManager.GetSettingsAsync(application, context.CancellationToken); if (settings.TryGetValue(Settings.TokenLifetimes.DeviceCode, out string? setting) && TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) { @@ -4084,7 +4084,7 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); var name = context.IssuedTokenType switch @@ -4096,7 +4096,7 @@ public static partial class OpenIddictServerHandlers _ => Settings.TokenLifetimes.IssuedToken }; - var settings = await _applicationManager.GetSettingsAsync(application); + var settings = await _applicationManager.GetSettingsAsync(application, context.CancellationToken); if (settings.TryGetValue(name, out string? setting) && TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) { @@ -4178,7 +4178,7 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); // Note: refresh tokens are only bound to the provided certificate when the client @@ -4186,7 +4186,7 @@ public static partial class OpenIddictServerHandlers // are already sender-constrained via standard client authentication, which is more // flexible than certificate-based token binding, as rotating client credentials is // easier in that case (specially when using PKI-based mTLS client authentication). - if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public)) + if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public, context.CancellationToken)) { principal.SetClaim(Claims.Confirmation, CreateConfirmationClaim(certificate)); } @@ -4274,10 +4274,10 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); - var settings = await _applicationManager.GetSettingsAsync(application); + var settings = await _applicationManager.GetSettingsAsync(application, context.CancellationToken); if (settings.TryGetValue(Settings.TokenLifetimes.RequestToken, out string? setting) && TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) { @@ -4419,10 +4419,10 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); - var settings = await _applicationManager.GetSettingsAsync(application); + var settings = await _applicationManager.GetSettingsAsync(application, context.CancellationToken); if (settings.TryGetValue(Settings.TokenLifetimes.RefreshToken, out string? setting) && TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) { @@ -4472,7 +4472,7 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); // Note: refresh tokens are only bound to the provided certificate when the client @@ -4480,7 +4480,7 @@ public static partial class OpenIddictServerHandlers // are already sender-constrained via standard client authentication, which is more // flexible than certificate-based token binding, as rotating client credentials is // easier in that case (specially when using PKI-based mTLS client authentication). - if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public)) + if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public, context.CancellationToken)) { principal.SetClaim(Claims.Confirmation, CreateConfirmationClaim(certificate)); } @@ -4594,10 +4594,10 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); - var settings = await _applicationManager.GetSettingsAsync(application); + var settings = await _applicationManager.GetSettingsAsync(application, context.CancellationToken); if (settings.TryGetValue(Settings.TokenLifetimes.IdentityToken, out string? setting) && TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) { @@ -4718,10 +4718,10 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId) + var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); - var settings = await _applicationManager.GetSettingsAsync(application); + var settings = await _applicationManager.GetSettingsAsync(application, context.CancellationToken); if (settings.TryGetValue(Settings.TokenLifetimes.UserCode, out string? setting) && TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) { @@ -5255,13 +5255,13 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0008)); } - var token = await _tokenManager.FindByIdAsync(identifier) + var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0265)); // Replace the device code details by the payload derived from the new device code principal, // that includes all the user claims populated by the application after authenticating the user. var descriptor = new OpenIddictTokenDescriptor(); - await _tokenManager.PopulateAsync(descriptor, token); + await _tokenManager.PopulateAsync(descriptor, token, context.CancellationToken); // Note: the lifetime is deliberately extended to give more time to the client to redeem the code. descriptor.ExpirationDate = context.DeviceCodePrincipal.GetExpirationDate(); @@ -5270,9 +5270,9 @@ public static partial class OpenIddictServerHandlers descriptor.Status = Statuses.Valid; descriptor.Subject = context.DeviceCodePrincipal.GetClaim(Claims.Subject); - await _tokenManager.UpdateAsync(token, descriptor); + await _tokenManager.UpdateAsync(token, descriptor, context.CancellationToken); - context.Logger.LogTrace(6021, SR.GetResourceString(SR.ID6021), await _tokenManager.GetIdAsync(token)); + context.Logger.LogTrace(6021, SR.GetResourceString(SR.ID6021), await _tokenManager.GetIdAsync(token, context.CancellationToken)); } } @@ -5850,14 +5850,14 @@ public static partial class OpenIddictServerHandlers return; } - var token = await _tokenManager.FindByIdAsync(identifier); + var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken); if (token is null) { return; } // Mark the token as redeemed to prevent future reuses. - await _tokenManager.TryRedeemAsync(token); + await _tokenManager.TryRedeemAsync(token, context.CancellationToken); } } diff --git a/src/OpenIddict.Server/OpenIddictServerTransaction.cs b/src/OpenIddict.Server/OpenIddictServerTransaction.cs index 3720f112..49b63487 100644 --- a/src/OpenIddict.Server/OpenIddictServerTransaction.cs +++ b/src/OpenIddict.Server/OpenIddictServerTransaction.cs @@ -17,14 +17,8 @@ namespace OpenIddict.Server; public sealed class OpenIddictServerTransaction { /// - /// Gets or sets the cancellation token that will be - /// used to determine if the operation was aborted. + /// Gets or sets the cancellation token used to determine if the operation was aborted. /// - /// - /// Note: for security reasons, this property shouldn't be used by event - /// handlers to abort security-sensitive operations. As such, it is - /// recommended to use this property only for user-dependent operations. - /// public CancellationToken CancellationToken { get; set; } /// diff --git a/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandler.cs b/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandler.cs index 7d2a633e..953fabc5 100644 --- a/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandler.cs +++ b/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandler.cs @@ -42,13 +42,23 @@ public sealed class OpenIddictValidationAspNetCoreHandler : AuthenticationHandle /// public async Task HandleRequestAsync() { + // Note: to ensure internal operations are not immediately cancelled when the request is aborted + // (which may represent a security risk if sensitive operations are in progress), an ad-hoc token + // source is always created and configured to be triggered 5 seconds after the request is aborted. + var source = new CancellationTokenSource(); + var registration = Context.RequestAborted.Register(static state => + ((CancellationTokenSource) state!).CancelAfter(TimeSpan.FromSeconds(5)), source); + + Response.RegisterForDispose(source); + Response.RegisterForDispose(registration); + // Note: the transaction may be already attached when replaying an ASP.NET Core request // (e.g when using the built-in status code pages middleware with the re-execute mode). var transaction = Context.Features.Get()?.Transaction; if (transaction is null) { // Create a new transaction and attach the HTTP request to make it available to the ASP.NET Core handlers. - transaction = await _factory.CreateTransactionAsync(); + transaction = await _factory.CreateTransactionAsync(source.Token); transaction.Properties[typeof(HttpRequest).FullName!] = new WeakReference(Request); // Attach the OpenIddict validation transaction to the ASP.NET Core features @@ -56,11 +66,7 @@ public sealed class OpenIddictValidationAspNetCoreHandler : AuthenticationHandle Context.Features.Set(new OpenIddictValidationAspNetCoreFeature { Transaction = transaction }); } - var context = new ProcessRequestContext(transaction) - { - CancellationToken = Context.RequestAborted - }; - + var context = new ProcessRequestContext(transaction); await _dispatcher.DispatchAsync(context); if (context.IsRequestHandled) @@ -77,7 +83,6 @@ public sealed class OpenIddictValidationAspNetCoreHandler : AuthenticationHandle { var notification = new ProcessErrorContext(transaction) { - CancellationToken = Context.RequestAborted, Error = context.Error ?? Errors.InvalidRequest, ErrorDescription = context.ErrorDescription, ErrorUri = context.ErrorUri, @@ -114,10 +119,7 @@ public sealed class OpenIddictValidationAspNetCoreHandler : AuthenticationHandle var context = transaction.GetProperty(typeof(ProcessAuthenticationContext).FullName!); if (context is null) { - await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction) - { - CancellationToken = Context.RequestAborted - }); + await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction)); // Store the context object in the transaction so it can be later retrieved by handlers // that want to access the authentication result without triggering a new authentication flow. @@ -214,7 +216,6 @@ public sealed class OpenIddictValidationAspNetCoreHandler : AuthenticationHandle var context = new ProcessChallengeContext(transaction) { - CancellationToken = Context.RequestAborted, Response = new OpenIddictResponse() }; @@ -229,7 +230,6 @@ public sealed class OpenIddictValidationAspNetCoreHandler : AuthenticationHandle { var notification = new ProcessErrorContext(transaction) { - CancellationToken = Context.RequestAborted, Error = context.Error ?? Errors.InvalidRequest, ErrorDescription = context.ErrorDescription, ErrorUri = context.ErrorUri, diff --git a/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandlers.cs b/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandlers.cs index 19a756f1..a91401ba 100644 --- a/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandlers.cs +++ b/src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandlers.cs @@ -332,7 +332,7 @@ public static partial class OpenIddictValidationAspNetCoreHandlers // If a client certificate was used during the TLS handshake, attach it to the context. if (request.IsHttps && await request.HttpContext.Connection.GetClientCertificateAsync( - request.HttpContext.RequestAborted) is X509Certificate2 certificate) + context.CancellationToken) is X509Certificate2 certificate) { context.Transaction.RemoteCertificate = certificate; } diff --git a/src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandler.cs b/src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandler.cs index 606c1994..cb4251a2 100644 --- a/src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandler.cs +++ b/src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandler.cs @@ -37,13 +37,23 @@ public sealed class OpenIddictValidationOwinHandler : AuthenticationHandler protected override async Task InitializeCoreAsync() { + // Note: to ensure internal operations are not immediately cancelled when the request is aborted + // (which may represent a security risk if sensitive operations are in progress), an ad-hoc token + // source is always created and configured to be triggered 5 seconds after the request is aborted. + var source = new CancellationTokenSource(); + var registration = Request.CallCancelled.Register(static state => + ((CancellationTokenSource) state!).CancelAfter(TimeSpan.FromSeconds(5)), source); + + Response.OnSendingHeaders(static state => ((CancellationTokenSource) state!).Dispose(), source); + Response.OnSendingHeaders(static state => ((CancellationTokenRegistration) state!).Dispose(), registration); + // Note: the transaction may be already attached when replaying an OWIN request // (e.g when using a status code pages middleware re-invoking the OWIN pipeline). var transaction = Context.Get(typeof(OpenIddictValidationTransaction).FullName); if (transaction is null) { // Create a new transaction and attach the OWIN request to make it available to the OWIN handlers. - transaction = await _factory.CreateTransactionAsync(); + transaction = await _factory.CreateTransactionAsync(source.Token); transaction.Properties[typeof(IOwinRequest).FullName!] = new WeakReference(Request); // Attach the OpenIddict validation transaction to the OWIN shared dictionary @@ -51,11 +61,7 @@ public sealed class OpenIddictValidationOwinHandler : AuthenticationHandler(typeof(ProcessAuthenticationContext).FullName!); if (context is null) { - await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction) - { - CancellationToken = Request.CallCancelled - }); + await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction)); // Store the context object in the transaction so it can be later retrieved by handlers // that want to access the authentication result without triggering a new authentication flow. @@ -222,7 +224,6 @@ public sealed class OpenIddictValidationOwinHandler : AuthenticationHandler GetClientCertificateAsync(IOwinContext context) + static async ValueTask GetClientCertificateAsync( + IOwinContext context, CancellationToken cancellationToken) { // If a loading function was provided by the OWIN host, always invoke it before trying // to resolve the certificate to ensure it is present in the environment dictionary. if (context.Get>("ssl.LoadClientCertAsync") is Func loader) { - await loader(); + await loader().WaitAsync(cancellationToken); } return context.Get("ssl.ClientCertificate") is X509Certificate certificate diff --git a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs index 602470a5..37bed945 100644 --- a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs +++ b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs @@ -607,7 +607,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers else if (string.Equals(encoding, ContentEncodings.Gzip, StringComparison.OrdinalIgnoreCase)) { - stream ??= await response.Content.ReadAsStreamAsync(); + stream ??= await response.Content.ReadAsStreamAsync().WaitAsync(context.CancellationToken); stream = new GZipStream(stream, CompressionMode.Decompress); } @@ -621,13 +621,13 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers // For more information, read https://www.rfc-editor.org/rfc/rfc9110.html#name-deflate-coding. else if (string.Equals(encoding, ContentEncodings.Deflate, StringComparison.OrdinalIgnoreCase)) { - stream ??= await response.Content.ReadAsStreamAsync(); + stream ??= await response.Content.ReadAsStreamAsync().WaitAsync(context.CancellationToken); stream = new ZLibStream(stream, CompressionMode.Decompress); } else if (string.Equals(encoding, ContentEncodings.Brotli, StringComparison.OrdinalIgnoreCase)) { - stream ??= await response.Content.ReadAsStreamAsync(); + stream ??= await response.Content.ReadAsStreamAsync().WaitAsync(context.CancellationToken); stream = new BrotliStream(stream, CompressionMode.Decompress); } #endif @@ -651,7 +651,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers // (e.g if the JSON deserialization process fails, the stream is read as a string // during a second pass a second time for logging/debuggability purposes). var content = new StreamContent(stream); - await content.LoadIntoBufferAsync(); + await content.LoadIntoBufferAsync(context.CancellationToken); // Copy the headers from the original content to the new instance. foreach (var header in response.Content.Headers) @@ -724,7 +724,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception)) { context.Logger.LogError(6183, exception, SR.GetResourceString(SR.ID6183), - await response.Content.ReadAsStringAsync()); + await response.Content.ReadAsStringAsync(context.CancellationToken)); context.Reject( error: Errors.ServerError, @@ -902,7 +902,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers if (!response.IsSuccessStatusCode && string.IsNullOrEmpty(context.Transaction.Response?.Error)) { context.Logger.LogError(6184, SR.GetResourceString(SR.ID6184), response.StatusCode, - await response.Content.ReadAsStringAsync()); + await response.Content.ReadAsStringAsync(context.CancellationToken)); context.Reject( error: (int) response.StatusCode switch @@ -926,7 +926,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers if (context.Transaction.Response is null) { context.Logger.LogError(6185, SR.GetResourceString(SR.ID6185), response.StatusCode, - response.Content.Headers.ContentType, await response.Content.ReadAsStringAsync()); + response.Content.Headers.ContentType, await response.Content.ReadAsStringAsync(context.CancellationToken)); context.Reject( error: Errors.ServerError, diff --git a/src/OpenIddict.Validation/IOpenIddictValidationFactory.cs b/src/OpenIddict.Validation/IOpenIddictValidationFactory.cs index d88c5d26..5ad893d4 100644 --- a/src/OpenIddict.Validation/IOpenIddictValidationFactory.cs +++ b/src/OpenIddict.Validation/IOpenIddictValidationFactory.cs @@ -18,9 +18,13 @@ public interface IOpenIddictValidationFactory /// Creates a new that is used as a /// way to store per-request data needed to process the requested operation. /// + /// The that can be used to abort the operation. + /// + /// Note: the specified is automatically attached to the returned transaction. + /// /// /// A that can be used to monitor the asynchronous /// operation, whose result returns the created transaction. /// - ValueTask CreateTransactionAsync(); + ValueTask CreateTransactionAsync(CancellationToken cancellationToken); } diff --git a/src/OpenIddict.Validation/OpenIddictValidationDispatcher.cs b/src/OpenIddict.Validation/OpenIddictValidationDispatcher.cs index 61ecfcc4..b0fc80e1 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationDispatcher.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationDispatcher.cs @@ -40,6 +40,8 @@ public sealed class OpenIddictValidationDispatcher : IOpenIddictValidationDispat await foreach (var handler in GetHandlersAsync()) { + context.CancellationToken.ThrowIfCancellationRequested(); + try { await handler.HandleAsync(context); diff --git a/src/OpenIddict.Validation/OpenIddictValidationEvents.cs b/src/OpenIddict.Validation/OpenIddictValidationEvents.cs index eea07a41..0fd03904 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationEvents.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationEvents.cs @@ -31,19 +31,9 @@ public static partial class OpenIddictValidationEvents public OpenIddictValidationTransaction Transaction { get; } /// - /// Gets or sets the cancellation token that will be - /// used to determine if the operation was aborted. + /// Gets the cancellation token used to determine if the operation was aborted. /// - /// - /// Note: for security reasons, this property shouldn't be used by event - /// handlers to abort security-sensitive operations. As such, it is - /// recommended to use this property only for user-dependent operations. - /// - public CancellationToken CancellationToken - { - get => Transaction.CancellationToken; - set => Transaction.CancellationToken = value; - } + public CancellationToken CancellationToken => Transaction.CancellationToken; /// /// Gets or sets the endpoint type that handled the request, if applicable. diff --git a/src/OpenIddict.Validation/OpenIddictValidationFactory.cs b/src/OpenIddict.Validation/OpenIddictValidationFactory.cs index 85e836c9..4b806f42 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationFactory.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationFactory.cs @@ -31,10 +31,18 @@ public sealed class OpenIddictValidationFactory : IOpenIddictValidationFactory } /// - public ValueTask CreateTransactionAsync() - => new(new OpenIddictValidationTransaction + public ValueTask CreateTransactionAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return new(Task.FromCanceled(cancellationToken)); + } + + return new(new OpenIddictValidationTransaction { + CancellationToken = cancellationToken, Logger = _logger, Options = _options.CurrentValue }); + } } diff --git a/src/OpenIddict.Validation/OpenIddictValidationHandlers.Protection.cs b/src/OpenIddict.Validation/OpenIddictValidationHandlers.Protection.cs index 7c79cce3..1a49d049 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationHandlers.Protection.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationHandlers.Protection.cs @@ -220,7 +220,7 @@ public static partial class OpenIddictValidationHandlers } // If the reference token cannot be found, don't return an error to allow another handler to validate it. - var token = await _tokenManager.FindByReferenceIdAsync(context.Token); + var token = await _tokenManager.FindByReferenceIdAsync(context.Token, context.CancellationToken); if (token is null) { return; @@ -230,8 +230,8 @@ public static partial class OpenIddictValidationHandlers if (!(context.ValidTokenTypes.Count switch { 0 => true, // If no specific token type is expected, accept all token types at this stage. - 1 => await _tokenManager.HasTypeAsync(token, context.ValidTokenTypes.ElementAt(0)), - _ => await _tokenManager.HasTypeAsync(token, [.. context.ValidTokenTypes]) + 1 => await _tokenManager.HasTypeAsync(token, context.ValidTokenTypes.ElementAt(0), context.CancellationToken), + _ => await _tokenManager.HasTypeAsync(token, [.. context.ValidTokenTypes], context.CancellationToken) })) { context.Reject( @@ -242,7 +242,7 @@ public static partial class OpenIddictValidationHandlers return; } - var payload = await _tokenManager.GetPayloadAsync(token); + var payload = await _tokenManager.GetPayloadAsync(token, context.CancellationToken); if (string.IsNullOrEmpty(payload)) { throw new InvalidOperationException(SR.GetResourceString(SR.ID0026)); @@ -253,7 +253,7 @@ public static partial class OpenIddictValidationHandlers // used to restore the properties associated with the token. context.IsReferenceToken = true; context.Token = payload; - context.TokenId = await _tokenManager.GetIdAsync(token); + context.TokenId = await _tokenManager.GetIdAsync(token, context.CancellationToken); } } @@ -562,7 +562,7 @@ public static partial class OpenIddictValidationHandlers } // If the token entry cannot be found, return a generic error. - var token = await _tokenManager.FindByIdAsync(identifier); + var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken); if (token is null) { context.Reject( @@ -576,9 +576,9 @@ public static partial class OpenIddictValidationHandlers // If the token was not validated as a reference token but has a reference identifier attached, this // may indicate that the payload stored in the database has leaked and is being used as a regular, // non-reference token. To prevent this, reject the token if the reference identifier is not null. - if (!context.IsReferenceToken && !string.IsNullOrEmpty(await _tokenManager.GetReferenceIdAsync(token))) + if (!context.IsReferenceToken && !string.IsNullOrEmpty(await _tokenManager.GetReferenceIdAsync(token, context.CancellationToken))) { - context.Logger.LogWarning(6292, SR.GetResourceString(SR.ID6292), await _tokenManager.GetIdAsync(token)); + context.Logger.LogWarning(6292, SR.GetResourceString(SR.ID6292), await _tokenManager.GetIdAsync(token, context.CancellationToken)); context.Reject( error: Errors.InvalidToken, @@ -590,11 +590,11 @@ public static partial class OpenIddictValidationHandlers // Restore the creation/expiration dates/identifiers from the token entry metadata. context.Principal - .SetCreationDate(await _tokenManager.GetCreationDateAsync(token)) - .SetExpirationDate(await _tokenManager.GetExpirationDateAsync(token)) - .SetAuthorizationId(context.AuthorizationId = await _tokenManager.GetAuthorizationIdAsync(token)) - .SetTokenId(context.TokenId = await _tokenManager.GetIdAsync(token)) - .SetTokenType(await _tokenManager.GetTypeAsync(token)); + .SetCreationDate(await _tokenManager.GetCreationDateAsync(token, context.CancellationToken)) + .SetExpirationDate(await _tokenManager.GetExpirationDateAsync(token, context.CancellationToken)) + .SetAuthorizationId(context.AuthorizationId = await _tokenManager.GetAuthorizationIdAsync(token, context.CancellationToken)) + .SetTokenId(context.TokenId = await _tokenManager.GetIdAsync(token, context.CancellationToken)) + .SetTokenType(await _tokenManager.GetTypeAsync(token, context.CancellationToken)); } } @@ -922,10 +922,10 @@ public static partial class OpenIddictValidationHandlers Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); Debug.Assert(!string.IsNullOrEmpty(context.TokenId), SR.GetResourceString(SR.ID4017)); - var token = await _tokenManager.FindByIdAsync(context.TokenId) + var token = await _tokenManager.FindByIdAsync(context.TokenId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0021)); - if (!await _tokenManager.HasStatusAsync(token, Statuses.Valid)) + if (!await _tokenManager.HasStatusAsync(token, Statuses.Valid, context.CancellationToken)) { context.Logger.LogInformation(6005, SR.GetResourceString(SR.ID6005), context.TokenId); @@ -972,8 +972,8 @@ public static partial class OpenIddictValidationHandlers Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); Debug.Assert(!string.IsNullOrEmpty(context.AuthorizationId), SR.GetResourceString(SR.ID4018)); - var authorization = await _authorizationManager.FindByIdAsync(context.AuthorizationId); - if (authorization is null || !await _authorizationManager.HasStatusAsync(authorization, Statuses.Valid)) + var authorization = await _authorizationManager.FindByIdAsync(context.AuthorizationId, context.CancellationToken); + if (authorization is null || !await _authorizationManager.HasStatusAsync(authorization, Statuses.Valid, context.CancellationToken)) { context.Logger.LogInformation(6006, SR.GetResourceString(SR.ID6006), context.AuthorizationId); diff --git a/src/OpenIddict.Validation/OpenIddictValidationService.cs b/src/OpenIddict.Validation/OpenIddictValidationService.cs index 5dbe97c0..b3da7d7a 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationService.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationService.cs @@ -47,7 +47,7 @@ public class OpenIddictValidationService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(cancellationToken); var context = new ProcessAuthenticationContext(transaction) { @@ -92,7 +92,7 @@ public class OpenIddictValidationService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(cancellationToken); var request = new OpenIddictRequest(); request = await PrepareConfigurationRequestAsync(); @@ -214,7 +214,7 @@ public class OpenIddictValidationService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(cancellationToken); var request = new OpenIddictRequest(); request = await PrepareJsonWebKeySetRequestAsync(); @@ -344,7 +344,7 @@ public class OpenIddictValidationService var dispatcher = scope.ServiceProvider.GetRequiredService(); var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(cancellationToken); request = await PrepareIntrospectionRequestAsync(); request = await ApplyIntrospectionRequestAsync(); @@ -357,7 +357,6 @@ public class OpenIddictValidationService { var context = new PrepareIntrospectionRequestContext(transaction) { - CancellationToken = cancellationToken, ClientAuthenticationMethod = method, Configuration = configuration, RemoteUri = uri, @@ -381,7 +380,6 @@ public class OpenIddictValidationService { var context = new ApplyIntrospectionRequestContext(transaction) { - CancellationToken = cancellationToken, RemoteUri = uri, Configuration = configuration, Request = request @@ -405,7 +403,6 @@ public class OpenIddictValidationService { var context = new ExtractIntrospectionResponseContext(transaction) { - CancellationToken = cancellationToken, RemoteUri = uri, Configuration = configuration, Request = request @@ -431,7 +428,6 @@ public class OpenIddictValidationService { var context = new HandleIntrospectionResponseContext(transaction) { - CancellationToken = cancellationToken, RemoteUri = uri, Configuration = configuration, Request = request, diff --git a/src/OpenIddict.Validation/OpenIddictValidationTransaction.cs b/src/OpenIddict.Validation/OpenIddictValidationTransaction.cs index 8d04dc98..341f851a 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationTransaction.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationTransaction.cs @@ -17,14 +17,8 @@ namespace OpenIddict.Validation; public sealed class OpenIddictValidationTransaction { /// - /// Gets or sets the cancellation token that will be - /// used to determine if the operation was aborted. + /// Gets or sets the cancellation token used to determine if the operation was aborted. /// - /// - /// Note: for security reasons, this property shouldn't be used by event - /// handlers to abort security-sensitive operations. As such, it is - /// recommended to use this property only for user-dependent operations. - /// public CancellationToken CancellationToken { get; set; } ///