Browse Source

Allow cooperative cancellation of metadata retrieval and HTTP requests

pull/1695/head
Kévin Chalet 3 years ago
parent
commit
ec1b122282
  1. 4
      src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandlers.cs
  2. 2
      src/OpenIddict.Client.Owin/OpenIddictClientOwinHandlers.cs
  3. 5
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs
  4. 16
      src/OpenIddict.Client/OpenIddictClientHandlers.cs
  5. 24
      src/OpenIddict.Client/OpenIddictClientService.cs
  6. 8
      src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandlers.cs
  7. 4
      src/OpenIddict.Server.Owin/OpenIddictServerOwinHandlers.cs
  8. 2
      src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandlers.cs
  9. 5
      src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs
  10. 5
      src/OpenIddict.Validation/OpenIddictValidationHandlers.cs
  11. 9
      src/OpenIddict.Validation/OpenIddictValidationService.cs

4
src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandlers.cs

@ -277,7 +277,7 @@ public static partial class OpenIddictClientAspNetCoreHandlers
return;
}
context.Transaction.Request = new OpenIddictRequest(await request.ReadFormAsync(request.HttpContext.RequestAborted));
context.Transaction.Request = new OpenIddictRequest(await request.ReadFormAsync(context.CancellationToken));
}
else
@ -1201,7 +1201,7 @@ public static partial class OpenIddictClientAspNetCoreHandlers
response.ContentType = "text/plain;charset=UTF-8";
stream.Seek(offset: 0, loc: SeekOrigin.Begin);
await stream.CopyToAsync(response.Body, 4096, response.HttpContext.RequestAborted);
await stream.CopyToAsync(response.Body, 4096, context.CancellationToken);
context.HandleRequest();
}

2
src/OpenIddict.Client.Owin/OpenIddictClientOwinHandlers.cs

@ -1325,7 +1325,7 @@ public static partial class OpenIddictClientOwinHandlers
response.ContentType = "text/plain;charset=UTF-8";
stream.Seek(offset: 0, loc: SeekOrigin.Begin);
await stream.CopyToAsync(response.Body, 4096, response.Context.Request.CallCancelled);
await stream.CopyToAsync(response.Body, 4096, context.CancellationToken);
context.HandleRequest();
}

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

@ -442,7 +442,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
// response stream to be buffered so that can it can be read multiple times if needed
// (e.g if the JSON deserialization process fails, the stream is read as a string
// during a second pass a second time for logging/debuggability purposes).
response = await client.SendAsync(request, HttpCompletionOption.ResponseContentRead);
response = await client.SendAsync(request, HttpCompletionOption.ResponseContentRead, context.CancellationToken);
}
// If an exception is thrown at this stage, this likely means a persistent network error occurred.
@ -689,7 +689,8 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
{
// Note: ReadFromJsonAsync() automatically validates the content encoding and transparently
// transcodes the response stream if a non-UTF-8 response is returned by the remote server.
context.Transaction.Response = await response.Content.ReadFromJsonAsync<OpenIddictResponse>();
context.Transaction.Response = await response.Content.ReadFromJsonAsync<OpenIddictResponse>(
cancellationToken: context.CancellationToken);
}
// If an exception is thrown at this stage, this likely means the returned response was not a valid

16
src/OpenIddict.Client/OpenIddictClientHandlers.cs

@ -364,7 +364,9 @@ public static partial class OpenIddictClientHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0292));
// Resolve and attach the server configuration to the context if none has been set already.
context.Configuration ??= await context.Registration.ConfigurationManager.GetConfigurationAsync(default) ??
context.Configuration ??= await context.Registration.ConfigurationManager
.GetConfigurationAsync(context.CancellationToken)
.WaitAsync(context.CancellationToken) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0140));
// Ensure the selected grant type, if explicitly set, is listed as supported in the configuration.
@ -954,7 +956,9 @@ public static partial class OpenIddictClientHandlers
}
// Resolve and attach the server configuration to the context.
context.Configuration = await context.Registration.ConfigurationManager.GetConfigurationAsync(default) ??
context.Configuration = await context.Registration.ConfigurationManager
.GetConfigurationAsync(context.CancellationToken)
.WaitAsync(context.CancellationToken) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0140));
}
}
@ -3903,7 +3907,9 @@ public static partial class OpenIddictClientHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0292));
// Resolve and attach the server configuration to the context if none has been set already.
context.Configuration ??= await context.Registration.ConfigurationManager.GetConfigurationAsync(default) ??
context.Configuration ??= await context.Registration.ConfigurationManager
.GetConfigurationAsync(context.CancellationToken)
.WaitAsync(context.CancellationToken) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0140));
}
}
@ -4977,7 +4983,9 @@ public static partial class OpenIddictClientHandlers
throw new InvalidOperationException(SR.GetResourceString(SR.ID0292));
// Resolve and attach the server configuration to the context if none has been set already.
context.Configuration ??= await context.Registration.ConfigurationManager.GetConfigurationAsync(default) ??
context.Configuration ??= await context.Registration.ConfigurationManager
.GetConfigurationAsync(context.CancellationToken)
.WaitAsync(context.CancellationToken) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0140));
}
}

