From 17cf934cea14d8c59eee152d928bf7cc71c63a98 Mon Sep 17 00:00:00 2001 From: OpenIddict Bot <32257313+openiddict-bot@users.noreply.github.com> Date: Wed, 19 Mar 2025 16:14:49 +0000 Subject: [PATCH 1/2] Update the sponsors section --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b65f2ffe..0e41e999 100644 --- a/README.md +++ b/README.md @@ -175,7 +175,7 @@ To reference the OpenIddict MyGet feed, **create a `NuGet.config` file** (at the

-Sébastien RosSchmitt ChristianSebastian StehleCommunicatie CockpitJasmin SavardThomasDigitalOps Co. Ltd.EYERIDE Fleet Management SystemJulien DebacheStian HåveRavindu LiyanapathiranaHieronymusBlazeAkhan ZhakiyanovCorentin BBarry DorransDevQ S.r.l.GrégoireForterroMarcelJens WillmerBlauhaus Technology (Pty) LtdJan TrejbalAviationexam s.r.o.MonoforRatiodata SEDennis van ZettenJeroenLombiq Technologies Ltd.Andrew Babbittsoftaware gmbhSingular SystemsSCP-srlRealisable SoftwareSipke SchoorstraJoshua Nixon +Sébastien RosSchmitt ChristianSebastian StehleCommunicatie CockpitJasmin SavardThomasDigitalOps Co. Ltd.EYERIDE Fleet Management SystemJulien DebacheStian HåveRavindu LiyanapathiranaHieronymusBlazeAkhan ZhakiyanovCorentin BBarry DorransDevQ S.r.l.GrégoireForterroMarcelJens WillmerBlauhaus Technology (Pty) LtdJan TrejbalAviationexam s.r.o.MonoforRatiodata SEDennis van ZettenJeroenLombiq Technologies Ltd.Andrew Babbittsoftaware gmbhSingular SystemsSCP-srlRealisable SoftwareSipke SchoorstraJoshua NixonAlok Sharma -------------- From bef75c4f56b1d6571a41a4ddcd0fea67fcb07d23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Wed, 19 Mar 2025 19:36:12 +0100 Subject: [PATCH 2/2] Use the CreateAsyncScope() helper to avoid having to manually cast IServiceProvider to IAsyncDisposable --- .../Worker.cs | 28 +- .../Worker.cs | 32 +- .../Worker.cs | 2 +- .../Worker.cs | 2 +- .../OpenIddict.Sandbox.Wpf.Client/Worker.cs | 2 +- ...penIddictClientSystemIntegrationService.cs | 56 +- .../OpenIddictClientService.cs | 2572 +++++++---------- src/OpenIddict.Quartz/OpenIddictQuartzJob.cs | 168 +- .../OpenIddictValidationService.cs | 560 ++-- .../OpenIddictServerOwinIntegrationTests.cs | 2 +- ...penIddictValidationOwinIntegrationTests.cs | 2 +- 11 files changed, 1474 insertions(+), 1952 deletions(-) diff --git a/sandbox/OpenIddict.Sandbox.AspNetCore.Client/Worker.cs b/sandbox/OpenIddict.Sandbox.AspNetCore.Client/Worker.cs index c13e41bf..62108875 100644 --- a/sandbox/OpenIddict.Sandbox.AspNetCore.Client/Worker.cs +++ b/sandbox/OpenIddict.Sandbox.AspNetCore.Client/Worker.cs @@ -4,33 +4,17 @@ namespace OpenIddict.Sandbox.AspNetCore.Client; public class Worker : IHostedService { - private readonly IServiceProvider _serviceProvider; + private readonly IServiceProvider _provider; - public Worker(IServiceProvider serviceProvider) - => _serviceProvider = serviceProvider; + public Worker(IServiceProvider provider) + => _provider = provider; public async Task StartAsync(CancellationToken cancellationToken) { - var scope = _serviceProvider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); - try - { - var context = scope.ServiceProvider.GetRequiredService(); - await context.Database.EnsureCreatedAsync(cancellationToken); - } - - finally - { - if (scope is IAsyncDisposable disposable) - { - await disposable.DisposeAsync(); - } - - else - { - scope.Dispose(); - } - } + var context = scope.ServiceProvider.GetRequiredService(); + await context.Database.EnsureCreatedAsync(cancellationToken); } public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; diff --git a/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Worker.cs b/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Worker.cs index 7d79458c..c8b5ec0a 100644 --- a/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Worker.cs +++ b/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Worker.cs @@ -9,36 +9,20 @@ namespace OpenIddict.Sandbox.AspNetCore.Server; public class Worker : IHostedService { - private readonly IServiceProvider _serviceProvider; + private readonly IServiceProvider _provider; - public Worker(IServiceProvider serviceProvider) - => _serviceProvider = serviceProvider; + public Worker(IServiceProvider provider) + => _provider = provider; public async Task StartAsync(CancellationToken cancellationToken) { - var scope = _serviceProvider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); - try - { - var context = scope.ServiceProvider.GetRequiredService(); - await context.Database.EnsureCreatedAsync(cancellationToken); - - await RegisterApplicationsAsync(scope.ServiceProvider); - await RegisterScopesAsync(scope.ServiceProvider); - } - - finally - { - if (scope is IAsyncDisposable disposable) - { - await disposable.DisposeAsync(); - } + var context = scope.ServiceProvider.GetRequiredService(); + await context.Database.EnsureCreatedAsync(cancellationToken); - else - { - scope.Dispose(); - } - } + await RegisterApplicationsAsync(scope.ServiceProvider); + await RegisterScopesAsync(scope.ServiceProvider); static async Task RegisterApplicationsAsync(IServiceProvider provider) { diff --git a/sandbox/OpenIddict.Sandbox.Console.Client/Worker.cs b/sandbox/OpenIddict.Sandbox.Console.Client/Worker.cs index fc054ee5..00df826d 100644 --- a/sandbox/OpenIddict.Sandbox.Console.Client/Worker.cs +++ b/sandbox/OpenIddict.Sandbox.Console.Client/Worker.cs @@ -13,7 +13,7 @@ public class Worker : IHostedService public async Task StartAsync(CancellationToken cancellationToken) { - using var scope = _provider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); var context = scope.ServiceProvider.GetRequiredService(); await context.Database.EnsureCreatedAsync(cancellationToken); diff --git a/sandbox/OpenIddict.Sandbox.WinForms.Client/Worker.cs b/sandbox/OpenIddict.Sandbox.WinForms.Client/Worker.cs index 10aed3f9..6bfca1b3 100644 --- a/sandbox/OpenIddict.Sandbox.WinForms.Client/Worker.cs +++ b/sandbox/OpenIddict.Sandbox.WinForms.Client/Worker.cs @@ -15,7 +15,7 @@ public class Worker : IHostedService public async Task StartAsync(CancellationToken cancellationToken) { - using var scope = _provider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); var context = scope.ServiceProvider.GetRequiredService(); await context.Database.EnsureCreatedAsync(cancellationToken); diff --git a/sandbox/OpenIddict.Sandbox.Wpf.Client/Worker.cs b/sandbox/OpenIddict.Sandbox.Wpf.Client/Worker.cs index 027cc21e..0f65a8d5 100644 --- a/sandbox/OpenIddict.Sandbox.Wpf.Client/Worker.cs +++ b/sandbox/OpenIddict.Sandbox.Wpf.Client/Worker.cs @@ -15,7 +15,7 @@ public class Worker : IHostedService public async Task StartAsync(CancellationToken cancellationToken) { - using var scope = _provider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); var context = scope.ServiceProvider.GetRequiredService(); await context.Database.EnsureCreatedAsync(cancellationToken); diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationService.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationService.cs index 1548d3a4..c3c2bf59 100644 --- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationService.cs +++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationService.cs @@ -146,49 +146,33 @@ public sealed class OpenIddictClientSystemIntegrationService cancellationToken.ThrowIfCancellationRequested(); - var scope = _provider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - - // Create a client transaction and store the specified instance so - // it can be retrieved by the event handlers that need to access it. - var transaction = await factory.CreateTransactionAsync(); - transaction.SetProperty(typeof(TProperty).FullName!, property); + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); - var context = new ProcessRequestContext(transaction) - { - CancellationToken = cancellationToken - }; + // Create a client transaction and store the specified instance so + // it can be retrieved by the event handlers that need to access it. + var transaction = await factory.CreateTransactionAsync(); + transaction.SetProperty(typeof(TProperty).FullName!, property); - await dispatcher.DispatchAsync(context); + var context = new ProcessRequestContext(transaction) + { + CancellationToken = cancellationToken + }; - if (context.IsRejected) - { - await dispatcher.DispatchAsync(new ProcessErrorContext(transaction) - { - CancellationToken = cancellationToken, - Error = context.Error ?? Errors.InvalidRequest, - ErrorDescription = context.ErrorDescription, - ErrorUri = context.ErrorUri, - Response = new OpenIddictResponse() - }); - } - } + await dispatcher.DispatchAsync(context); - finally + if (context.IsRejected) { - if (scope is IAsyncDisposable disposable) - { - await disposable.DisposeAsync(); - } - - else + await dispatcher.DispatchAsync(new ProcessErrorContext(transaction) { - scope.Dispose(); - } + CancellationToken = cancellationToken, + Error = context.Error ?? Errors.InvalidRequest, + ErrorDescription = context.ErrorDescription, + ErrorUri = context.ErrorUri, + Response = new OpenIddictResponse() + }); } } diff --git a/src/OpenIddict.Client/OpenIddictClientService.cs b/src/OpenIddict.Client/OpenIddictClientService.cs index d0ebfcaf..5af6b082 100644 --- a/src/OpenIddict.Client/OpenIddictClientService.cs +++ b/src/OpenIddict.Client/OpenIddictClientService.cs @@ -282,77 +282,59 @@ public class OpenIddictClientService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - - var transaction = await factory.CreateTransactionAsync(); - - var context = new ProcessAuthenticationContext(transaction) - { - CancellationToken = request.CancellationToken, - Nonce = request.Nonce - }; + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); - if (request.Properties is { Count: > 0 }) - { - foreach (var property in request.Properties) - { - context.Properties[property.Key] = property.Value; - } - } + var transaction = await factory.CreateTransactionAsync(); - await dispatcher.DispatchAsync(context); + var context = new ProcessAuthenticationContext(transaction) + { + CancellationToken = request.CancellationToken, + Nonce = request.Nonce + }; - if (context.IsRejected) + if (request.Properties is { Count: > 0 }) + { + foreach (var property in request.Properties) { - throw new ProtocolException( - SR.FormatID0374(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); + context.Properties[property.Key] = property.Value; } + } - else - { - Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013)); + await dispatcher.DispatchAsync(context); - return new() - { - AuthorizationCode = context.AuthorizationCode, - AuthorizationResponse = context.Request is not null ? new(context.Request.GetParameters()) : new(), - BackchannelAccessToken = context.BackchannelAccessToken, - BackchannelAccessTokenExpirationDate = context.BackchannelAccessTokenExpirationDate, - BackchannelIdentityToken = context.BackchannelIdentityToken, - BackchannelIdentityTokenPrincipal = context.BackchannelIdentityTokenPrincipal, - FrontchannelAccessToken = context.FrontchannelAccessToken, - FrontchannelAccessTokenExpirationDate = context.FrontchannelAccessTokenExpirationDate, - FrontchannelIdentityToken = context.FrontchannelIdentityToken, - FrontchannelIdentityTokenPrincipal = context.FrontchannelIdentityTokenPrincipal, - Principal = context.MergedPrincipal, - Properties = context.Properties, - RefreshToken = context.RefreshToken, - StateTokenPrincipal = context.StateTokenPrincipal, - TokenResponse = context.TokenResponse ?? new(), - UserInfoTokenPrincipal = context.UserInfoTokenPrincipal - }; - } + if (context.IsRejected) + { + throw new ProtocolException( + SR.FormatID0374(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } - finally + else { - if (scope is IAsyncDisposable disposable) - { - await disposable.DisposeAsync(); - } + Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013)); - else + return new() { - scope.Dispose(); - } + AuthorizationCode = context.AuthorizationCode, + AuthorizationResponse = context.Request is not null ? new(context.Request.GetParameters()) : new(), + BackchannelAccessToken = context.BackchannelAccessToken, + BackchannelAccessTokenExpirationDate = context.BackchannelAccessTokenExpirationDate, + BackchannelIdentityToken = context.BackchannelIdentityToken, + BackchannelIdentityTokenPrincipal = context.BackchannelIdentityTokenPrincipal, + FrontchannelAccessToken = context.FrontchannelAccessToken, + FrontchannelAccessTokenExpirationDate = context.FrontchannelAccessTokenExpirationDate, + FrontchannelIdentityToken = context.FrontchannelIdentityToken, + FrontchannelIdentityTokenPrincipal = context.FrontchannelIdentityTokenPrincipal, + Principal = context.MergedPrincipal, + Properties = context.Properties, + RefreshToken = context.RefreshToken, + StateTokenPrincipal = context.StateTokenPrincipal, + TokenResponse = context.TokenResponse ?? new(), + UserInfoTokenPrincipal = context.UserInfoTokenPrincipal + }; } } @@ -373,80 +355,62 @@ public class OpenIddictClientService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); - - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - - var transaction = await factory.CreateTransactionAsync(); - - var context = new ProcessChallengeContext(transaction) - { - CancellationToken = request.CancellationToken, - CodeChallengeMethod = request.CodeChallengeMethod, - GrantType = request.GrantType, - IdentityTokenHint = request.IdentityTokenHint, - Issuer = request.Issuer, - LoginHint = request.LoginHint, - Principal = new ClaimsPrincipal(new ClaimsIdentity()), - ProviderName = request.ProviderName, - RegistrationId = request.RegistrationId, - Request = request.AdditionalAuthorizationRequestParameters - is Dictionary parameters ? new(parameters) : new(), - ResponseMode = request.ResponseMode, - ResponseType = request.ResponseType - }; - - if (request.Scopes is { Count: > 0 }) - { - context.Scopes.UnionWith(request.Scopes); - } - - if (request.Properties is { Count: > 0 }) - { - foreach (var property in request.Properties) - { - context.Properties[property.Key] = property.Value; - } - } + await using var scope = _provider.CreateAsyncScope(); + + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); + + var transaction = await factory.CreateTransactionAsync(); + + var context = new ProcessChallengeContext(transaction) + { + CancellationToken = request.CancellationToken, + CodeChallengeMethod = request.CodeChallengeMethod, + GrantType = request.GrantType, + IdentityTokenHint = request.IdentityTokenHint, + Issuer = request.Issuer, + LoginHint = request.LoginHint, + Principal = new ClaimsPrincipal(new ClaimsIdentity()), + ProviderName = request.ProviderName, + RegistrationId = request.RegistrationId, + Request = request.AdditionalAuthorizationRequestParameters + is Dictionary parameters ? new(parameters) : new(), + ResponseMode = request.ResponseMode, + ResponseType = request.ResponseType + }; - await dispatcher.DispatchAsync(context); + if (request.Scopes is { Count: > 0 }) + { + context.Scopes.UnionWith(request.Scopes); + } - if (context.IsRejected) + if (request.Properties is { Count: > 0 }) + { + foreach (var property in request.Properties) { - throw new ProtocolException( - SR.FormatID0374(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); + context.Properties[property.Key] = property.Value; } + } - if (string.IsNullOrEmpty(context.Nonce)) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0352)); - } + await dispatcher.DispatchAsync(context); - return new() - { - Nonce = context.Nonce, - Properties = context.Properties - }; + if (context.IsRejected) + { + throw new ProtocolException( + SR.FormatID0374(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } - finally + if (string.IsNullOrEmpty(context.Nonce)) { - if (scope is IAsyncDisposable disposable) - { - await disposable.DisposeAsync(); - } - - else - { - scope.Dispose(); - } + throw new InvalidOperationException(SR.GetResourceString(SR.ID0352)); } + + return new() + { + Nonce = context.Nonce, + Properties = context.Properties + }; } /// @@ -467,79 +431,61 @@ public class OpenIddictClientService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); - - var context = new ProcessAuthenticationContext(transaction) - { - CancellationToken = request.CancellationToken, - GrantType = GrantTypes.ClientCredentials, - Issuer = request.Issuer, - ProviderName = request.ProviderName, - RegistrationId = request.RegistrationId, - TokenRequest = request.AdditionalTokenRequestParameters - is Dictionary parameters ? new(parameters) : new(), - }; + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); + var transaction = await factory.CreateTransactionAsync(); - if (request.Scopes is { Count: > 0 }) - { - context.Scopes.UnionWith(request.Scopes); - } - - if (request.Properties is { Count: > 0 }) - { - foreach (var property in request.Properties) - { - context.Properties[property.Key] = property.Value; - } - } + var context = new ProcessAuthenticationContext(transaction) + { + CancellationToken = request.CancellationToken, + GrantType = GrantTypes.ClientCredentials, + Issuer = request.Issuer, + ProviderName = request.ProviderName, + RegistrationId = request.RegistrationId, + TokenRequest = request.AdditionalTokenRequestParameters + is Dictionary parameters ? new(parameters) : new(), + }; - await dispatcher.DispatchAsync(context); + if (request.Scopes is { Count: > 0 }) + { + context.Scopes.UnionWith(request.Scopes); + } - if (context.IsRejected) + if (request.Properties is { Count: > 0 }) + { + foreach (var property in request.Properties) { - throw new ProtocolException( - SR.FormatID0435(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); + context.Properties[property.Key] = property.Value; } + } - Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013)); - Debug.Assert(context.TokenResponse is not null, SR.GetResourceString(SR.ID4007)); + await dispatcher.DispatchAsync(context); - return new() - { - AccessToken = context.BackchannelAccessToken!, - AccessTokenExpirationDate = context.BackchannelAccessTokenExpirationDate, - IdentityToken = context.BackchannelIdentityToken, - IdentityTokenPrincipal = context.BackchannelIdentityTokenPrincipal, - Principal = context.MergedPrincipal, - Properties = context.Properties, - RefreshToken = context.RefreshToken, - TokenResponse = context.TokenResponse, - UserInfoToken = context.UserInfoToken, - UserInfoTokenPrincipal = context.UserInfoTokenPrincipal - }; + if (context.IsRejected) + { + throw new ProtocolException( + SR.FormatID0435(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } - finally - { - if (scope is IAsyncDisposable disposable) - { - await disposable.DisposeAsync(); - } + Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013)); + Debug.Assert(context.TokenResponse is not null, SR.GetResourceString(SR.ID4007)); - else - { - scope.Dispose(); - } - } + return new() + { + AccessToken = context.BackchannelAccessToken!, + AccessTokenExpirationDate = context.BackchannelAccessTokenExpirationDate, + IdentityToken = context.BackchannelIdentityToken, + IdentityTokenPrincipal = context.BackchannelIdentityTokenPrincipal, + Principal = context.MergedPrincipal, + Properties = context.Properties, + RefreshToken = context.RefreshToken, + TokenResponse = context.TokenResponse, + UserInfoToken = context.UserInfoToken, + UserInfoTokenPrincipal = context.UserInfoTokenPrincipal + }; } /// @@ -568,80 +514,62 @@ public class OpenIddictClientService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); - - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); - - var context = new ProcessAuthenticationContext(transaction) - { - CancellationToken = request.CancellationToken, - DisableUserInfoRetrieval = request.DisableUserInfo, - DisableUserInfoValidation = request.DisableUserInfo, - GrantType = request.GrantType, - ProviderName = request.ProviderName, - RegistrationId = request.RegistrationId, - TokenRequest = request.AdditionalTokenRequestParameters - is Dictionary parameters ? new(parameters) : new() - }; - - if (request.Scopes is { Count: > 0 }) - { - context.Scopes.UnionWith(request.Scopes); - } - - if (request.Properties is { Count: > 0 }) - { - foreach (var property in request.Properties) - { - context.Properties[property.Key] = property.Value; - } - } + await using var scope = _provider.CreateAsyncScope(); + + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); + var transaction = await factory.CreateTransactionAsync(); + + var context = new ProcessAuthenticationContext(transaction) + { + CancellationToken = request.CancellationToken, + DisableUserInfoRetrieval = request.DisableUserInfo, + DisableUserInfoValidation = request.DisableUserInfo, + GrantType = request.GrantType, + ProviderName = request.ProviderName, + RegistrationId = request.RegistrationId, + TokenRequest = request.AdditionalTokenRequestParameters + is Dictionary parameters ? new(parameters) : new() + }; - await dispatcher.DispatchAsync(context); + if (request.Scopes is { Count: > 0 }) + { + context.Scopes.UnionWith(request.Scopes); + } - if (context.IsRejected) + if (request.Properties is { Count: > 0 }) + { + foreach (var property in request.Properties) { - throw new ProtocolException( - SR.FormatID0374(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); + context.Properties[property.Key] = property.Value; } + } - Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013)); - Debug.Assert(context.TokenResponse is not null, SR.GetResourceString(SR.ID4007)); + await dispatcher.DispatchAsync(context); - return new() - { - AccessToken = context.BackchannelAccessToken!, - AccessTokenExpirationDate = context.BackchannelAccessTokenExpirationDate, - IdentityToken = context.BackchannelIdentityToken, - IdentityTokenPrincipal = context.BackchannelIdentityTokenPrincipal, - Principal = context.MergedPrincipal, - Properties = context.Properties, - RefreshToken = context.RefreshToken, - TokenResponse = context.TokenResponse, - UserInfoToken = context.UserInfoToken, - UserInfoTokenPrincipal = context.UserInfoTokenPrincipal - }; + if (context.IsRejected) + { + throw new ProtocolException( + SR.FormatID0374(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } - finally - { - if (scope is IAsyncDisposable disposable) - { - await disposable.DisposeAsync(); - } + Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013)); + Debug.Assert(context.TokenResponse is not null, SR.GetResourceString(SR.ID4007)); - else - { - scope.Dispose(); - } - } + return new() + { + AccessToken = context.BackchannelAccessToken!, + AccessTokenExpirationDate = context.BackchannelAccessTokenExpirationDate, + IdentityToken = context.BackchannelIdentityToken, + IdentityTokenPrincipal = context.BackchannelIdentityTokenPrincipal, + Principal = context.MergedPrincipal, + Properties = context.Properties, + RefreshToken = context.RefreshToken, + TokenResponse = context.TokenResponse, + UserInfoToken = context.UserInfoToken, + UserInfoTokenPrincipal = context.UserInfoTokenPrincipal + }; } /// @@ -670,84 +598,66 @@ public class OpenIddictClientService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(); - var context = new ProcessAuthenticationContext(transaction) - { - CancellationToken = source.Token, - DeviceCode = request.DeviceCode, - DisableUserInfoRetrieval = request.DisableUserInfo, - DisableUserInfoValidation = request.DisableUserInfo, - GrantType = GrantTypes.DeviceCode, - Issuer = request.Issuer, - ProviderName = request.ProviderName, - RegistrationId = request.RegistrationId, - TokenRequest = request.AdditionalTokenRequestParameters - is Dictionary parameters ? new(parameters) : new(), - }; + var context = new ProcessAuthenticationContext(transaction) + { + CancellationToken = source.Token, + DeviceCode = request.DeviceCode, + DisableUserInfoRetrieval = request.DisableUserInfo, + DisableUserInfoValidation = request.DisableUserInfo, + GrantType = GrantTypes.DeviceCode, + Issuer = request.Issuer, + ProviderName = request.ProviderName, + RegistrationId = request.RegistrationId, + TokenRequest = request.AdditionalTokenRequestParameters + is Dictionary parameters ? new(parameters) : new(), + }; - if (request.Scopes is { Count: > 0 }) - { - context.Scopes.UnionWith(request.Scopes); - } + if (request.Scopes is { Count: > 0 }) + { + context.Scopes.UnionWith(request.Scopes); + } - if (request.Properties is { Count: > 0 }) + if (request.Properties is { Count: > 0 }) + { + foreach (var property in request.Properties) { - foreach (var property in request.Properties) - { - context.Properties[property.Key] = property.Value; - } + context.Properties[property.Key] = property.Value; } + } - await dispatcher.DispatchAsync(context); - - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0374(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + await dispatcher.DispatchAsync(context); - else - { - Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013)); - - return new() - { - AccessToken = context.BackchannelAccessToken!, - AccessTokenExpirationDate = context.BackchannelAccessTokenExpirationDate, - IdentityToken = context.BackchannelIdentityToken, - IdentityTokenPrincipal = context.BackchannelIdentityTokenPrincipal, - Principal = context.MergedPrincipal, - Properties = context.Properties, - RefreshToken = context.RefreshToken, - TokenResponse = context.TokenResponse ?? new(), - UserInfoToken = context.UserInfoToken, - UserInfoTokenPrincipal = context.UserInfoTokenPrincipal - }; - } + if (context.IsRejected) + { + throw new ProtocolException( + SR.FormatID0374(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } - finally + else { - if (scope is IAsyncDisposable disposable) - { - await disposable.DisposeAsync(); - } + Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013)); - else + return new() { - scope.Dispose(); - } + AccessToken = context.BackchannelAccessToken!, + AccessTokenExpirationDate = context.BackchannelAccessTokenExpirationDate, + IdentityToken = context.BackchannelIdentityToken, + IdentityTokenPrincipal = context.BackchannelIdentityTokenPrincipal, + Principal = context.MergedPrincipal, + Properties = context.Properties, + RefreshToken = context.RefreshToken, + TokenResponse = context.TokenResponse ?? new(), + UserInfoToken = context.UserInfoToken, + UserInfoTokenPrincipal = context.UserInfoTokenPrincipal + }; } } @@ -786,78 +696,60 @@ public class OpenIddictClientService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var transaction = await factory.CreateTransactionAsync(); - var context = new ProcessChallengeContext(transaction) - { - CancellationToken = request.CancellationToken, - DeviceAuthorizationRequest = request.AdditionalDeviceAuthorizationRequestParameters - is Dictionary parameters ? new(parameters) : new(), - GrantType = GrantTypes.DeviceCode, - Issuer = request.Issuer, - Principal = new ClaimsPrincipal(new ClaimsIdentity()), - ProviderName = request.ProviderName, - RegistrationId = request.RegistrationId, - Request = new() - }; + var context = new ProcessChallengeContext(transaction) + { + CancellationToken = request.CancellationToken, + DeviceAuthorizationRequest = request.AdditionalDeviceAuthorizationRequestParameters + is Dictionary parameters ? new(parameters) : new(), + GrantType = GrantTypes.DeviceCode, + Issuer = request.Issuer, + Principal = new ClaimsPrincipal(new ClaimsIdentity()), + ProviderName = request.ProviderName, + RegistrationId = request.RegistrationId, + Request = new() + }; - if (request.Scopes is { Count: > 0 }) - { - context.Scopes.UnionWith(request.Scopes); - } + if (request.Scopes is { Count: > 0 }) + { + context.Scopes.UnionWith(request.Scopes); + } - if (request.Properties is { Count: > 0 }) + if (request.Properties is { Count: > 0 }) + { + foreach (var property in request.Properties) { - foreach (var property in request.Properties) - { - context.Properties[property.Key] = property.Value; - } + context.Properties[property.Key] = property.Value; } + } - await dispatcher.DispatchAsync(context); - - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0374(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + await dispatcher.DispatchAsync(context); - return new() - { - DeviceAuthorizationResponse = context.DeviceAuthorizationResponse ?? new(), - DeviceCode = context.DeviceCode!, - ExpiresIn = TimeSpan.FromSeconds((double) context.DeviceAuthorizationResponse?.ExpiresIn!), - Interval = TimeSpan.FromSeconds((long?) context.DeviceAuthorizationResponse[Parameters.Interval] ?? 5), - Properties = context.Properties, - UserCode = context.UserCode!, - VerificationUri = new Uri(context.DeviceAuthorizationResponse?.VerificationUri!, UriKind.Absolute), - VerificationUriComplete = context.DeviceAuthorizationResponse?.VerificationUriComplete - is string value ? new Uri(value, UriKind.Absolute) : null - }; + if (context.IsRejected) + { + throw new ProtocolException( + SR.FormatID0374(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } - finally + return new() { - if (scope is IAsyncDisposable disposable) - { - await disposable.DisposeAsync(); - } - - else - { - scope.Dispose(); - } - } + DeviceAuthorizationResponse = context.DeviceAuthorizationResponse ?? new(), + DeviceCode = context.DeviceCode!, + ExpiresIn = TimeSpan.FromSeconds((double) context.DeviceAuthorizationResponse?.ExpiresIn!), + Interval = TimeSpan.FromSeconds((long?) context.DeviceAuthorizationResponse[Parameters.Interval] ?? 5), + Properties = context.Properties, + UserCode = context.UserCode!, + VerificationUri = new Uri(context.DeviceAuthorizationResponse?.VerificationUri!, UriKind.Absolute), + VerificationUriComplete = context.DeviceAuthorizationResponse?.VerificationUriComplete + is string value ? new Uri(value, UriKind.Absolute) : null + }; } /// @@ -877,83 +769,65 @@ public class OpenIddictClientService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); - - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); - - var context = new ProcessAuthenticationContext(transaction) - { - CancellationToken = request.CancellationToken, - DisableUserInfoRetrieval = request.DisableUserInfo, - DisableUserInfoValidation = request.DisableUserInfo, - GrantType = GrantTypes.Password, - Issuer = request.Issuer, - Password = request.Password, - ProviderName = request.ProviderName, - RegistrationId = request.RegistrationId, - TokenRequest = request.AdditionalTokenRequestParameters - is Dictionary parameters ? new(parameters) : new(), - Username = request.Username - }; - - if (request.Scopes is { Count: > 0 }) - { - context.Scopes.UnionWith(request.Scopes); - } - - if (request.Properties is { Count: > 0 }) - { - foreach (var property in request.Properties) - { - context.Properties[property.Key] = property.Value; - } - } + await using var scope = _provider.CreateAsyncScope(); + + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); + var transaction = await factory.CreateTransactionAsync(); + + var context = new ProcessAuthenticationContext(transaction) + { + CancellationToken = request.CancellationToken, + DisableUserInfoRetrieval = request.DisableUserInfo, + DisableUserInfoValidation = request.DisableUserInfo, + GrantType = GrantTypes.Password, + Issuer = request.Issuer, + Password = request.Password, + ProviderName = request.ProviderName, + RegistrationId = request.RegistrationId, + TokenRequest = request.AdditionalTokenRequestParameters + is Dictionary parameters ? new(parameters) : new(), + Username = request.Username + }; - await dispatcher.DispatchAsync(context); + if (request.Scopes is { Count: > 0 }) + { + context.Scopes.UnionWith(request.Scopes); + } - if (context.IsRejected) + if (request.Properties is { Count: > 0 }) + { + foreach (var property in request.Properties) { - throw new ProtocolException( - SR.FormatID0374(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); + context.Properties[property.Key] = property.Value; } + } - Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013)); - Debug.Assert(context.TokenResponse is not null, SR.GetResourceString(SR.ID4007)); + await dispatcher.DispatchAsync(context); - return new() - { - AccessToken = context.BackchannelAccessToken!, - AccessTokenExpirationDate = context.BackchannelAccessTokenExpirationDate, - IdentityToken = context.BackchannelIdentityToken, - IdentityTokenPrincipal = context.BackchannelIdentityTokenPrincipal, - Principal = context.MergedPrincipal, - Properties = context.Properties, - RefreshToken = context.RefreshToken, - TokenResponse = context.TokenResponse, - UserInfoToken = context.UserInfoToken, - UserInfoTokenPrincipal = context.UserInfoTokenPrincipal - }; + if (context.IsRejected) + { + throw new ProtocolException( + SR.FormatID0374(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } - finally - { - if (scope is IAsyncDisposable disposable) - { - await disposable.DisposeAsync(); - } + Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013)); + Debug.Assert(context.TokenResponse is not null, SR.GetResourceString(SR.ID4007)); - else - { - scope.Dispose(); - } - } + return new() + { + AccessToken = context.BackchannelAccessToken!, + AccessTokenExpirationDate = context.BackchannelAccessTokenExpirationDate, + IdentityToken = context.BackchannelIdentityToken, + IdentityTokenPrincipal = context.BackchannelIdentityTokenPrincipal, + Principal = context.MergedPrincipal, + Properties = context.Properties, + RefreshToken = context.RefreshToken, + TokenResponse = context.TokenResponse, + UserInfoToken = context.UserInfoToken, + UserInfoTokenPrincipal = context.UserInfoTokenPrincipal + }; } /// @@ -974,82 +848,64 @@ public class OpenIddictClientService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); - - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); - - var context = new ProcessAuthenticationContext(transaction) - { - CancellationToken = request.CancellationToken, - DisableUserInfoRetrieval = request.DisableUserInfo, - DisableUserInfoValidation = request.DisableUserInfo, - GrantType = GrantTypes.RefreshToken, - Issuer = request.Issuer, - ProviderName = request.ProviderName, - RefreshToken = request.RefreshToken, - RegistrationId = request.RegistrationId, - TokenRequest = request.AdditionalTokenRequestParameters - is Dictionary parameters ? new(parameters) : new(), - }; - - if (request.Scopes is { Count: > 0 }) - { - context.Scopes.UnionWith(request.Scopes); - } - - if (request.Properties is { Count: > 0 }) - { - foreach (var property in request.Properties) - { - context.Properties[property.Key] = property.Value; - } - } + await using var scope = _provider.CreateAsyncScope(); + + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); + var transaction = await factory.CreateTransactionAsync(); + + var context = new ProcessAuthenticationContext(transaction) + { + CancellationToken = request.CancellationToken, + DisableUserInfoRetrieval = request.DisableUserInfo, + DisableUserInfoValidation = request.DisableUserInfo, + GrantType = GrantTypes.RefreshToken, + Issuer = request.Issuer, + ProviderName = request.ProviderName, + RefreshToken = request.RefreshToken, + RegistrationId = request.RegistrationId, + TokenRequest = request.AdditionalTokenRequestParameters + is Dictionary parameters ? new(parameters) : new(), + }; - await dispatcher.DispatchAsync(context); + if (request.Scopes is { Count: > 0 }) + { + context.Scopes.UnionWith(request.Scopes); + } - if (context.IsRejected) + if (request.Properties is { Count: > 0 }) + { + foreach (var property in request.Properties) { - throw new ProtocolException( - SR.FormatID0319(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); + context.Properties[property.Key] = property.Value; } + } - Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013)); - Debug.Assert(context.TokenResponse is not null, SR.GetResourceString(SR.ID4007)); + await dispatcher.DispatchAsync(context); - return new() - { - AccessToken = context.BackchannelAccessToken!, - AccessTokenExpirationDate = context.BackchannelAccessTokenExpirationDate, - IdentityToken = context.BackchannelIdentityToken, - IdentityTokenPrincipal = context.BackchannelIdentityTokenPrincipal, - Principal = context.MergedPrincipal, - Properties = context.Properties, - RefreshToken = context.RefreshToken, - TokenResponse = context.TokenResponse, - UserInfoToken = context.UserInfoToken, - UserInfoTokenPrincipal = context.UserInfoTokenPrincipal - }; + if (context.IsRejected) + { + throw new ProtocolException( + SR.FormatID0319(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } - finally - { - if (scope is IAsyncDisposable disposable) - { - await disposable.DisposeAsync(); - } + Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013)); + Debug.Assert(context.TokenResponse is not null, SR.GetResourceString(SR.ID4007)); - else - { - scope.Dispose(); - } - } + return new() + { + AccessToken = context.BackchannelAccessToken!, + AccessTokenExpirationDate = context.BackchannelAccessTokenExpirationDate, + IdentityToken = context.BackchannelIdentityToken, + IdentityTokenPrincipal = context.BackchannelIdentityTokenPrincipal, + Principal = context.MergedPrincipal, + Properties = context.Properties, + RefreshToken = context.RefreshToken, + TokenResponse = context.TokenResponse, + UserInfoToken = context.UserInfoToken, + UserInfoTokenPrincipal = context.UserInfoTokenPrincipal + }; } /// @@ -1069,68 +925,50 @@ public class OpenIddictClientService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); - - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); - - var context = new ProcessIntrospectionContext(transaction) - { - CancellationToken = request.CancellationToken, - IntrospectionRequest = request.AdditionalIntrospectionRequestParameters - is Dictionary parameters ? new(parameters) : new(), - Issuer = request.Issuer, - ProviderName = request.ProviderName, - RegistrationId = request.RegistrationId, - Token = request.Token, - TokenTypeHint = request.TokenTypeHint - }; - - if (request.Properties is { Count: > 0 }) - { - foreach (var property in request.Properties) - { - context.Properties[property.Key] = property.Value; - } - } - - await dispatcher.DispatchAsync(context); + await using var scope = _provider.CreateAsyncScope(); + + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); + var transaction = await factory.CreateTransactionAsync(); + + var context = new ProcessIntrospectionContext(transaction) + { + CancellationToken = request.CancellationToken, + IntrospectionRequest = request.AdditionalIntrospectionRequestParameters + is Dictionary parameters ? new(parameters) : new(), + Issuer = request.Issuer, + ProviderName = request.ProviderName, + RegistrationId = request.RegistrationId, + Token = request.Token, + TokenTypeHint = request.TokenTypeHint + }; - if (context.IsRejected) + if (request.Properties is { Count: > 0 }) + { + foreach (var property in request.Properties) { - throw new ProtocolException( - SR.FormatID0428(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); + context.Properties[property.Key] = property.Value; } + } - Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013)); - Debug.Assert(context.IntrospectionResponse is not null, SR.GetResourceString(SR.ID4007)); + await dispatcher.DispatchAsync(context); - return new() - { - IntrospectionResponse = context.IntrospectionResponse, - Principal = context.Principal!, - Properties = context.Properties - }; + if (context.IsRejected) + { + throw new ProtocolException( + SR.FormatID0428(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } - finally - { - if (scope is IAsyncDisposable disposable) - { - await disposable.DisposeAsync(); - } + Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013)); + Debug.Assert(context.IntrospectionResponse is not null, SR.GetResourceString(SR.ID4007)); - else - { - scope.Dispose(); - } - } + return new() + { + IntrospectionResponse = context.IntrospectionResponse, + Principal = context.Principal!, + Properties = context.Properties + }; } /// @@ -1150,67 +988,49 @@ public class OpenIddictClientService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); - - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); - - var context = new ProcessRevocationContext(transaction) - { - CancellationToken = request.CancellationToken, - Issuer = request.Issuer, - ProviderName = request.ProviderName, - RegistrationId = request.RegistrationId, - RevocationRequest = request.AdditionalRevocationRequestParameters - is Dictionary parameters ? new(parameters) : new(), - Token = request.Token, - TokenTypeHint = request.TokenTypeHint - }; - - if (request.Properties is { Count: > 0 }) - { - foreach (var property in request.Properties) - { - context.Properties[property.Key] = property.Value; - } - } - - await dispatcher.DispatchAsync(context); + await using var scope = _provider.CreateAsyncScope(); + + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); + var transaction = await factory.CreateTransactionAsync(); + + var context = new ProcessRevocationContext(transaction) + { + CancellationToken = request.CancellationToken, + Issuer = request.Issuer, + ProviderName = request.ProviderName, + RegistrationId = request.RegistrationId, + RevocationRequest = request.AdditionalRevocationRequestParameters + is Dictionary parameters ? new(parameters) : new(), + Token = request.Token, + TokenTypeHint = request.TokenTypeHint + }; - if (context.IsRejected) + if (request.Properties is { Count: > 0 }) + { + foreach (var property in request.Properties) { - throw new ProtocolException( - SR.FormatID0429(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); + context.Properties[property.Key] = property.Value; } + } - Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013)); - Debug.Assert(context.RevocationResponse is not null, SR.GetResourceString(SR.ID4007)); + await dispatcher.DispatchAsync(context); - return new() - { - Properties = context.Properties, - RevocationResponse = context.RevocationResponse - }; + if (context.IsRejected) + { + throw new ProtocolException( + SR.FormatID0429(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } - finally - { - if (scope is IAsyncDisposable disposable) - { - await disposable.DisposeAsync(); - } + Debug.Assert(context.Registration.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013)); + Debug.Assert(context.RevocationResponse is not null, SR.GetResourceString(SR.ID4007)); - else - { - scope.Dispose(); - } - } + return new() + { + Properties = context.Properties, + RevocationResponse = context.RevocationResponse + }; } /// @@ -1243,131 +1063,113 @@ public class OpenIddictClientService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); + var transaction = await factory.CreateTransactionAsync(); - var request = new OpenIddictRequest(); - request = await PrepareConfigurationRequestAsync(); - request = await ApplyConfigurationRequestAsync(); - var response = await ExtractConfigurationResponseAsync(); + var request = new OpenIddictRequest(); + request = await PrepareConfigurationRequestAsync(); + request = await ApplyConfigurationRequestAsync(); + var response = await ExtractConfigurationResponseAsync(); - return await HandleConfigurationResponseAsync() ?? - throw new InvalidOperationException(SR.GetResourceString(SR.ID0145)); + return await HandleConfigurationResponseAsync() ?? + throw new InvalidOperationException(SR.GetResourceString(SR.ID0145)); - async ValueTask PrepareConfigurationRequestAsync() + async ValueTask PrepareConfigurationRequestAsync() + { + var context = new PrepareConfigurationRequestContext(transaction) { - var context = new PrepareConfigurationRequestContext(transaction) - { - CancellationToken = cancellationToken, - RemoteUri = uri, - Registration = registration, - Request = request - }; - - await dispatcher.DispatchAsync(context); - - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0148(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + CancellationToken = cancellationToken, + RemoteUri = uri, + Registration = registration, + Request = request + }; - return context.Request; - } + await dispatcher.DispatchAsync(context); - async ValueTask ApplyConfigurationRequestAsync() + if (context.IsRejected) { - var context = new ApplyConfigurationRequestContext(transaction) - { - CancellationToken = cancellationToken, - RemoteUri = uri, - Registration = registration, - Request = request - }; - - await dispatcher.DispatchAsync(context); + throw new ProtocolException( + SR.FormatID0148(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0149(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + return context.Request; + } - context.Logger.LogInformation(SR.GetResourceString(SR.ID6186), context.RemoteUri, context.Request); + async ValueTask ApplyConfigurationRequestAsync() + { + var context = new ApplyConfigurationRequestContext(transaction) + { + CancellationToken = cancellationToken, + RemoteUri = uri, + Registration = registration, + Request = request + }; - return context.Request; - } + await dispatcher.DispatchAsync(context); - async ValueTask ExtractConfigurationResponseAsync() + if (context.IsRejected) { - var context = new ExtractConfigurationResponseContext(transaction) - { - CancellationToken = cancellationToken, - RemoteUri = uri, - Registration = registration, - Request = request - }; - - await dispatcher.DispatchAsync(context); + throw new ProtocolException( + SR.FormatID0149(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0150(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + context.Logger.LogInformation(SR.GetResourceString(SR.ID6186), context.RemoteUri, context.Request); - Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); + return context.Request; + } - context.Logger.LogInformation(SR.GetResourceString(SR.ID6187), context.RemoteUri, context.Response); + async ValueTask ExtractConfigurationResponseAsync() + { + var context = new ExtractConfigurationResponseContext(transaction) + { + CancellationToken = cancellationToken, + RemoteUri = uri, + Registration = registration, + Request = request + }; - return context.Response; - } + await dispatcher.DispatchAsync(context); - async ValueTask HandleConfigurationResponseAsync() + if (context.IsRejected) { - var context = new HandleConfigurationResponseContext(transaction) - { - CancellationToken = cancellationToken, - RemoteUri = uri, - Registration = registration, - Request = request, - Response = response - }; + throw new ProtocolException( + SR.FormatID0150(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - await dispatcher.DispatchAsync(context); + Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0151(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + context.Logger.LogInformation(SR.GetResourceString(SR.ID6187), context.RemoteUri, context.Response); - return context.Configuration; - } + return context.Response; } - finally + async ValueTask HandleConfigurationResponseAsync() { - if (scope is IAsyncDisposable disposable) + var context = new HandleConfigurationResponseContext(transaction) { - await disposable.DisposeAsync(); - } + CancellationToken = cancellationToken, + RemoteUri = uri, + Registration = registration, + Request = request, + Response = response + }; + + await dispatcher.DispatchAsync(context); - else + if (context.IsRejected) { - scope.Dispose(); + throw new ProtocolException( + SR.FormatID0151(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } + + return context.Configuration; } } @@ -1388,71 +1190,53 @@ public class OpenIddictClientService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); - - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - - var transaction = await factory.CreateTransactionAsync(); + await using var scope = _provider.CreateAsyncScope(); - var context = new ProcessSignOutContext(transaction) - { - CancellationToken = request.CancellationToken, - IdentityTokenHint = request.IdentityTokenHint, - Issuer = request.Issuer, - LoginHint = request.LoginHint, - Principal = new ClaimsPrincipal(new ClaimsIdentity()), - ProviderName = request.ProviderName, - RegistrationId = request.RegistrationId, - Request = request.AdditionalEndSessionRequestParameters - is Dictionary parameters ? new(parameters) : new(), - }; + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); - if (request.Properties is { Count: > 0 }) - { - foreach (var property in request.Properties) - { - context.Properties[property.Key] = property.Value; - } - } + var transaction = await factory.CreateTransactionAsync(); - await dispatcher.DispatchAsync(context); + var context = new ProcessSignOutContext(transaction) + { + CancellationToken = request.CancellationToken, + IdentityTokenHint = request.IdentityTokenHint, + Issuer = request.Issuer, + LoginHint = request.LoginHint, + Principal = new ClaimsPrincipal(new ClaimsIdentity()), + ProviderName = request.ProviderName, + RegistrationId = request.RegistrationId, + Request = request.AdditionalEndSessionRequestParameters + is Dictionary parameters ? new(parameters) : new(), + }; - if (context.IsRejected) + if (request.Properties is { Count: > 0 }) + { + foreach (var property in request.Properties) { - throw new ProtocolException( - message: SR.GetResourceString(SR.ID0434), - context.Error, context.ErrorDescription, context.ErrorUri); + context.Properties[property.Key] = property.Value; } + } - if (string.IsNullOrEmpty(context.Nonce)) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0352)); - } + await dispatcher.DispatchAsync(context); - return new() - { - Nonce = context.Nonce, - Properties = context.Properties - }; + if (context.IsRejected) + { + throw new ProtocolException( + message: SR.GetResourceString(SR.ID0434), + context.Error, context.ErrorDescription, context.ErrorUri); } - finally + if (string.IsNullOrEmpty(context.Nonce)) { - if (scope is IAsyncDisposable disposable) - { - await disposable.DisposeAsync(); - } - - else - { - scope.Dispose(); - } + throw new InvalidOperationException(SR.GetResourceString(SR.ID0352)); } + + return new() + { + Nonce = context.Nonce, + Properties = context.Properties + }; } /// @@ -1485,132 +1269,114 @@ public class OpenIddictClientService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); + var transaction = await factory.CreateTransactionAsync(); - var request = new OpenIddictRequest(); - request = await PrepareJsonWebKeySetRequestAsync(); - request = await ApplyJsonWebKeySetRequestAsync(); + var request = new OpenIddictRequest(); + request = await PrepareJsonWebKeySetRequestAsync(); + request = await ApplyJsonWebKeySetRequestAsync(); - var response = await ExtractJsonWebKeySetResponseAsync(); + var response = await ExtractJsonWebKeySetResponseAsync(); - return await HandleJsonWebKeySetResponseAsync() ?? - throw new InvalidOperationException(SR.GetResourceString(SR.ID0147)); + return await HandleJsonWebKeySetResponseAsync() ?? + throw new InvalidOperationException(SR.GetResourceString(SR.ID0147)); - async ValueTask PrepareJsonWebKeySetRequestAsync() + async ValueTask PrepareJsonWebKeySetRequestAsync() + { + var context = new PrepareJsonWebKeySetRequestContext(transaction) { - var context = new PrepareJsonWebKeySetRequestContext(transaction) - { - CancellationToken = cancellationToken, - RemoteUri = uri, - Registration = registration, - Request = request - }; - - await dispatcher.DispatchAsync(context); - - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0152(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + CancellationToken = cancellationToken, + RemoteUri = uri, + Registration = registration, + Request = request + }; - return context.Request; - } + await dispatcher.DispatchAsync(context); - async ValueTask ApplyJsonWebKeySetRequestAsync() + if (context.IsRejected) { - var context = new ApplyJsonWebKeySetRequestContext(transaction) - { - CancellationToken = cancellationToken, - RemoteUri = uri, - Registration = registration, - Request = request - }; - - await dispatcher.DispatchAsync(context); + throw new ProtocolException( + SR.FormatID0152(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0153(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + return context.Request; + } - context.Logger.LogInformation(SR.GetResourceString(SR.ID6188), context.RemoteUri, context.Request); + async ValueTask ApplyJsonWebKeySetRequestAsync() + { + var context = new ApplyJsonWebKeySetRequestContext(transaction) + { + CancellationToken = cancellationToken, + RemoteUri = uri, + Registration = registration, + Request = request + }; - return context.Request; - } + await dispatcher.DispatchAsync(context); - async ValueTask ExtractJsonWebKeySetResponseAsync() + if (context.IsRejected) { - var context = new ExtractJsonWebKeySetResponseContext(transaction) - { - CancellationToken = cancellationToken, - RemoteUri = uri, - Registration = registration, - Request = request - }; - - await dispatcher.DispatchAsync(context); + throw new ProtocolException( + SR.FormatID0153(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0154(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + context.Logger.LogInformation(SR.GetResourceString(SR.ID6188), context.RemoteUri, context.Request); - Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); + return context.Request; + } - context.Logger.LogInformation(SR.GetResourceString(SR.ID6189), context.RemoteUri, context.Response); + async ValueTask ExtractJsonWebKeySetResponseAsync() + { + var context = new ExtractJsonWebKeySetResponseContext(transaction) + { + CancellationToken = cancellationToken, + RemoteUri = uri, + Registration = registration, + Request = request + }; - return context.Response; - } + await dispatcher.DispatchAsync(context); - async ValueTask HandleJsonWebKeySetResponseAsync() + if (context.IsRejected) { - var context = new HandleJsonWebKeySetResponseContext(transaction) - { - CancellationToken = cancellationToken, - RemoteUri = uri, - Registration = registration, - Request = request, - Response = response - }; + throw new ProtocolException( + SR.FormatID0154(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - await dispatcher.DispatchAsync(context); + Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0155(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + context.Logger.LogInformation(SR.GetResourceString(SR.ID6189), context.RemoteUri, context.Response); - return context.JsonWebKeySet; - } + return context.Response; } - finally + async ValueTask HandleJsonWebKeySetResponseAsync() { - if (scope is IAsyncDisposable disposable) + var context = new HandleJsonWebKeySetResponseContext(transaction) { - await disposable.DisposeAsync(); - } + CancellationToken = cancellationToken, + RemoteUri = uri, + Registration = registration, + Request = request, + Response = response + }; - else + await dispatcher.DispatchAsync(context); + + if (context.IsRejected) { - scope.Dispose(); + throw new ProtocolException( + SR.FormatID0155(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } + + return context.JsonWebKeySet; } } @@ -1658,135 +1424,117 @@ public class OpenIddictClientService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); + var transaction = await factory.CreateTransactionAsync(); - request = await PrepareDeviceAuthorizationRequestAsync(); - request = await ApplyDeviceAuthorizationRequestAsync(); + request = await PrepareDeviceAuthorizationRequestAsync(); + request = await ApplyDeviceAuthorizationRequestAsync(); - var response = await ExtractDeviceAuthorizationResponseAsync(); + var response = await ExtractDeviceAuthorizationResponseAsync(); - return await HandleDeviceAuthorizationResponseAsync(); + return await HandleDeviceAuthorizationResponseAsync(); - async ValueTask PrepareDeviceAuthorizationRequestAsync() + async ValueTask PrepareDeviceAuthorizationRequestAsync() + { + var context = new PrepareDeviceAuthorizationRequestContext(transaction) { - var context = new PrepareDeviceAuthorizationRequestContext(transaction) - { - CancellationToken = cancellationToken, - ClientAuthenticationMethod = method, - RemoteUri = uri, - Configuration = configuration, - Registration = registration, - Request = request - }; - - await dispatcher.DispatchAsync(context); + CancellationToken = cancellationToken, + ClientAuthenticationMethod = method, + RemoteUri = uri, + Configuration = configuration, + Registration = registration, + Request = request + }; - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0398(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + await dispatcher.DispatchAsync(context); - return context.Request; - } - - async ValueTask ApplyDeviceAuthorizationRequestAsync() + if (context.IsRejected) { - var context = new ApplyDeviceAuthorizationRequestContext(transaction) - { - CancellationToken = cancellationToken, - RemoteUri = uri, - Configuration = configuration, - Registration = registration, - Request = request - }; - - await dispatcher.DispatchAsync(context); + throw new ProtocolException( + SR.FormatID0398(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0399(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + return context.Request; + } - context.Logger.LogInformation(SR.GetResourceString(SR.ID6217), context.RemoteUri, context.Request); + async ValueTask ApplyDeviceAuthorizationRequestAsync() + { + var context = new ApplyDeviceAuthorizationRequestContext(transaction) + { + CancellationToken = cancellationToken, + RemoteUri = uri, + Configuration = configuration, + Registration = registration, + Request = request + }; - return context.Request; - } + await dispatcher.DispatchAsync(context); - async ValueTask ExtractDeviceAuthorizationResponseAsync() + if (context.IsRejected) { - var context = new ExtractDeviceAuthorizationResponseContext(transaction) - { - CancellationToken = cancellationToken, - RemoteUri = uri, - Configuration = configuration, - Registration = registration, - Request = request - }; - - await dispatcher.DispatchAsync(context); + throw new ProtocolException( + SR.FormatID0399(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0400(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + context.Logger.LogInformation(SR.GetResourceString(SR.ID6217), context.RemoteUri, context.Request); - Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); + return context.Request; + } - context.Logger.LogInformation(SR.GetResourceString(SR.ID6218), context.RemoteUri, context.Response); + async ValueTask ExtractDeviceAuthorizationResponseAsync() + { + var context = new ExtractDeviceAuthorizationResponseContext(transaction) + { + CancellationToken = cancellationToken, + RemoteUri = uri, + Configuration = configuration, + Registration = registration, + Request = request + }; - return context.Response; - } + await dispatcher.DispatchAsync(context); - async ValueTask HandleDeviceAuthorizationResponseAsync() + if (context.IsRejected) { - var context = new HandleDeviceAuthorizationResponseContext(transaction) - { - CancellationToken = cancellationToken, - RemoteUri = uri, - Configuration = configuration, - Registration = registration, - Request = request, - Response = response - }; + throw new ProtocolException( + SR.FormatID0400(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - await dispatcher.DispatchAsync(context); + Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0401(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + context.Logger.LogInformation(SR.GetResourceString(SR.ID6218), context.RemoteUri, context.Response); - return context.Response; - } + return context.Response; } - finally + async ValueTask HandleDeviceAuthorizationResponseAsync() { - if (scope is IAsyncDisposable disposable) + var context = new HandleDeviceAuthorizationResponseContext(transaction) { - await disposable.DisposeAsync(); - } + CancellationToken = cancellationToken, + RemoteUri = uri, + Configuration = configuration, + Registration = registration, + Request = request, + Response = response + }; - else + await dispatcher.DispatchAsync(context); + + if (context.IsRejected) { - scope.Dispose(); + throw new ProtocolException( + SR.FormatID0401(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } + + return context.Response; } } @@ -1829,137 +1577,119 @@ public class OpenIddictClientService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); + var transaction = await factory.CreateTransactionAsync(); - request = await PrepareIntrospectionRequestAsync(); - request = await ApplyIntrospectionRequestAsync(); + request = await PrepareIntrospectionRequestAsync(); + request = await ApplyIntrospectionRequestAsync(); - var response = await ExtractIntrospectionResponseAsync(); + var response = await ExtractIntrospectionResponseAsync(); - return await HandleIntrospectionResponseAsync(); + return await HandleIntrospectionResponseAsync(); - async ValueTask PrepareIntrospectionRequestAsync() + async ValueTask PrepareIntrospectionRequestAsync() + { + var context = new PrepareIntrospectionRequestContext(transaction) { - var context = new PrepareIntrospectionRequestContext(transaction) - { - CancellationToken = cancellationToken, - ClientAuthenticationMethod = method, - Configuration = configuration, - Registration = registration, - RemoteUri = uri, - Request = request - }; - - await dispatcher.DispatchAsync(context); - - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0158(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + CancellationToken = cancellationToken, + ClientAuthenticationMethod = method, + Configuration = configuration, + Registration = registration, + RemoteUri = uri, + Request = request + }; - return context.Request; - } + await dispatcher.DispatchAsync(context); - async ValueTask ApplyIntrospectionRequestAsync() + if (context.IsRejected) { - var context = new ApplyIntrospectionRequestContext(transaction) - { - CancellationToken = cancellationToken, - Configuration = configuration, - Registration = registration, - RemoteUri = uri, - Request = request - }; - - await dispatcher.DispatchAsync(context); + throw new ProtocolException( + SR.FormatID0158(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0159(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + return context.Request; + } - context.Logger.LogInformation(SR.GetResourceString(SR.ID6192), context.RemoteUri, context.Request); + async ValueTask ApplyIntrospectionRequestAsync() + { + var context = new ApplyIntrospectionRequestContext(transaction) + { + CancellationToken = cancellationToken, + Configuration = configuration, + Registration = registration, + RemoteUri = uri, + Request = request + }; - return context.Request; - } + await dispatcher.DispatchAsync(context); - async ValueTask ExtractIntrospectionResponseAsync() + if (context.IsRejected) { - var context = new ExtractIntrospectionResponseContext(transaction) - { - CancellationToken = cancellationToken, - Configuration = configuration, - Registration = registration, - RemoteUri = uri, - Request = request - }; + throw new ProtocolException( + SR.FormatID0159(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - await dispatcher.DispatchAsync(context); + context.Logger.LogInformation(SR.GetResourceString(SR.ID6192), context.RemoteUri, context.Request); - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0160(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } - - Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); + return context.Request; + } - context.Logger.LogInformation(SR.GetResourceString(SR.ID6193), context.RemoteUri, context.Response); + async ValueTask ExtractIntrospectionResponseAsync() + { + var context = new ExtractIntrospectionResponseContext(transaction) + { + CancellationToken = cancellationToken, + Configuration = configuration, + Registration = registration, + RemoteUri = uri, + Request = request + }; - return context.Response; - } + await dispatcher.DispatchAsync(context); - async ValueTask<(OpenIddictResponse, ClaimsPrincipal)> HandleIntrospectionResponseAsync() + if (context.IsRejected) { - var context = new HandleIntrospectionResponseContext(transaction) - { - CancellationToken = cancellationToken, - Configuration = configuration, - Registration = registration, - RemoteUri = uri, - Request = request, - Response = response - }; + throw new ProtocolException( + SR.FormatID0160(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - await dispatcher.DispatchAsync(context); + Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0161(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } - - Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); + context.Logger.LogInformation(SR.GetResourceString(SR.ID6193), context.RemoteUri, context.Response); - return (context.Response, context.Principal); - } + return context.Response; } - finally + async ValueTask<(OpenIddictResponse, ClaimsPrincipal)> HandleIntrospectionResponseAsync() { - if (scope is IAsyncDisposable disposable) + var context = new HandleIntrospectionResponseContext(transaction) { - await disposable.DisposeAsync(); - } + CancellationToken = cancellationToken, + Configuration = configuration, + Registration = registration, + RemoteUri = uri, + Request = request, + Response = response + }; - else + await dispatcher.DispatchAsync(context); + + if (context.IsRejected) { - scope.Dispose(); + throw new ProtocolException( + SR.FormatID0161(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } + + Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); + + return (context.Response, context.Principal); } } @@ -2007,135 +1737,117 @@ public class OpenIddictClientService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); + var transaction = await factory.CreateTransactionAsync(); - request = await PreparePushedAuthorizationRequestAsync(); - request = await ApplyPushedAuthorizationRequestAsync(); + request = await PreparePushedAuthorizationRequestAsync(); + request = await ApplyPushedAuthorizationRequestAsync(); - var response = await ExtractPushedAuthorizationResponseAsync(); + var response = await ExtractPushedAuthorizationResponseAsync(); - return await HandlePushedAuthorizationResponseAsync(); + return await HandlePushedAuthorizationResponseAsync(); - async ValueTask PreparePushedAuthorizationRequestAsync() + async ValueTask PreparePushedAuthorizationRequestAsync() + { + var context = new PreparePushedAuthorizationRequestContext(transaction) { - var context = new PreparePushedAuthorizationRequestContext(transaction) - { - CancellationToken = cancellationToken, - ClientAuthenticationMethod = method, - RemoteUri = uri, - Configuration = configuration, - Registration = registration, - Request = request - }; - - await dispatcher.DispatchAsync(context); - - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0461(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + CancellationToken = cancellationToken, + ClientAuthenticationMethod = method, + RemoteUri = uri, + Configuration = configuration, + Registration = registration, + Request = request + }; - return context.Request; - } + await dispatcher.DispatchAsync(context); - async ValueTask ApplyPushedAuthorizationRequestAsync() + if (context.IsRejected) { - var context = new ApplyPushedAuthorizationRequestContext(transaction) - { - CancellationToken = cancellationToken, - RemoteUri = uri, - Configuration = configuration, - Registration = registration, - Request = request - }; - - await dispatcher.DispatchAsync(context); + throw new ProtocolException( + SR.FormatID0461(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0462(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + return context.Request; + } - context.Logger.LogInformation(SR.GetResourceString(SR.ID6235), context.RemoteUri, context.Request); + async ValueTask ApplyPushedAuthorizationRequestAsync() + { + var context = new ApplyPushedAuthorizationRequestContext(transaction) + { + CancellationToken = cancellationToken, + RemoteUri = uri, + Configuration = configuration, + Registration = registration, + Request = request + }; - return context.Request; - } + await dispatcher.DispatchAsync(context); - async ValueTask ExtractPushedAuthorizationResponseAsync() + if (context.IsRejected) { - var context = new ExtractPushedAuthorizationResponseContext(transaction) - { - CancellationToken = cancellationToken, - RemoteUri = uri, - Configuration = configuration, - Registration = registration, - Request = request - }; - - await dispatcher.DispatchAsync(context); + throw new ProtocolException( + SR.FormatID0462(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0463(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + context.Logger.LogInformation(SR.GetResourceString(SR.ID6235), context.RemoteUri, context.Request); - Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); + return context.Request; + } - context.Logger.LogInformation(SR.GetResourceString(SR.ID6236), context.RemoteUri, context.Response); + async ValueTask ExtractPushedAuthorizationResponseAsync() + { + var context = new ExtractPushedAuthorizationResponseContext(transaction) + { + CancellationToken = cancellationToken, + RemoteUri = uri, + Configuration = configuration, + Registration = registration, + Request = request + }; - return context.Response; - } + await dispatcher.DispatchAsync(context); - async ValueTask HandlePushedAuthorizationResponseAsync() + if (context.IsRejected) { - var context = new HandlePushedAuthorizationResponseContext(transaction) - { - CancellationToken = cancellationToken, - RemoteUri = uri, - Configuration = configuration, - Registration = registration, - Request = request, - Response = response - }; + throw new ProtocolException( + SR.FormatID0463(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - await dispatcher.DispatchAsync(context); + Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0464(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + context.Logger.LogInformation(SR.GetResourceString(SR.ID6236), context.RemoteUri, context.Response); - return context.Response; - } + return context.Response; } - finally + async ValueTask HandlePushedAuthorizationResponseAsync() { - if (scope is IAsyncDisposable disposable) + var context = new HandlePushedAuthorizationResponseContext(transaction) { - await disposable.DisposeAsync(); - } + CancellationToken = cancellationToken, + RemoteUri = uri, + Configuration = configuration, + Registration = registration, + Request = request, + Response = response + }; + + await dispatcher.DispatchAsync(context); - else + if (context.IsRejected) { - scope.Dispose(); + throw new ProtocolException( + SR.FormatID0464(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } + + return context.Response; } } @@ -2178,135 +1890,117 @@ public class OpenIddictClientService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); + var transaction = await factory.CreateTransactionAsync(); - request = await PrepareRevocationRequestAsync(); - request = await ApplyRevocationRequestAsync(); + request = await PrepareRevocationRequestAsync(); + request = await ApplyRevocationRequestAsync(); - var response = await ExtractRevocationResponseAsync(); + var response = await ExtractRevocationResponseAsync(); - return await HandleRevocationResponseAsync(); + return await HandleRevocationResponseAsync(); - async ValueTask PrepareRevocationRequestAsync() + async ValueTask PrepareRevocationRequestAsync() + { + var context = new PrepareRevocationRequestContext(transaction) { - var context = new PrepareRevocationRequestContext(transaction) - { - CancellationToken = cancellationToken, - ClientAuthenticationMethod = method, - Configuration = configuration, - Registration = registration, - RemoteUri = uri, - Request = request - }; - - await dispatcher.DispatchAsync(context); - - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0430(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + CancellationToken = cancellationToken, + ClientAuthenticationMethod = method, + Configuration = configuration, + Registration = registration, + RemoteUri = uri, + Request = request + }; - return context.Request; - } + await dispatcher.DispatchAsync(context); - async ValueTask ApplyRevocationRequestAsync() + if (context.IsRejected) { - var context = new ApplyRevocationRequestContext(transaction) - { - CancellationToken = cancellationToken, - Configuration = configuration, - Registration = registration, - RemoteUri = uri, - Request = request - }; - - await dispatcher.DispatchAsync(context); + throw new ProtocolException( + SR.FormatID0430(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0431(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + return context.Request; + } - context.Logger.LogInformation(SR.GetResourceString(SR.ID6192), context.RemoteUri, context.Request); + async ValueTask ApplyRevocationRequestAsync() + { + var context = new ApplyRevocationRequestContext(transaction) + { + CancellationToken = cancellationToken, + Configuration = configuration, + Registration = registration, + RemoteUri = uri, + Request = request + }; - return context.Request; - } + await dispatcher.DispatchAsync(context); - async ValueTask ExtractRevocationResponseAsync() + if (context.IsRejected) { - var context = new ExtractRevocationResponseContext(transaction) - { - CancellationToken = cancellationToken, - Configuration = configuration, - Registration = registration, - RemoteUri = uri, - Request = request - }; - - await dispatcher.DispatchAsync(context); + throw new ProtocolException( + SR.FormatID0431(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0432(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + context.Logger.LogInformation(SR.GetResourceString(SR.ID6192), context.RemoteUri, context.Request); - Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); + return context.Request; + } - context.Logger.LogInformation(SR.GetResourceString(SR.ID6193), context.RemoteUri, context.Response); + async ValueTask ExtractRevocationResponseAsync() + { + var context = new ExtractRevocationResponseContext(transaction) + { + CancellationToken = cancellationToken, + Configuration = configuration, + Registration = registration, + RemoteUri = uri, + Request = request + }; - return context.Response; - } + await dispatcher.DispatchAsync(context); - async ValueTask HandleRevocationResponseAsync() + if (context.IsRejected) { - var context = new HandleRevocationResponseContext(transaction) - { - CancellationToken = cancellationToken, - Configuration = configuration, - Registration = registration, - RemoteUri = uri, - Request = request, - Response = response - }; + throw new ProtocolException( + SR.FormatID0432(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - await dispatcher.DispatchAsync(context); + Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0433(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + context.Logger.LogInformation(SR.GetResourceString(SR.ID6193), context.RemoteUri, context.Response); - return context.Response; - } + return context.Response; } - finally + async ValueTask HandleRevocationResponseAsync() { - if (scope is IAsyncDisposable disposable) + var context = new HandleRevocationResponseContext(transaction) { - await disposable.DisposeAsync(); - } + CancellationToken = cancellationToken, + Configuration = configuration, + Registration = registration, + RemoteUri = uri, + Request = request, + Response = response + }; + + await dispatcher.DispatchAsync(context); - else + if (context.IsRejected) { - scope.Dispose(); + throw new ProtocolException( + SR.FormatID0433(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } + + return context.Response; } } @@ -2354,135 +2048,117 @@ public class OpenIddictClientService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); + var transaction = await factory.CreateTransactionAsync(); - request = await PrepareTokenRequestAsync(); - request = await ApplyTokenRequestAsync(); + request = await PrepareTokenRequestAsync(); + request = await ApplyTokenRequestAsync(); - var response = await ExtractTokenResponseAsync(); + var response = await ExtractTokenResponseAsync(); - return await HandleTokenResponseAsync(); + return await HandleTokenResponseAsync(); - async ValueTask PrepareTokenRequestAsync() + async ValueTask PrepareTokenRequestAsync() + { + var context = new PrepareTokenRequestContext(transaction) { - var context = new PrepareTokenRequestContext(transaction) - { - CancellationToken = cancellationToken, - ClientAuthenticationMethod = method, - Configuration = configuration, - Registration = registration, - RemoteUri = uri, - Request = request - }; - - await dispatcher.DispatchAsync(context); - - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0320(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + CancellationToken = cancellationToken, + ClientAuthenticationMethod = method, + Configuration = configuration, + Registration = registration, + RemoteUri = uri, + Request = request + }; - return context.Request; - } + await dispatcher.DispatchAsync(context); - async ValueTask ApplyTokenRequestAsync() + if (context.IsRejected) { - var context = new ApplyTokenRequestContext(transaction) - { - CancellationToken = cancellationToken, - Configuration = configuration, - Registration = registration, - RemoteUri = uri, - Request = request - }; - - await dispatcher.DispatchAsync(context); + throw new ProtocolException( + SR.FormatID0320(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0321(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + return context.Request; + } - context.Logger.LogInformation(SR.GetResourceString(SR.ID6192), context.RemoteUri, context.Request); + async ValueTask ApplyTokenRequestAsync() + { + var context = new ApplyTokenRequestContext(transaction) + { + CancellationToken = cancellationToken, + Configuration = configuration, + Registration = registration, + RemoteUri = uri, + Request = request + }; - return context.Request; - } + await dispatcher.DispatchAsync(context); - async ValueTask ExtractTokenResponseAsync() + if (context.IsRejected) { - var context = new ExtractTokenResponseContext(transaction) - { - CancellationToken = cancellationToken, - Configuration = configuration, - Registration = registration, - RemoteUri = uri, - Request = request - }; - - await dispatcher.DispatchAsync(context); + throw new ProtocolException( + SR.FormatID0321(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0322(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + context.Logger.LogInformation(SR.GetResourceString(SR.ID6192), context.RemoteUri, context.Request); - Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); + return context.Request; + } - context.Logger.LogInformation(SR.GetResourceString(SR.ID6193), context.RemoteUri, context.Response); + async ValueTask ExtractTokenResponseAsync() + { + var context = new ExtractTokenResponseContext(transaction) + { + CancellationToken = cancellationToken, + Configuration = configuration, + Registration = registration, + RemoteUri = uri, + Request = request + }; - return context.Response; - } + await dispatcher.DispatchAsync(context); - async ValueTask HandleTokenResponseAsync() + if (context.IsRejected) { - var context = new HandleTokenResponseContext(transaction) - { - CancellationToken = cancellationToken, - Configuration = configuration, - Registration = registration, - RemoteUri = uri, - Request = request, - Response = response - }; + throw new ProtocolException( + SR.FormatID0322(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - await dispatcher.DispatchAsync(context); + Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0323(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + context.Logger.LogInformation(SR.GetResourceString(SR.ID6193), context.RemoteUri, context.Response); - return context.Response; - } + return context.Response; } - finally + async ValueTask HandleTokenResponseAsync() { - if (scope is IAsyncDisposable disposable) + var context = new HandleTokenResponseContext(transaction) { - await disposable.DisposeAsync(); - } + CancellationToken = cancellationToken, + Configuration = configuration, + Registration = registration, + RemoteUri = uri, + Request = request, + Response = response + }; + + await dispatcher.DispatchAsync(context); - else + if (context.IsRejected) { - scope.Dispose(); + throw new ProtocolException( + SR.FormatID0323(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } + + return context.Response; } } @@ -2525,137 +2201,119 @@ public class OpenIddictClientService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); + var transaction = await factory.CreateTransactionAsync(); - request = await PrepareUserInfoRequestAsync(); - request = await ApplyUserInfoRequestAsync(); + request = await PrepareUserInfoRequestAsync(); + request = await ApplyUserInfoRequestAsync(); - var (response, token) = await ExtractUserInfoResponseAsync(); + var (response, token) = await ExtractUserInfoResponseAsync(); - return await HandleUserInfoResponseAsync(); + return await HandleUserInfoResponseAsync(); - async ValueTask PrepareUserInfoRequestAsync() + async ValueTask PrepareUserInfoRequestAsync() + { + var context = new PrepareUserInfoRequestContext(transaction) { - var context = new PrepareUserInfoRequestContext(transaction) - { - CancellationToken = cancellationToken, - Configuration = configuration, - RemoteUri = uri, - Registration = registration, - Request = request - }; - - context.TokenBindingMethods.UnionWith(methods); - - await dispatcher.DispatchAsync(context); + CancellationToken = cancellationToken, + Configuration = configuration, + RemoteUri = uri, + Registration = registration, + Request = request + }; - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0324(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + context.TokenBindingMethods.UnionWith(methods); - return context.Request; - } + await dispatcher.DispatchAsync(context); - async ValueTask ApplyUserInfoRequestAsync() + if (context.IsRejected) { - var context = new ApplyUserInfoRequestContext(transaction) - { - CancellationToken = cancellationToken, - Configuration = configuration, - RemoteUri = uri, - Registration = registration, - Request = request - }; - - await dispatcher.DispatchAsync(context); + throw new ProtocolException( + SR.FormatID0324(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0325(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + return context.Request; + } - context.Logger.LogInformation(SR.GetResourceString(SR.ID6194), context.RemoteUri, context.Request); + async ValueTask ApplyUserInfoRequestAsync() + { + var context = new ApplyUserInfoRequestContext(transaction) + { + CancellationToken = cancellationToken, + Configuration = configuration, + RemoteUri = uri, + Registration = registration, + Request = request + }; - return context.Request; - } + await dispatcher.DispatchAsync(context); - async ValueTask<(OpenIddictResponse, string?)> ExtractUserInfoResponseAsync() + if (context.IsRejected) { - var context = new ExtractUserInfoResponseContext(transaction) - { - CancellationToken = cancellationToken, - Configuration = configuration, - RemoteUri = uri, - Registration = registration, - Request = request - }; - - await dispatcher.DispatchAsync(context); + throw new ProtocolException( + SR.FormatID0325(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0326(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + context.Logger.LogInformation(SR.GetResourceString(SR.ID6194), context.RemoteUri, context.Request); - Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); + return context.Request; + } - context.Logger.LogInformation(SR.GetResourceString(SR.ID6195), context.RemoteUri, context.Response); + async ValueTask<(OpenIddictResponse, string?)> ExtractUserInfoResponseAsync() + { + var context = new ExtractUserInfoResponseContext(transaction) + { + CancellationToken = cancellationToken, + Configuration = configuration, + RemoteUri = uri, + Registration = registration, + Request = request + }; - return (context.Response, context.UserInfoToken); - } + await dispatcher.DispatchAsync(context); - async ValueTask<(OpenIddictResponse, (ClaimsPrincipal?, string?))> HandleUserInfoResponseAsync() + if (context.IsRejected) { - var context = new HandleUserInfoResponseContext(transaction) - { - CancellationToken = cancellationToken, - Configuration = configuration, - Registration = registration, - RemoteUri = uri, - Request = request, - Response = response, - UserInfoToken = token - }; + throw new ProtocolException( + SR.FormatID0326(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - await dispatcher.DispatchAsync(context); + Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0327(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + context.Logger.LogInformation(SR.GetResourceString(SR.ID6195), context.RemoteUri, context.Response); - return (context.Response, (context.Principal, context.UserInfoToken)); - } + return (context.Response, context.UserInfoToken); } - finally + async ValueTask<(OpenIddictResponse, (ClaimsPrincipal?, string?))> HandleUserInfoResponseAsync() { - if (scope is IAsyncDisposable disposable) + var context = new HandleUserInfoResponseContext(transaction) { - await disposable.DisposeAsync(); - } + CancellationToken = cancellationToken, + Configuration = configuration, + Registration = registration, + RemoteUri = uri, + Request = request, + Response = response, + UserInfoToken = token + }; - else + await dispatcher.DispatchAsync(context); + + if (context.IsRejected) { - scope.Dispose(); + throw new ProtocolException( + SR.FormatID0327(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } + + return (context.Response, (context.Principal, context.UserInfoToken)); } } } diff --git a/src/OpenIddict.Quartz/OpenIddictQuartzJob.cs b/src/OpenIddict.Quartz/OpenIddictQuartzJob.cs index 6fab9690..e297240e 100644 --- a/src/OpenIddict.Quartz/OpenIddictQuartzJob.cs +++ b/src/OpenIddict.Quartz/OpenIddictQuartzJob.cs @@ -55,124 +55,108 @@ public sealed class OpenIddictQuartzJob : IJob // Note: this job is registered as a transient service. As such, it cannot directly depend on scoped services // like the core managers. To work around this limitation, a scope is manually created for each invocation. - var scope = _provider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); - try - { - // Important: since authorizations that still have tokens attached are never - // pruned, the tokens MUST be deleted before deleting the authorizations. - - if (!_options.CurrentValue.DisableTokenPruning) - { - var manager = scope.ServiceProvider.GetService() ?? - throw new JobExecutionException(new InvalidOperationException(SR.GetResourceString(SR.ID0278))) - { - RefireImmediately = false, - UnscheduleAllTriggers = true, - UnscheduleFiringTrigger = true - }; - - var threshold = _options.CurrentValue.TimeProvider.GetUtcNow() - _options.CurrentValue.MinimumTokenLifespan; + // Important: since authorizations that still have tokens attached are never + // pruned, the tokens MUST be deleted before deleting the authorizations. - try + if (!_options.CurrentValue.DisableTokenPruning) + { + var manager = scope.ServiceProvider.GetService() ?? + throw new JobExecutionException(new InvalidOperationException(SR.GetResourceString(SR.ID0278))) { - await manager.PruneAsync(threshold, context.CancellationToken); - } + RefireImmediately = false, + UnscheduleAllTriggers = true, + UnscheduleFiringTrigger = true + }; - // OperationCanceledExceptions are typically thrown when the host is about to shut down. - // To allow the host to shut down as fast as possible, this exception type is special-cased - // to prevent further processing in this job and inform Quartz.NET it shouldn't be refired. - catch (OperationCanceledException exception) when (context.CancellationToken.IsCancellationRequested) - { - throw new JobExecutionException(exception) - { - RefireImmediately = false - }; - } - - // AggregateExceptions are generally thrown by the manager itself when one or multiple exception(s) - // occurred while trying to prune the entities. In this case, add the inner exceptions to the collection. - catch (AggregateException exception) when (!OpenIddictHelpers.IsFatal(exception)) - { - exceptions ??= []; - exceptions.AddRange(exception.InnerExceptions); - } + var threshold = _options.CurrentValue.TimeProvider.GetUtcNow() - _options.CurrentValue.MinimumTokenLifespan; - // Other non-fatal exceptions are assumed to be transient and are added to the exceptions collection - // to be re-thrown later (typically, at the very end of this job, as an AggregateException). - catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception)) + try + { + await manager.PruneAsync(threshold, context.CancellationToken); + } + + // OperationCanceledExceptions are typically thrown when the host is about to shut down. + // To allow the host to shut down as fast as possible, this exception type is special-cased + // to prevent further processing in this job and inform Quartz.NET it shouldn't be refired. + catch (OperationCanceledException exception) when (context.CancellationToken.IsCancellationRequested) + { + throw new JobExecutionException(exception) { - exceptions ??= []; - exceptions.Add(exception); - } + RefireImmediately = false + }; } - if (!_options.CurrentValue.DisableAuthorizationPruning) + // AggregateExceptions are generally thrown by the manager itself when one or multiple exception(s) + // occurred while trying to prune the entities. In this case, add the inner exceptions to the collection. + catch (AggregateException exception) when (!OpenIddictHelpers.IsFatal(exception)) { - var manager = scope.ServiceProvider.GetService() ?? - throw new JobExecutionException(new InvalidOperationException(SR.GetResourceString(SR.ID0278))) - { - RefireImmediately = false, - UnscheduleAllTriggers = true, - UnscheduleFiringTrigger = true - }; + exceptions ??= []; + exceptions.AddRange(exception.InnerExceptions); + } - var threshold = _options.CurrentValue.TimeProvider.GetUtcNow() - _options.CurrentValue.MinimumAuthorizationLifespan; + // Other non-fatal exceptions are assumed to be transient and are added to the exceptions collection + // to be re-thrown later (typically, at the very end of this job, as an AggregateException). + catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception)) + { + exceptions ??= []; + exceptions.Add(exception); + } + } - try + if (!_options.CurrentValue.DisableAuthorizationPruning) + { + var manager = scope.ServiceProvider.GetService() ?? + throw new JobExecutionException(new InvalidOperationException(SR.GetResourceString(SR.ID0278))) { - await manager.PruneAsync(threshold, context.CancellationToken); - } + RefireImmediately = false, + UnscheduleAllTriggers = true, + UnscheduleFiringTrigger = true + }; - // OperationCanceledExceptions are typically thrown when the host is about to shut down. - // To allow the host to shut down as fast as possible, this exception type is special-cased - // to prevent further processing in this job and inform Quartz.NET it shouldn't be refired. - catch (OperationCanceledException exception) when (context.CancellationToken.IsCancellationRequested) - { - throw new JobExecutionException(exception) - { - RefireImmediately = false - }; - } - - // AggregateExceptions are generally thrown by the manager itself when one or multiple exception(s) - // occurred while trying to prune the entities. In this case, add the inner exceptions to the collection. - catch (AggregateException exception) when (!OpenIddictHelpers.IsFatal(exception)) - { - exceptions ??= []; - exceptions.AddRange(exception.InnerExceptions); - } + var threshold = _options.CurrentValue.TimeProvider.GetUtcNow() - _options.CurrentValue.MinimumAuthorizationLifespan; - // Other non-fatal exceptions are assumed to be transient and are added to the exceptions collection - // to be re-thrown later (typically, at the very end of this job, as an AggregateException). - catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception)) - { - exceptions ??= []; - exceptions.Add(exception); - } + try + { + await manager.PruneAsync(threshold, context.CancellationToken); } - if (exceptions is not null) + // OperationCanceledExceptions are typically thrown when the host is about to shut down. + // To allow the host to shut down as fast as possible, this exception type is special-cased + // to prevent further processing in this job and inform Quartz.NET it shouldn't be refired. + catch (OperationCanceledException exception) when (context.CancellationToken.IsCancellationRequested) { - throw new JobExecutionException(new AggregateException(exceptions)) + throw new JobExecutionException(exception) { - // Only refire the job if the maximum refire count set in the options wasn't reached. - RefireImmediately = context.RefireCount < _options.CurrentValue.MaximumRefireCount + RefireImmediately = false }; } - } - finally - { - if (scope is IAsyncDisposable disposable) + // AggregateExceptions are generally thrown by the manager itself when one or multiple exception(s) + // occurred while trying to prune the entities. In this case, add the inner exceptions to the collection. + catch (AggregateException exception) when (!OpenIddictHelpers.IsFatal(exception)) { - await disposable.DisposeAsync(); + exceptions ??= []; + exceptions.AddRange(exception.InnerExceptions); } - else + // Other non-fatal exceptions are assumed to be transient and are added to the exceptions collection + // to be re-thrown later (typically, at the very end of this job, as an AggregateException). + catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception)) { - scope.Dispose(); + exceptions ??= []; + exceptions.Add(exception); } } + + if (exceptions is not null) + { + throw new JobExecutionException(new AggregateException(exceptions)) + { + // Only refire the job if the maximum refire count set in the options wasn't reached. + RefireImmediately = context.RefireCount < _options.CurrentValue.MaximumRefireCount + }; + } } } diff --git a/src/OpenIddict.Validation/OpenIddictValidationService.cs b/src/OpenIddict.Validation/OpenIddictValidationService.cs index 453d4a16..ec3d23de 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationService.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationService.cs @@ -46,47 +46,29 @@ public class OpenIddictValidationService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); + var transaction = await factory.CreateTransactionAsync(); - var context = new ProcessAuthenticationContext(transaction) - { - AccessToken = token - }; - - await dispatcher.DispatchAsync(context); - - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0163(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + var context = new ProcessAuthenticationContext(transaction) + { + AccessToken = token + }; - Debug.Assert(context.AccessTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); + await dispatcher.DispatchAsync(context); - return context.AccessTokenPrincipal; + if (context.IsRejected) + { + throw new ProtocolException( + SR.FormatID0163(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } - finally - { - if (scope is IAsyncDisposable disposable) - { - await disposable.DisposeAsync(); - } + Debug.Assert(context.AccessTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); - else - { - scope.Dispose(); - } - } + return context.AccessTokenPrincipal; } /// @@ -112,123 +94,105 @@ public class OpenIddictValidationService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); + var transaction = await factory.CreateTransactionAsync(); - var request = new OpenIddictRequest(); - request = await PrepareConfigurationRequestAsync(); - request = await ApplyConfigurationRequestAsync(); - var response = await ExtractConfigurationResponseAsync(); + var request = new OpenIddictRequest(); + request = await PrepareConfigurationRequestAsync(); + request = await ApplyConfigurationRequestAsync(); + var response = await ExtractConfigurationResponseAsync(); - return await HandleConfigurationResponseAsync() ?? - throw new InvalidOperationException(SR.GetResourceString(SR.ID0145)); + return await HandleConfigurationResponseAsync() ?? + throw new InvalidOperationException(SR.GetResourceString(SR.ID0145)); - async ValueTask PrepareConfigurationRequestAsync() + async ValueTask PrepareConfigurationRequestAsync() + { + var context = new PrepareConfigurationRequestContext(transaction) { - var context = new PrepareConfigurationRequestContext(transaction) - { - RemoteUri = uri, - Request = request - }; - - await dispatcher.DispatchAsync(context); - - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0148(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } - - return context.Request; - } + RemoteUri = uri, + Request = request + }; - async ValueTask ApplyConfigurationRequestAsync() - { - var context = new ApplyConfigurationRequestContext(transaction) - { - RemoteUri = uri, - Request = request - }; + await dispatcher.DispatchAsync(context); - await dispatcher.DispatchAsync(context); + if (context.IsRejected) + { + throw new ProtocolException( + SR.FormatID0148(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0149(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + return context.Request; + } - context.Logger.LogInformation(SR.GetResourceString(SR.ID6186), context.RemoteUri, context.Request); + async ValueTask ApplyConfigurationRequestAsync() + { + var context = new ApplyConfigurationRequestContext(transaction) + { + RemoteUri = uri, + Request = request + }; - return context.Request; - } + await dispatcher.DispatchAsync(context); - async ValueTask ExtractConfigurationResponseAsync() + if (context.IsRejected) { - var context = new ExtractConfigurationResponseContext(transaction) - { - RemoteUri = uri, - Request = request - }; - - await dispatcher.DispatchAsync(context); + throw new ProtocolException( + SR.FormatID0149(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0150(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + context.Logger.LogInformation(SR.GetResourceString(SR.ID6186), context.RemoteUri, context.Request); - Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); + return context.Request; + } - context.Logger.LogInformation(SR.GetResourceString(SR.ID6187), context.RemoteUri, context.Response); + async ValueTask ExtractConfigurationResponseAsync() + { + var context = new ExtractConfigurationResponseContext(transaction) + { + RemoteUri = uri, + Request = request + }; - return context.Response; - } + await dispatcher.DispatchAsync(context); - async ValueTask HandleConfigurationResponseAsync() + if (context.IsRejected) { - var context = new HandleConfigurationResponseContext(transaction) - { - RemoteUri = uri, - Request = request, - Response = response - }; - - await dispatcher.DispatchAsync(context); - - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0151(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } - - return context.Configuration; + throw new ProtocolException( + SR.FormatID0150(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } + + Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); + + context.Logger.LogInformation(SR.GetResourceString(SR.ID6187), context.RemoteUri, context.Response); + + return context.Response; } - finally + async ValueTask HandleConfigurationResponseAsync() { - if (scope is IAsyncDisposable disposable) + var context = new HandleConfigurationResponseContext(transaction) { - await disposable.DisposeAsync(); - } + RemoteUri = uri, + Request = request, + Response = response + }; + + await dispatcher.DispatchAsync(context); - else + if (context.IsRejected) { - scope.Dispose(); + throw new ProtocolException( + SR.FormatID0151(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } + + return context.Configuration; } } @@ -255,123 +219,105 @@ public class OpenIddictValidationService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); + var transaction = await factory.CreateTransactionAsync(); - var request = new OpenIddictRequest(); - request = await PrepareJsonWebKeySetRequestAsync(); - request = await ApplyJsonWebKeySetRequestAsync(); + var request = new OpenIddictRequest(); + request = await PrepareJsonWebKeySetRequestAsync(); + request = await ApplyJsonWebKeySetRequestAsync(); - var response = await ExtractJsonWebKeySetResponseAsync(); + var response = await ExtractJsonWebKeySetResponseAsync(); - return await HandleJsonWebKeySetResponseAsync() ?? - throw new InvalidOperationException(SR.GetResourceString(SR.ID0147)); + return await HandleJsonWebKeySetResponseAsync() ?? + throw new InvalidOperationException(SR.GetResourceString(SR.ID0147)); - async ValueTask PrepareJsonWebKeySetRequestAsync() + async ValueTask PrepareJsonWebKeySetRequestAsync() + { + var context = new PrepareJsonWebKeySetRequestContext(transaction) { - var context = new PrepareJsonWebKeySetRequestContext(transaction) - { - RemoteUri = uri, - Request = request - }; - - await dispatcher.DispatchAsync(context); - - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0152(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } - - return context.Request; - } + RemoteUri = uri, + Request = request + }; - async ValueTask ApplyJsonWebKeySetRequestAsync() - { - var context = new ApplyJsonWebKeySetRequestContext(transaction) - { - RemoteUri = uri, - Request = request - }; + await dispatcher.DispatchAsync(context); - await dispatcher.DispatchAsync(context); + if (context.IsRejected) + { + throw new ProtocolException( + SR.FormatID0152(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0153(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + return context.Request; + } - context.Logger.LogInformation(SR.GetResourceString(SR.ID6188), context.RemoteUri, context.Request); + async ValueTask ApplyJsonWebKeySetRequestAsync() + { + var context = new ApplyJsonWebKeySetRequestContext(transaction) + { + RemoteUri = uri, + Request = request + }; - return context.Request; - } + await dispatcher.DispatchAsync(context); - async ValueTask ExtractJsonWebKeySetResponseAsync() + if (context.IsRejected) { - var context = new ExtractJsonWebKeySetResponseContext(transaction) - { - RemoteUri = uri, - Request = request - }; - - await dispatcher.DispatchAsync(context); + throw new ProtocolException( + SR.FormatID0153(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0154(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + context.Logger.LogInformation(SR.GetResourceString(SR.ID6188), context.RemoteUri, context.Request); - Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); + return context.Request; + } - context.Logger.LogInformation(SR.GetResourceString(SR.ID6189), context.RemoteUri, context.Response); + async ValueTask ExtractJsonWebKeySetResponseAsync() + { + var context = new ExtractJsonWebKeySetResponseContext(transaction) + { + RemoteUri = uri, + Request = request + }; - return context.Response; - } + await dispatcher.DispatchAsync(context); - async ValueTask HandleJsonWebKeySetResponseAsync() + if (context.IsRejected) { - var context = new HandleJsonWebKeySetResponseContext(transaction) - { - Request = request, - Response = response - }; - - await dispatcher.DispatchAsync(context); - - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0155(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } - - return context.SecurityKeys; + throw new ProtocolException( + SR.FormatID0154(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } + + Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); + + context.Logger.LogInformation(SR.GetResourceString(SR.ID6189), context.RemoteUri, context.Response); + + return context.Response; } - finally + async ValueTask HandleJsonWebKeySetResponseAsync() { - if (scope is IAsyncDisposable disposable) + var context = new HandleJsonWebKeySetResponseContext(transaction) { - await disposable.DisposeAsync(); - } + Request = request, + Response = response + }; + + await dispatcher.DispatchAsync(context); - else + if (context.IsRejected) { - scope.Dispose(); + throw new ProtocolException( + SR.FormatID0155(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } + + return context.SecurityKeys; } } @@ -413,133 +359,115 @@ public class OpenIddictValidationService // Note: this service is registered as a singleton service. As such, it cannot // directly depend on scoped services like the validation provider. To work around // this limitation, a scope is manually created for each method to this service. - var scope = _provider.CreateScope(); + await using var scope = _provider.CreateAsyncScope(); - // Note: a try/finally block is deliberately used here to ensure the service scope - // can be disposed of asynchronously if it implements IAsyncDisposable. - try - { - var dispatcher = scope.ServiceProvider.GetRequiredService(); - var factory = scope.ServiceProvider.GetRequiredService(); - var transaction = await factory.CreateTransactionAsync(); + var dispatcher = scope.ServiceProvider.GetRequiredService(); + var factory = scope.ServiceProvider.GetRequiredService(); + var transaction = await factory.CreateTransactionAsync(); - request = await PrepareIntrospectionRequestAsync(); - request = await ApplyIntrospectionRequestAsync(); + request = await PrepareIntrospectionRequestAsync(); + request = await ApplyIntrospectionRequestAsync(); - var response = await ExtractIntrospectionResponseAsync(); + var response = await ExtractIntrospectionResponseAsync(); - return await HandleIntrospectionResponseAsync(); + return await HandleIntrospectionResponseAsync(); - async ValueTask PrepareIntrospectionRequestAsync() + async ValueTask PrepareIntrospectionRequestAsync() + { + var context = new PrepareIntrospectionRequestContext(transaction) { - var context = new PrepareIntrospectionRequestContext(transaction) - { - CancellationToken = cancellationToken, - ClientAuthenticationMethod = method, - RemoteUri = uri, - Configuration = configuration, - Request = request - }; - - await dispatcher.DispatchAsync(context); - - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0158(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } - - return context.Request; - } + CancellationToken = cancellationToken, + ClientAuthenticationMethod = method, + RemoteUri = uri, + Configuration = configuration, + Request = request + }; + + await dispatcher.DispatchAsync(context); - async ValueTask ApplyIntrospectionRequestAsync() + if (context.IsRejected) { - var context = new ApplyIntrospectionRequestContext(transaction) - { - CancellationToken = cancellationToken, - RemoteUri = uri, - Configuration = configuration, - Request = request - }; - - await dispatcher.DispatchAsync(context); - - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0159(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } - - context.Logger.LogInformation(SR.GetResourceString(SR.ID6192), context.RemoteUri, context.Request); - - return context.Request; + throw new ProtocolException( + SR.FormatID0158(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } - async ValueTask ExtractIntrospectionResponseAsync() + return context.Request; + } + + async ValueTask ApplyIntrospectionRequestAsync() + { + var context = new ApplyIntrospectionRequestContext(transaction) { - var context = new ExtractIntrospectionResponseContext(transaction) - { - CancellationToken = cancellationToken, - RemoteUri = uri, - Configuration = configuration, - Request = request - }; + CancellationToken = cancellationToken, + RemoteUri = uri, + Configuration = configuration, + Request = request + }; - await dispatcher.DispatchAsync(context); + await dispatcher.DispatchAsync(context); - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0160(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } + if (context.IsRejected) + { + throw new ProtocolException( + SR.FormatID0159(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); + } - Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); + context.Logger.LogInformation(SR.GetResourceString(SR.ID6192), context.RemoteUri, context.Request); - context.Logger.LogInformation(SR.GetResourceString(SR.ID6193), context.RemoteUri, context.Response); + return context.Request; + } - return context.Response; - } + async ValueTask ExtractIntrospectionResponseAsync() + { + var context = new ExtractIntrospectionResponseContext(transaction) + { + CancellationToken = cancellationToken, + RemoteUri = uri, + Configuration = configuration, + Request = request + }; + + await dispatcher.DispatchAsync(context); - async ValueTask<(OpenIddictResponse, ClaimsPrincipal)> HandleIntrospectionResponseAsync() + if (context.IsRejected) { - var context = new HandleIntrospectionResponseContext(transaction) - { - CancellationToken = cancellationToken, - RemoteUri = uri, - Configuration = configuration, - Request = request, - Response = response - }; - - await dispatcher.DispatchAsync(context); - - if (context.IsRejected) - { - throw new ProtocolException( - SR.FormatID0161(context.Error, context.ErrorDescription, context.ErrorUri), - context.Error, context.ErrorDescription, context.ErrorUri); - } - - Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); - - return (context.Response, context.Principal); + throw new ProtocolException( + SR.FormatID0160(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } + + Debug.Assert(context.Response is not null, SR.GetResourceString(SR.ID4007)); + + context.Logger.LogInformation(SR.GetResourceString(SR.ID6193), context.RemoteUri, context.Response); + + return context.Response; } - finally + async ValueTask<(OpenIddictResponse, ClaimsPrincipal)> HandleIntrospectionResponseAsync() { - if (scope is IAsyncDisposable disposable) + var context = new HandleIntrospectionResponseContext(transaction) { - await disposable.DisposeAsync(); - } + CancellationToken = cancellationToken, + RemoteUri = uri, + Configuration = configuration, + Request = request, + Response = response + }; - else + await dispatcher.DispatchAsync(context); + + if (context.IsRejected) { - scope.Dispose(); + throw new ProtocolException( + SR.FormatID0161(context.Error, context.ErrorDescription, context.ErrorUri), + context.Error, context.ErrorDescription, context.ErrorUri); } + + Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); + + return (context.Response, context.Principal); } } } diff --git a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs index e9deeaab..2b11d0f1 100644 --- a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs +++ b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs @@ -579,7 +579,7 @@ public partial class OpenIddictServerOwinIntegrationTests : OpenIddictServerInte { app.Use(async (context, next) => { - using var scope = provider.CreateScope(); + await using var scope = provider.CreateAsyncScope(); context.Set(typeof(IServiceProvider).FullName, scope.ServiceProvider); diff --git a/test/OpenIddict.Validation.Owin.IntegrationTests/OpenIddictValidationOwinIntegrationTests.cs b/test/OpenIddict.Validation.Owin.IntegrationTests/OpenIddictValidationOwinIntegrationTests.cs index e2a11407..ac27ccc2 100644 --- a/test/OpenIddict.Validation.Owin.IntegrationTests/OpenIddictValidationOwinIntegrationTests.cs +++ b/test/OpenIddict.Validation.Owin.IntegrationTests/OpenIddictValidationOwinIntegrationTests.cs @@ -128,7 +128,7 @@ public partial class OpenIddictValidationOwinIntegrationTests : OpenIddictValida { app.Use(async (context, next) => { - using var scope = provider.CreateScope(); + await using var scope = provider.CreateAsyncScope(); context.Set(typeof(IServiceProvider).FullName, scope.ServiceProvider);