Browse Source

Update the client/server/validation stacks to always use the CancellationToken attached to the context

pull/2517/head
Kévin Chalet 2 months ago
parent
commit
e9d5a1c64f
  1. 2
      sandbox/OpenIddict.Sandbox.AspNet.Client/Controllers/HomeController.cs
  2. 2
      sandbox/OpenIddict.Sandbox.AspNetCore.Client/Controllers/HomeController.cs
  3. 28
      src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandler.cs
  4. 28
      src/OpenIddict.Client.Owin/OpenIddictClientOwinHandler.cs
  5. 4
      src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Authentication.cs
  6. 4
      src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Session.cs
  7. 2
      src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs
  8. 9
      src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationService.cs
  9. 2
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Userinfo.cs
  10. 14
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs
  11. 6
      src/OpenIddict.Client/IOpenIddictClientFactory.cs
  12. 16
      src/OpenIddict.Client/OpenIddictClientConfiguration.cs
  13. 2
      src/OpenIddict.Client/OpenIddictClientDispatcher.cs
  14. 14
      src/OpenIddict.Client/OpenIddictClientEvents.cs
  15. 12
      src/OpenIddict.Client/OpenIddictClientFactory.cs
  16. 40
      src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs
  17. 8
      src/OpenIddict.Client/OpenIddictClientHandlers.cs
  18. 84
      src/OpenIddict.Client/OpenIddictClientService.cs
  19. 8
      src/OpenIddict.Client/OpenIddictClientTransaction.cs
  20. 29
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandler.cs
  21. 2
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.cs
  22. 30
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandler.cs
  23. 8
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.cs
  24. 6
      src/OpenIddict.Server/IOpenIddictServerFactory.cs
  25. 6
      src/OpenIddict.Server/OpenIddictServerConfiguration.cs
  26. 2
      src/OpenIddict.Server/OpenIddictServerDispatcher.cs
  27. 14
      src/OpenIddict.Server/OpenIddictServerEvents.cs
  28. 12
      src/OpenIddict.Server/OpenIddictServerFactory.cs
  29. 104
      src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs
  30. 20
      src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs
  31. 34
      src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs
  32. 8
      src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs
  33. 64
      src/OpenIddict.Server/OpenIddictServerHandlers.Protection.cs
  34. 8
      src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs
  35. 36
      src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs
  36. 98
      src/OpenIddict.Server/OpenIddictServerHandlers.cs
  37. 8
      src/OpenIddict.Server/OpenIddictServerTransaction.cs
  38. 26
      src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandler.cs
  39. 2
      src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandlers.cs
  40. 26
      src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandler.cs
  41. 8
      src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandlers.cs
  42. 14
      src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs
  43. 6
      src/OpenIddict.Validation/IOpenIddictValidationFactory.cs
  44. 2
      src/OpenIddict.Validation/OpenIddictValidationDispatcher.cs
  45. 14
      src/OpenIddict.Validation/OpenIddictValidationEvents.cs
  46. 12
      src/OpenIddict.Validation/OpenIddictValidationFactory.cs
  47. 34
      src/OpenIddict.Validation/OpenIddictValidationHandlers.Protection.cs
  48. 12
      src/OpenIddict.Validation/OpenIddictValidationService.cs
  49. 8
      src/OpenIddict.Validation/OpenIddictValidationTransaction.cs

2
sandbox/OpenIddict.Sandbox.AspNet.Client/Controllers/HomeController.cs

@ -43,7 +43,7 @@ public class HomeController([FromKeyedServices("ApiClient")] HttpClient client,
return View("Index", new IndexViewModel return View("Index", new IndexViewModel
{ {
Message = await response.Content.ReadAsStringAsync(), Message = await response.Content.ReadAsStringAsync(cancellationToken),
Providers = from registration in await service.GetClientRegistrationsAsync(cancellationToken) Providers = from registration in await service.GetClientRegistrationsAsync(cancellationToken)
where !string.IsNullOrEmpty(registration.ProviderName) where !string.IsNullOrEmpty(registration.ProviderName)
where !string.IsNullOrEmpty(registration.ProviderDisplayName) where !string.IsNullOrEmpty(registration.ProviderDisplayName)

2
sandbox/OpenIddict.Sandbox.AspNetCore.Client/Controllers/HomeController.cs

@ -35,7 +35,7 @@ public class HomeController([FromKeyedServices("ApiClient")] HttpClient client,
return View("Index", new IndexViewModel return View("Index", new IndexViewModel
{ {
Message = await response.Content.ReadAsStringAsync(), Message = await response.Content.ReadAsStringAsync(cancellationToken),
Providers = from registration in await service.GetClientRegistrationsAsync(cancellationToken) Providers = from registration in await service.GetClientRegistrationsAsync(cancellationToken)
where !string.IsNullOrEmpty(registration.ProviderName) where !string.IsNullOrEmpty(registration.ProviderName)
where !string.IsNullOrEmpty(registration.ProviderDisplayName) where !string.IsNullOrEmpty(registration.ProviderDisplayName)

28
src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandler.cs

@ -44,13 +44,23 @@ public sealed class OpenIddictClientAspNetCoreHandler : AuthenticationHandler<Au
/// <inheritdoc/> /// <inheritdoc/>
public async Task<bool> HandleRequestAsync() public async Task<bool> 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 // 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). // (e.g when using the built-in status code pages middleware with the re-execute mode).
var transaction = Context.Features.Get<OpenIddictClientAspNetCoreFeature>()?.Transaction; var transaction = Context.Features.Get<OpenIddictClientAspNetCoreFeature>()?.Transaction;
if (transaction is null) if (transaction is null)
{ {
// Create a new transaction and attach the HTTP request to make it available to the ASP.NET Core handlers. // 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<HttpRequest>(Request); transaction.Properties[typeof(HttpRequest).FullName!] = new WeakReference<HttpRequest>(Request);
// Attach the OpenIddict client transaction to the ASP.NET Core features // Attach the OpenIddict client transaction to the ASP.NET Core features
@ -58,11 +68,7 @@ public sealed class OpenIddictClientAspNetCoreHandler : AuthenticationHandler<Au
Context.Features.Set(new OpenIddictClientAspNetCoreFeature { Transaction = transaction }); Context.Features.Set(new OpenIddictClientAspNetCoreFeature { Transaction = transaction });
} }
var context = new ProcessRequestContext(transaction) var context = new ProcessRequestContext(transaction);
{
CancellationToken = Context.RequestAborted
};
await _dispatcher.DispatchAsync(context); await _dispatcher.DispatchAsync(context);
if (context.IsRequestHandled) if (context.IsRequestHandled)
@ -79,7 +85,6 @@ public sealed class OpenIddictClientAspNetCoreHandler : AuthenticationHandler<Au
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
CancellationToken = Context.RequestAborted,
Error = context.Error ?? Errors.InvalidRequest, Error = context.Error ?? Errors.InvalidRequest,
ErrorDescription = context.ErrorDescription, ErrorDescription = context.ErrorDescription,
ErrorUri = context.ErrorUri, ErrorUri = context.ErrorUri,
@ -116,10 +121,7 @@ public sealed class OpenIddictClientAspNetCoreHandler : AuthenticationHandler<Au
var context = transaction.GetProperty<ProcessAuthenticationContext>(typeof(ProcessAuthenticationContext).FullName!); var context = transaction.GetProperty<ProcessAuthenticationContext>(typeof(ProcessAuthenticationContext).FullName!);
if (context is null) if (context is null)
{ {
await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction) await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction));
{
CancellationToken = Context.RequestAborted
});
// Store the context object in the transaction so it can be later retrieved by handlers // 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. // that want to access the authentication result without triggering a new authentication flow.
@ -377,7 +379,6 @@ public sealed class OpenIddictClientAspNetCoreHandler : AuthenticationHandler<Au
var context = new ProcessChallengeContext(transaction) var context = new ProcessChallengeContext(transaction)
{ {
CancellationToken = Context.RequestAborted,
Principal = new ClaimsPrincipal(new ClaimsIdentity()), Principal = new ClaimsPrincipal(new ClaimsIdentity()),
Request = new OpenIddictRequest() Request = new OpenIddictRequest()
}; };
@ -393,7 +394,6 @@ public sealed class OpenIddictClientAspNetCoreHandler : AuthenticationHandler<Au
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
CancellationToken = Context.RequestAborted,
Error = context.Error ?? Errors.InvalidRequest, Error = context.Error ?? Errors.InvalidRequest,
ErrorDescription = context.ErrorDescription, ErrorDescription = context.ErrorDescription,
ErrorUri = context.ErrorUri, ErrorUri = context.ErrorUri,
@ -423,7 +423,6 @@ public sealed class OpenIddictClientAspNetCoreHandler : AuthenticationHandler<Au
var context = new ProcessSignOutContext(transaction) var context = new ProcessSignOutContext(transaction)
{ {
CancellationToken = Context.RequestAborted,
Principal = new ClaimsPrincipal(new ClaimsIdentity()), Principal = new ClaimsPrincipal(new ClaimsIdentity()),
Request = new OpenIddictRequest() Request = new OpenIddictRequest()
}; };
@ -441,7 +440,6 @@ public sealed class OpenIddictClientAspNetCoreHandler : AuthenticationHandler<Au
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
CancellationToken = Context.RequestAborted,
Error = context.Error ?? Errors.InvalidRequest, Error = context.Error ?? Errors.InvalidRequest,
ErrorDescription = context.ErrorDescription, ErrorDescription = context.ErrorDescription,
ErrorUri = context.ErrorUri, ErrorUri = context.ErrorUri,

28
src/OpenIddict.Client.Owin/OpenIddictClientOwinHandler.cs

@ -46,13 +46,23 @@ public sealed class OpenIddictClientOwinHandler : AuthenticationHandler<Authenti
/// <inheritdoc/> /// <inheritdoc/>
protected override async Task InitializeCoreAsync() 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 // 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). // (e.g when using a status code pages middleware re-invoking the OWIN pipeline).
var transaction = Context.Get<OpenIddictClientTransaction>(typeof(OpenIddictClientTransaction).FullName); var transaction = Context.Get<OpenIddictClientTransaction>(typeof(OpenIddictClientTransaction).FullName);
if (transaction is null) if (transaction is null)
{ {
// Create a new transaction and attach the OWIN request to make it available to the OWIN handlers. // 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<IOwinRequest>(Request); transaction.Properties[typeof(IOwinRequest).FullName!] = new WeakReference<IOwinRequest>(Request);
// Attach the OpenIddict client transaction to the OWIN shared dictionary // Attach the OpenIddict client transaction to the OWIN shared dictionary
@ -60,11 +70,7 @@ public sealed class OpenIddictClientOwinHandler : AuthenticationHandler<Authenti
Context.Set(typeof(OpenIddictClientTransaction).FullName, transaction); Context.Set(typeof(OpenIddictClientTransaction).FullName, transaction);
} }
var context = new ProcessRequestContext(transaction) var context = new ProcessRequestContext(transaction);
{
CancellationToken = Request.CallCancelled
};
await _dispatcher.DispatchAsync(context); await _dispatcher.DispatchAsync(context);
// Store the context in the transaction so that it can be retrieved from InvokeAsync(). // Store the context in the transaction so that it can be retrieved from InvokeAsync().
@ -98,7 +104,6 @@ public sealed class OpenIddictClientOwinHandler : AuthenticationHandler<Authenti
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
CancellationToken = Request.CallCancelled,
Error = context.Error ?? Errors.InvalidRequest, Error = context.Error ?? Errors.InvalidRequest,
ErrorDescription = context.ErrorDescription, ErrorDescription = context.ErrorDescription,
ErrorUri = context.ErrorUri, ErrorUri = context.ErrorUri,
@ -135,10 +140,7 @@ public sealed class OpenIddictClientOwinHandler : AuthenticationHandler<Authenti
var context = transaction.GetProperty<ProcessAuthenticationContext>(typeof(ProcessAuthenticationContext).FullName!); var context = transaction.GetProperty<ProcessAuthenticationContext>(typeof(ProcessAuthenticationContext).FullName!);
if (context is null) if (context is null)
{ {
await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction) await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction));
{
CancellationToken = Request.CallCancelled
});
// Store the context object in the transaction so it can be later retrieved by handlers // 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. // that want to access the authentication result without triggering a new authentication flow.
@ -302,7 +304,6 @@ public sealed class OpenIddictClientOwinHandler : AuthenticationHandler<Authenti
var context = new ProcessChallengeContext(transaction) var context = new ProcessChallengeContext(transaction)
{ {
CancellationToken = Request.CallCancelled,
Principal = new ClaimsPrincipal(new ClaimsIdentity()), Principal = new ClaimsPrincipal(new ClaimsIdentity()),
Request = new OpenIddictRequest() Request = new OpenIddictRequest()
}; };
@ -318,7 +319,6 @@ public sealed class OpenIddictClientOwinHandler : AuthenticationHandler<Authenti
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
CancellationToken = Request.CallCancelled,
Error = context.Error ?? Errors.InvalidRequest, Error = context.Error ?? Errors.InvalidRequest,
ErrorDescription = context.ErrorDescription, ErrorDescription = context.ErrorDescription,
ErrorUri = context.ErrorUri, ErrorUri = context.ErrorUri,
@ -348,7 +348,6 @@ public sealed class OpenIddictClientOwinHandler : AuthenticationHandler<Authenti
var context = new ProcessSignOutContext(transaction) var context = new ProcessSignOutContext(transaction)
{ {
CancellationToken = Request.CallCancelled,
Principal = new ClaimsPrincipal(new ClaimsIdentity()), Principal = new ClaimsPrincipal(new ClaimsIdentity()),
Request = new OpenIddictRequest() Request = new OpenIddictRequest()
}; };
@ -364,7 +363,6 @@ public sealed class OpenIddictClientOwinHandler : AuthenticationHandler<Authenti
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
CancellationToken = Request.CallCancelled,
Error = context.Error ?? Errors.InvalidRequest, Error = context.Error ?? Errors.InvalidRequest,
ErrorDescription = context.ErrorDescription, ErrorDescription = context.ErrorDescription,
ErrorUri = context.ErrorUri, ErrorUri = context.ErrorUri,

4
src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Authentication.cs

@ -646,8 +646,8 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
_ => "Authentication failed. Please return to the application." _ => "Authentication failed. Please return to the application."
}); });
await response.OutputStream.WriteAsync(buffer); await response.OutputStream.WriteAsync(buffer.AsMemory(), context.CancellationToken);
await response.OutputStream.FlushAsync(); await response.OutputStream.FlushAsync(context.CancellationToken);
context.HandleRequest(); context.HandleRequest();
} }