24
src/OpenIddict.Client/OpenIddictClientService.cs

@ -183,7 +183,9 @@ public sealed class OpenIddictClientService
throw new ArgumentException(SR.GetResourceString(SR.ID0074), nameof(scopes));
}
var configuration = await registration.ConfigurationManager.GetConfigurationAsync(default) ??
var configuration = await registration.ConfigurationManager
.GetConfigurationAsync(cancellationToken)
.WaitAsync(cancellationToken) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0140));
cancellationToken.ThrowIfCancellationRequested();
@ -333,7 +335,9 @@ public sealed class OpenIddictClientService
throw new ArgumentException(SR.GetResourceString(SR.ID0074), nameof(scopes));
}
var configuration = await registration.ConfigurationManager.GetConfigurationAsync(default) ??
var configuration = await registration.ConfigurationManager
.GetConfigurationAsync(cancellationToken)
.WaitAsync(cancellationToken) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0140));
if (configuration.TokenEndpoint is not { IsAbsoluteUri: true } uri || !uri.IsWellFormedOriginalString())
@ -505,7 +509,9 @@ public sealed class OpenIddictClientService
throw new ArgumentException(SR.GetResourceString(SR.ID0074), nameof(scopes));
}
var configuration = await registration.ConfigurationManager.GetConfigurationAsync(default) ??
var configuration = await registration.ConfigurationManager
.GetConfigurationAsync(cancellationToken)
.WaitAsync(cancellationToken) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0140));
if (configuration.TokenEndpoint is not { IsAbsoluteUri: true } uri || !uri.IsWellFormedOriginalString())
@ -671,7 +677,9 @@ public sealed class OpenIddictClientService
throw new ArgumentException(SR.GetResourceString(SR.ID0074), nameof(scopes));
}
var configuration = await registration.ConfigurationManager.GetConfigurationAsync(default) ??
var configuration = await registration.ConfigurationManager
.GetConfigurationAsync(cancellationToken)
.WaitAsync(cancellationToken) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0140));
if (configuration.TokenEndpoint is not { IsAbsoluteUri: true } uri || !uri.IsWellFormedOriginalString())
@ -1100,7 +1108,9 @@ public sealed class OpenIddictClientService
throw new ArgumentException(SR.GetResourceString(SR.ID0144), nameof(uri));
}
var configuration = await registration.ConfigurationManager.GetConfigurationAsync(default) ??
var configuration = await registration.ConfigurationManager
.GetConfigurationAsync(cancellationToken)
.WaitAsync(cancellationToken) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0140));
cancellationToken.ThrowIfCancellationRequested();
@ -1265,7 +1275,9 @@ public sealed class OpenIddictClientService
throw new ArgumentException(SR.GetResourceString(SR.ID0144), nameof(uri));
}
var configuration = await registration.ConfigurationManager.GetConfigurationAsync(default) ??
var configuration = await registration.ConfigurationManager
.GetConfigurationAsync(cancellationToken)
.WaitAsync(cancellationToken) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0140));
cancellationToken.ThrowIfCancellationRequested();

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

@ -549,7 +549,7 @@ public static partial class OpenIddictServerAspNetCoreHandlers
return;
}
context.Transaction.Request = new OpenIddictRequest(await request.ReadFormAsync(request.HttpContext.RequestAborted));
context.Transaction.Request = new OpenIddictRequest(await request.ReadFormAsync(context.CancellationToken));
}
else
@ -624,7 +624,7 @@ public static partial class OpenIddictServerAspNetCoreHandlers
return;
}
context.Transaction.Request = new OpenIddictRequest(await request.ReadFormAsync(request.HttpContext.RequestAborted));
context.Transaction.Request = new OpenIddictRequest(await request.ReadFormAsync(context.CancellationToken));
}
else
@ -1134,7 +1134,7 @@ public static partial class OpenIddictServerAspNetCoreHandlers
response.ContentType = "application/json;charset=UTF-8";
stream.Seek(offset: 0, loc: SeekOrigin.Begin);
await stream.CopyToAsync(response.Body, 4096, response.HttpContext.RequestAborted);
await stream.CopyToAsync(response.Body, 4096, context.CancellationToken);
context.HandleRequest();
}
@ -1308,7 +1308,7 @@ public static partial class OpenIddictServerAspNetCoreHandlers
response.ContentType = "text/plain;charset=UTF-8";
stream.Seek(offset: 0, loc: SeekOrigin.Begin);
await stream.CopyToAsync(response.Body, 4096, response.HttpContext.RequestAborted);
await stream.CopyToAsync(response.Body, 4096, context.CancellationToken);
context.HandleRequest();
}

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