4
src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Session.cs

@ -646,8 +646,8 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
_ => "Logout failed. Please return to the application." _ => "Logout failed. Please return to the application."
}); });
await response.OutputStream.WriteAsync(buffer); await response.OutputStream.WriteAsync(buffer.AsMemory(), context.CancellationToken);
await response.OutputStream.FlushAsync(); await response.OutputStream.FlushAsync(context.CancellationToken);
context.HandleRequest(); context.HandleRequest();
} }

2
src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs

@ -457,7 +457,7 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
context.Transaction.Request = new OpenIddictRequest(await OpenIddictHelpers.ParseFormAsync( context.Transaction.Request = new OpenIddictRequest(await OpenIddictHelpers.ParseFormAsync(
stream : request.InputStream, stream : request.InputStream,
encoding : GetEncoding(type) is { CodePage: not 65000 } encoding ? encoding : Encoding.UTF8, encoding : GetEncoding(type) is { CodePage: not 65000 } encoding ? encoding : Encoding.UTF8,
cancellationToken: CancellationToken.None)); cancellationToken: context.CancellationToken));
} }
else else

9
src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationService.cs

@ -147,21 +147,16 @@ public sealed class OpenIddictClientSystemIntegrationService
// Create a client transaction and store the specified instance so // Create a client transaction and store the specified instance so
// it can be retrieved by the event handlers that need to access it. // 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); transaction.SetProperty(typeof(TProperty).FullName!, property);
var context = new ProcessRequestContext(transaction) var context = new ProcessRequestContext(transaction);
{
CancellationToken = cancellationToken
};
await dispatcher.DispatchAsync(context); await dispatcher.DispatchAsync(context);
if (context.IsRejected) if (context.IsRejected)
{ {
await dispatcher.DispatchAsync(new ProcessErrorContext(transaction) await dispatcher.DispatchAsync(new ProcessErrorContext(transaction)
{ {
CancellationToken = cancellationToken,
Error = context.Error ?? Errors.InvalidRequest, Error = context.Error ?? Errors.InvalidRequest,
ErrorDescription = context.ErrorDescription, ErrorDescription = context.ErrorDescription,
ErrorUri = context.ErrorUri, ErrorUri = context.ErrorUri,

2
src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Userinfo.cs

@ -127,7 +127,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
MediaTypes.JsonWebToken, StringComparison.OrdinalIgnoreCase)) MediaTypes.JsonWebToken, StringComparison.OrdinalIgnoreCase))
{ {
context.Response = new OpenIddictResponse(); context.Response = new OpenIddictResponse();
context.UserInfoToken = await response.Content.ReadAsStringAsync(); context.UserInfoToken = await response.Content.ReadAsStringAsync(context.CancellationToken);
return; return;
} }

14
src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs

@ -611,7 +611,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
else if (string.Equals(encoding, ContentEncodings.Gzip, StringComparison.OrdinalIgnoreCase)) 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); 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. // For more information, read https://www.rfc-editor.org/rfc/rfc9110.html#name-deflate-coding.
else if (string.Equals(encoding, ContentEncodings.Deflate, StringComparison.OrdinalIgnoreCase)) 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); stream = new ZLibStream(stream, CompressionMode.Decompress);
} }
else if (string.Equals(encoding, ContentEncodings.Brotli, StringComparison.OrdinalIgnoreCase)) 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); stream = new BrotliStream(stream, CompressionMode.Decompress);
} }
#endif #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 // (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). // during a second pass a second time for logging/debuggability purposes).
var content = new StreamContent(stream); var content = new StreamContent(stream);
await content.LoadIntoBufferAsync(); await content.LoadIntoBufferAsync(context.CancellationToken);
// Copy the headers from the original content to the new instance. // Copy the headers from the original content to the new instance.
foreach (var header in response.Content.Headers) foreach (var header in response.Content.Headers)
@ -728,7 +728,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception)) catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{ {
context.Logger.LogError(6183, exception, SR.GetResourceString(SR.ID6183), context.Logger.LogError(6183, exception, SR.GetResourceString(SR.ID6183),
await response.Content.ReadAsStringAsync()); await response.Content.ReadAsStringAsync(context.CancellationToken));
context.Reject( context.Reject(
error: Errors.ServerError, error: Errors.ServerError,
@ -949,7 +949,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
if (!response.IsSuccessStatusCode && string.IsNullOrEmpty(context.Transaction.Response?.Error)) if (!response.IsSuccessStatusCode && string.IsNullOrEmpty(context.Transaction.Response?.Error))
{ {
context.Logger.LogError(6184, SR.GetResourceString(SR.ID6184), response.StatusCode, context.Logger.LogError(6184, SR.GetResourceString(SR.ID6184), response.StatusCode,
await response.Content.ReadAsStringAsync()); await response.Content.ReadAsStringAsync(context.CancellationToken));
context.Reject( context.Reject(
error: (int) response.StatusCode switch error: (int) response.StatusCode switch
@ -973,7 +973,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
if (context.Transaction.Response is null) if (context.Transaction.Response is null)
{ {
context.Logger.LogError(6185, SR.GetResourceString(SR.ID6185), response.StatusCode, 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( context.Reject(
error: Errors.ServerError, error: Errors.ServerError,

6
src/OpenIddict.Client/IOpenIddictClientFactory.cs

@ -18,9 +18,13 @@ public interface IOpenIddictClientFactory
/// Creates a new <see cref="OpenIddictClientTransaction"/> that is used as a /// Creates a new <see cref="OpenIddictClientTransaction"/> that is used as a
/// way to store per-request data needed to process the requested operation. /// way to store per-request data needed to process the requested operation.
/// </summary> /// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <remarks>
/// Note: the specified <see cref="CancellationToken"/> is automatically attached to the returned transaction.
/// </remarks>
/// <returns> /// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous /// A <see cref="ValueTask"/> that can be used to monitor the asynchronous
/// operation, whose result returns the created transaction. /// operation, whose result returns the created transaction.
/// </returns> /// </returns>
ValueTask<OpenIddictClientTransaction> CreateTransactionAsync(); ValueTask<OpenIddictClientTransaction> CreateTransactionAsync(CancellationToken cancellationToken);
} }

16
src/OpenIddict.Client/OpenIddictClientConfiguration.cs

@ -88,8 +88,8 @@ public sealed class OpenIddictClientConfiguration : IPostConfigureOptions<OpenId
// Implicitly add the redirect_uri attached to the client registrations // Implicitly add the redirect_uri attached to the client registrations
// to the list of redirection endpoints URIs if they haven't been added. // to the list of redirection endpoints URIs if they haven't been added.
options.RedirectionEndpointUris.AddRange(options.Registrations options.RedirectionEndpointUris.AddRange(options.Registrations
.Where(registration => registration.RedirectUri is not null) .Where(static registration => registration.RedirectUri is not null)
.Select(registration => registration.RedirectUri!) .Select(static registration => registration.RedirectUri!)
.Where(uri => !options.RedirectionEndpointUris.Contains(uri)) .Where(uri => !options.RedirectionEndpointUris.Contains(uri))
.Distinct() .Distinct()
.ToList()); .ToList());
@ -97,8 +97,8 @@ public sealed class OpenIddictClientConfiguration : IPostConfigureOptions<OpenId
// Implicitly add the post_logout_redirect_uri attached to the client registrations // Implicitly add the post_logout_redirect_uri attached to the client registrations
// to the list of post-logout redirection endpoints URIs if they haven't been added. // to the list of post-logout redirection endpoints URIs if they haven't been added.
options.PostLogoutRedirectionEndpointUris.AddRange(options.Registrations options.PostLogoutRedirectionEndpointUris.AddRange(options.Registrations
.Where(registration => registration.PostLogoutRedirectUri is not null) .Where(static registration => registration.PostLogoutRedirectUri is not null)
.Select(registration => registration.PostLogoutRedirectUri!) .Select(static registration => registration.PostLogoutRedirectUri!)
.Where(uri => !options.PostLogoutRedirectionEndpointUris.Contains(uri)) .Where(uri => !options.PostLogoutRedirectionEndpointUris.Contains(uri))
.Distinct() .Distinct()
.ToList()); .ToList());
@ -113,9 +113,9 @@ public sealed class OpenIddictClientConfiguration : IPostConfigureOptions<OpenId
options.SigningCredentials.Sort((left, right) => Compare(left.Key, right.Key, now)); options.SigningCredentials.Sort((left, right) => Compare(left.Key, right.Key, now));
// Generate a key identifier for the encryption/signing keys that don't already have one. // 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) foreach (var key in options.EncryptionCredentials.Select(static credentials => credentials.Key)
.Concat(options.SigningCredentials.Select(credentials => credentials.Key)) .Concat(options.SigningCredentials.Select(static credentials => credentials.Key))
.Where(key => string.IsNullOrEmpty(key.KeyId))) .Where(static key => string.IsNullOrEmpty(key.KeyId)))
{ {
key.KeyId = GetKeyIdentifier(key); key.KeyId = GetKeyIdentifier(key);
} }
@ -354,7 +354,7 @@ public sealed class OpenIddictClientConfiguration : IPostConfigureOptions<OpenId
// //
// Note: a string comparer ignoring casing is deliberately used to prevent two // Note: a string comparer ignoring casing is deliberately used to prevent two
// registrations using the same identifier with a different casing from being added. // registrations using the same identifier with a different casing from being added.
if (options.Registrations.Count != options.Registrations.Select(registration => registration.RegistrationId) if (options.Registrations.Count != options.Registrations.Select(static registration => registration.RegistrationId)
.Distinct(StringComparer.OrdinalIgnoreCase) .Distinct(StringComparer.OrdinalIgnoreCase)
.Count()) .Count())
{ {

2
src/OpenIddict.Client/OpenIddictClientDispatcher.cs

@ -40,6 +40,8 @@ public sealed class OpenIddictClientDispatcher : IOpenIddictClientDispatcher
await foreach (var handler in GetHandlersAsync()) await foreach (var handler in GetHandlersAsync())
{ {
context.CancellationToken.ThrowIfCancellationRequested();
try try
{ {
await handler.HandleAsync(context); await handler.HandleAsync(context);

14
src/OpenIddict.Client/OpenIddictClientEvents.cs

@ -32,19 +32,9 @@ public static partial class OpenIddictClientEvents
public OpenIddictClientTransaction Transaction { get; } public OpenIddictClientTransaction Transaction { get; }
/// <summary> /// <summary>
/// Gets or sets the cancellation token that will be /// Gets the cancellation token used to determine if the operation was aborted.
/// used to determine if the operation was aborted.
/// </summary> /// </summary>
/// <remarks> public CancellationToken CancellationToken => Transaction.CancellationToken;
/// 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.
/// </remarks>
public CancellationToken CancellationToken
{
get => Transaction.CancellationToken;
set => Transaction.CancellationToken = value;
}
/// <summary> /// <summary>
/// Gets or sets the endpoint type that handled the request, if applicable. /// Gets or sets the endpoint type that handled the request, if applicable.

12
src/OpenIddict.Client/OpenIddictClientFactory.cs

@ -31,10 +31,18 @@ public sealed class OpenIddictClientFactory : IOpenIddictClientFactory
} }
/// <inheritdoc/> /// <inheritdoc/>
public ValueTask<OpenIddictClientTransaction> CreateTransactionAsync() public ValueTask<OpenIddictClientTransaction> CreateTransactionAsync(CancellationToken cancellationToken)
=> new(new OpenIddictClientTransaction {
if (cancellationToken.IsCancellationRequested)
{
return new(Task.FromCanceled<OpenIddictClientTransaction>(cancellationToken));
}
return new(new OpenIddictClientTransaction
{ {
CancellationToken = cancellationToken,
Logger = _logger, Logger = _logger,
Options = _options.CurrentValue Options = _options.CurrentValue
}); });
}
} }

40
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. // 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) if (token is null)
{ {
return; return;
@ -284,8 +284,8 @@ public static partial class OpenIddictClientHandlers
if (!(context.ValidTokenTypes.Count switch if (!(context.ValidTokenTypes.Count switch
{ {
0 => true, // If no specific token type is expected, accept all token types at this stage. 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)), 1 => await _tokenManager.HasTypeAsync(token, context.ValidTokenTypes.ElementAt(0), context.CancellationToken),
_ => await _tokenManager.HasTypeAsync(token, [.. context.ValidTokenTypes]) _ => await _tokenManager.HasTypeAsync(token, [.. context.ValidTokenTypes], context.CancellationToken)
})) }))
{ {
context.Reject( context.Reject(
@ -296,7 +296,7 @@ public static partial class OpenIddictClientHandlers
return; return;
} }
var payload = await _tokenManager.GetPayloadAsync(token); var payload = await _tokenManager.GetPayloadAsync(token, context.CancellationToken);
if (string.IsNullOrEmpty(payload)) if (string.IsNullOrEmpty(payload))
{ {
throw new InvalidOperationException(SR.GetResourceString(SR.ID0026)); 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. // used to restore the properties associated with the token.
context.IsReferenceToken = true; context.IsReferenceToken = true;
context.Token = payload; 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. // 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) if (token is null)
{ {
context.Reject( 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 // 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, // 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. // 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( context.Reject(
error: Errors.InvalidToken, error: Errors.InvalidToken,
@ -603,10 +603,10 @@ public static partial class OpenIddictClientHandlers
// Restore the creation/expiration dates/identifiers from the token entry metadata. // Restore the creation/expiration dates/identifiers from the token entry metadata.
context.Principal context.Principal
.SetCreationDate(await _tokenManager.GetCreationDateAsync(token)) .SetCreationDate(await _tokenManager.GetCreationDateAsync(token, context.CancellationToken))
.SetExpirationDate(await _tokenManager.GetExpirationDateAsync(token)) .SetExpirationDate(await _tokenManager.GetExpirationDateAsync(token, context.CancellationToken))
.SetTokenId(context.TokenId = await _tokenManager.GetIdAsync(token)) .SetTokenId(context.TokenId = await _tokenManager.GetIdAsync(token, context.CancellationToken))
.SetTokenType(await _tokenManager.GetTypeAsync(token)); .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(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
Debug.Assert(!string.IsNullOrEmpty(context.TokenId), SR.GetResourceString(SR.ID4017)); 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)); ?? 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); context.Logger.LogInformation(6002, SR.GetResourceString(SR.ID6002), context.TokenId);
@ -876,7 +876,7 @@ public static partial class OpenIddictClientHandlers
return; 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); 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. // 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)); ?? 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. // Attach the token identifier to the principal so that it can be stored in the token.
context.Principal.SetTokenId(identifier); context.Principal.SetTokenId(identifier);
@ -1172,11 +1172,11 @@ public static partial class OpenIddictClientHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0009)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0021));
var descriptor = new OpenIddictTokenDescriptor(); var descriptor = new OpenIddictTokenDescriptor();
await _tokenManager.PopulateAsync(descriptor, token); await _tokenManager.PopulateAsync(descriptor, token, context.CancellationToken);
// Attach the generated token to the token entry. // Attach the generated token to the token entry.
descriptor.Payload = context.Token; descriptor.Payload = context.Token;
@ -1187,7 +1187,7 @@ public static partial class OpenIddictClientHandlers
descriptor.ReferenceId = Base64Url.EncodeToString(RandomNumberGenerator.GetBytes(count: 256 / 8)); 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); context.Logger.LogTrace(6014, SR.GetResourceString(SR.ID6014), context.Token, identifier, context.TokenType);

8
src/OpenIddict.Client/OpenIddictClientHandlers.cs

@ -7,7 +7,9 @@
using System.Collections.Immutable; using System.Collections.Immutable;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Buffers.Text;
using System.Security.Claims; using System.Security.Claims;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
@ -18,8 +20,6 @@ using Microsoft.Extensions.Primitives;
using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using static OpenIddict.Abstractions.OpenIddictExceptions; using static OpenIddict.Abstractions.OpenIddictExceptions;
using System.Runtime.CompilerServices;
using System.Buffers.Text;
#if !NET #if !NET
using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto.Digests;
@ -857,8 +857,8 @@ public static partial class OpenIddictClientHandlers
} }
// Mark the token as redeemed to prevent future reuses. // Mark the token as redeemed to prevent future reuses.
var token = await _tokenManager.FindByIdAsync(identifier); var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken);
if (token is not null && !await _tokenManager.TryRedeemAsync(token)) if (token is not null && !await _tokenManager.TryRedeemAsync(token, context.CancellationToken))
{ {
context.Reject( context.Reject(
error: Errors.InvalidToken, error: Errors.InvalidToken,

84
src/OpenIddict.Client/OpenIddictClientService.cs

@ -266,11 +266,10 @@ public class OpenIddictClientService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(request.CancellationToken);
var context = new ProcessAuthenticationContext(transaction) var context = new ProcessAuthenticationContext(transaction)
{ {
CancellationToken = request.CancellationToken,
Nonce = request.Nonce, Nonce = request.Nonce,
Request = new(), Request = new(),
TokenEndpointClientCertificate = request.TokenBindingCertificate, TokenEndpointClientCertificate = request.TokenBindingCertificate,
@ -340,11 +339,10 @@ public class OpenIddictClientService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(request.CancellationToken);
var context = new ProcessChallengeContext(transaction) var context = new ProcessChallengeContext(transaction)
{ {
CancellationToken = request.CancellationToken,
CodeChallengeMethod = request.CodeChallengeMethod, CodeChallengeMethod = request.CodeChallengeMethod,
GrantType = request.GrantType, GrantType = request.GrantType,
IdentityTokenHint = request.IdentityTokenHint, IdentityTokenHint = request.IdentityTokenHint,
@ -422,11 +420,10 @@ public class OpenIddictClientService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(request.CancellationToken);
var context = new ProcessAuthenticationContext(transaction) var context = new ProcessAuthenticationContext(transaction)
{ {
CancellationToken = request.CancellationToken,
GrantType = GrantTypes.ClientCredentials, GrantType = GrantTypes.ClientCredentials,
Issuer = request.Issuer, Issuer = request.Issuer,
ProviderName = request.ProviderName, ProviderName = request.ProviderName,
@ -513,11 +510,10 @@ public class OpenIddictClientService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(request.CancellationToken);
var context = new ProcessAuthenticationContext(transaction) var context = new ProcessAuthenticationContext(transaction)
{ {
CancellationToken = request.CancellationToken,
DisableUserInfoRetrieval = request.DisableUserInfo, DisableUserInfoRetrieval = request.DisableUserInfo,
DisableUserInfoValidation = request.DisableUserInfo, DisableUserInfoValidation = request.DisableUserInfo,
GrantType = request.GrantType, GrantType = request.GrantType,
@ -607,11 +603,10 @@ public class OpenIddictClientService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(request.CancellationToken);
var context = new ProcessAuthenticationContext(transaction) var context = new ProcessAuthenticationContext(transaction)
{ {
CancellationToken = source.Token,
DeviceCode = request.DeviceCode, DeviceCode = request.DeviceCode,
DisableUserInfoRetrieval = request.DisableUserInfo, DisableUserInfoRetrieval = request.DisableUserInfo,
DisableUserInfoValidation = request.DisableUserInfo, DisableUserInfoValidation = request.DisableUserInfo,
@ -714,11 +709,10 @@ public class OpenIddictClientService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(request.CancellationToken);
var context = new ProcessChallengeContext(transaction) var context = new ProcessChallengeContext(transaction)
{ {
CancellationToken = request.CancellationToken,
DeviceAuthorizationRequest = request.AdditionalDeviceAuthorizationRequestParameters DeviceAuthorizationRequest = request.AdditionalDeviceAuthorizationRequestParameters
is Dictionary<string, OpenIddictParameter> parameters ? new(parameters) : new(), is Dictionary<string, OpenIddictParameter> parameters ? new(parameters) : new(),
GrantType = GrantTypes.DeviceCode, GrantType = GrantTypes.DeviceCode,
@ -793,11 +787,10 @@ public class OpenIddictClientService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(request.CancellationToken);
var context = new ProcessAuthenticationContext(transaction) var context = new ProcessAuthenticationContext(transaction)
{ {
CancellationToken = request.CancellationToken,
DisableUserInfoRetrieval = request.DisableUserInfo, DisableUserInfoRetrieval = request.DisableUserInfo,
DisableUserInfoValidation = request.DisableUserInfo, DisableUserInfoValidation = request.DisableUserInfo,
GrantType = GrantTypes.Password, GrantType = GrantTypes.Password,
@ -881,13 +874,12 @@ public class OpenIddictClientService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(request.CancellationToken);
var context = new ProcessAuthenticationContext(transaction) var context = new ProcessAuthenticationContext(transaction)
{ {
ActorToken = request.ActorToken, ActorToken = request.ActorToken,
ActorTokenType = request.ActorTokenType, ActorTokenType = request.ActorTokenType,
CancellationToken = request.CancellationToken,
DisableUserInfoRetrieval = request.DisableUserInfo, DisableUserInfoRetrieval = request.DisableUserInfo,
DisableUserInfoValidation = request.DisableUserInfo, DisableUserInfoValidation = request.DisableUserInfo,
GrantType = GrantTypes.TokenExchange, GrantType = GrantTypes.TokenExchange,
@ -969,11 +961,10 @@ public class OpenIddictClientService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(request.CancellationToken);
var context = new ProcessAuthenticationContext(transaction) var context = new ProcessAuthenticationContext(transaction)
{ {
CancellationToken = request.CancellationToken,
DisableUserInfoRetrieval = request.DisableUserInfo, DisableUserInfoRetrieval = request.DisableUserInfo,
DisableUserInfoValidation = request.DisableUserInfo, DisableUserInfoValidation = request.DisableUserInfo,
GrantType = GrantTypes.RefreshToken, GrantType = GrantTypes.RefreshToken,
@ -1055,11 +1046,10 @@ public class OpenIddictClientService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(request.CancellationToken);
var context = new ProcessIntrospectionContext(transaction) var context = new ProcessIntrospectionContext(transaction)
{ {
CancellationToken = request.CancellationToken,
IntrospectionRequest = request.AdditionalIntrospectionRequestParameters IntrospectionRequest = request.AdditionalIntrospectionRequestParameters
is Dictionary<string, OpenIddictParameter> parameters ? new(parameters) : new(), is Dictionary<string, OpenIddictParameter> parameters ? new(parameters) : new(),
Issuer = request.Issuer, Issuer = request.Issuer,
@ -1115,11 +1105,10 @@ public class OpenIddictClientService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(request.CancellationToken);
var context = new ProcessRevocationContext(transaction) var context = new ProcessRevocationContext(transaction)
{ {
CancellationToken = request.CancellationToken,
Issuer = request.Issuer, Issuer = request.Issuer,
ProviderName = request.ProviderName, ProviderName = request.ProviderName,
RegistrationId = request.RegistrationId, RegistrationId = request.RegistrationId,
@ -1183,7 +1172,7 @@ public class OpenIddictClientService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(cancellationToken);
var request = new OpenIddictRequest(); var request = new OpenIddictRequest();
request = await PrepareConfigurationRequestAsync(); request = await PrepareConfigurationRequestAsync();
@ -1197,7 +1186,6 @@ public class OpenIddictClientService
{ {
var context = new PrepareConfigurationRequestContext(transaction) var context = new PrepareConfigurationRequestContext(transaction)
{ {
CancellationToken = cancellationToken,
RemoteUri = uri, RemoteUri = uri,
Registration = registration, Registration = registration,
Request = request Request = request
@ -1219,7 +1207,6 @@ public class OpenIddictClientService
{ {
var context = new ApplyConfigurationRequestContext(transaction) var context = new ApplyConfigurationRequestContext(transaction)
{ {
CancellationToken = cancellationToken,
RemoteUri = uri, RemoteUri = uri,
Registration = registration, Registration = registration,
Request = request Request = request
@ -1243,7 +1230,6 @@ public class OpenIddictClientService
{ {
var context = new ExtractConfigurationResponseContext(transaction) var context = new ExtractConfigurationResponseContext(transaction)
{ {
CancellationToken = cancellationToken,
RemoteUri = uri, RemoteUri = uri,
Registration = registration, Registration = registration,
Request = request Request = request
@ -1269,7 +1255,6 @@ public class OpenIddictClientService
{ {
var context = new HandleConfigurationResponseContext(transaction) var context = new HandleConfigurationResponseContext(transaction)
{ {
CancellationToken = cancellationToken,
RemoteUri = uri, RemoteUri = uri,
Registration = registration, Registration = registration,
Request = request, Request = request,
@ -1308,11 +1293,10 @@ public class OpenIddictClientService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(request.CancellationToken);
var context = new ProcessSignOutContext(transaction) var context = new ProcessSignOutContext(transaction)
{ {
CancellationToken = request.CancellationToken,
IdentityTokenHint = request.IdentityTokenHint, IdentityTokenHint = request.IdentityTokenHint,
Issuer = request.Issuer, Issuer = request.Issuer,
LoginHint = request.LoginHint, LoginHint = request.LoginHint,
@ -1379,7 +1363,7 @@ public class OpenIddictClientService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(cancellationToken);
var request = new OpenIddictRequest(); var request = new OpenIddictRequest();
request = await PrepareJsonWebKeySetRequestAsync(); request = await PrepareJsonWebKeySetRequestAsync();
@ -1394,7 +1378,6 @@ public class OpenIddictClientService
{ {
var context = new PrepareJsonWebKeySetRequestContext(transaction) var context = new PrepareJsonWebKeySetRequestContext(transaction)
{ {
CancellationToken = cancellationToken,
RemoteUri = uri, RemoteUri = uri,
Registration = registration, Registration = registration,
Request = request Request = request
@ -1416,7 +1399,6 @@ public class OpenIddictClientService
{ {
var context = new ApplyJsonWebKeySetRequestContext(transaction) var context = new ApplyJsonWebKeySetRequestContext(transaction)
{ {
CancellationToken = cancellationToken,
RemoteUri = uri, RemoteUri = uri,
Registration = registration, Registration = registration,
Request = request Request = request
@ -1440,7 +1422,6 @@ public class OpenIddictClientService
{ {
var context = new ExtractJsonWebKeySetResponseContext(transaction) var context = new ExtractJsonWebKeySetResponseContext(transaction)
{ {
CancellationToken = cancellationToken,
RemoteUri = uri, RemoteUri = uri,
Registration = registration, Registration = registration,
Request = request Request = request
@ -1466,7 +1447,6 @@ public class OpenIddictClientService
{ {
var context = new HandleJsonWebKeySetResponseContext(transaction) var context = new HandleJsonWebKeySetResponseContext(transaction)
{ {
CancellationToken = cancellationToken,
RemoteUri = uri, RemoteUri = uri,
Registration = registration, Registration = registration,
Request = request, Request = request,
@ -1521,7 +1501,7 @@ public class OpenIddictClientService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(cancellationToken);
request = await PrepareDeviceAuthorizationRequestAsync(); request = await PrepareDeviceAuthorizationRequestAsync();
request = await ApplyDeviceAuthorizationRequestAsync(); request = await ApplyDeviceAuthorizationRequestAsync();
@ -1534,7 +1514,6 @@ public class OpenIddictClientService
{ {
var context = new PrepareDeviceAuthorizationRequestContext(transaction) var context = new PrepareDeviceAuthorizationRequestContext(transaction)
{ {
CancellationToken = cancellationToken,
ClientAuthenticationMethod = method, ClientAuthenticationMethod = method,
Configuration = configuration, Configuration = configuration,
RemoteUri = uri, RemoteUri = uri,
@ -1559,7 +1538,6 @@ public class OpenIddictClientService
{ {
var context = new ApplyDeviceAuthorizationRequestContext(transaction) var context = new ApplyDeviceAuthorizationRequestContext(transaction)
{ {
CancellationToken = cancellationToken,
RemoteUri = uri, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
@ -1584,7 +1562,6 @@ public class OpenIddictClientService
{ {
var context = new ExtractDeviceAuthorizationResponseContext(transaction) var context = new ExtractDeviceAuthorizationResponseContext(transaction)
{ {
CancellationToken = cancellationToken,
RemoteUri = uri, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
@ -1611,7 +1588,6 @@ public class OpenIddictClientService
{ {
var context = new HandleDeviceAuthorizationResponseContext(transaction) var context = new HandleDeviceAuthorizationResponseContext(transaction)
{ {
CancellationToken = cancellationToken,
RemoteUri = uri, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
@ -1666,7 +1642,7 @@ public class OpenIddictClientService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(cancellationToken);
request = await PrepareIntrospectionRequestAsync(); request = await PrepareIntrospectionRequestAsync();
request = await ApplyIntrospectionRequestAsync(); request = await ApplyIntrospectionRequestAsync();
@ -1679,7 +1655,6 @@ public class OpenIddictClientService
{ {
var context = new PrepareIntrospectionRequestContext(transaction) var context = new PrepareIntrospectionRequestContext(transaction)
{ {
CancellationToken = cancellationToken,
ClientAuthenticationMethod = method, ClientAuthenticationMethod = method,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
@ -1704,7 +1679,6 @@ public class OpenIddictClientService
{ {
var context = new ApplyIntrospectionRequestContext(transaction) var context = new ApplyIntrospectionRequestContext(transaction)
{ {
CancellationToken = cancellationToken,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
RemoteUri = uri, RemoteUri = uri,
@ -1729,7 +1703,6 @@ public class OpenIddictClientService
{ {
var context = new ExtractIntrospectionResponseContext(transaction) var context = new ExtractIntrospectionResponseContext(transaction)
{ {
CancellationToken = cancellationToken,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
RemoteUri = uri, RemoteUri = uri,
@ -1756,7 +1729,6 @@ public class OpenIddictClientService
{ {
var context = new HandleIntrospectionResponseContext(transaction) var context = new HandleIntrospectionResponseContext(transaction)
{ {
CancellationToken = cancellationToken,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
RemoteUri = uri, RemoteUri = uri,
@ -1814,7 +1786,7 @@ public class OpenIddictClientService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(cancellationToken);
request = await PreparePushedAuthorizationRequestAsync(); request = await PreparePushedAuthorizationRequestAsync();
request = await ApplyPushedAuthorizationRequestAsync(); request = await ApplyPushedAuthorizationRequestAsync();
@ -1827,7 +1799,6 @@ public class OpenIddictClientService
{ {
var context = new PreparePushedAuthorizationRequestContext(transaction) var context = new PreparePushedAuthorizationRequestContext(transaction)
{ {
CancellationToken = cancellationToken,
ClientAuthenticationMethod = method, ClientAuthenticationMethod = method,
RemoteUri = uri, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
@ -1852,7 +1823,6 @@ public class OpenIddictClientService
{ {
var context = new ApplyPushedAuthorizationRequestContext(transaction) var context = new ApplyPushedAuthorizationRequestContext(transaction)
{ {
CancellationToken = cancellationToken,
RemoteUri = uri, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
@ -1877,7 +1847,6 @@ public class OpenIddictClientService
{ {
var context = new ExtractPushedAuthorizationResponseContext(transaction) var context = new ExtractPushedAuthorizationResponseContext(transaction)
{ {
CancellationToken = cancellationToken,
RemoteUri = uri, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
@ -1904,7 +1873,6 @@ public class OpenIddictClientService
{ {
var context = new HandlePushedAuthorizationResponseContext(transaction) var context = new HandlePushedAuthorizationResponseContext(transaction)
{ {
CancellationToken = cancellationToken,
RemoteUri = uri, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
@ -1959,7 +1927,7 @@ public class OpenIddictClientService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(cancellationToken);
request = await PrepareRevocationRequestAsync(); request = await PrepareRevocationRequestAsync();
request = await ApplyRevocationRequestAsync(); request = await ApplyRevocationRequestAsync();
@ -1972,7 +1940,6 @@ public class OpenIddictClientService
{ {
var context = new PrepareRevocationRequestContext(transaction) var context = new PrepareRevocationRequestContext(transaction)
{ {
CancellationToken = cancellationToken,
ClientAuthenticationMethod = method, ClientAuthenticationMethod = method,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
@ -1997,7 +1964,6 @@ public class OpenIddictClientService
{ {
var context = new ApplyRevocationRequestContext(transaction) var context = new ApplyRevocationRequestContext(transaction)
{ {
CancellationToken = cancellationToken,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
RemoteUri = uri, RemoteUri = uri,
@ -2022,7 +1988,6 @@ public class OpenIddictClientService
{ {
var context = new ExtractRevocationResponseContext(transaction) var context = new ExtractRevocationResponseContext(transaction)
{ {
CancellationToken = cancellationToken,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
RemoteUri = uri, RemoteUri = uri,
@ -2049,7 +2014,6 @@ public class OpenIddictClientService
{ {
var context = new HandleRevocationResponseContext(transaction) var context = new HandleRevocationResponseContext(transaction)
{ {
CancellationToken = cancellationToken,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
RemoteUri = uri, RemoteUri = uri,
@ -2105,7 +2069,7 @@ public class OpenIddictClientService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(cancellationToken);
request = await PrepareTokenRequestAsync(); request = await PrepareTokenRequestAsync();
request = await ApplyTokenRequestAsync(); request = await ApplyTokenRequestAsync();
@ -2118,7 +2082,6 @@ public class OpenIddictClientService
{ {
var context = new PrepareTokenRequestContext(transaction) var context = new PrepareTokenRequestContext(transaction)
{ {
CancellationToken = cancellationToken,
ClientAuthenticationMethod = method, ClientAuthenticationMethod = method,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
@ -2143,7 +2106,6 @@ public class OpenIddictClientService
{ {
var context = new ApplyTokenRequestContext(transaction) var context = new ApplyTokenRequestContext(transaction)
{ {
CancellationToken = cancellationToken,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
RemoteUri = uri, RemoteUri = uri,
@ -2169,7 +2131,6 @@ public class OpenIddictClientService
{ {
var context = new ExtractTokenResponseContext(transaction) var context = new ExtractTokenResponseContext(transaction)
{ {
CancellationToken = cancellationToken,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
RemoteUri = uri, RemoteUri = uri,
@ -2197,7 +2158,6 @@ public class OpenIddictClientService
{ {
var context = new HandleTokenResponseContext(transaction) var context = new HandleTokenResponseContext(transaction)
{ {
CancellationToken = cancellationToken,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
RemoteUri = uri, RemoteUri = uri,
@ -2252,7 +2212,7 @@ public class OpenIddictClientService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictClientDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictClientFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(cancellationToken);
request = await PrepareUserInfoRequestAsync(); request = await PrepareUserInfoRequestAsync();
request = await ApplyUserInfoRequestAsync(); request = await ApplyUserInfoRequestAsync();
@ -2265,7 +2225,6 @@ public class OpenIddictClientService
{ {
var context = new PrepareUserInfoRequestContext(transaction) var context = new PrepareUserInfoRequestContext(transaction)
{ {
CancellationToken = cancellationToken,
Configuration = configuration, Configuration = configuration,
RemoteUri = uri, RemoteUri = uri,
Registration = registration, Registration = registration,
@ -2289,7 +2248,6 @@ public class OpenIddictClientService
{ {
var context = new ApplyUserInfoRequestContext(transaction) var context = new ApplyUserInfoRequestContext(transaction)
{ {
CancellationToken = cancellationToken,
Configuration = configuration, Configuration = configuration,
RemoteUri = uri, RemoteUri = uri,
Registration = registration, Registration = registration,
@ -2314,7 +2272,6 @@ public class OpenIddictClientService
{ {
var context = new ExtractUserInfoResponseContext(transaction) var context = new ExtractUserInfoResponseContext(transaction)
{ {
CancellationToken = cancellationToken,
Configuration = configuration, Configuration = configuration,
RemoteUri = uri, RemoteUri = uri,
Registration = registration, Registration = registration,
@ -2341,7 +2298,6 @@ public class OpenIddictClientService
{ {
var context = new HandleUserInfoResponseContext(transaction) var context = new HandleUserInfoResponseContext(transaction)
{ {
CancellationToken = cancellationToken,
Configuration = configuration, Configuration = configuration,
Registration = registration, Registration = registration,
RemoteUri = uri, RemoteUri = uri,

8
src/OpenIddict.Client/OpenIddictClientTransaction.cs

@ -16,14 +16,8 @@ namespace OpenIddict.Client;
public sealed class OpenIddictClientTransaction public sealed class OpenIddictClientTransaction
{ {
/// <summary> /// <summary>
/// Gets or sets the cancellation token that will be /// Gets or sets the cancellation token used to determine if the operation was aborted.
/// used to determine if the operation was aborted.
/// </summary> /// </summary>
/// <remarks>
/// 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.
/// </remarks>
public CancellationToken CancellationToken { get; set; } public CancellationToken CancellationToken { get; set; }
/// <summary> /// <summary>

29
src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandler.cs

@ -44,13 +44,23 @@ public sealed class OpenIddictServerAspNetCoreHandler : AuthenticationHandler<Au
/// <inheritdoc/> /// <inheritdoc/>
public async Task<bool> HandleRequestAsync() public async Task<bool> 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 // 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). // (e.g when using the built-in status code pages middleware with the re-execute mode).
var transaction = Context.Features.Get<OpenIddictServerAspNetCoreFeature>()?.Transaction; var transaction = Context.Features.Get<OpenIddictServerAspNetCoreFeature>()?.Transaction;
if (transaction is null) if (transaction is null)
{ {
// Create a new transaction and attach the HTTP request to make it available to the ASP.NET Core handlers. // 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<HttpRequest>(Request); transaction.Properties[typeof(HttpRequest).FullName!] = new WeakReference<HttpRequest>(Request);
// Attach the OpenIddict server transaction to the ASP.NET Core features // Attach the OpenIddict server transaction to the ASP.NET Core features
@ -58,11 +68,7 @@ public sealed class OpenIddictServerAspNetCoreHandler : AuthenticationHandler<Au
Context.Features.Set(new OpenIddictServerAspNetCoreFeature { Transaction = transaction }); Context.Features.Set(new OpenIddictServerAspNetCoreFeature { Transaction = transaction });
} }
var context = new ProcessRequestContext(transaction) var context = new ProcessRequestContext(transaction);
{
CancellationToken = Context.RequestAborted
};
await _dispatcher.DispatchAsync(context); await _dispatcher.DispatchAsync(context);
if (context.IsRequestHandled) if (context.IsRequestHandled)
@ -79,7 +85,6 @@ public sealed class OpenIddictServerAspNetCoreHandler : AuthenticationHandler<Au
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
CancellationToken = Context.RequestAborted,
Error = context.Error ?? Errors.InvalidRequest, Error = context.Error ?? Errors.InvalidRequest,
ErrorDescription = context.ErrorDescription, ErrorDescription = context.ErrorDescription,
ErrorUri = context.ErrorUri, ErrorUri = context.ErrorUri,
@ -116,10 +121,7 @@ public sealed class OpenIddictServerAspNetCoreHandler : AuthenticationHandler<Au
var context = transaction.GetProperty<ProcessAuthenticationContext>(typeof(ProcessAuthenticationContext).FullName!); var context = transaction.GetProperty<ProcessAuthenticationContext>(typeof(ProcessAuthenticationContext).FullName!);
if (context is null) if (context is null)
{ {
await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction) await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction));
{
CancellationToken = Context.RequestAborted
});
// Store the context object in the transaction so it can be later retrieved by handlers // 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. // that want to access the authentication result without triggering a new authentication flow.
@ -393,7 +395,6 @@ public sealed class OpenIddictServerAspNetCoreHandler : AuthenticationHandler<Au
var context = new ProcessChallengeContext(transaction) var context = new ProcessChallengeContext(transaction)
{ {
CancellationToken = Context.RequestAborted,
Response = new OpenIddictResponse() Response = new OpenIddictResponse()
}; };
@ -408,7 +409,6 @@ public sealed class OpenIddictServerAspNetCoreHandler : AuthenticationHandler<Au
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
CancellationToken = Context.RequestAborted,
Error = context.Error ?? Errors.InvalidRequest, Error = context.Error ?? Errors.InvalidRequest,
ErrorDescription = context.ErrorDescription, ErrorDescription = context.ErrorDescription,
ErrorUri = context.ErrorUri, ErrorUri = context.ErrorUri,
@ -442,7 +442,6 @@ public sealed class OpenIddictServerAspNetCoreHandler : AuthenticationHandler<Au
var context = new ProcessSignInContext(transaction) var context = new ProcessSignInContext(transaction)
{ {
CancellationToken = Context.RequestAborted,
Principal = user, Principal = user,
Response = new OpenIddictResponse() Response = new OpenIddictResponse()
}; };
@ -483,7 +482,6 @@ public sealed class OpenIddictServerAspNetCoreHandler : AuthenticationHandler<Au
var context = new ProcessSignOutContext(transaction) var context = new ProcessSignOutContext(transaction)
{ {
CancellationToken = Context.RequestAborted,
Response = new OpenIddictResponse() Response = new OpenIddictResponse()
}; };
@ -500,7 +498,6 @@ public sealed class OpenIddictServerAspNetCoreHandler : AuthenticationHandler<Au
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
CancellationToken = Context.RequestAborted,
Error = context.Error ?? Errors.InvalidRequest, Error = context.Error ?? Errors.InvalidRequest,
ErrorDescription = context.ErrorDescription, ErrorDescription = context.ErrorDescription,
ErrorUri = context.ErrorUri, ErrorUri = context.ErrorUri,

2
src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.cs

@ -705,7 +705,7 @@ public static partial class OpenIddictServerAspNetCoreHandlers
// If a client certificate was used during the TLS handshake, attach it to the context. // If a client certificate was used during the TLS handshake, attach it to the context.
if (request.IsHttps && await request.HttpContext.Connection.GetClientCertificateAsync( if (request.IsHttps && await request.HttpContext.Connection.GetClientCertificateAsync(
request.HttpContext.RequestAborted) is X509Certificate2 certificate) context.CancellationToken) is X509Certificate2 certificate)
{ {
context.Transaction.RemoteCertificate = certificate; context.Transaction.RemoteCertificate = certificate;
} }

30
src/OpenIddict.Server.Owin/OpenIddictServerOwinHandler.cs

@ -37,13 +37,23 @@ public sealed class OpenIddictServerOwinHandler : AuthenticationHandler<Authenti
/// <inheritdoc/> /// <inheritdoc/>
protected override async Task InitializeCoreAsync() 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 // 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). // (e.g when using a status code pages middleware re-invoking the OWIN pipeline).
var transaction = Context.Get<OpenIddictServerTransaction>(typeof(OpenIddictServerTransaction).FullName); var transaction = Context.Get<OpenIddictServerTransaction>(typeof(OpenIddictServerTransaction).FullName);
if (transaction is null) if (transaction is null)
{ {
// Create a new transaction and attach the OWIN request to make it available to the OWIN handlers. // 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<IOwinRequest>(Request); transaction.Properties[typeof(IOwinRequest).FullName!] = new WeakReference<IOwinRequest>(Request);
// Attach the OpenIddict server transaction to the OWIN shared dictionary // Attach the OpenIddict server transaction to the OWIN shared dictionary
@ -51,11 +61,7 @@ public sealed class OpenIddictServerOwinHandler : AuthenticationHandler<Authenti
Context.Set(typeof(OpenIddictServerTransaction).FullName, transaction); Context.Set(typeof(OpenIddictServerTransaction).FullName, transaction);
} }
var context = new ProcessRequestContext(transaction) var context = new ProcessRequestContext(transaction);
{
CancellationToken = Request.CallCancelled
};
await _dispatcher.DispatchAsync(context); await _dispatcher.DispatchAsync(context);
// Store the context in the transaction so that it can be retrieved from InvokeAsync(). // Store the context in the transaction so that it can be retrieved from InvokeAsync().
@ -89,7 +95,6 @@ public sealed class OpenIddictServerOwinHandler : AuthenticationHandler<Authenti
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
CancellationToken = Request.CallCancelled,
Error = context.Error ?? Errors.InvalidRequest, Error = context.Error ?? Errors.InvalidRequest,
ErrorDescription = context.ErrorDescription, ErrorDescription = context.ErrorDescription,
ErrorUri = context.ErrorUri, ErrorUri = context.ErrorUri,
@ -126,10 +131,7 @@ public sealed class OpenIddictServerOwinHandler : AuthenticationHandler<Authenti
var context = transaction.GetProperty<ProcessAuthenticationContext>(typeof(ProcessAuthenticationContext).FullName!); var context = transaction.GetProperty<ProcessAuthenticationContext>(typeof(ProcessAuthenticationContext).FullName!);
if (context is null) if (context is null)
{ {
await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction) await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction));
{
CancellationToken = Request.CallCancelled
});
// Store the context object in the transaction so it can be later retrieved by handlers // 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. // that want to access the authentication result without triggering a new authentication flow.
@ -290,7 +292,6 @@ public sealed class OpenIddictServerOwinHandler : AuthenticationHandler<Authenti
var context = new ProcessChallengeContext(transaction) var context = new ProcessChallengeContext(transaction)
{ {
CancellationToken = Request.CallCancelled,
Response = new OpenIddictResponse() Response = new OpenIddictResponse()
}; };
@ -305,7 +306,6 @@ public sealed class OpenIddictServerOwinHandler : AuthenticationHandler<Authenti
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
CancellationToken = Request.CallCancelled,
Error = context.Error ?? Errors.InvalidRequest, Error = context.Error ?? Errors.InvalidRequest,
ErrorDescription = context.ErrorDescription, ErrorDescription = context.ErrorDescription,
ErrorUri = context.ErrorUri, ErrorUri = context.ErrorUri,
@ -333,7 +333,6 @@ public sealed class OpenIddictServerOwinHandler : AuthenticationHandler<Authenti
var context = new ProcessSignInContext(transaction) var context = new ProcessSignInContext(transaction)
{ {
CancellationToken = Request.CallCancelled,
Principal = signin.Principal, Principal = signin.Principal,
Response = new OpenIddictResponse() Response = new OpenIddictResponse()
}; };
@ -349,7 +348,6 @@ public sealed class OpenIddictServerOwinHandler : AuthenticationHandler<Authenti
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
CancellationToken = Request.CallCancelled,
Error = context.Error ?? Errors.InvalidRequest, Error = context.Error ?? Errors.InvalidRequest,
ErrorDescription = context.ErrorDescription, ErrorDescription = context.ErrorDescription,
ErrorUri = context.ErrorUri, ErrorUri = context.ErrorUri,
@ -377,7 +375,6 @@ public sealed class OpenIddictServerOwinHandler : AuthenticationHandler<Authenti
var context = new ProcessSignOutContext(transaction) var context = new ProcessSignOutContext(transaction)
{ {
CancellationToken = Request.CallCancelled,
Response = new OpenIddictResponse() Response = new OpenIddictResponse()
}; };
@ -392,7 +389,6 @@ public sealed class OpenIddictServerOwinHandler : AuthenticationHandler<Authenti
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
CancellationToken = Request.CallCancelled,
Error = context.Error ?? Errors.InvalidRequest, Error = context.Error ?? Errors.InvalidRequest,
ErrorDescription = context.ErrorDescription, ErrorDescription = context.ErrorDescription,
ErrorUri = context.ErrorUri, ErrorUri = context.ErrorUri,

8
src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.cs

@ -766,18 +766,20 @@ public static partial class OpenIddictServerOwinHandlers
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0120)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0120));
// If a client certificate was used during the TLS handshake, attach it to the context. // If a client certificate was used during the TLS handshake, attach it to the context.
if (request.IsSecure && await GetClientCertificateAsync(request.Context) is X509Certificate2 certificate) if (request.IsSecure && await GetClientCertificateAsync(request.Context,
context.CancellationToken) is X509Certificate2 certificate)
{ {
context.Transaction.RemoteCertificate = certificate; context.Transaction.RemoteCertificate = certificate;
} }
static async ValueTask<X509Certificate2?> GetClientCertificateAsync(IOwinContext context) static async ValueTask<X509Certificate2?> GetClientCertificateAsync(
IOwinContext context, CancellationToken cancellationToken)
{ {
// If a loading function was provided by the OWIN host, always invoke it before trying // 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. // to resolve the certificate to ensure it is present in the environment dictionary.
if (context.Get<Func<Task>>("ssl.LoadClientCertAsync") is Func<Task> loader) if (context.Get<Func<Task>>("ssl.LoadClientCertAsync") is Func<Task> loader)
{ {
await loader(); await loader().WaitAsync(cancellationToken);
} }
return context.Get<X509Certificate>("ssl.ClientCertificate") is X509Certificate certificate return context.Get<X509Certificate>("ssl.ClientCertificate") is X509Certificate certificate

6
src/OpenIddict.Server/IOpenIddictServerFactory.cs

@ -18,9 +18,13 @@ public interface IOpenIddictServerFactory
/// Creates a new <see cref="OpenIddictServerTransaction"/> that is used as a /// Creates a new <see cref="OpenIddictServerTransaction"/> that is used as a
/// way to store per-request data needed to process the requested operation. /// way to store per-request data needed to process the requested operation.
/// </summary> /// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <remarks>
/// Note: the specified <see cref="CancellationToken"/> is automatically attached to the returned transaction.
/// </remarks>
/// <returns> /// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous /// A <see cref="ValueTask"/> that can be used to monitor the asynchronous
/// operation, whose result returns the created transaction. /// operation, whose result returns the created transaction.
/// </returns> /// </returns>
ValueTask<OpenIddictServerTransaction> CreateTransactionAsync(); ValueTask<OpenIddictServerTransaction> CreateTransactionAsync(CancellationToken cancellationToken);
} }

6
src/OpenIddict.Server/OpenIddictServerConfiguration.cs

@ -77,9 +77,9 @@ public sealed class OpenIddictServerConfiguration : IPostConfigureOptions<OpenId
options.SigningCredentials.Sort((left, right) => Compare(left.Key, right.Key, now)); options.SigningCredentials.Sort((left, right) => Compare(left.Key, right.Key, now));
// Generate a key identifier for the encryption/signing keys that don't already have one. // 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) foreach (var key in options.EncryptionCredentials.Select(static credentials => credentials.Key)
.Concat(options.SigningCredentials.Select(credentials => credentials.Key)) .Concat(options.SigningCredentials.Select(static credentials => credentials.Key))
.Where(key => string.IsNullOrEmpty(key.KeyId))) .Where(static key => string.IsNullOrEmpty(key.KeyId)))
{ {
key.KeyId = GetKeyIdentifier(key); key.KeyId = GetKeyIdentifier(key);
} }

2
src/OpenIddict.Server/OpenIddictServerDispatcher.cs

@ -40,6 +40,8 @@ public sealed class OpenIddictServerDispatcher : IOpenIddictServerDispatcher
await foreach (var handler in GetHandlersAsync()) await foreach (var handler in GetHandlersAsync())
{ {
context.CancellationToken.ThrowIfCancellationRequested();
try try
{ {
await handler.HandleAsync(context); await handler.HandleAsync(context);

14
src/OpenIddict.Server/OpenIddictServerEvents.cs

@ -30,19 +30,9 @@ public static partial class OpenIddictServerEvents
public OpenIddictServerTransaction Transaction { get; } public OpenIddictServerTransaction Transaction { get; }
/// <summary> /// <summary>
/// Gets or sets the cancellation token that will be /// Gets the cancellation token used to determine if the operation was aborted.
/// used to determine if the operation was aborted.
/// </summary> /// </summary>
/// <remarks> public CancellationToken CancellationToken => Transaction.CancellationToken;
/// 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.
/// </remarks>
public CancellationToken CancellationToken
{
get => Transaction.CancellationToken;
set => Transaction.CancellationToken = value;
}
/// <summary> /// <summary>
/// Gets or sets the endpoint type that handled the request, if applicable. /// Gets or sets the endpoint type that handled the request, if applicable.

12
src/OpenIddict.Server/OpenIddictServerFactory.cs

@ -31,10 +31,18 @@ public sealed class OpenIddictServerFactory : IOpenIddictServerFactory
} }
/// <inheritdoc/> /// <inheritdoc/>
public ValueTask<OpenIddictServerTransaction> CreateTransactionAsync() public ValueTask<OpenIddictServerTransaction> CreateTransactionAsync(CancellationToken cancellationToken)
=> new(new OpenIddictServerTransaction {
if (cancellationToken.IsCancellationRequested)
{
return new(Task.FromCanceled<OpenIddictServerTransaction>(cancellationToken));
}
return new(new OpenIddictServerTransaction
{ {
CancellationToken = cancellationToken,
Logger = _logger, Logger = _logger,
Options = _options.CurrentValue Options = _options.CurrentValue
}); });
}
} }

104
src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs

@ -1396,14 +1396,14 @@ public static partial class OpenIddictServerHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
// To prevent downgrade attacks, ensure that authorization requests returning // To prevent downgrade attacks, ensure that authorization requests returning
// an access token directly from the authorization endpoint are rejected if // an access token directly from the authorization endpoint are rejected if
// the client_id corresponds to a confidential application. // the client_id corresponds to a confidential application.
if (context.Request.HasResponseType(ResponseTypes.Token) && 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); 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)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
// If no explicit redirect_uri was specified, retrieve the URI associated with the // 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. // client and ensure exactly one redirect_uri was attached to the client definition.
if (string.IsNullOrEmpty(context.RedirectUri)) 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) if (uris.Length is not 1)
{ {
context.Logger.LogInformation(6033, SR.GetResourceString(SR.ID6033), Parameters.RedirectUri); 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. // 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); 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)); 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)) if (!string.IsNullOrEmpty(name))
{ {
scopes.Remove(name); scopes.Remove(name);
@ -1615,9 +1615,9 @@ public static partial class OpenIddictServerHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); 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)) if (!string.IsNullOrEmpty(name))
{ {
resources.Remove(name); resources.Remove(name);
@ -1672,11 +1672,11 @@ public static partial class OpenIddictServerHandlers
Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
// Reject the request if the application is not allowed to use the authorization endpoint. // 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); 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)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
// Reject the request if the application is not allowed to use the authorization code grant. // Reject the request if the application is not allowed to use the authorization code grant.
if (context.Request.IsAuthorizationCodeFlow() && 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); 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. // Reject the request if the application is not allowed to use the implicit grant.
if (context.Request.IsImplicitFlow() && 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); 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. // Reject the request if the application is not allowed to use the authorization code/implicit grants.
if (context.Request.IsHybridFlow() && if (context.Request.IsHybridFlow() &&
(!await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.AuthorizationCode) || (!await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.AuthorizationCode, context.CancellationToken) ||
!await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.Implicit))) !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.Implicit, context.CancellationToken)))
{ {
context.Logger.LogInformation(6051, SR.GetResourceString(SR.ID6051), context.ClientId); 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 // Reject the request if the offline_access scope was request and
// if the application is not allowed to use the refresh token grant. // if the application is not allowed to use the refresh token grant.
if (context.Request.HasScope(Scopes.OfflineAccess) && 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); 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)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
// Reject requests that specify a response_type for which no permission was granted. // 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:". // Note: response type permissions are always prefixed with "rst:".
const string prefix = Permissions.Prefixes.ResponseType; 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. // Ignore permissions that are not response type permissions.
if (!permission.StartsWith(prefix, StringComparison.Ordinal)) 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)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
foreach (var scope in context.Request.GetScopes()) 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. // 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); 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)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
foreach (var resource in context.Request.GetResources()) foreach (var resource in context.Request.GetResources())
{ {
// Reject the request if the application is not allowed to use the iterated resource. // 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); context.Logger.LogInformation(6281, SR.GetResourceString(SR.ID6278), context.ClientId, resource);
@ -2014,10 +2014,10 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
var application = await _applicationManager.FindByClientIdAsync(context.ClientId) var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken)
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); ?? 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)) if (string.IsNullOrEmpty(context.Request.RequestUri))
{ {
@ -2080,10 +2080,10 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
var application = await _applicationManager.FindByClientIdAsync(context.ClientId) var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken)
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); ?? 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); 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)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
// To prevent downgrade attacks, ensure that pushed authorization requests returning // To prevent downgrade attacks, ensure that pushed authorization requests returning
// an access token directly from the authorization endpoint are rejected if // an access token directly from the authorization endpoint are rejected if
// the client_id corresponds to a confidential application. // the client_id corresponds to a confidential application.
if (context.Request.HasResponseType(ResponseTypes.Token) && 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); 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)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
// If no explicit redirect_uri was specified, retrieve the URI associated with the // 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. // client and ensure exactly one redirect_uri was attached to the client definition.
if (string.IsNullOrEmpty(context.RedirectUri)) 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) if (uris.Length is not 1)
{ {
context.Logger.LogInformation(6240, SR.GetResourceString(SR.ID6240), Parameters.RedirectUri); 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. // 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); 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)); 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)) if (!string.IsNullOrEmpty(name))
{ {
scopes.Remove(name); scopes.Remove(name);
@ -3702,9 +3702,9 @@ public static partial class OpenIddictServerHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); 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)) if (!string.IsNullOrEmpty(name))
{ {
resources.Remove(name); resources.Remove(name);
@ -3759,11 +3759,11 @@ public static partial class OpenIddictServerHandlers
Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
// Reject the request if the application is not allowed to use the pushed authorization endpoint. // 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); 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)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
// Reject the request if the application is not allowed to use the authorization code grant. // Reject the request if the application is not allowed to use the authorization code grant.
if (context.Request.IsAuthorizationCodeFlow() && 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); 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. // Reject the request if the application is not allowed to use the implicit grant.
if (context.Request.IsImplicitFlow() && 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); 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. // Reject the request if the application is not allowed to use the authorization code/implicit grants.
if (context.Request.IsHybridFlow() && if (context.Request.IsHybridFlow() &&
(!await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.AuthorizationCode) || (!await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.AuthorizationCode, context.CancellationToken) ||
!await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.Implicit))) !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.Implicit, context.CancellationToken)))
{ {
context.Logger.LogInformation(6257, SR.GetResourceString(SR.ID6257), context.ClientId); 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 // Reject the request if the offline_access scope was request and
// if the application is not allowed to use the refresh token grant. // if the application is not allowed to use the refresh token grant.
if (context.Request.HasScope(Scopes.OfflineAccess) && 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); 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)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
// Reject requests that specify a response_type for which no permission was granted. // 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:". // Note: response type permissions are always prefixed with "rst:".
const string prefix = Permissions.Prefixes.ResponseType; 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. // Ignore permissions that are not response type permissions.
if (!permission.StartsWith(prefix, StringComparison.Ordinal)) 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)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
foreach (var scope in context.Request.GetScopes()) 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. // 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); 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)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
foreach (var resource in context.Request.GetResources()) foreach (var resource in context.Request.GetResources())
{ {
// Reject the request if the application is not allowed to use the iterated resource. // 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); context.Logger.LogInformation(6283, SR.GetResourceString(SR.ID6279), context.ClientId, resource);
@ -4100,10 +4100,10 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
var application = await _applicationManager.FindByClientIdAsync(context.ClientId) var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken)
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); ?? 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); context.Logger.LogInformation(6240, SR.GetResourceString(SR.ID6240), Parameters.CodeChallenge);

20
src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs

@ -481,9 +481,9 @@ public static partial class OpenIddictServerHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); 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)) if (!string.IsNullOrEmpty(name))
{ {
scopes.Remove(name); scopes.Remove(name);
@ -595,14 +595,14 @@ public static partial class OpenIddictServerHandlers
Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
// Reject the request if the application is not allowed to use the device authorization endpoint. // 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. // Note: the legacy "ept:device" permission is still allowed for backward compatibility.
if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.DeviceAuthorization) && if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.DeviceAuthorization, context.CancellationToken) &&
!await _applicationManager.HasPermissionAsync(application, "ept:device")) !await _applicationManager.HasPermissionAsync(application, "ept:device", context.CancellationToken))
{ {
context.Logger.LogInformation(6062, SR.GetResourceString(SR.ID6062), context.ClientId); 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)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
// Reject the request if the application is not allowed to use the device code grant. // 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); 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 // Reject the request if the offline_access scope was request and
// if the application is not allowed to use the refresh token grant. // if the application is not allowed to use the refresh token grant.
if (context.Request.HasScope(Scopes.OfflineAccess) && 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); 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)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
foreach (var scope in context.Request.GetScopes()) 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. // 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); context.Logger.LogInformation(6063, SR.GetResourceString(SR.ID6063), context.ClientId, scope);

34
src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs

@ -1047,9 +1047,9 @@ public static partial class OpenIddictServerHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); 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)) if (!string.IsNullOrEmpty(name))
{ {
scopes.Remove(name); scopes.Remove(name);
@ -1163,9 +1163,9 @@ public static partial class OpenIddictServerHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); 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)) if (!string.IsNullOrEmpty(name))
{ {
resources.Remove(name); resources.Remove(name);
@ -1284,11 +1284,11 @@ public static partial class OpenIddictServerHandlers
Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
// Reject the request if the application is not allowed to use the token endpoint. // 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); 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)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
// Reject the request if the application is not allowed to use the specified grant type. // 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); 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 // Reject the request if the offline_access scope was request and if
// the application is not allowed to use the refresh token grant type. // the application is not allowed to use the refresh token grant type.
if (context.Request.HasScope(Scopes.OfflineAccess) && 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); 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)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
foreach (var scope in context.Request.GetScopes()) 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. // 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); 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)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
foreach (var audience in context.Request.GetAudiences()) foreach (var audience in context.Request.GetAudiences())
{ {
// Reject the request if the application is not allowed to use the iterated audience. // 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); 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)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
foreach (var resource in context.Request.GetResources()) foreach (var resource in context.Request.GetResources())
{ {
// Reject the request if the application is not allowed to use the iterated resource. // 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); 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)); 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)); ?? 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); context.Logger.LogInformation(6077, SR.GetResourceString(SR.ID6077), Parameters.CodeVerifier);

8
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)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
// Reject the request if the application is not allowed to use the introspection endpoint. // 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); context.Logger.LogInformation(6103, SR.GetResourceString(SR.ID6103), context.ClientId);
@ -816,11 +816,11 @@ public static partial class OpenIddictServerHandlers
return; 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
// Public clients are not allowed to access sensitive claims as authentication cannot be enforced. // 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); context.Logger.LogInformation(6107, SR.GetResourceString(SR.ID6107), context.Request.ClientId);

64
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. // 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. // Important: at this stage, the issuer isn't guaranteed to be valid or legitimate.
var application = await _applicationManager.FindByClientIdAsync(token.Issuer); var application = await _applicationManager.FindByClientIdAsync(token.Issuer, context.CancellationToken);
if (application is not null && await _applicationManager.GetJsonWebKeySetAsync(application) if (application is not null && await _applicationManager.GetJsonWebKeySetAsync(application, context.CancellationToken)
is JsonWebKeySet set) is JsonWebKeySet set)
{ {
return set.GetSigningKeys(); 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. // 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) if (token is null)
{ {
return; return;
@ -369,8 +369,8 @@ public static partial class OpenIddictServerHandlers
if (!(context.ValidTokenTypes.Count switch if (!(context.ValidTokenTypes.Count switch
{ {
0 => true, // If no specific token type is expected, accept all token types at this stage. 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)), 1 => await _tokenManager.HasTypeAsync(token, context.ValidTokenTypes.ElementAt(0), context.CancellationToken),
_ => await _tokenManager.HasTypeAsync(token, [.. context.ValidTokenTypes]) _ => await _tokenManager.HasTypeAsync(token, [.. context.ValidTokenTypes], context.CancellationToken)
})) }))
{ {
context.Reject( context.Reject(
@ -407,7 +407,7 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
var payload = await _tokenManager.GetPayloadAsync(token); var payload = await _tokenManager.GetPayloadAsync(token, context.CancellationToken);
if (string.IsNullOrEmpty(payload)) if (string.IsNullOrEmpty(payload))
{ {
throw new InvalidOperationException(SR.GetResourceString(SR.ID0026)); 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. // used to restore the properties associated with the token.
context.IsReferenceToken = true; context.IsReferenceToken = true;
context.Token = payload; 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. // 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) if (token is null)
{ {
context.Reject( 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 // 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, // 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. // 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( context.Reject(
error: Errors.InvalidToken, error: Errors.InvalidToken,
@ -855,11 +855,11 @@ public static partial class OpenIddictServerHandlers
// Restore the creation/expiration dates/identifiers from the token entry metadata. // Restore the creation/expiration dates/identifiers from the token entry metadata.
context.Principal context.Principal
.SetCreationDate(await _tokenManager.GetCreationDateAsync(token)) .SetCreationDate(await _tokenManager.GetCreationDateAsync(token, context.CancellationToken))
.SetExpirationDate(await _tokenManager.GetExpirationDateAsync(token)) .SetExpirationDate(await _tokenManager.GetExpirationDateAsync(token, context.CancellationToken))
.SetAuthorizationId(context.AuthorizationId = await _tokenManager.GetAuthorizationIdAsync(token)) .SetAuthorizationId(context.AuthorizationId = await _tokenManager.GetAuthorizationIdAsync(token, context.CancellationToken))
.SetTokenId(context.TokenId = await _tokenManager.GetIdAsync(token)) .SetTokenId(context.TokenId = await _tokenManager.GetIdAsync(token, context.CancellationToken))
.SetTokenType(await _tokenManager.GetTypeAsync(token)); .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(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
Debug.Assert(!string.IsNullOrEmpty(context.TokenId), SR.GetResourceString(SR.ID4017)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0021));
// If the token is already marked as redeemed, this may indicate that it was compromised. // 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. // 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. // 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. // 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)) if (!context.Principal.HasTokenType(TokenTypeIdentifiers.RefreshToken) || !await IsReusableAsync(token))
{ {
@ -1255,7 +1255,7 @@ public static partial class OpenIddictServerHandlers
try try
{ {
count = await _tokenManager.RevokeByAuthorizationIdAsync(context.AuthorizationId); count = await _tokenManager.RevokeByAuthorizationIdAsync(context.AuthorizationId, context.CancellationToken);
} }
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception)) 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 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); 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 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); context.Logger.LogInformation(6004, SR.GetResourceString(SR.ID6004), context.TokenId);
@ -1327,7 +1327,7 @@ public static partial class OpenIddictServerHandlers
return; 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); context.Logger.LogInformation(6005, SR.GetResourceString(SR.ID6005), context.TokenId);
@ -1367,7 +1367,7 @@ public static partial class OpenIddictServerHandlers
return false; return false;
} }
var date = await _tokenManager.GetRedemptionDateAsync(token); var date = await _tokenManager.GetRedemptionDateAsync(token, context.CancellationToken);
if (date is null || context.Options.TimeProvider.GetUtcNow() < if (date is null || context.Options.TimeProvider.GetUtcNow() <
date + context.Options.RefreshTokenReuseLeeway) 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(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
Debug.Assert(!string.IsNullOrEmpty(context.AuthorizationId), SR.GetResourceString(SR.ID4018)); Debug.Assert(!string.IsNullOrEmpty(context.AuthorizationId), SR.GetResourceString(SR.ID4018));
var authorization = await _authorizationManager.FindByIdAsync(context.AuthorizationId); var authorization = await _authorizationManager.FindByIdAsync(context.AuthorizationId, context.CancellationToken);
if (authorization is null || !await _authorizationManager.HasStatusAsync(authorization, Statuses.Valid)) if (authorization is null || !await _authorizationManager.HasStatusAsync(authorization, Statuses.Valid, context.CancellationToken))
{ {
context.Logger.LogInformation(6006, SR.GetResourceString(SR.ID6006), context.AuthorizationId); 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 the client application is known, associate it with the token.
if (!string.IsNullOrEmpty(context.ClientId)) 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)); ?? 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)); ?? 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. // Attach the token identifier to the principal so that it can be stored in the token payload.
context.Principal.SetTokenId(identifier); context.Principal.SetTokenId(identifier);
@ -1815,11 +1815,11 @@ public static partial class OpenIddictServerHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0009)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0021));
var descriptor = new OpenIddictTokenDescriptor(); var descriptor = new OpenIddictTokenDescriptor();
await _tokenManager.PopulateAsync(descriptor, token); await _tokenManager.PopulateAsync(descriptor, token, context.CancellationToken);
// Attach the generated token to the token entry. // Attach the generated token to the token entry.
descriptor.Payload = context.Token; 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 // 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. // 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 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); context.Logger.LogTrace(6014, SR.GetResourceString(SR.ID6014), context.Token, identifier, context.TokenType);

8
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)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
// Reject the request if the application is not allowed to use the revocation endpoint. // 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); context.Logger.LogInformation(6116, SR.GetResourceString(SR.ID6116), context.ClientId);
@ -671,7 +671,7 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
var token = await _tokenManager.FindByIdAsync(identifier); var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken);
if (token is null) if (token is null)
{ {
context.Logger.LogInformation(6123, SR.GetResourceString(SR.ID6123), identifier); 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. // 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( context.Reject(
error: Errors.UnsupportedTokenType, error: Errors.UnsupportedTokenType,

36
src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs

@ -599,10 +599,10 @@ public static partial class OpenIddictServerHandlers
if (!string.IsNullOrEmpty(context.ClientId)) 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)); ?? 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); 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 // 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. // 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. // Note: the legacy "ept:logout" permission is still allowed for backward compatibility.
if (!context.Options.IgnoreEndpointPermissions && if (!context.Options.IgnoreEndpointPermissions &&
!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.EndSession) && !await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.EndSession, context.CancellationToken) &&
!await _applicationManager.HasPermissionAsync(application, "ept:logout")) !await _applicationManager.HasPermissionAsync(application, "ept:logout", context.CancellationToken))
{ {
continue; continue;
} }
if (await _applicationManager.ValidatePostLogoutRedirectUriAsync(application, uri)) if (await _applicationManager.ValidatePostLogoutRedirectUriAsync(application, uri, context.CancellationToken))
{ {
return true; return true;
} }
@ -667,18 +667,18 @@ public static partial class OpenIddictServerHandlers
string.Equals(value.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase))) string.Equals(value.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase)))
{ {
await foreach (var application in _applicationManager.FindByPostLogoutRedirectUriAsync( 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. // Note: the legacy "ept:logout" permission is still allowed for backward compatibility.
if (!context.Options.IgnoreEndpointPermissions && if (!context.Options.IgnoreEndpointPermissions &&
!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.EndSession) && !await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.EndSession, context.CancellationToken) &&
!await _applicationManager.HasPermissionAsync(application, "ept:logout")) !await _applicationManager.HasPermissionAsync(application, "ept:logout", context.CancellationToken))
{ {
continue; continue;
} }
if (await _applicationManager.HasApplicationTypeAsync(application, ApplicationTypes.Native) && if (await _applicationManager.HasApplicationTypeAsync(application, ApplicationTypes.Native, context.CancellationToken) &&
await _applicationManager.ValidatePostLogoutRedirectUriAsync(application, uri)) await _applicationManager.ValidatePostLogoutRedirectUriAsync(application, uri, context.CancellationToken))
{ {
return true; return true;
} }
@ -729,14 +729,14 @@ public static partial class OpenIddictServerHandlers
Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
// Reject the request if the application is not allowed to use the end session endpoint. // 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. // Note: the legacy "ept:logout" permission is still allowed for backward compatibility.
if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.EndSession) && if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.EndSession, context.CancellationToken) &&
!await _applicationManager.HasPermissionAsync(application, "ept:logout")) !await _applicationManager.HasPermissionAsync(application, "ept:logout", context.CancellationToken))
{ {
context.Logger.LogInformation(6048, SR.GetResourceString(SR.ID6048), context.ClientId); context.Logger.LogInformation(6048, SR.GetResourceString(SR.ID6048), context.ClientId);
@ -858,7 +858,7 @@ public static partial class OpenIddictServerHandlers
foreach (var identifier in identifiers) foreach (var identifier in identifiers)
{ {
var application = await _applicationManager.FindByClientIdAsync(identifier); var application = await _applicationManager.FindByClientIdAsync(identifier, context.CancellationToken);
if (application is null) if (application is null)
{ {
continue; continue;
@ -866,13 +866,13 @@ public static partial class OpenIddictServerHandlers
// Note: the legacy "ept:logout" permission is still allowed for backward compatibility. // Note: the legacy "ept:logout" permission is still allowed for backward compatibility.
if (!context.Options.IgnoreEndpointPermissions && if (!context.Options.IgnoreEndpointPermissions &&
!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.EndSession) && !await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.EndSession, context.CancellationToken) &&
!await _applicationManager.HasPermissionAsync(application, "ept:logout")) !await _applicationManager.HasPermissionAsync(application, "ept:logout", context.CancellationToken))
{ {
continue; continue;
} }
if (await _applicationManager.ValidatePostLogoutRedirectUriAsync(application, uri)) if (await _applicationManager.ValidatePostLogoutRedirectUriAsync(application, uri, context.CancellationToken))
{ {
return true; return true;
} }

98
src/OpenIddict.Server/OpenIddictServerHandlers.cs

@ -1046,7 +1046,7 @@ public static partial class OpenIddictServerHandlers
// Retrieve the application details corresponding to the requested client_id. // 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. // 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) if (application is null)
{ {
context.Logger.LogInformation(6221, SR.GetResourceString(SR.ID6221), context.ClientId); context.Logger.LogInformation(6221, SR.GetResourceString(SR.ID6221), context.ClientId);
@ -1113,10 +1113,10 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
var application = await _applicationManager.FindByClientIdAsync(context.ClientId) var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken)
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); ?? 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. // Reject grant_type=client_credentials token requests if the application is a public client.
if (context.EndpointType is OpenIddictServerEndpointType.Token && if (context.EndpointType is OpenIddictServerEndpointType.Token &&
@ -1224,16 +1224,16 @@ public static partial class OpenIddictServerHandlers
return; return;
} }
var application = await _applicationManager.FindByClientIdAsync(context.ClientId) var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken)
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
// If the application is a public client, don't validate the client secret. // 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; 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); 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)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032));
// Note: to avoid building and introspecting a X.509 certificate chain and reduce the cost // 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( 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); 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 // 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 // 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). // 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. // Always clone the X.509 chain policy to ensure the original instance is never mutated.
policy = policy.Clone(); policy = policy.Clone();
@ -1455,7 +1455,7 @@ public static partial class OpenIddictServerHandlers
} }
if (!await _applicationManager.ValidateSelfSignedTlsClientCertificateAsync( 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); context.Logger.LogInformation(6283, SR.GetResourceString(SR.ID6283), context.ClientId);
@ -1481,9 +1481,9 @@ public static partial class OpenIddictServerHandlers
} }
if (await _applicationManager.GetPublicKeyInfrastructureTlsClientAuthenticationPolicyAsync( 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( !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); 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)); 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) 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)); 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) 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; return;
} }
var token = await _tokenManager.FindByIdAsync(identifier); var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken);
if (token is null) if (token is null)
{ {
return; 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). // 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()) 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( context.Reject(
error: Errors.InvalidToken, error: Errors.InvalidToken,
@ -3483,16 +3483,16 @@ public static partial class OpenIddictServerHandlers
// If the client application is known, associate it to the authorization. // If the client application is known, associate it to the authorization.
if (!string.IsNullOrEmpty(context.Request.ClientId)) 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)); ?? 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)); ?? 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)) if (string.IsNullOrEmpty(context.Request.ClientId))
{ {
@ -3610,10 +3610,10 @@ public static partial class OpenIddictServerHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); 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)); ?? 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) && if (settings.TryGetValue(Settings.TokenLifetimes.AccessToken, out string? setting) &&
TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value))
{ {
@ -3744,10 +3744,10 @@ public static partial class OpenIddictServerHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); 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)); ?? 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) && if (settings.TryGetValue(Settings.TokenLifetimes.AuthorizationCode, out string? setting) &&
TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value))
{ {
@ -3868,10 +3868,10 @@ public static partial class OpenIddictServerHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); 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)); ?? 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) && if (settings.TryGetValue(Settings.TokenLifetimes.DeviceCode, out string? setting) &&
TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value))
{ {
@ -4084,7 +4084,7 @@ public static partial class OpenIddictServerHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017));
var name = context.IssuedTokenType switch var name = context.IssuedTokenType switch
@ -4096,7 +4096,7 @@ public static partial class OpenIddictServerHandlers
_ => Settings.TokenLifetimes.IssuedToken _ => Settings.TokenLifetimes.IssuedToken
}; };
var settings = await _applicationManager.GetSettingsAsync(application); var settings = await _applicationManager.GetSettingsAsync(application, context.CancellationToken);
if (settings.TryGetValue(name, out string? setting) && if (settings.TryGetValue(name, out string? setting) &&
TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value))
{ {
@ -4178,7 +4178,7 @@ public static partial class OpenIddictServerHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017));
// Note: refresh tokens are only bound to the provided certificate when the client // 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 // are already sender-constrained via standard client authentication, which is more
// flexible than certificate-based token binding, as rotating client credentials is // flexible than certificate-based token binding, as rotating client credentials is
// easier in that case (specially when using PKI-based mTLS client authentication). // 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)); principal.SetClaim(Claims.Confirmation, CreateConfirmationClaim(certificate));
} }
@ -4274,10 +4274,10 @@ public static partial class OpenIddictServerHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); 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)); ?? 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) && if (settings.TryGetValue(Settings.TokenLifetimes.RequestToken, out string? setting) &&
TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value))
{ {
@ -4419,10 +4419,10 @@ public static partial class OpenIddictServerHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); 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)); ?? 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) && if (settings.TryGetValue(Settings.TokenLifetimes.RefreshToken, out string? setting) &&
TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value))
{ {
@ -4472,7 +4472,7 @@ public static partial class OpenIddictServerHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017));
// Note: refresh tokens are only bound to the provided certificate when the client // 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 // are already sender-constrained via standard client authentication, which is more
// flexible than certificate-based token binding, as rotating client credentials is // flexible than certificate-based token binding, as rotating client credentials is
// easier in that case (specially when using PKI-based mTLS client authentication). // 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)); principal.SetClaim(Claims.Confirmation, CreateConfirmationClaim(certificate));
} }
@ -4594,10 +4594,10 @@ public static partial class OpenIddictServerHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); 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)); ?? 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) && if (settings.TryGetValue(Settings.TokenLifetimes.IdentityToken, out string? setting) &&
TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value))
{ {
@ -4718,10 +4718,10 @@ public static partial class OpenIddictServerHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); 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)); ?? 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) && if (settings.TryGetValue(Settings.TokenLifetimes.UserCode, out string? setting) &&
TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value))
{ {
@ -5255,13 +5255,13 @@ public static partial class OpenIddictServerHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0008)); 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)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0265));
// Replace the device code details by the payload derived from the new device code principal, // 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. // that includes all the user claims populated by the application after authenticating the user.
var descriptor = new OpenIddictTokenDescriptor(); 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. // Note: the lifetime is deliberately extended to give more time to the client to redeem the code.
descriptor.ExpirationDate = context.DeviceCodePrincipal.GetExpirationDate(); descriptor.ExpirationDate = context.DeviceCodePrincipal.GetExpirationDate();
@ -5270,9 +5270,9 @@ public static partial class OpenIddictServerHandlers
descriptor.Status = Statuses.Valid; descriptor.Status = Statuses.Valid;
descriptor.Subject = context.DeviceCodePrincipal.GetClaim(Claims.Subject); 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; return;
} }
var token = await _tokenManager.FindByIdAsync(identifier); var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken);
if (token is null) if (token is null)
{ {
return; return;
} }
// Mark the token as redeemed to prevent future reuses. // Mark the token as redeemed to prevent future reuses.
await _tokenManager.TryRedeemAsync(token); await _tokenManager.TryRedeemAsync(token, context.CancellationToken);
} }
} }

8
src/OpenIddict.Server/OpenIddictServerTransaction.cs

@ -17,14 +17,8 @@ namespace OpenIddict.Server;
public sealed class OpenIddictServerTransaction public sealed class OpenIddictServerTransaction
{ {
/// <summary> /// <summary>
/// Gets or sets the cancellation token that will be /// Gets or sets the cancellation token used to determine if the operation was aborted.
/// used to determine if the operation was aborted.
/// </summary> /// </summary>
/// <remarks>
/// 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.
/// </remarks>
public CancellationToken CancellationToken { get; set; } public CancellationToken CancellationToken { get; set; }
/// <summary> /// <summary>

26
src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandler.cs

@ -42,13 +42,23 @@ public sealed class OpenIddictValidationAspNetCoreHandler : AuthenticationHandle
/// <inheritdoc/> /// <inheritdoc/>
public async Task<bool> HandleRequestAsync() public async Task<bool> 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 // 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). // (e.g when using the built-in status code pages middleware with the re-execute mode).
var transaction = Context.Features.Get<OpenIddictValidationAspNetCoreFeature>()?.Transaction; var transaction = Context.Features.Get<OpenIddictValidationAspNetCoreFeature>()?.Transaction;
if (transaction is null) if (transaction is null)
{ {
// Create a new transaction and attach the HTTP request to make it available to the ASP.NET Core handlers. // 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<HttpRequest>(Request); transaction.Properties[typeof(HttpRequest).FullName!] = new WeakReference<HttpRequest>(Request);
// Attach the OpenIddict validation transaction to the ASP.NET Core features // 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 }); Context.Features.Set(new OpenIddictValidationAspNetCoreFeature { Transaction = transaction });
} }
var context = new ProcessRequestContext(transaction) var context = new ProcessRequestContext(transaction);
{
CancellationToken = Context.RequestAborted
};
await _dispatcher.DispatchAsync(context); await _dispatcher.DispatchAsync(context);
if (context.IsRequestHandled) if (context.IsRequestHandled)
@ -77,7 +83,6 @@ public sealed class OpenIddictValidationAspNetCoreHandler : AuthenticationHandle
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
CancellationToken = Context.RequestAborted,
Error = context.Error ?? Errors.InvalidRequest, Error = context.Error ?? Errors.InvalidRequest,
ErrorDescription = context.ErrorDescription, ErrorDescription = context.ErrorDescription,
ErrorUri = context.ErrorUri, ErrorUri = context.ErrorUri,
@ -114,10 +119,7 @@ public sealed class OpenIddictValidationAspNetCoreHandler : AuthenticationHandle
var context = transaction.GetProperty<ProcessAuthenticationContext>(typeof(ProcessAuthenticationContext).FullName!); var context = transaction.GetProperty<ProcessAuthenticationContext>(typeof(ProcessAuthenticationContext).FullName!);
if (context is null) if (context is null)
{ {
await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction) await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction));
{
CancellationToken = Context.RequestAborted
});
// Store the context object in the transaction so it can be later retrieved by handlers // 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. // 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) var context = new ProcessChallengeContext(transaction)
{ {
CancellationToken = Context.RequestAborted,
Response = new OpenIddictResponse() Response = new OpenIddictResponse()
}; };
@ -229,7 +230,6 @@ public sealed class OpenIddictValidationAspNetCoreHandler : AuthenticationHandle
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
CancellationToken = Context.RequestAborted,
Error = context.Error ?? Errors.InvalidRequest, Error = context.Error ?? Errors.InvalidRequest,
ErrorDescription = context.ErrorDescription, ErrorDescription = context.ErrorDescription,
ErrorUri = context.ErrorUri, ErrorUri = context.ErrorUri,

2
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 a client certificate was used during the TLS handshake, attach it to the context.
if (request.IsHttps && await request.HttpContext.Connection.GetClientCertificateAsync( if (request.IsHttps && await request.HttpContext.Connection.GetClientCertificateAsync(
request.HttpContext.RequestAborted) is X509Certificate2 certificate) context.CancellationToken) is X509Certificate2 certificate)
{ {
context.Transaction.RemoteCertificate = certificate; context.Transaction.RemoteCertificate = certificate;
} }

26
src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandler.cs

@ -37,13 +37,23 @@ public sealed class OpenIddictValidationOwinHandler : AuthenticationHandler<Auth
/// <inheritdoc/> /// <inheritdoc/>
protected override async Task InitializeCoreAsync() 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 // 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). // (e.g when using a status code pages middleware re-invoking the OWIN pipeline).
var transaction = Context.Get<OpenIddictValidationTransaction>(typeof(OpenIddictValidationTransaction).FullName); var transaction = Context.Get<OpenIddictValidationTransaction>(typeof(OpenIddictValidationTransaction).FullName);
if (transaction is null) if (transaction is null)
{ {
// Create a new transaction and attach the OWIN request to make it available to the OWIN handlers. // 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<IOwinRequest>(Request); transaction.Properties[typeof(IOwinRequest).FullName!] = new WeakReference<IOwinRequest>(Request);
// Attach the OpenIddict validation transaction to the OWIN shared dictionary // Attach the OpenIddict validation transaction to the OWIN shared dictionary
@ -51,11 +61,7 @@ public sealed class OpenIddictValidationOwinHandler : AuthenticationHandler<Auth
Context.Set(typeof(OpenIddictValidationTransaction).FullName, transaction); Context.Set(typeof(OpenIddictValidationTransaction).FullName, transaction);
} }
var context = new ProcessRequestContext(transaction) var context = new ProcessRequestContext(transaction);
{
CancellationToken = Request.CallCancelled
};
await _dispatcher.DispatchAsync(context); await _dispatcher.DispatchAsync(context);
// Store the context in the transaction so that it can be retrieved from InvokeAsync(). // Store the context in the transaction so that it can be retrieved from InvokeAsync().
@ -89,7 +95,6 @@ public sealed class OpenIddictValidationOwinHandler : AuthenticationHandler<Auth
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
CancellationToken = Request.CallCancelled,
Error = context.Error ?? Errors.InvalidRequest, Error = context.Error ?? Errors.InvalidRequest,
ErrorDescription = context.ErrorDescription, ErrorDescription = context.ErrorDescription,
ErrorUri = context.ErrorUri, ErrorUri = context.ErrorUri,
@ -126,10 +131,7 @@ public sealed class OpenIddictValidationOwinHandler : AuthenticationHandler<Auth
var context = transaction.GetProperty<ProcessAuthenticationContext>(typeof(ProcessAuthenticationContext).FullName!); var context = transaction.GetProperty<ProcessAuthenticationContext>(typeof(ProcessAuthenticationContext).FullName!);
if (context is null) if (context is null)
{ {
await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction) await _dispatcher.DispatchAsync(context = new ProcessAuthenticationContext(transaction));
{
CancellationToken = Request.CallCancelled
});
// Store the context object in the transaction so it can be later retrieved by handlers // 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. // that want to access the authentication result without triggering a new authentication flow.
@ -222,7 +224,6 @@ public sealed class OpenIddictValidationOwinHandler : AuthenticationHandler<Auth
var context = new ProcessChallengeContext(transaction) var context = new ProcessChallengeContext(transaction)
{ {
CancellationToken = Request.CallCancelled,
Response = new OpenIddictResponse() Response = new OpenIddictResponse()
}; };
@ -237,7 +238,6 @@ public sealed class OpenIddictValidationOwinHandler : AuthenticationHandler<Auth
{ {
var notification = new ProcessErrorContext(transaction) var notification = new ProcessErrorContext(transaction)
{ {
CancellationToken = Request.CallCancelled,
Error = context.Error ?? Errors.InvalidRequest, Error = context.Error ?? Errors.InvalidRequest,
ErrorDescription = context.ErrorDescription, ErrorDescription = context.ErrorDescription,
ErrorUri = context.ErrorUri, ErrorUri = context.ErrorUri,

8
src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandlers.cs

@ -334,18 +334,20 @@ public static partial class OpenIddictValidationOwinHandlers
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0120)); ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0120));
// If a client certificate was used during the TLS handshake, attach it to the context. // If a client certificate was used during the TLS handshake, attach it to the context.
if (request.IsSecure && await GetClientCertificateAsync(request.Context) is X509Certificate2 certificate) if (request.IsSecure && await GetClientCertificateAsync(request.Context,
context.CancellationToken) is X509Certificate2 certificate)
{ {
context.Transaction.RemoteCertificate = certificate; context.Transaction.RemoteCertificate = certificate;
} }
static async ValueTask<X509Certificate2?> GetClientCertificateAsync(IOwinContext context) static async ValueTask<X509Certificate2?> GetClientCertificateAsync(
IOwinContext context, CancellationToken cancellationToken)
{ {
// If a loading function was provided by the OWIN host, always invoke it before trying // 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. // to resolve the certificate to ensure it is present in the environment dictionary.
if (context.Get<Func<Task>>("ssl.LoadClientCertAsync") is Func<Task> loader) if (context.Get<Func<Task>>("ssl.LoadClientCertAsync") is Func<Task> loader)
{ {
await loader(); await loader().WaitAsync(cancellationToken);
} }
return context.Get<X509Certificate>("ssl.ClientCertificate") is X509Certificate certificate return context.Get<X509Certificate>("ssl.ClientCertificate") is X509Certificate certificate

14
src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs

@ -607,7 +607,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
else if (string.Equals(encoding, ContentEncodings.Gzip, StringComparison.OrdinalIgnoreCase)) 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); 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. // For more information, read https://www.rfc-editor.org/rfc/rfc9110.html#name-deflate-coding.
else if (string.Equals(encoding, ContentEncodings.Deflate, StringComparison.OrdinalIgnoreCase)) 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); stream = new ZLibStream(stream, CompressionMode.Decompress);
} }
else if (string.Equals(encoding, ContentEncodings.Brotli, StringComparison.OrdinalIgnoreCase)) 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); stream = new BrotliStream(stream, CompressionMode.Decompress);
} }
#endif #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 // (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). // during a second pass a second time for logging/debuggability purposes).
var content = new StreamContent(stream); var content = new StreamContent(stream);
await content.LoadIntoBufferAsync(); await content.LoadIntoBufferAsync(context.CancellationToken);
// Copy the headers from the original content to the new instance. // Copy the headers from the original content to the new instance.
foreach (var header in response.Content.Headers) foreach (var header in response.Content.Headers)
@ -724,7 +724,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception)) catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{ {
context.Logger.LogError(6183, exception, SR.GetResourceString(SR.ID6183), context.Logger.LogError(6183, exception, SR.GetResourceString(SR.ID6183),
await response.Content.ReadAsStringAsync()); await response.Content.ReadAsStringAsync(context.CancellationToken));
context.Reject( context.Reject(
error: Errors.ServerError, error: Errors.ServerError,
@ -902,7 +902,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
if (!response.IsSuccessStatusCode && string.IsNullOrEmpty(context.Transaction.Response?.Error)) if (!response.IsSuccessStatusCode && string.IsNullOrEmpty(context.Transaction.Response?.Error))
{ {
context.Logger.LogError(6184, SR.GetResourceString(SR.ID6184), response.StatusCode, context.Logger.LogError(6184, SR.GetResourceString(SR.ID6184), response.StatusCode,
await response.Content.ReadAsStringAsync()); await response.Content.ReadAsStringAsync(context.CancellationToken));
context.Reject( context.Reject(
error: (int) response.StatusCode switch error: (int) response.StatusCode switch
@ -926,7 +926,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
if (context.Transaction.Response is null) if (context.Transaction.Response is null)
{ {
context.Logger.LogError(6185, SR.GetResourceString(SR.ID6185), response.StatusCode, 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( context.Reject(
error: Errors.ServerError, error: Errors.ServerError,

6
src/OpenIddict.Validation/IOpenIddictValidationFactory.cs

@ -18,9 +18,13 @@ public interface IOpenIddictValidationFactory
/// Creates a new <see cref="OpenIddictValidationTransaction"/> that is used as a /// Creates a new <see cref="OpenIddictValidationTransaction"/> that is used as a
/// way to store per-request data needed to process the requested operation. /// way to store per-request data needed to process the requested operation.
/// </summary> /// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <remarks>
/// Note: the specified <see cref="CancellationToken"/> is automatically attached to the returned transaction.
/// </remarks>
/// <returns> /// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous /// A <see cref="ValueTask"/> that can be used to monitor the asynchronous
/// operation, whose result returns the created transaction. /// operation, whose result returns the created transaction.
/// </returns> /// </returns>
ValueTask<OpenIddictValidationTransaction> CreateTransactionAsync(); ValueTask<OpenIddictValidationTransaction> CreateTransactionAsync(CancellationToken cancellationToken);
} }

2
src/OpenIddict.Validation/OpenIddictValidationDispatcher.cs

@ -40,6 +40,8 @@ public sealed class OpenIddictValidationDispatcher : IOpenIddictValidationDispat
await foreach (var handler in GetHandlersAsync()) await foreach (var handler in GetHandlersAsync())
{ {
context.CancellationToken.ThrowIfCancellationRequested();
try try
{ {
await handler.HandleAsync(context); await handler.HandleAsync(context);

14
src/OpenIddict.Validation/OpenIddictValidationEvents.cs

@ -31,19 +31,9 @@ public static partial class OpenIddictValidationEvents
public OpenIddictValidationTransaction Transaction { get; } public OpenIddictValidationTransaction Transaction { get; }
/// <summary> /// <summary>
/// Gets or sets the cancellation token that will be /// Gets the cancellation token used to determine if the operation was aborted.
/// used to determine if the operation was aborted.
/// </summary> /// </summary>
/// <remarks> public CancellationToken CancellationToken => Transaction.CancellationToken;
/// 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.
/// </remarks>
public CancellationToken CancellationToken
{
get => Transaction.CancellationToken;
set => Transaction.CancellationToken = value;
}
/// <summary> /// <summary>
/// Gets or sets the endpoint type that handled the request, if applicable. /// Gets or sets the endpoint type that handled the request, if applicable.

12
src/OpenIddict.Validation/OpenIddictValidationFactory.cs

@ -31,10 +31,18 @@ public sealed class OpenIddictValidationFactory : IOpenIddictValidationFactory
} }
/// <inheritdoc/> /// <inheritdoc/>
public ValueTask<OpenIddictValidationTransaction> CreateTransactionAsync() public ValueTask<OpenIddictValidationTransaction> CreateTransactionAsync(CancellationToken cancellationToken)
=> new(new OpenIddictValidationTransaction {
if (cancellationToken.IsCancellationRequested)
{
return new(Task.FromCanceled<OpenIddictValidationTransaction>(cancellationToken));
}
return new(new OpenIddictValidationTransaction
{ {
CancellationToken = cancellationToken,
Logger = _logger, Logger = _logger,
Options = _options.CurrentValue Options = _options.CurrentValue
}); });
}
} }

34
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. // 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) if (token is null)
{ {
return; return;
@ -230,8 +230,8 @@ public static partial class OpenIddictValidationHandlers
if (!(context.ValidTokenTypes.Count switch if (!(context.ValidTokenTypes.Count switch
{ {
0 => true, // If no specific token type is expected, accept all token types at this stage. 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)), 1 => await _tokenManager.HasTypeAsync(token, context.ValidTokenTypes.ElementAt(0), context.CancellationToken),
_ => await _tokenManager.HasTypeAsync(token, [.. context.ValidTokenTypes]) _ => await _tokenManager.HasTypeAsync(token, [.. context.ValidTokenTypes], context.CancellationToken)
})) }))
{ {
context.Reject( context.Reject(
@ -242,7 +242,7 @@ public static partial class OpenIddictValidationHandlers
return; return;
} }
var payload = await _tokenManager.GetPayloadAsync(token); var payload = await _tokenManager.GetPayloadAsync(token, context.CancellationToken);
if (string.IsNullOrEmpty(payload)) if (string.IsNullOrEmpty(payload))
{ {
throw new InvalidOperationException(SR.GetResourceString(SR.ID0026)); 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. // used to restore the properties associated with the token.
context.IsReferenceToken = true; context.IsReferenceToken = true;
context.Token = payload; 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. // 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) if (token is null)
{ {
context.Reject( 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 // 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, // 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. // 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( context.Reject(
error: Errors.InvalidToken, error: Errors.InvalidToken,
@ -590,11 +590,11 @@ public static partial class OpenIddictValidationHandlers
// Restore the creation/expiration dates/identifiers from the token entry metadata. // Restore the creation/expiration dates/identifiers from the token entry metadata.
context.Principal context.Principal
.SetCreationDate(await _tokenManager.GetCreationDateAsync(token)) .SetCreationDate(await _tokenManager.GetCreationDateAsync(token, context.CancellationToken))
.SetExpirationDate(await _tokenManager.GetExpirationDateAsync(token)) .SetExpirationDate(await _tokenManager.GetExpirationDateAsync(token, context.CancellationToken))
.SetAuthorizationId(context.AuthorizationId = await _tokenManager.GetAuthorizationIdAsync(token)) .SetAuthorizationId(context.AuthorizationId = await _tokenManager.GetAuthorizationIdAsync(token, context.CancellationToken))
.SetTokenId(context.TokenId = await _tokenManager.GetIdAsync(token)) .SetTokenId(context.TokenId = await _tokenManager.GetIdAsync(token, context.CancellationToken))
.SetTokenType(await _tokenManager.GetTypeAsync(token)); .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(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
Debug.Assert(!string.IsNullOrEmpty(context.TokenId), SR.GetResourceString(SR.ID4017)); 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)); ?? 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); 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(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
Debug.Assert(!string.IsNullOrEmpty(context.AuthorizationId), SR.GetResourceString(SR.ID4018)); Debug.Assert(!string.IsNullOrEmpty(context.AuthorizationId), SR.GetResourceString(SR.ID4018));
var authorization = await _authorizationManager.FindByIdAsync(context.AuthorizationId); var authorization = await _authorizationManager.FindByIdAsync(context.AuthorizationId, context.CancellationToken);
if (authorization is null || !await _authorizationManager.HasStatusAsync(authorization, Statuses.Valid)) if (authorization is null || !await _authorizationManager.HasStatusAsync(authorization, Statuses.Valid, context.CancellationToken))
{ {
context.Logger.LogInformation(6006, SR.GetResourceString(SR.ID6006), context.AuthorizationId); context.Logger.LogInformation(6006, SR.GetResourceString(SR.ID6006), context.AuthorizationId);

12
src/OpenIddict.Validation/OpenIddictValidationService.cs

@ -47,7 +47,7 @@ public class OpenIddictValidationService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(cancellationToken);
var context = new ProcessAuthenticationContext(transaction) var context = new ProcessAuthenticationContext(transaction)
{ {
@ -92,7 +92,7 @@ public class OpenIddictValidationService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(cancellationToken);
var request = new OpenIddictRequest(); var request = new OpenIddictRequest();
request = await PrepareConfigurationRequestAsync(); request = await PrepareConfigurationRequestAsync();
@ -214,7 +214,7 @@ public class OpenIddictValidationService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(cancellationToken);
var request = new OpenIddictRequest(); var request = new OpenIddictRequest();
request = await PrepareJsonWebKeySetRequestAsync(); request = await PrepareJsonWebKeySetRequestAsync();
@ -344,7 +344,7 @@ public class OpenIddictValidationService
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationDispatcher>(); var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationDispatcher>();
var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationFactory>(); var factory = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationFactory>();
var transaction = await factory.CreateTransactionAsync(); var transaction = await factory.CreateTransactionAsync(cancellationToken);
request = await PrepareIntrospectionRequestAsync(); request = await PrepareIntrospectionRequestAsync();
request = await ApplyIntrospectionRequestAsync(); request = await ApplyIntrospectionRequestAsync();
@ -357,7 +357,6 @@ public class OpenIddictValidationService
{ {
var context = new PrepareIntrospectionRequestContext(transaction) var context = new PrepareIntrospectionRequestContext(transaction)
{ {
CancellationToken = cancellationToken,
ClientAuthenticationMethod = method, ClientAuthenticationMethod = method,
Configuration = configuration, Configuration = configuration,
RemoteUri = uri, RemoteUri = uri,
@ -381,7 +380,6 @@ public class OpenIddictValidationService
{ {
var context = new ApplyIntrospectionRequestContext(transaction) var context = new ApplyIntrospectionRequestContext(transaction)
{ {
CancellationToken = cancellationToken,
RemoteUri = uri, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
Request = request Request = request
@ -405,7 +403,6 @@ public class OpenIddictValidationService
{ {
var context = new ExtractIntrospectionResponseContext(transaction) var context = new ExtractIntrospectionResponseContext(transaction)
{ {
CancellationToken = cancellationToken,
RemoteUri = uri, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
Request = request Request = request
@ -431,7 +428,6 @@ public class OpenIddictValidationService
{ {
var context = new HandleIntrospectionResponseContext(transaction) var context = new HandleIntrospectionResponseContext(transaction)
{ {
CancellationToken = cancellationToken,
RemoteUri = uri, RemoteUri = uri,
Configuration = configuration, Configuration = configuration,
Request = request, Request = request,

8
src/OpenIddict.Validation/OpenIddictValidationTransaction.cs

@ -17,14 +17,8 @@ namespace OpenIddict.Validation;
public sealed class OpenIddictValidationTransaction public sealed class OpenIddictValidationTransaction
{ {
/// <summary> /// <summary>
/// Gets or sets the cancellation token that will be /// Gets or sets the cancellation token used to determine if the operation was aborted.
/// used to determine if the operation was aborted.
/// </summary> /// </summary>
/// <remarks>
/// 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.
/// </remarks>
public CancellationToken CancellationToken { get; set; } public CancellationToken CancellationToken { get; set; }
/// <summary> /// <summary>

Loading…
Cancel
Save