@ -1306,7 +1306,7 @@ public static partial class OpenIddictServerOwinHandlers
response.ContentType = "application/json;charset=UTF-8";
stream.Seek(offset: 0, loc: SeekOrigin.Begin);
await stream.CopyToAsync(response.Body, 4096, response.Context.Request.CallCancelled);
await stream.CopyToAsync(response.Body, 4096, context.CancellationToken);
context.HandleRequest();
}
@ -1426,7 +1426,7 @@ public static partial class OpenIddictServerOwinHandlers
response.ContentType = "text/plain;charset=UTF-8";
stream.Seek(offset: 0, loc: SeekOrigin.Begin);
await stream.CopyToAsync(response.Body, 4096, response.Context.Request.CallCancelled);
await stream.CopyToAsync(response.Body, 4096, context.CancellationToken);
context.HandleRequest();
}

2
src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandlers.cs

@ -264,7 +264,7 @@ public static partial class OpenIddictValidationAspNetCoreHandlers
// Resolve the access token from the standard access_token form parameter.
// See https://tools.ietf.org/html/rfc6750#section-2.2 for more information.
var form = await request.ReadFormAsync(request.HttpContext.RequestAborted);
var form = await request.ReadFormAsync(context.CancellationToken);
if (form.TryGetValue(Parameters.AccessToken, out StringValues token))
{
context.AccessToken = token;

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

@ -441,7 +441,7 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
// response stream to be buffered so that can it can be read multiple times if needed
// (e.g if the JSON deserialization process fails, the stream is read as a string
// during a second pass a second time for logging/debuggability purposes).
response = await client.SendAsync(request, HttpCompletionOption.ResponseContentRead);
response = await client.SendAsync(request, HttpCompletionOption.ResponseContentRead, context.CancellationToken);
}
// If an exception is thrown at this stage, this likely means a persistent network error occurred.
@ -688,7 +688,8 @@ public static partial class OpenIddictValidationSystemNetHttpHandlers
{
// Note: ReadFromJsonAsync() automatically validates the content encoding and transparently
// transcodes the response stream if a non-UTF-8 response is returned by the remote server.
context.Transaction.Response = await response.Content.ReadFromJsonAsync<OpenIddictResponse>();
context.Transaction.Response = await response.Content.ReadFromJsonAsync<OpenIddictResponse>(
cancellationToken: context.CancellationToken);
}
// If an exception is thrown at this stage, this likely means the returned response was not a valid

5
src/OpenIddict.Validation/OpenIddictValidationHandlers.cs

@ -6,6 +6,7 @@
using System.Collections.Immutable;
using System.ComponentModel;
using OpenIddict.Extensions;
namespace OpenIddict.Validation;
@ -60,7 +61,9 @@ public static partial class OpenIddictValidationHandlers
throw new ArgumentNullException(nameof(context));
}
context.Configuration = await context.Options.ConfigurationManager.GetConfigurationAsync(default) ??
context.Configuration = await context.Options.ConfigurationManager
.GetConfigurationAsync(context.CancellationToken)
.WaitAsync(context.CancellationToken) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0140));
}
}

9
src/OpenIddict.Validation/OpenIddictValidationService.cs

@ -10,6 +10,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using OpenIddict.Extensions;
using static OpenIddict.Abstractions.OpenIddictExceptions;
namespace OpenIddict.Validation;
@ -50,7 +51,9 @@ public sealed class OpenIddictValidationService
try
{
var options = _provider.GetRequiredService<IOptionsMonitor<OpenIddictValidationOptions>>();
var configuration = await options.CurrentValue.ConfigurationManager.GetConfigurationAsync(default) ??
var configuration = await options.CurrentValue.ConfigurationManager
.GetConfigurationAsync(cancellationToken)
.WaitAsync(cancellationToken) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0140));
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationDispatcher>();
@ -416,7 +419,9 @@ public sealed class OpenIddictValidationService
try
{
var options = _provider.GetRequiredService<IOptionsMonitor<OpenIddictValidationOptions>>();
var configuration = await options.CurrentValue.ConfigurationManager.GetConfigurationAsync(default) ??
var configuration = await options.CurrentValue.ConfigurationManager
.GetConfigurationAsync(cancellationToken)
.WaitAsync(cancellationToken) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0140));
var dispatcher = scope.ServiceProvider.GetRequiredService<IOpenIddictValidationDispatcher>();

Loading…
Cancel
Save