Browse Source

Add nullable annotations to OpenIddict.Validation, OpenIddict.Validation.AspNetCore, OpenIddict.Validation.Owin, OpenIddict.Validation.ServerIntegration, OpenIddict.Validation.SystemNetHttp and OpenIddict.Validation.DataProtection

pull/1038/head
Kévin Chalet 6 years ago
parent
commit
3df97d59e6
  1. 5
      src/OpenIddict.Validation.AspNetCore/OpenIddict.Validation.AspNetCore.csproj
  2. 11
      src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreBuilder.cs
  3. 23
      src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreConfiguration.cs
  4. 6
      src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreExtensions.cs
  5. 2
      src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreFeature.cs
  6. 38
      src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandler.cs
  7. 3
      src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandlerFilters.cs
  8. 128
      src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandlers.cs
  9. 13
      src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHelpers.cs
  10. 5
      src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreOptions.cs
  11. 3
      src/OpenIddict.Validation.DataProtection/IOpenIddictValidationDataProtectionFormatter.cs
  12. 5
      src/OpenIddict.Validation.DataProtection/OpenIddict.Validation.DataProtection.csproj
  13. 13
      src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionBuilder.cs
  14. 7
      src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionConfiguration.cs
  15. 6
      src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionExtensions.cs
  16. 7
      src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionFormatter.cs
  17. 13
      src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionHandlers.cs
  18. 2
      src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionOptions.cs
  19. 1
      src/OpenIddict.Validation.Owin/OpenIddict.Validation.Owin.csproj
  20. 11
      src/OpenIddict.Validation.Owin/OpenIddictValidationOwinBuilder.cs
  21. 3
      src/OpenIddict.Validation.Owin/OpenIddictValidationOwinConfiguration.cs
  22. 6
      src/OpenIddict.Validation.Owin/OpenIddictValidationOwinExtensions.cs
  23. 34
      src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandler.cs
  24. 3
      src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandlerFilters.cs
  25. 134
      src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandlers.cs
  26. 15
      src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHelpers.cs
  27. 9
      src/OpenIddict.Validation.Owin/OpenIddictValidationOwinMiddleware.cs
  28. 5
      src/OpenIddict.Validation.Owin/OpenIddictValidationOwinMiddlewareFactory.cs
  29. 5
      src/OpenIddict.Validation.Owin/OpenIddictValidationOwinOptions.cs
  30. 1
      src/OpenIddict.Validation.ServerIntegration/OpenIddict.Validation.ServerIntegration.csproj
  31. 9
      src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationBuilder.cs
  32. 7
      src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationConfiguration.cs
  33. 6
      src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationExtensions.cs
  34. 1
      src/OpenIddict.Validation.SystemNetHttp/OpenIddict.Validation.SystemNetHttp.csproj
  35. 11
      src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpBuilder.cs
  36. 13
      src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpConfiguration.cs
  37. 6
      src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpExtensions.cs
  38. 3
      src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlerFilters.cs
  39. 9
      src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.Introspection.cs
  40. 42
      src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.cs
  41. 9
      src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHelpers.cs
  42. 2
      src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpOptions.cs
  43. 3
      src/OpenIddict.Validation/IOpenIddictValidationDispatcher.cs
  44. 3
      src/OpenIddict.Validation/IOpenIddictValidationHandler.cs
  45. 3
      src/OpenIddict.Validation/IOpenIddictValidationHandlerFilter.cs
  46. 1
      src/OpenIddict.Validation/OpenIddict.Validation.csproj
  47. 49
      src/OpenIddict.Validation/OpenIddictValidationBuilder.cs
  48. 72
      src/OpenIddict.Validation/OpenIddictValidationConfiguration.cs
  49. 9
      src/OpenIddict.Validation/OpenIddictValidationDispatcher.cs
  50. 126
      src/OpenIddict.Validation/OpenIddictValidationEvents.Discovery.cs
  51. 74
      src/OpenIddict.Validation/OpenIddictValidationEvents.Introspection.cs
  52. 102
      src/OpenIddict.Validation/OpenIddictValidationEvents.cs
  53. 7
      src/OpenIddict.Validation/OpenIddictValidationExtensions.cs
  54. 7
      src/OpenIddict.Validation/OpenIddictValidationFactory.cs
  55. 5
      src/OpenIddict.Validation/OpenIddictValidationHandler.cs
  56. 15
      src/OpenIddict.Validation/OpenIddictValidationHandlerDescriptor.cs
  57. 9
      src/OpenIddict.Validation/OpenIddictValidationHandlerFilters.cs
  58. 73
      src/OpenIddict.Validation/OpenIddictValidationHandlers.Discovery.cs
  59. 79
      src/OpenIddict.Validation/OpenIddictValidationHandlers.Introspection.cs
  60. 151
      src/OpenIddict.Validation/OpenIddictValidationHandlers.cs
  61. 9
      src/OpenIddict.Validation/OpenIddictValidationHelpers.cs
  62. 12
      src/OpenIddict.Validation/OpenIddictValidationOptions.cs
  63. 5
      src/OpenIddict.Validation/OpenIddictValidationRetriever.cs
  64. 29
      src/OpenIddict.Validation/OpenIddictValidationService.cs
  65. 16
      src/OpenIddict.Validation/OpenIddictValidationTransaction.cs

5
src/OpenIddict.Validation.AspNetCore/OpenIddict.Validation.AspNetCore.csproj

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net461;netcoreapp2.1;netcoreapp3.1</TargetFrameworks> <TargetFrameworks>net461;netcoreapp2.1;netcoreapp3.1</TargetFrameworks>
<Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
@ -14,12 +15,12 @@
</ItemGroup> </ItemGroup>
<ItemGroup <ItemGroup
Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' And $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '3.1')) "> Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' And $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '3.0')) ">
<FrameworkReference Include="Microsoft.AspNetCore.App" /> <FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup> </ItemGroup>
<ItemGroup <ItemGroup
Condition=" '$(TargetFrameworkIdentifier)' != '.NETCoreApp' Or $([MSBuild]::VersionLessThan($(TargetFrameworkVersion), '3.1')) "> Condition=" '$(TargetFrameworkIdentifier)' != '.NETCoreApp' Or $([MSBuild]::VersionLessThan($(TargetFrameworkVersion), '3.0')) ">
<PackageReference Include="Microsoft.AspNetCore.Authentication" /> <PackageReference Include="Microsoft.AspNetCore.Authentication" />
</ItemGroup> </ItemGroup>

11
src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreBuilder.cs

@ -6,7 +6,6 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using JetBrains.Annotations;
using OpenIddict.Validation.AspNetCore; using OpenIddict.Validation.AspNetCore;
using SR = OpenIddict.Abstractions.OpenIddictResources; using SR = OpenIddict.Abstractions.OpenIddictResources;
@ -22,7 +21,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// Initializes a new instance of <see cref="OpenIddictValidationAspNetCoreBuilder"/>. /// Initializes a new instance of <see cref="OpenIddictValidationAspNetCoreBuilder"/>.
/// </summary> /// </summary>
/// <param name="services">The services collection.</param> /// <param name="services">The services collection.</param>
public OpenIddictValidationAspNetCoreBuilder([NotNull] IServiceCollection services) public OpenIddictValidationAspNetCoreBuilder(IServiceCollection services)
=> Services = services ?? throw new ArgumentNullException(nameof(services)); => Services = services ?? throw new ArgumentNullException(nameof(services));
/// <summary> /// <summary>
@ -37,7 +36,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="configuration">The delegate used to configure the OpenIddict options.</param> /// <param name="configuration">The delegate used to configure the OpenIddict options.</param>
/// <remarks>This extension can be safely called multiple times.</remarks> /// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictValidationAspNetCoreBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationAspNetCoreBuilder"/>.</returns>
public OpenIddictValidationAspNetCoreBuilder Configure([NotNull] Action<OpenIddictValidationAspNetCoreOptions> configuration) public OpenIddictValidationAspNetCoreBuilder Configure(Action<OpenIddictValidationAspNetCoreOptions> configuration)
{ {
if (configuration == null) if (configuration == null)
{ {
@ -54,7 +53,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <param name="realm">The issuer address.</param> /// <param name="realm">The issuer address.</param>
/// <returns>The <see cref="OpenIddictValidationAspNetCoreBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationAspNetCoreBuilder"/>.</returns>
public OpenIddictValidationAspNetCoreBuilder SetRealm([NotNull] string realm) public OpenIddictValidationAspNetCoreBuilder SetRealm(string realm)
{ {
if (string.IsNullOrEmpty(realm)) if (string.IsNullOrEmpty(realm))
{ {
@ -70,7 +69,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="obj">The object to compare with the current object.</param> /// <param name="obj">The object to compare with the current object.</param>
/// <returns><c>true</c> if the specified object is equal to the current object; otherwise, false.</returns> /// <returns><c>true</c> if the specified object is equal to the current object; otherwise, false.</returns>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals([CanBeNull] object obj) => base.Equals(obj); public override bool Equals(object? obj) => base.Equals(obj);
/// <summary> /// <summary>
/// Serves as the default hash function. /// Serves as the default hash function.
@ -84,6 +83,6 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <returns>A string that represents the current object.</returns> /// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString(); public override string? ToString() => base.ToString();
} }
} }

23
src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreConfiguration.cs

@ -5,7 +5,7 @@
*/ */
using System; using System;
using JetBrains.Annotations; using System.Collections.Generic;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using SR = OpenIddict.Abstractions.OpenIddictResources; using SR = OpenIddict.Abstractions.OpenIddictResources;
@ -23,7 +23,7 @@ namespace OpenIddict.Validation.AspNetCore
/// Registers the OpenIddict validation handler in the global authentication options. /// Registers the OpenIddict validation handler in the global authentication options.
/// </summary> /// </summary>
/// <param name="options">The options instance to initialize.</param> /// <param name="options">The options instance to initialize.</param>
public void Configure([NotNull] AuthenticationOptions options) public void Configure(AuthenticationOptions options)
{ {
if (options == null) if (options == null)
{ {
@ -41,7 +41,7 @@ namespace OpenIddict.Validation.AspNetCore
OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme, displayName: null); OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme, displayName: null);
} }
public void Configure([NotNull] OpenIddictValidationOptions options) public void Configure(OpenIddictValidationOptions options)
{ {
if (options == null) if (options == null)
{ {
@ -57,28 +57,29 @@ namespace OpenIddict.Validation.AspNetCore
/// </summary> /// </summary>
/// <param name="name">The name of the options instance to configure, if applicable.</param> /// <param name="name">The name of the options instance to configure, if applicable.</param>
/// <param name="options">The options instance to initialize.</param> /// <param name="options">The options instance to initialize.</param>
public void PostConfigure([CanBeNull] string name, [NotNull] AuthenticationOptions options) public void PostConfigure(string name, AuthenticationOptions options)
{ {
if (options == null) if (options == null)
{ {
throw new ArgumentNullException(nameof(options)); throw new ArgumentNullException(nameof(options));
} }
bool TryValidate(string scheme) if (!TryValidate(options.SchemeMap, options.DefaultSignInScheme) ||
!TryValidate(options.SchemeMap, options.DefaultSignOutScheme))
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID1164));
}
static bool TryValidate(IDictionary<string, AuthenticationSchemeBuilder> map, string? scheme)
{ {
// If the scheme was not set or if it cannot be found in the map, return true. // If the scheme was not set or if it cannot be found in the map, return true.
if (string.IsNullOrEmpty(scheme) || !options.SchemeMap.TryGetValue(scheme, out var builder)) if (string.IsNullOrEmpty(scheme) || !map.TryGetValue(scheme, out var builder))
{ {
return true; return true;
} }
return builder.HandlerType != typeof(OpenIddictValidationAspNetCoreHandler); return builder.HandlerType != typeof(OpenIddictValidationAspNetCoreHandler);
} }
if (!TryValidate(options.DefaultSignInScheme) || !TryValidate(options.DefaultSignOutScheme))
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID1164));
}
} }
} }
} }

6
src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreExtensions.cs

@ -6,7 +6,6 @@
using System; using System;
using System.Linq; using System.Linq;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -28,7 +27,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="builder">The services builder used by OpenIddict to register new services.</param> /// <param name="builder">The services builder used by OpenIddict to register new services.</param>
/// <remarks>This extension can be safely called multiple times.</remarks> /// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictValidationAspNetCoreBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationAspNetCoreBuilder"/>.</returns>
public static OpenIddictValidationAspNetCoreBuilder UseAspNetCore([NotNull] this OpenIddictValidationBuilder builder) public static OpenIddictValidationAspNetCoreBuilder UseAspNetCore(this OpenIddictValidationBuilder builder)
{ {
if (builder == null) if (builder == null)
{ {
@ -67,8 +66,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <remarks>This extension can be safely called multiple times.</remarks> /// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public static OpenIddictValidationBuilder UseAspNetCore( public static OpenIddictValidationBuilder UseAspNetCore(
[NotNull] this OpenIddictValidationBuilder builder, this OpenIddictValidationBuilder builder, Action<OpenIddictValidationAspNetCoreBuilder> configuration)
[NotNull] Action<OpenIddictValidationAspNetCoreBuilder> configuration)
{ {
if (builder == null) if (builder == null)
{ {

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

@ -15,6 +15,6 @@ namespace OpenIddict.Validation.AspNetCore
/// Gets or sets the validation transaction that encapsulates all specific /// Gets or sets the validation transaction that encapsulates all specific
/// information about an individual OpenID Connect validation request. /// information about an individual OpenID Connect validation request.
/// </summary> /// </summary>
public OpenIddictValidationTransaction Transaction { get; set; } public OpenIddictValidationTransaction? Transaction { get; set; }
} }
} }

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

@ -6,9 +6,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -33,18 +33,19 @@ namespace OpenIddict.Validation.AspNetCore
/// Creates a new instance of the <see cref="OpenIddictValidationAspNetCoreHandler"/> class. /// Creates a new instance of the <see cref="OpenIddictValidationAspNetCoreHandler"/> class.
/// </summary> /// </summary>
public OpenIddictValidationAspNetCoreHandler( public OpenIddictValidationAspNetCoreHandler(
[NotNull] IOpenIddictValidationDispatcher dispatcher, IOpenIddictValidationDispatcher dispatcher,
[NotNull] IOpenIddictValidationFactory factory, IOpenIddictValidationFactory factory,
[NotNull] IOptionsMonitor<OpenIddictValidationAspNetCoreOptions> options, IOptionsMonitor<OpenIddictValidationAspNetCoreOptions> options,
[NotNull] ILoggerFactory logger, ILoggerFactory logger,
[NotNull] UrlEncoder encoder, UrlEncoder encoder,
[NotNull] ISystemClock clock) ISystemClock clock)
: base(options, logger, encoder, clock) : base(options, logger, encoder, clock)
{ {
_dispatcher = dispatcher; _dispatcher = dispatcher;
_factory = factory; _factory = factory;
} }
/// <inheritdoc/>
public async Task<bool> HandleRequestAsync() public async Task<bool> HandleRequestAsync()
{ {
// Note: the transaction may be already attached when replaying an ASP.NET Core request // Note: the transaction may be already attached when replaying an ASP.NET Core request
@ -54,7 +55,7 @@ namespace OpenIddict.Validation.AspNetCore
{ {
// Create a new transaction and attach the HTTP request to make it available to the ASP.NET Core handlers. // Create a new transaction and attach the HTTP request to make it available to the ASP.NET Core handlers.
transaction = await _factory.CreateTransactionAsync(); transaction = await _factory.CreateTransactionAsync();
transaction.Properties[typeof(HttpRequest).FullName] = new WeakReference<HttpRequest>(Request); transaction.Properties[typeof(HttpRequest).FullName!] = new WeakReference<HttpRequest>(Request);
// Attach the OpenIddict validation transaction to the ASP.NET Core features // Attach the OpenIddict validation transaction to the ASP.NET Core features
// so that it can retrieved while performing challenge/forbid operations. // so that it can retrieved while performing challenge/forbid operations.
@ -104,6 +105,7 @@ namespace OpenIddict.Validation.AspNetCore
return false; return false;
} }
/// <inheritdoc/>
protected override async Task<AuthenticateResult> HandleAuthenticateAsync() protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{ {
var transaction = Context.Features.Get<OpenIddictValidationAspNetCoreFeature>()?.Transaction ?? var transaction = Context.Features.Get<OpenIddictValidationAspNetCoreFeature>()?.Transaction ??
@ -112,7 +114,7 @@ namespace OpenIddict.Validation.AspNetCore
// Note: in many cases, the authentication token was already validated by the time this action is called // Note: in many cases, the authentication token was already validated by the time this action is called
// (generally later in the pipeline, when using the pass-through mode). To avoid having to re-validate it, // (generally later in the pipeline, when using the pass-through mode). To avoid having to re-validate it,
// the authentication context is resolved from the transaction. If it's not available, a new one is created. // the authentication context is resolved from the transaction. If it's not available, a new one is created.
var context = transaction.GetProperty<ProcessAuthenticationContext>(typeof(ProcessAuthenticationContext).FullName); var context = transaction.GetProperty<ProcessAuthenticationContext>(typeof(ProcessAuthenticationContext).FullName!);
if (context == null) if (context == null)
{ {
context = new ProcessAuthenticationContext(transaction); context = new ProcessAuthenticationContext(transaction);
@ -120,7 +122,7 @@ namespace OpenIddict.Validation.AspNetCore
// Store the context object in the transaction so it can be later retrieved by handlers // Store the context object in the transaction so it can be later retrieved by handlers
// that want to access the authentication result without triggering a new authentication flow. // that want to access the authentication result without triggering a new authentication flow.
transaction.SetProperty(typeof(ProcessAuthenticationContext).FullName, context); transaction.SetProperty(typeof(ProcessAuthenticationContext).FullName!, context);
} }
if (context.IsRequestHandled || context.IsRequestSkipped) if (context.IsRequestHandled || context.IsRequestSkipped)
@ -138,7 +140,7 @@ namespace OpenIddict.Validation.AspNetCore
return AuthenticateResult.NoResult(); return AuthenticateResult.NoResult();
} }
var properties = new AuthenticationProperties(new Dictionary<string, string> var properties = new AuthenticationProperties(new Dictionary<string, string?>
{ {
[OpenIddictValidationAspNetCoreConstants.Properties.Error] = context.Error, [OpenIddictValidationAspNetCoreConstants.Properties.Error] = context.Error,
[OpenIddictValidationAspNetCoreConstants.Properties.ErrorDescription] = context.ErrorDescription, [OpenIddictValidationAspNetCoreConstants.Properties.ErrorDescription] = context.ErrorDescription,
@ -150,6 +152,10 @@ namespace OpenIddict.Validation.AspNetCore
else else
{ {
Debug.Assert(context.Principal != null, SR.GetResourceString(SR.ID5006));
Debug.Assert(!string.IsNullOrEmpty(context.Principal.GetTokenType()), SR.GetResourceString(SR.ID5009));
Debug.Assert(!string.IsNullOrEmpty(context.Token), SR.GetResourceString(SR.ID5010));
// Store the token to allow any ASP.NET Core component (e.g a controller) // Store the token to allow any ASP.NET Core component (e.g a controller)
// to retrieve it (e.g to make an API request to another application). // to retrieve it (e.g to make an API request to another application).
var properties = new AuthenticationProperties(); var properties = new AuthenticationProperties();
@ -157,7 +163,7 @@ namespace OpenIddict.Validation.AspNetCore
{ {
new AuthenticationToken new AuthenticationToken
{ {
Name = context.TokenType, Name = context.Principal.GetTokenType(),
Value = context.Token Value = context.Token
} }
}); });
@ -168,12 +174,13 @@ namespace OpenIddict.Validation.AspNetCore
} }
} }
protected override async Task HandleChallengeAsync([CanBeNull] AuthenticationProperties properties) /// <inheritdoc/>
protected override async Task HandleChallengeAsync(AuthenticationProperties? properties)
{ {
var transaction = Context.Features.Get<OpenIddictValidationAspNetCoreFeature>()?.Transaction ?? var transaction = Context.Features.Get<OpenIddictValidationAspNetCoreFeature>()?.Transaction ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID1165)); throw new InvalidOperationException(SR.GetResourceString(SR.ID1165));
transaction.Properties[typeof(AuthenticationProperties).FullName] = properties ?? new AuthenticationProperties(); transaction.Properties[typeof(AuthenticationProperties).FullName!] = properties ?? new AuthenticationProperties();
var context = new ProcessChallengeContext(transaction) var context = new ProcessChallengeContext(transaction)
{ {
@ -210,7 +217,8 @@ namespace OpenIddict.Validation.AspNetCore
} }
} }
protected override Task HandleForbiddenAsync([CanBeNull] AuthenticationProperties properties) /// <inheritdoc/>
protected override Task HandleForbiddenAsync(AuthenticationProperties? properties)
=> HandleChallengeAsync(properties); => HandleChallengeAsync(properties);
} }
} }

3
src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHandlerFilters.cs

@ -7,7 +7,6 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore; using Microsoft.AspNetCore;
using static OpenIddict.Validation.OpenIddictValidationEvents; using static OpenIddict.Validation.OpenIddictValidationEvents;
@ -24,7 +23,7 @@ namespace OpenIddict.Validation.AspNetCore
/// </summary> /// </summary>
public class RequireHttpRequest : IOpenIddictValidationHandlerFilter<BaseContext> public class RequireHttpRequest : IOpenIddictValidationHandlerFilter<BaseContext>
{ {
public ValueTask<bool> IsActiveAsync([NotNull] BaseContext context) public ValueTask<bool> IsActiveAsync(BaseContext context)
{ {
if (context == null) if (context == null)
{ {

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

@ -8,12 +8,12 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using System.Text.Json; using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore; using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@ -82,14 +82,8 @@ namespace OpenIddict.Validation.AspNetCore
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(ProcessRequestContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessRequestContext context)
{ {
if (context == null) if (context == null)
{ {
@ -120,7 +114,7 @@ namespace OpenIddict.Validation.AspNetCore
return default; return default;
} }
if (!Uri.TryCreate(request.Scheme + "://" + request.Host + request.PathBase, UriKind.Absolute, out Uri issuer) || if (!Uri.TryCreate(request.Scheme + "://" + request.Host + request.PathBase, UriKind.Absolute, out Uri? issuer) ||
!issuer.IsWellFormedOriginalString()) !issuer.IsWellFormedOriginalString())
{ {
context.Reject( context.Reject(
@ -153,14 +147,8 @@ namespace OpenIddict.Validation.AspNetCore
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(ProcessAuthenticationContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context)
{ {
if (context == null) if (context == null)
{ {
@ -213,14 +201,8 @@ namespace OpenIddict.Validation.AspNetCore
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public async ValueTask HandleAsync(ProcessAuthenticationContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public async ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context)
{ {
if (context == null) if (context == null)
{ {
@ -277,14 +259,8 @@ namespace OpenIddict.Validation.AspNetCore
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(ProcessAuthenticationContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context)
{ {
if (context == null) if (context == null)
{ {
@ -336,21 +312,15 @@ namespace OpenIddict.Validation.AspNetCore
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(ProcessChallengeContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessChallengeContext context)
{ {
if (context == null) if (context == null)
{ {
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
var properties = context.Transaction.GetProperty<AuthenticationProperties>(typeof(AuthenticationProperties).FullName); var properties = context.Transaction.GetProperty<AuthenticationProperties>(typeof(AuthenticationProperties).FullName!);
if (properties != null) if (properties != null)
{ {
context.Response.Error = properties.GetString(Properties.Error); context.Response.Error = properties.GetString(Properties.Error);
@ -380,20 +350,16 @@ namespace OpenIddict.Validation.AspNetCore
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(TContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] TContext context)
{ {
if (context == null) if (context == null)
{ {
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
Debug.Assert(context.Transaction.Response != null, SR.GetResourceString(SR.ID5007));
// This handler only applies to ASP.NET Core requests. If the HTTP context cannot be resolved, // This handler only applies to ASP.NET Core requests. If the HTTP context cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack. // this may indicate that the request was incorrectly processed by another server stack.
var response = context.Transaction.GetHttpRequest()?.HttpContext.Response; var response = context.Transaction.GetHttpRequest()?.HttpContext.Response;
@ -402,7 +368,7 @@ namespace OpenIddict.Validation.AspNetCore
throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); throw new InvalidOperationException(SR.GetResourceString(SR.ID1113));
} }
response.StatusCode = context.Response.Error switch response.StatusCode = context.Transaction.Response.Error switch
{ {
null => 200, null => 200,
@ -436,14 +402,8 @@ namespace OpenIddict.Validation.AspNetCore
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(TContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] TContext context)
{ {
if (context == null) if (context == null)
{ {
@ -475,7 +435,7 @@ namespace OpenIddict.Validation.AspNetCore
{ {
private readonly IOptionsMonitor<OpenIddictValidationAspNetCoreOptions> _options; private readonly IOptionsMonitor<OpenIddictValidationAspNetCoreOptions> _options;
public AttachWwwAuthenticateHeader([NotNull] IOptionsMonitor<OpenIddictValidationAspNetCoreOptions> options) public AttachWwwAuthenticateHeader(IOptionsMonitor<OpenIddictValidationAspNetCoreOptions> options)
=> _options = options; => _options = options;
/// <summary> /// <summary>
@ -489,20 +449,16 @@ namespace OpenIddict.Validation.AspNetCore
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(TContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] TContext context)
{ {
if (context == null) if (context == null)
{ {
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
Debug.Assert(context.Transaction.Response != null, SR.GetResourceString(SR.ID5007));
// This handler only applies to ASP.NET Core requests. If the HTTP context cannot be resolved, // This handler only applies to ASP.NET Core requests. If the HTTP context cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack. // this may indicate that the request was incorrectly processed by another server stack.
var response = context.Transaction.GetHttpRequest()?.HttpContext.Response; var response = context.Transaction.GetHttpRequest()?.HttpContext.Response;
@ -511,7 +467,7 @@ namespace OpenIddict.Validation.AspNetCore
throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); throw new InvalidOperationException(SR.GetResourceString(SR.ID1113));
} }
var scheme = context.Response.Error switch var scheme = context.Transaction.Response.Error switch
{ {
Errors.InvalidToken => Schemes.Bearer, Errors.InvalidToken => Schemes.Bearer,
Errors.MissingToken => Schemes.Bearer, Errors.MissingToken => Schemes.Bearer,
@ -534,11 +490,11 @@ namespace OpenIddict.Validation.AspNetCore
parameters[Parameters.Realm] = _options.CurrentValue.Realm; parameters[Parameters.Realm] = _options.CurrentValue.Realm;
} }
foreach (var parameter in context.Response.GetParameters()) foreach (var parameter in context.Transaction.Response.GetParameters())
{ {
// Note: the error details are only included if the error was not caused by a missing token, as recommended // Note: the error details are only included if the error was not caused by a missing token, as recommended
// by the OAuth 2.0 bearer specification: https://tools.ietf.org/html/rfc6750#section-3.1. // by the OAuth 2.0 bearer specification: https://tools.ietf.org/html/rfc6750#section-3.1.
if (string.Equals(context.Response.Error, Errors.MissingToken, StringComparison.Ordinal) && if (string.Equals(context.Transaction.Response.Error, Errors.MissingToken, StringComparison.Ordinal) &&
(string.Equals(parameter.Key, Parameters.Error, StringComparison.Ordinal) || (string.Equals(parameter.Key, Parameters.Error, StringComparison.Ordinal) ||
string.Equals(parameter.Key, Parameters.ErrorDescription, StringComparison.Ordinal) || string.Equals(parameter.Key, Parameters.ErrorDescription, StringComparison.Ordinal) ||
string.Equals(parameter.Key, Parameters.ErrorUri, StringComparison.Ordinal))) string.Equals(parameter.Key, Parameters.ErrorUri, StringComparison.Ordinal)))
@ -547,7 +503,7 @@ namespace OpenIddict.Validation.AspNetCore
} }
// Ignore values that can't be represented as unique strings. // Ignore values that can't be represented as unique strings.
var value = (string) parameter.Value; var value = (string?) parameter.Value;
if (string.IsNullOrEmpty(value)) if (string.IsNullOrEmpty(value))
{ {
continue; continue;
@ -598,14 +554,8 @@ namespace OpenIddict.Validation.AspNetCore
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(TContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] TContext context)
{ {
if (context == null) if (context == null)
{ {
@ -626,7 +576,7 @@ namespace OpenIddict.Validation.AspNetCore
return default; return default;
} }
context.Logger.LogInformation(SR.GetResourceString(SR.ID7141), context.Response); context.Logger.LogInformation(SR.GetResourceString(SR.ID7141), context.Transaction.Response);
context.HandleRequest(); context.HandleRequest();
return default; return default;
@ -650,14 +600,8 @@ namespace OpenIddict.Validation.AspNetCore
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public async ValueTask HandleAsync(TContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public async ValueTask HandleAsync([NotNull] TContext context)
{ {
if (context == null) if (context == null)
{ {
@ -672,10 +616,10 @@ namespace OpenIddict.Validation.AspNetCore
throw new InvalidOperationException(SR.GetResourceString(SR.ID1113)); throw new InvalidOperationException(SR.GetResourceString(SR.ID1113));
} }
context.Logger.LogInformation(SR.GetResourceString(SR.ID7142), context.Response); context.Logger.LogInformation(SR.GetResourceString(SR.ID7142), context.Transaction.Response);
using var stream = new MemoryStream(); using var stream = new MemoryStream();
await JsonSerializer.SerializeAsync(stream, context.Response, new JsonSerializerOptions await JsonSerializer.SerializeAsync(stream, context.Transaction.Response, new JsonSerializerOptions
{ {
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
WriteIndented = false WriteIndented = false

13
src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreHelpers.cs

@ -5,7 +5,6 @@
*/ */
using System; using System;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using OpenIddict.Abstractions; using OpenIddict.Abstractions;
using OpenIddict.Validation; using OpenIddict.Validation;
@ -24,19 +23,19 @@ namespace Microsoft.AspNetCore
/// </summary> /// </summary>
/// <param name="transaction">The transaction instance.</param> /// <param name="transaction">The transaction instance.</param>
/// <returns>The <see cref="HttpRequest"/> instance or <c>null</c> if it couldn't be found.</returns> /// <returns>The <see cref="HttpRequest"/> instance or <c>null</c> if it couldn't be found.</returns>
public static HttpRequest GetHttpRequest([NotNull] this OpenIddictValidationTransaction transaction) public static HttpRequest? GetHttpRequest(this OpenIddictValidationTransaction transaction)
{ {
if (transaction == null) if (transaction == null)
{ {
throw new ArgumentNullException(nameof(transaction)); throw new ArgumentNullException(nameof(transaction));
} }
if (!transaction.Properties.TryGetValue(typeof(HttpRequest).FullName, out object property)) if (!transaction.Properties.TryGetValue(typeof(HttpRequest).FullName!, out object? property))
{ {
return null; return null;
} }
if (property is WeakReference<HttpRequest> reference && reference.TryGetTarget(out HttpRequest request)) if (property is WeakReference<HttpRequest> reference && reference.TryGetTarget(out HttpRequest? request))
{ {
return request; return request;
} }
@ -49,7 +48,7 @@ namespace Microsoft.AspNetCore
/// </summary> /// </summary>
/// <param name="context">The context instance.</param> /// <param name="context">The context instance.</param>
/// <returns>The <see cref="OpenIddictValidationEndpointType"/>.</returns> /// <returns>The <see cref="OpenIddictValidationEndpointType"/>.</returns>
public static OpenIddictValidationEndpointType GetOpenIddictValidationEndpointType([NotNull] this HttpContext context) public static OpenIddictValidationEndpointType GetOpenIddictValidationEndpointType(this HttpContext context)
{ {
if (context == null) if (context == null)
{ {
@ -64,7 +63,7 @@ namespace Microsoft.AspNetCore
/// </summary> /// </summary>
/// <param name="context">The context instance.</param> /// <param name="context">The context instance.</param>
/// <returns>The <see cref="OpenIddictRequest"/> instance or <c>null</c> if it couldn't be found.</returns> /// <returns>The <see cref="OpenIddictRequest"/> instance or <c>null</c> if it couldn't be found.</returns>
public static OpenIddictRequest GetOpenIddictValidationRequest([NotNull] this HttpContext context) public static OpenIddictRequest? GetOpenIddictValidationRequest(this HttpContext context)
{ {
if (context == null) if (context == null)
{ {
@ -79,7 +78,7 @@ namespace Microsoft.AspNetCore
/// </summary> /// </summary>
/// <param name="context">The context instance.</param> /// <param name="context">The context instance.</param>
/// <returns>The <see cref="OpenIddictResponse"/> instance or <c>null</c> if it couldn't be found.</returns> /// <returns>The <see cref="OpenIddictResponse"/> instance or <c>null</c> if it couldn't be found.</returns>
public static OpenIddictResponse GetOpenIddictValidationResponse([NotNull] this HttpContext context) public static OpenIddictResponse? GetOpenIddictValidationResponse(this HttpContext context)
{ {
if (context == null) if (context == null)
{ {

5
src/OpenIddict.Validation.AspNetCore/OpenIddictValidationAspNetCoreOptions.cs

@ -14,9 +14,8 @@ namespace OpenIddict.Validation.AspNetCore
public class OpenIddictValidationAspNetCoreOptions : AuthenticationSchemeOptions public class OpenIddictValidationAspNetCoreOptions : AuthenticationSchemeOptions
{ {
/// <summary> /// <summary>
/// Gets or sets the optional "realm" value returned to /// Gets or sets the optional "realm" value returned to the caller as part of the WWW-Authenticate header.
/// the caller as part of the WWW-Authenticate header.
/// </summary> /// </summary>
public string Realm { get; set; } public string? Realm { get; set; }
} }
} }

3
src/OpenIddict.Validation.DataProtection/IOpenIddictValidationDataProtectionFormatter.cs

@ -6,12 +6,11 @@
using System.IO; using System.IO;
using System.Security.Claims; using System.Security.Claims;
using JetBrains.Annotations;
namespace OpenIddict.Validation.DataProtection namespace OpenIddict.Validation.DataProtection
{ {
public interface IOpenIddictValidationDataProtectionFormatter public interface IOpenIddictValidationDataProtectionFormatter
{ {
ClaimsPrincipal ReadToken([NotNull] BinaryReader reader); ClaimsPrincipal? ReadToken(BinaryReader reader);
} }
} }

5
src/OpenIddict.Validation.DataProtection/OpenIddict.Validation.DataProtection.csproj

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net461;netcoreapp3.1;netstandard2.0;netstandard2.1</TargetFrameworks> <TargetFrameworks>net461;netcoreapp3.1;netstandard2.0;netstandard2.1</TargetFrameworks>
<Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
@ -14,12 +15,12 @@
</ItemGroup> </ItemGroup>
<ItemGroup <ItemGroup
Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' And $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '3.1')) "> Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' And $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '3.0')) ">
<FrameworkReference Include="Microsoft.AspNetCore.App" /> <FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup> </ItemGroup>
<ItemGroup <ItemGroup
Condition=" '$(TargetFrameworkIdentifier)' != '.NETCoreApp' Or $([MSBuild]::VersionLessThan($(TargetFrameworkVersion), '3.1')) "> Condition=" '$(TargetFrameworkIdentifier)' != '.NETCoreApp' Or $([MSBuild]::VersionLessThan($(TargetFrameworkVersion), '3.0')) ">
<PackageReference Include="Microsoft.AspNetCore.DataProtection" /> <PackageReference Include="Microsoft.AspNetCore.DataProtection" />
</ItemGroup> </ItemGroup>

13
src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionBuilder.cs

@ -6,7 +6,6 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using JetBrains.Annotations;
using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.DataProtection;
using OpenIddict.Validation.DataProtection; using OpenIddict.Validation.DataProtection;
@ -22,7 +21,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// Initializes a new instance of <see cref="OpenIddictValidationDataProtectionBuilder"/>. /// Initializes a new instance of <see cref="OpenIddictValidationDataProtectionBuilder"/>.
/// </summary> /// </summary>
/// <param name="services">The services collection.</param> /// <param name="services">The services collection.</param>
public OpenIddictValidationDataProtectionBuilder([NotNull] IServiceCollection services) public OpenIddictValidationDataProtectionBuilder(IServiceCollection services)
=> Services = services ?? throw new ArgumentNullException(nameof(services)); => Services = services ?? throw new ArgumentNullException(nameof(services));
/// <summary> /// <summary>
@ -37,7 +36,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="configuration">The delegate used to configure the OpenIddict options.</param> /// <param name="configuration">The delegate used to configure the OpenIddict options.</param>
/// <remarks>This extension can be safely called multiple times.</remarks> /// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictValidationDataProtectionBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationDataProtectionBuilder"/>.</returns>
public OpenIddictValidationDataProtectionBuilder Configure([NotNull] Action<OpenIddictValidationDataProtectionOptions> configuration) public OpenIddictValidationDataProtectionBuilder Configure(Action<OpenIddictValidationDataProtectionOptions> configuration)
{ {
if (configuration == null) if (configuration == null)
{ {
@ -55,7 +54,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <param name="provider">The data protection provider used to create token protectors.</param> /// <param name="provider">The data protection provider used to create token protectors.</param>
/// <returns>The <see cref="OpenIddictValidationDataProtectionBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationDataProtectionBuilder"/>.</returns>
public OpenIddictValidationDataProtectionBuilder UseDataProtectionProvider([NotNull] IDataProtectionProvider provider) public OpenIddictValidationDataProtectionBuilder UseDataProtectionProvider(IDataProtectionProvider provider)
{ {
if (provider == null) if (provider == null)
{ {
@ -70,7 +69,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <param name="formatter">The formatter used to read tokens.</param> /// <param name="formatter">The formatter used to read tokens.</param>
/// <returns>The <see cref="OpenIddictValidationDataProtectionBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationDataProtectionBuilder"/>.</returns>
public OpenIddictValidationDataProtectionBuilder UseFormatter([NotNull] IOpenIddictValidationDataProtectionFormatter formatter) public OpenIddictValidationDataProtectionBuilder UseFormatter(IOpenIddictValidationDataProtectionFormatter formatter)
{ {
if (formatter == null) if (formatter == null)
{ {
@ -86,7 +85,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="obj">The object to compare with the current object.</param> /// <param name="obj">The object to compare with the current object.</param>
/// <returns><c>true</c> if the specified object is equal to the current object; otherwise, false.</returns> /// <returns><c>true</c> if the specified object is equal to the current object; otherwise, false.</returns>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals([CanBeNull] object obj) => base.Equals(obj); public override bool Equals(object? obj) => base.Equals(obj);
/// <summary> /// <summary>
/// Serves as the default hash function. /// Serves as the default hash function.
@ -100,6 +99,6 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <returns>A string that represents the current object.</returns> /// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString(); public override string? ToString() => base.ToString();
} }
} }

7
src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionConfiguration.cs

@ -5,7 +5,6 @@
*/ */
using System; using System;
using JetBrains.Annotations;
using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -23,10 +22,10 @@ namespace OpenIddict.Validation.DataProtection
/// Creates a new instance of the <see cref="OpenIddictValidationDataProtectionConfiguration"/> class. /// Creates a new instance of the <see cref="OpenIddictValidationDataProtectionConfiguration"/> class.
/// </summary> /// </summary>
/// <param name="dataProtectionProvider">The ASP.NET Core Data Protection provider.</param> /// <param name="dataProtectionProvider">The ASP.NET Core Data Protection provider.</param>
public OpenIddictValidationDataProtectionConfiguration([NotNull] IDataProtectionProvider dataProtectionProvider) public OpenIddictValidationDataProtectionConfiguration(IDataProtectionProvider dataProtectionProvider)
=> _dataProtectionProvider = dataProtectionProvider; => _dataProtectionProvider = dataProtectionProvider;
public void Configure([NotNull] OpenIddictValidationOptions options) public void Configure(OpenIddictValidationOptions options)
{ {
if (options == null) if (options == null)
{ {
@ -43,7 +42,7 @@ namespace OpenIddict.Validation.DataProtection
/// </summary> /// </summary>
/// <param name="name">The name of the options instance to configure, if applicable.</param> /// <param name="name">The name of the options instance to configure, if applicable.</param>
/// <param name="options">The options instance to initialize.</param> /// <param name="options">The options instance to initialize.</param>
public void PostConfigure([CanBeNull] string name, [NotNull] OpenIddictValidationDataProtectionOptions options) public void PostConfigure(string name, OpenIddictValidationDataProtectionOptions options)
{ {
if (options == null) if (options == null)
{ {

6
src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionExtensions.cs

@ -6,7 +6,6 @@
using System; using System;
using System.Linq; using System.Linq;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using OpenIddict.Validation; using OpenIddict.Validation;
@ -26,7 +25,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="builder">The services builder used by OpenIddict to register new services.</param> /// <param name="builder">The services builder used by OpenIddict to register new services.</param>
/// <remarks>This extension can be safely called multiple times.</remarks> /// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public static OpenIddictValidationDataProtectionBuilder UseDataProtection([NotNull] this OpenIddictValidationBuilder builder) public static OpenIddictValidationDataProtectionBuilder UseDataProtection(this OpenIddictValidationBuilder builder)
{ {
if (builder == null) if (builder == null)
{ {
@ -57,8 +56,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <remarks>This extension can be safely called multiple times.</remarks> /// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public static OpenIddictValidationBuilder UseDataProtection( public static OpenIddictValidationBuilder UseDataProtection(
[NotNull] this OpenIddictValidationBuilder builder, this OpenIddictValidationBuilder builder, Action<OpenIddictValidationDataProtectionBuilder> configuration)
[NotNull] Action<OpenIddictValidationDataProtectionBuilder> configuration)
{ {
if (builder == null) if (builder == null)
{ {

7
src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionFormatter.cs

@ -10,7 +10,6 @@ using System.Collections.Immutable;
using System.IO; using System.IO;
using System.Security.Claims; using System.Security.Claims;
using System.Text.Json; using System.Text.Json;
using JetBrains.Annotations;
using OpenIddict.Abstractions; using OpenIddict.Abstractions;
using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Abstractions.OpenIddictConstants;
using Properties = OpenIddict.Validation.DataProtection.OpenIddictValidationDataProtectionConstants.Properties; using Properties = OpenIddict.Validation.DataProtection.OpenIddictValidationDataProtectionConstants.Properties;
@ -19,7 +18,7 @@ namespace OpenIddict.Validation.DataProtection
{ {
public class OpenIddictValidationDataProtectionFormatter : IOpenIddictValidationDataProtectionFormatter public class OpenIddictValidationDataProtectionFormatter : IOpenIddictValidationDataProtectionFormatter
{ {
public ClaimsPrincipal ReadToken([NotNull] BinaryReader reader) public ClaimsPrincipal? ReadToken(BinaryReader reader)
{ {
if (reader == null) if (reader == null)
{ {
@ -58,7 +57,7 @@ namespace OpenIddict.Validation.DataProtection
.SetClaim(Claims.Private.TokenId, GetProperty(properties, Properties.InternalTokenId)) .SetClaim(Claims.Private.TokenId, GetProperty(properties, Properties.InternalTokenId))
.SetClaim(Claims.Private.UserCodeLifetime, GetProperty(properties, Properties.UserCodeLifetime)); .SetClaim(Claims.Private.UserCodeLifetime, GetProperty(properties, Properties.UserCodeLifetime));
static (ClaimsPrincipal principal, IReadOnlyDictionary<string, string> properties) Read(BinaryReader reader) static (ClaimsPrincipal? principal, IReadOnlyDictionary<string, string> properties) Read(BinaryReader reader)
{ {
// Read the version of the format used to serialize the ticket. // Read the version of the format used to serialize the ticket.
var version = reader.ReadInt32(); var version = reader.ReadInt32();
@ -175,7 +174,7 @@ namespace OpenIddict.Validation.DataProtection
return value; return value;
} }
static string GetProperty(IReadOnlyDictionary<string, string> properties, string name) static string? GetProperty(IReadOnlyDictionary<string, string> properties, string name)
=> properties.TryGetValue(name, out var value) ? value : null; => properties.TryGetValue(name, out var value) ? value : null;
static ImmutableArray<string> GetArrayProperty(IReadOnlyDictionary<string, string> properties, string name) static ImmutableArray<string> GetArrayProperty(IReadOnlyDictionary<string, string> properties, string name)

13
src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionHandlers.cs

@ -9,7 +9,6 @@ using System.Collections.Immutable;
using System.ComponentModel; using System.ComponentModel;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -41,7 +40,7 @@ namespace OpenIddict.Validation.DataProtection
{ {
private readonly IOptionsMonitor<OpenIddictValidationDataProtectionOptions> _options; private readonly IOptionsMonitor<OpenIddictValidationDataProtectionOptions> _options;
public ValidateDataProtectionToken([NotNull] IOptionsMonitor<OpenIddictValidationDataProtectionOptions> options) public ValidateDataProtectionToken(IOptionsMonitor<OpenIddictValidationDataProtectionOptions> options)
=> _options = options; => _options = options;
/// <summary> /// <summary>
@ -54,14 +53,8 @@ namespace OpenIddict.Validation.DataProtection
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(ProcessAuthenticationContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context)
{ {
if (context == null) if (context == null)
{ {

2
src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionOptions.cs

@ -20,7 +20,7 @@ namespace OpenIddict.Validation.DataProtection
/// When this property is set to <c>null</c>, the data protection provider /// When this property is set to <c>null</c>, the data protection provider
/// is directly retrieved from the dependency injection container. /// is directly retrieved from the dependency injection container.
/// </summary> /// </summary>
public IDataProtectionProvider DataProtectionProvider { get; set; } public IDataProtectionProvider DataProtectionProvider { get; set; } = default!;
/// <summary> /// <summary>
/// Gets or sets the formatter used to read Data Protection tokens. /// Gets or sets the formatter used to read Data Protection tokens.

1
src/OpenIddict.Validation.Owin/OpenIddict.Validation.Owin.csproj

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net461</TargetFramework> <TargetFramework>net461</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>

11
src/OpenIddict.Validation.Owin/OpenIddictValidationOwinBuilder.cs

@ -6,7 +6,6 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using JetBrains.Annotations;
using Microsoft.Owin.Security; using Microsoft.Owin.Security;
using OpenIddict.Validation.Owin; using OpenIddict.Validation.Owin;
using SR = OpenIddict.Abstractions.OpenIddictResources; using SR = OpenIddict.Abstractions.OpenIddictResources;
@ -23,7 +22,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// Initializes a new instance of <see cref="OpenIddictValidationOwinBuilder"/>. /// Initializes a new instance of <see cref="OpenIddictValidationOwinBuilder"/>.
/// </summary> /// </summary>
/// <param name="services">The services collection.</param> /// <param name="services">The services collection.</param>
public OpenIddictValidationOwinBuilder([NotNull] IServiceCollection services) public OpenIddictValidationOwinBuilder(IServiceCollection services)
=> Services = services ?? throw new ArgumentNullException(nameof(services)); => Services = services ?? throw new ArgumentNullException(nameof(services));
/// <summary> /// <summary>
@ -38,7 +37,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="configuration">The delegate used to configure the OpenIddict options.</param> /// <param name="configuration">The delegate used to configure the OpenIddict options.</param>
/// <remarks>This extension can be safely called multiple times.</remarks> /// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictValidationOwinBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationOwinBuilder"/>.</returns>
public OpenIddictValidationOwinBuilder Configure([NotNull] Action<OpenIddictValidationOwinOptions> configuration) public OpenIddictValidationOwinBuilder Configure(Action<OpenIddictValidationOwinOptions> configuration)
{ {
if (configuration == null) if (configuration == null)
{ {
@ -70,7 +69,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <param name="realm">The issuer address.</param> /// <param name="realm">The issuer address.</param>
/// <returns>The <see cref="OpenIddictValidationOwinBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationOwinBuilder"/>.</returns>
public OpenIddictValidationOwinBuilder SetRealm([NotNull] string realm) public OpenIddictValidationOwinBuilder SetRealm(string realm)
{ {
if (string.IsNullOrEmpty(realm)) if (string.IsNullOrEmpty(realm))
{ {
@ -86,7 +85,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="obj">The object to compare with the current object.</param> /// <param name="obj">The object to compare with the current object.</param>
/// <returns><c>true</c> if the specified object is equal to the current object; otherwise, false.</returns> /// <returns><c>true</c> if the specified object is equal to the current object; otherwise, false.</returns>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals([CanBeNull] object obj) => base.Equals(obj); public override bool Equals(object? obj) => base.Equals(obj);
/// <summary> /// <summary>
/// Serves as the default hash function. /// Serves as the default hash function.
@ -100,6 +99,6 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <returns>A string that represents the current object.</returns> /// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString(); public override string? ToString() => base.ToString();
} }
} }

3
src/OpenIddict.Validation.Owin/OpenIddictValidationOwinConfiguration.cs

@ -5,7 +5,6 @@
*/ */
using System; using System;
using JetBrains.Annotations;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace OpenIddict.Validation.Owin namespace OpenIddict.Validation.Owin
@ -15,7 +14,7 @@ namespace OpenIddict.Validation.Owin
/// </summary> /// </summary>
public class OpenIddictValidationOwinConfiguration : IConfigureOptions<OpenIddictValidationOptions> public class OpenIddictValidationOwinConfiguration : IConfigureOptions<OpenIddictValidationOptions>
{ {
public void Configure([NotNull] OpenIddictValidationOptions options) public void Configure(OpenIddictValidationOptions options)
{ {
if (options == null) if (options == null)
{ {

6
src/OpenIddict.Validation.Owin/OpenIddictValidationOwinExtensions.cs

@ -6,7 +6,6 @@
using System; using System;
using System.Linq; using System.Linq;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using OpenIddict.Validation; using OpenIddict.Validation;
@ -27,7 +26,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="builder">The services builder used by OpenIddict to register new services.</param> /// <param name="builder">The services builder used by OpenIddict to register new services.</param>
/// <remarks>This extension can be safely called multiple times.</remarks> /// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictValidationOwinBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationOwinBuilder"/>.</returns>
public static OpenIddictValidationOwinBuilder UseOwin([NotNull] this OpenIddictValidationBuilder builder) public static OpenIddictValidationOwinBuilder UseOwin(this OpenIddictValidationBuilder builder)
{ {
if (builder == null) if (builder == null)
{ {
@ -64,8 +63,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <remarks>This extension can be safely called multiple times.</remarks> /// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public static OpenIddictValidationBuilder UseOwin( public static OpenIddictValidationBuilder UseOwin(
[NotNull] this OpenIddictValidationBuilder builder, this OpenIddictValidationBuilder builder, Action<OpenIddictValidationOwinBuilder> configuration)
[NotNull] Action<OpenIddictValidationOwinBuilder> configuration)
{ {
if (builder == null) if (builder == null)
{ {

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

@ -6,9 +6,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Security.Claims; using System.Security.Claims;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Owin; using Microsoft.Owin;
using Microsoft.Owin.Security; using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure; using Microsoft.Owin.Security.Infrastructure;
@ -33,13 +33,14 @@ namespace OpenIddict.Validation.Owin
/// <param name="dispatcher">The OpenIddict validation provider used by this instance.</param> /// <param name="dispatcher">The OpenIddict validation provider used by this instance.</param>
/// <param name="factory">The OpenIddict validation factory used by this instance.</param> /// <param name="factory">The OpenIddict validation factory used by this instance.</param>
public OpenIddictValidationOwinHandler( public OpenIddictValidationOwinHandler(
[NotNull] IOpenIddictValidationDispatcher dispatcher, IOpenIddictValidationDispatcher dispatcher,
[NotNull] IOpenIddictValidationFactory factory) IOpenIddictValidationFactory factory)
{ {
_dispatcher = dispatcher; _dispatcher = dispatcher;
_factory = factory; _factory = factory;
} }
/// <inheritdoc/>
protected override async Task InitializeCoreAsync() protected override async Task InitializeCoreAsync()
{ {
// Note: the transaction may be already attached when replaying an OWIN request // Note: the transaction may be already attached when replaying an OWIN request
@ -49,7 +50,7 @@ namespace OpenIddict.Validation.Owin
{ {
// Create a new transaction and attach the OWIN request to make it available to the OWIN handlers. // Create a new transaction and attach the OWIN request to make it available to the OWIN handlers.
transaction = await _factory.CreateTransactionAsync(); transaction = await _factory.CreateTransactionAsync();
transaction.Properties[typeof(IOwinRequest).FullName] = new WeakReference<IOwinRequest>(Request); transaction.Properties[typeof(IOwinRequest).FullName!] = new WeakReference<IOwinRequest>(Request);
// Attach the OpenIddict validation transaction to the OWIN shared dictionary // Attach the OpenIddict validation transaction to the OWIN shared dictionary
// so that it can retrieved while performing sign-in/sign-out operations. // so that it can retrieved while performing sign-in/sign-out operations.
@ -60,9 +61,10 @@ namespace OpenIddict.Validation.Owin
await _dispatcher.DispatchAsync(context); await _dispatcher.DispatchAsync(context);
// Store the context in the transaction so that it can be retrieved from InvokeAsync(). // Store the context in the transaction so that it can be retrieved from InvokeAsync().
transaction.SetProperty(typeof(ProcessRequestContext).FullName, context); transaction.SetProperty(typeof(ProcessRequestContext).FullName!, context);
} }
/// <inheritdoc/>
public override async Task<bool> InvokeAsync() public override async Task<bool> InvokeAsync()
{ {
// Note: due to internal differences between ASP.NET Core and Katana, the request MUST start being processed // Note: due to internal differences between ASP.NET Core and Katana, the request MUST start being processed
@ -72,7 +74,7 @@ namespace OpenIddict.Validation.Owin
var transaction = Context.Get<OpenIddictValidationTransaction>(typeof(OpenIddictValidationTransaction).FullName) ?? var transaction = Context.Get<OpenIddictValidationTransaction>(typeof(OpenIddictValidationTransaction).FullName) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID1165)); throw new InvalidOperationException(SR.GetResourceString(SR.ID1165));
var context = transaction.GetProperty<ProcessRequestContext>(typeof(ProcessRequestContext).FullName) ?? var context = transaction.GetProperty<ProcessRequestContext>(typeof(ProcessRequestContext).FullName!) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID1165)); throw new InvalidOperationException(SR.GetResourceString(SR.ID1165));
if (context.IsRequestHandled) if (context.IsRequestHandled)
@ -115,7 +117,8 @@ namespace OpenIddict.Validation.Owin
return false; return false;
} }
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync() /// <inheritdoc/>
protected override async Task<AuthenticationTicket?> AuthenticateCoreAsync()
{ {
var transaction = Context.Get<OpenIddictValidationTransaction>(typeof(OpenIddictValidationTransaction).FullName) ?? var transaction = Context.Get<OpenIddictValidationTransaction>(typeof(OpenIddictValidationTransaction).FullName) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID1165)); throw new InvalidOperationException(SR.GetResourceString(SR.ID1165));
@ -123,7 +126,7 @@ namespace OpenIddict.Validation.Owin
// Note: in many cases, the authentication token was already validated by the time this action is called // Note: in many cases, the authentication token was already validated by the time this action is called
// (generally later in the pipeline, when using the pass-through mode). To avoid having to re-validate it, // (generally later in the pipeline, when using the pass-through mode). To avoid having to re-validate it,
// the authentication context is resolved from the transaction. If it's not available, a new one is created. // the authentication context is resolved from the transaction. If it's not available, a new one is created.
var context = transaction.GetProperty<ProcessAuthenticationContext>(typeof(ProcessAuthenticationContext).FullName); var context = transaction.GetProperty<ProcessAuthenticationContext>(typeof(ProcessAuthenticationContext).FullName!);
if (context == null) if (context == null)
{ {
context = new ProcessAuthenticationContext(transaction); context = new ProcessAuthenticationContext(transaction);
@ -131,7 +134,7 @@ namespace OpenIddict.Validation.Owin
// Store the context object in the transaction so it can be later retrieved by handlers // Store the context object in the transaction so it can be later retrieved by handlers
// that want to access the authentication result without triggering a new authentication flow. // that want to access the authentication result without triggering a new authentication flow.
transaction.SetProperty(typeof(ProcessAuthenticationContext).FullName, context); transaction.SetProperty(typeof(ProcessAuthenticationContext).FullName!, context);
} }
if (context.IsRequestHandled || context.IsRequestSkipped) if (context.IsRequestHandled || context.IsRequestSkipped)
@ -149,7 +152,7 @@ namespace OpenIddict.Validation.Owin
return null; return null;
} }
var properties = new AuthenticationProperties(new Dictionary<string, string> var properties = new AuthenticationProperties(new Dictionary<string, string?>
{ {
[OpenIddictValidationOwinConstants.Properties.Error] = context.Error, [OpenIddictValidationOwinConstants.Properties.Error] = context.Error,
[OpenIddictValidationOwinConstants.Properties.ErrorDescription] = context.ErrorDescription, [OpenIddictValidationOwinConstants.Properties.ErrorDescription] = context.ErrorDescription,
@ -161,17 +164,22 @@ namespace OpenIddict.Validation.Owin
else else
{ {
Debug.Assert(context.Principal != null, SR.GetResourceString(SR.ID5006));
Debug.Assert(!string.IsNullOrEmpty(context.Principal.GetTokenType()), SR.GetResourceString(SR.ID5009));
Debug.Assert(!string.IsNullOrEmpty(context.Token), SR.GetResourceString(SR.ID5010));
// Store the token to allow any OWIN/Katana component (e.g a controller) // Store the token to allow any OWIN/Katana component (e.g a controller)
// to retrieve it (e.g to make an API request to another application). // to retrieve it (e.g to make an API request to another application).
var properties = new AuthenticationProperties(new Dictionary<string, string> var properties = new AuthenticationProperties(new Dictionary<string, string?>
{ {
[context.TokenType] = context.Token [context.Principal.GetTokenType()!] = context.Token
}); });
return new AuthenticationTicket((ClaimsIdentity) context.Principal.Identity, properties); return new AuthenticationTicket((ClaimsIdentity) context.Principal.Identity, properties);
} }
} }
/// <inheritdoc/>
protected override async Task TeardownCoreAsync() protected override async Task TeardownCoreAsync()
{ {
// Note: OWIN authentication handlers cannot reliabily write to the response stream // Note: OWIN authentication handlers cannot reliabily write to the response stream
@ -195,7 +203,7 @@ namespace OpenIddict.Validation.Owin
var transaction = Context.Get<OpenIddictValidationTransaction>(typeof(OpenIddictValidationTransaction).FullName) ?? var transaction = Context.Get<OpenIddictValidationTransaction>(typeof(OpenIddictValidationTransaction).FullName) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID1165)); throw new InvalidOperationException(SR.GetResourceString(SR.ID1165));
transaction.Properties[typeof(AuthenticationProperties).FullName] = challenge.Properties ?? new AuthenticationProperties(); transaction.Properties[typeof(AuthenticationProperties).FullName!] = challenge.Properties ?? new AuthenticationProperties();
var context = new ProcessChallengeContext(transaction) var context = new ProcessChallengeContext(transaction)
{ {

3
src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHandlerFilters.cs

@ -6,7 +6,6 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Owin; using Owin;
using static OpenIddict.Validation.OpenIddictValidationEvents; using static OpenIddict.Validation.OpenIddictValidationEvents;
@ -22,7 +21,7 @@ namespace OpenIddict.Validation.Owin
/// </summary> /// </summary>
public class RequireOwinRequest : IOpenIddictValidationHandlerFilter<BaseContext> public class RequireOwinRequest : IOpenIddictValidationHandlerFilter<BaseContext>
{ {
public ValueTask<bool> IsActiveAsync([NotNull] BaseContext context) public ValueTask<bool> IsActiveAsync(BaseContext context)
{ {
if (context == null) if (context == null)
{ {

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

@ -8,12 +8,12 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using System.Text.Json; using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.Owin.Security; using Microsoft.Owin.Security;
@ -79,14 +79,8 @@ namespace OpenIddict.Validation.Owin
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(ProcessRequestContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessRequestContext context)
{ {
if (context == null) if (context == null)
{ {
@ -117,7 +111,7 @@ namespace OpenIddict.Validation.Owin
return default; return default;
} }
if (!Uri.TryCreate(request.Scheme + "://" + request.Host + request.PathBase, UriKind.Absolute, out Uri issuer) || if (!Uri.TryCreate(request.Scheme + "://" + request.Host + request.PathBase, UriKind.Absolute, out Uri? issuer) ||
!issuer.IsWellFormedOriginalString()) !issuer.IsWellFormedOriginalString())
{ {
context.Reject( context.Reject(
@ -150,14 +144,8 @@ namespace OpenIddict.Validation.Owin
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(ProcessAuthenticationContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context)
{ {
if (context == null) if (context == null)
{ {
@ -210,14 +198,8 @@ namespace OpenIddict.Validation.Owin
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public async ValueTask HandleAsync(ProcessAuthenticationContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public async ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context)
{ {
if (context == null) if (context == null)
{ {
@ -275,14 +257,8 @@ namespace OpenIddict.Validation.Owin
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(ProcessAuthenticationContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context)
{ {
if (context == null) if (context == null)
{ {
@ -335,21 +311,15 @@ namespace OpenIddict.Validation.Owin
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(ProcessChallengeContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessChallengeContext context)
{ {
if (context == null) if (context == null)
{ {
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
var properties = context.Transaction.GetProperty<AuthenticationProperties>(typeof(AuthenticationProperties).FullName); var properties = context.Transaction.GetProperty<AuthenticationProperties>(typeof(AuthenticationProperties).FullName!);
if (properties != null) if (properties != null)
{ {
context.Response.Error = GetProperty(properties, Properties.Error); context.Response.Error = GetProperty(properties, Properties.Error);
@ -360,8 +330,8 @@ namespace OpenIddict.Validation.Owin
return default; return default;
static string GetProperty(AuthenticationProperties properties, string name) static string? GetProperty(AuthenticationProperties properties, string name)
=> properties.Dictionary.TryGetValue(name, out string value) ? value : null; => properties.Dictionary.TryGetValue(name, out string? value) ? value : null;
} }
} }
@ -382,20 +352,16 @@ namespace OpenIddict.Validation.Owin
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(TContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] TContext context)
{ {
if (context == null) if (context == null)
{ {
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
Debug.Assert(context.Transaction.Response != null, SR.GetResourceString(SR.ID5007));
// This handler only applies to OWIN requests. If The OWIN request cannot be resolved, // This handler only applies to OWIN requests. If The OWIN request cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack. // this may indicate that the request was incorrectly processed by another server stack.
var response = context.Transaction.GetOwinRequest()?.Context.Response; var response = context.Transaction.GetOwinRequest()?.Context.Response;
@ -404,7 +370,7 @@ namespace OpenIddict.Validation.Owin
throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); throw new InvalidOperationException(SR.GetResourceString(SR.ID1119));
} }
response.StatusCode = context.Response.Error switch response.StatusCode = context.Transaction.Response.Error switch
{ {
null => 200, null => 200,
@ -438,14 +404,8 @@ namespace OpenIddict.Validation.Owin
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(TContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] TContext context)
{ {
if (context == null) if (context == null)
{ {
@ -477,7 +437,7 @@ namespace OpenIddict.Validation.Owin
{ {
private readonly IOptionsMonitor<OpenIddictValidationOwinOptions> _options; private readonly IOptionsMonitor<OpenIddictValidationOwinOptions> _options;
public AttachWwwAuthenticateHeader([NotNull] IOptionsMonitor<OpenIddictValidationOwinOptions> options) public AttachWwwAuthenticateHeader(IOptionsMonitor<OpenIddictValidationOwinOptions> options)
=> _options = options; => _options = options;
/// <summary> /// <summary>
@ -491,20 +451,16 @@ namespace OpenIddict.Validation.Owin
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(TContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] TContext context)
{ {
if (context == null) if (context == null)
{ {
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
Debug.Assert(context.Transaction.Response != null, SR.GetResourceString(SR.ID5007));
// This handler only applies to OWIN requests. If The OWIN request cannot be resolved, // This handler only applies to OWIN requests. If The OWIN request cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack. // this may indicate that the request was incorrectly processed by another server stack.
var response = context.Transaction.GetOwinRequest()?.Context.Response; var response = context.Transaction.GetOwinRequest()?.Context.Response;
@ -513,12 +469,12 @@ namespace OpenIddict.Validation.Owin
throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); throw new InvalidOperationException(SR.GetResourceString(SR.ID1119));
} }
if (string.IsNullOrEmpty(context.Response.Error)) if (string.IsNullOrEmpty(context.Transaction.Response.Error))
{ {
return default; return default;
} }
var scheme = context.Response.Error switch var scheme = context.Transaction.Response.Error switch
{ {
Errors.InvalidToken => Schemes.Bearer, Errors.InvalidToken => Schemes.Bearer,
Errors.MissingToken => Schemes.Bearer, Errors.MissingToken => Schemes.Bearer,
@ -541,11 +497,11 @@ namespace OpenIddict.Validation.Owin
parameters[Parameters.Realm] = _options.CurrentValue.Realm; parameters[Parameters.Realm] = _options.CurrentValue.Realm;
} }
foreach (var parameter in context.Response.GetParameters()) foreach (var parameter in context.Transaction.Response.GetParameters())
{ {
// Note: the error details are only included if the error was not caused by a missing token, as recommended // Note: the error details are only included if the error was not caused by a missing token, as recommended
// by the OAuth 2.0 bearer specification: https://tools.ietf.org/html/rfc6750#section-3.1. // by the OAuth 2.0 bearer specification: https://tools.ietf.org/html/rfc6750#section-3.1.
if (string.Equals(context.Response.Error, Errors.MissingToken, StringComparison.Ordinal) && if (string.Equals(context.Transaction.Response.Error, Errors.MissingToken, StringComparison.Ordinal) &&
(string.Equals(parameter.Key, Parameters.Error, StringComparison.Ordinal) || (string.Equals(parameter.Key, Parameters.Error, StringComparison.Ordinal) ||
string.Equals(parameter.Key, Parameters.ErrorDescription, StringComparison.Ordinal) || string.Equals(parameter.Key, Parameters.ErrorDescription, StringComparison.Ordinal) ||
string.Equals(parameter.Key, Parameters.ErrorUri, StringComparison.Ordinal))) string.Equals(parameter.Key, Parameters.ErrorUri, StringComparison.Ordinal)))
@ -554,7 +510,7 @@ namespace OpenIddict.Validation.Owin
} }
// Ignore values that can't be represented as unique strings. // Ignore values that can't be represented as unique strings.
var value = (string) parameter.Value; var value = (string?) parameter.Value;
if (string.IsNullOrEmpty(value)) if (string.IsNullOrEmpty(value))
{ {
continue; continue;
@ -605,14 +561,8 @@ namespace OpenIddict.Validation.Owin
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(TContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] TContext context)
{ {
if (context == null) if (context == null)
{ {
@ -633,7 +583,7 @@ namespace OpenIddict.Validation.Owin
return default; return default;
} }
context.Logger.LogInformation(SR.GetResourceString(SR.ID7141), context.Response); context.Logger.LogInformation(SR.GetResourceString(SR.ID7141), context.Transaction.Response);
context.HandleRequest(); context.HandleRequest();
return default; return default;
@ -657,14 +607,8 @@ namespace OpenIddict.Validation.Owin
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public async ValueTask HandleAsync(TContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public async ValueTask HandleAsync([NotNull] TContext context)
{ {
if (context == null) if (context == null)
{ {
@ -679,10 +623,10 @@ namespace OpenIddict.Validation.Owin
throw new InvalidOperationException(SR.GetResourceString(SR.ID1119)); throw new InvalidOperationException(SR.GetResourceString(SR.ID1119));
} }
context.Logger.LogInformation(SR.GetResourceString(SR.ID7142), context.Response); context.Logger.LogInformation(SR.GetResourceString(SR.ID7142), context.Transaction.Response);
using var stream = new MemoryStream(); using var stream = new MemoryStream();
await JsonSerializer.SerializeAsync(stream, context.Response, new JsonSerializerOptions await JsonSerializer.SerializeAsync(stream, context.Transaction.Response, new JsonSerializerOptions
{ {
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
WriteIndented = false WriteIndented = false

15
src/OpenIddict.Validation.Owin/OpenIddictValidationOwinHelpers.cs

@ -5,7 +5,6 @@
*/ */
using System; using System;
using JetBrains.Annotations;
using Microsoft.Owin; using Microsoft.Owin;
using OpenIddict.Abstractions; using OpenIddict.Abstractions;
using OpenIddict.Validation; using OpenIddict.Validation;
@ -26,7 +25,7 @@ namespace Owin
/// </summary> /// </summary>
/// <param name="app">The application builder used to register middleware instances.</param> /// <param name="app">The application builder used to register middleware instances.</param>
/// <returns>The <see cref="IAppBuilder"/>.</returns> /// <returns>The <see cref="IAppBuilder"/>.</returns>
public static IAppBuilder UseOpenIddictValidation([NotNull] this IAppBuilder app) public static IAppBuilder UseOpenIddictValidation(this IAppBuilder app)
{ {
if (app == null) if (app == null)
{ {
@ -41,19 +40,19 @@ namespace Owin
/// </summary> /// </summary>
/// <param name="transaction">The transaction instance.</param> /// <param name="transaction">The transaction instance.</param>
/// <returns>The <see cref="IOwinRequest"/> instance or <c>null</c> if it couldn't be found.</returns> /// <returns>The <see cref="IOwinRequest"/> instance or <c>null</c> if it couldn't be found.</returns>
public static IOwinRequest GetOwinRequest([NotNull] this OpenIddictValidationTransaction transaction) public static IOwinRequest? GetOwinRequest(this OpenIddictValidationTransaction transaction)
{ {
if (transaction == null) if (transaction == null)
{ {
throw new ArgumentNullException(nameof(transaction)); throw new ArgumentNullException(nameof(transaction));
} }
if (!transaction.Properties.TryGetValue(typeof(IOwinRequest).FullName, out object property)) if (!transaction.Properties.TryGetValue(typeof(IOwinRequest).FullName!, out object? property))
{ {
return null; return null;
} }
if (property is WeakReference<IOwinRequest> reference && reference.TryGetTarget(out IOwinRequest request)) if (property is WeakReference<IOwinRequest> reference && reference.TryGetTarget(out IOwinRequest? request))
{ {
return request; return request;
} }
@ -66,7 +65,7 @@ namespace Owin
/// </summary> /// </summary>
/// <param name="context">The context instance.</param> /// <param name="context">The context instance.</param>
/// <returns>The <see cref="OpenIddictValidationEndpointType"/>.</returns> /// <returns>The <see cref="OpenIddictValidationEndpointType"/>.</returns>
public static OpenIddictValidationEndpointType GetOpenIddictValidationEndpointType([NotNull] this IOwinContext context) public static OpenIddictValidationEndpointType GetOpenIddictValidationEndpointType(this IOwinContext context)
{ {
if (context == null) if (context == null)
{ {
@ -81,7 +80,7 @@ namespace Owin
/// </summary> /// </summary>
/// <param name="context">The context instance.</param> /// <param name="context">The context instance.</param>
/// <returns>The <see cref="OpenIddictRequest"/> instance or <c>null</c> if it couldn't be found.</returns> /// <returns>The <see cref="OpenIddictRequest"/> instance or <c>null</c> if it couldn't be found.</returns>
public static OpenIddictRequest GetOpenIddictValidationRequest([NotNull] this IOwinContext context) public static OpenIddictRequest? GetOpenIddictValidationRequest(this IOwinContext context)
{ {
if (context == null) if (context == null)
{ {
@ -96,7 +95,7 @@ namespace Owin
/// </summary> /// </summary>
/// <param name="context">The context instance.</param> /// <param name="context">The context instance.</param>
/// <returns>The <see cref="OpenIddictResponse"/> instance or <c>null</c> if it couldn't be found.</returns> /// <returns>The <see cref="OpenIddictResponse"/> instance or <c>null</c> if it couldn't be found.</returns>
public static OpenIddictResponse GetOpenIddictValidationResponse([NotNull] this IOwinContext context) public static OpenIddictResponse? GetOpenIddictValidationResponse(this IOwinContext context)
{ {
if (context == null) if (context == null)
{ {

9
src/OpenIddict.Validation.Owin/OpenIddictValidationOwinMiddleware.cs

@ -4,7 +4,6 @@
* the license and the contributors participating to this project. * the license and the contributors participating to this project.
*/ */
using JetBrains.Annotations;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.Owin; using Microsoft.Owin;
using Microsoft.Owin.Security.Infrastructure; using Microsoft.Owin.Security.Infrastructure;
@ -30,10 +29,10 @@ namespace OpenIddict.Validation.Owin
/// <param name="dispatcher">The OpenIddict validation dispatcher.</param> /// <param name="dispatcher">The OpenIddict validation dispatcher.</param>
/// <param name="factory">The OpenIddict validation factory.</param> /// <param name="factory">The OpenIddict validation factory.</param>
public OpenIddictValidationOwinMiddleware( public OpenIddictValidationOwinMiddleware(
[CanBeNull] OwinMiddleware next, OwinMiddleware? next,
[NotNull] IOptionsMonitor<OpenIddictValidationOwinOptions> options, IOptionsMonitor<OpenIddictValidationOwinOptions> options,
[NotNull] IOpenIddictValidationDispatcher dispatcher, IOpenIddictValidationDispatcher dispatcher,
[NotNull] IOpenIddictValidationFactory factory) IOpenIddictValidationFactory factory)
: base(next, options.CurrentValue) : base(next, options.CurrentValue)
{ {
_dispatcher = dispatcher; _dispatcher = dispatcher;

5
src/OpenIddict.Validation.Owin/OpenIddictValidationOwinMiddlewareFactory.cs

@ -6,7 +6,6 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.Owin; using Microsoft.Owin;
@ -24,7 +23,7 @@ namespace OpenIddict.Validation.Owin
/// Creates a new instance of the <see cref="OpenIddictValidationOwinMiddlewareFactory"/> class. /// Creates a new instance of the <see cref="OpenIddictValidationOwinMiddlewareFactory"/> class.
/// </summary> /// </summary>
/// <param name="next">The next middleware in the pipeline, if applicable.</param> /// <param name="next">The next middleware in the pipeline, if applicable.</param>
public OpenIddictValidationOwinMiddlewareFactory([CanBeNull] OwinMiddleware next) public OpenIddictValidationOwinMiddlewareFactory(OwinMiddleware? next)
: base(next) : base(next)
{ {
} }
@ -38,7 +37,7 @@ namespace OpenIddict.Validation.Owin
/// <returns> /// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation. /// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
public override Task Invoke([NotNull] IOwinContext context) public override Task Invoke(IOwinContext context)
{ {
if (context == null) if (context == null)
{ {

5
src/OpenIddict.Validation.Owin/OpenIddictValidationOwinOptions.cs

@ -21,9 +21,8 @@ namespace OpenIddict.Validation.Owin
=> AuthenticationMode = AuthenticationMode.Passive; => AuthenticationMode = AuthenticationMode.Passive;
/// <summary> /// <summary>
/// Gets or sets the optional "realm" value returned to /// Gets or sets the optional "realm" value returned to the caller as part of the WWW-Authenticate header.
/// the caller as part of the WWW-Authenticate header.
/// </summary> /// </summary>
public string Realm { get; set; } public string? Realm { get; set; }
} }
} }

1
src/OpenIddict.Validation.ServerIntegration/OpenIddict.Validation.ServerIntegration.csproj

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net461;netstandard2.0;netstandard2.1</TargetFrameworks> <TargetFrameworks>net461;netstandard2.0;netstandard2.1</TargetFrameworks>
<Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>

9
src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationBuilder.cs

@ -6,7 +6,6 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using JetBrains.Annotations;
using OpenIddict.Validation.ServerIntegration; using OpenIddict.Validation.ServerIntegration;
namespace Microsoft.Extensions.DependencyInjection namespace Microsoft.Extensions.DependencyInjection
@ -20,7 +19,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// Initializes a new instance of <see cref="OpenIddictValidationBuilder"/>. /// Initializes a new instance of <see cref="OpenIddictValidationBuilder"/>.
/// </summary> /// </summary>
/// <param name="services">The services collection.</param> /// <param name="services">The services collection.</param>
public OpenIddictValidationServerIntegrationBuilder([NotNull] IServiceCollection services) public OpenIddictValidationServerIntegrationBuilder(IServiceCollection services)
=> Services = services ?? throw new ArgumentNullException(nameof(services)); => Services = services ?? throw new ArgumentNullException(nameof(services));
/// <summary> /// <summary>
@ -35,7 +34,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="configuration">The delegate used to configure the OpenIddict options.</param> /// <param name="configuration">The delegate used to configure the OpenIddict options.</param>
/// <remarks>This extension can be safely called multiple times.</remarks> /// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictValidationServerIntegrationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationServerIntegrationBuilder"/>.</returns>
public OpenIddictValidationServerIntegrationBuilder Configure([NotNull] Action<OpenIddictValidationServerIntegrationOptions> configuration) public OpenIddictValidationServerIntegrationBuilder Configure(Action<OpenIddictValidationServerIntegrationOptions> configuration)
{ {
if (configuration == null) if (configuration == null)
{ {
@ -53,7 +52,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="obj">The object to compare with the current object.</param> /// <param name="obj">The object to compare with the current object.</param>
/// <returns><c>true</c> if the specified object is equal to the current object; otherwise, false.</returns> /// <returns><c>true</c> if the specified object is equal to the current object; otherwise, false.</returns>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals([CanBeNull] object obj) => base.Equals(obj); public override bool Equals(object? obj) => base.Equals(obj);
/// <summary> /// <summary>
/// Serves as the default hash function. /// Serves as the default hash function.
@ -67,6 +66,6 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <returns>A string that represents the current object.</returns> /// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString(); public override string? ToString() => base.ToString();
} }
} }

7
src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationConfiguration.cs

@ -5,7 +5,6 @@
*/ */
using System; using System;
using JetBrains.Annotations;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using OpenIddict.Server; using OpenIddict.Server;
@ -25,7 +24,7 @@ namespace OpenIddict.Validation.ServerIntegration
/// Creates a new instance of the <see cref="OpenIddictValidationServerIntegrationConfiguration"/> class. /// Creates a new instance of the <see cref="OpenIddictValidationServerIntegrationConfiguration"/> class.
/// </summary> /// </summary>
/// <param name="options">The OpenIddict server options.</param> /// <param name="options">The OpenIddict server options.</param>
public OpenIddictValidationServerIntegrationConfiguration([NotNull] IOptionsMonitor<OpenIddictServerOptions> options) public OpenIddictValidationServerIntegrationConfiguration(IOptionsMonitor<OpenIddictServerOptions> options)
=> _options = options; => _options = options;
/// <summary> /// <summary>
@ -33,7 +32,7 @@ namespace OpenIddict.Validation.ServerIntegration
/// and ensures that the configuration is in a consistent and valid state. /// and ensures that the configuration is in a consistent and valid state.
/// </summary> /// </summary>
/// <param name="options">The options instance to initialize.</param> /// <param name="options">The options instance to initialize.</param>
public void Configure([NotNull] OpenIddictValidationOptions options) public void Configure(OpenIddictValidationOptions options)
{ {
if (options == null) if (options == null)
{ {
@ -66,7 +65,7 @@ namespace OpenIddict.Validation.ServerIntegration
/// </summary> /// </summary>
/// <param name="name">The name of the options instance to configure, if applicable.</param> /// <param name="name">The name of the options instance to configure, if applicable.</param>
/// <param name="options">The options instance to initialize.</param> /// <param name="options">The options instance to initialize.</param>
public void PostConfigure([CanBeNull] string name, [NotNull] OpenIddictValidationOptions options) public void PostConfigure(string name, OpenIddictValidationOptions options)
{ {
if (options == null) if (options == null)
{ {

6
src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationExtensions.cs

@ -5,7 +5,6 @@
*/ */
using System; using System;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using OpenIddict.Validation; using OpenIddict.Validation;
@ -25,7 +24,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="builder">The services builder used by OpenIddict to register new services.</param> /// <param name="builder">The services builder used by OpenIddict to register new services.</param>
/// <remarks>This extension can be safely called multiple times.</remarks> /// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public static OpenIddictValidationServerIntegrationBuilder UseLocalServer([NotNull] this OpenIddictValidationBuilder builder) public static OpenIddictValidationServerIntegrationBuilder UseLocalServer(this OpenIddictValidationBuilder builder)
{ {
if (builder == null) if (builder == null)
{ {
@ -51,8 +50,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <remarks>This extension can be safely called multiple times.</remarks> /// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
public static OpenIddictValidationBuilder UseLocalServer( public static OpenIddictValidationBuilder UseLocalServer(
[NotNull] this OpenIddictValidationBuilder builder, this OpenIddictValidationBuilder builder, Action<OpenIddictValidationServerIntegrationBuilder> configuration)
[NotNull] Action<OpenIddictValidationServerIntegrationBuilder> configuration)
{ {
if (builder == null) if (builder == null)
{ {

1
src/OpenIddict.Validation.SystemNetHttp/OpenIddict.Validation.SystemNetHttp.csproj

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net461;netstandard2.0;netstandard2.1</TargetFrameworks> <TargetFrameworks>net461;netstandard2.0;netstandard2.1</TargetFrameworks>
<Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>

11
src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpBuilder.cs

@ -7,7 +7,6 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Net.Http; using System.Net.Http;
using JetBrains.Annotations;
using OpenIddict.Validation.SystemNetHttp; using OpenIddict.Validation.SystemNetHttp;
using Polly; using Polly;
@ -22,7 +21,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// Initializes a new instance of <see cref="OpenIddictValidationBuilder"/>. /// Initializes a new instance of <see cref="OpenIddictValidationBuilder"/>.
/// </summary> /// </summary>
/// <param name="services">The services collection.</param> /// <param name="services">The services collection.</param>
public OpenIddictValidationSystemNetHttpBuilder([NotNull] IServiceCollection services) public OpenIddictValidationSystemNetHttpBuilder(IServiceCollection services)
=> Services = services ?? throw new ArgumentNullException(nameof(services)); => Services = services ?? throw new ArgumentNullException(nameof(services));
/// <summary> /// <summary>
@ -37,7 +36,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="configuration">The delegate used to configure the OpenIddict options.</param> /// <param name="configuration">The delegate used to configure the OpenIddict options.</param>
/// <remarks>This extension can be safely called multiple times.</remarks> /// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictValidationSystemNetHttpBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationSystemNetHttpBuilder"/>.</returns>
public OpenIddictValidationSystemNetHttpBuilder Configure([NotNull] Action<OpenIddictValidationSystemNetHttpOptions> configuration) public OpenIddictValidationSystemNetHttpBuilder Configure(Action<OpenIddictValidationSystemNetHttpOptions> configuration)
{ {
if (configuration == null) if (configuration == null)
{ {
@ -54,7 +53,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <param name="policy">The HTTP Polly error policy.</param> /// <param name="policy">The HTTP Polly error policy.</param>
/// <returns>The <see cref="OpenIddictValidationSystemNetHttpBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationSystemNetHttpBuilder"/>.</returns>
public OpenIddictValidationSystemNetHttpBuilder SetHttpErrorPolicy([CanBeNull] IAsyncPolicy<HttpResponseMessage> policy) public OpenIddictValidationSystemNetHttpBuilder SetHttpErrorPolicy(IAsyncPolicy<HttpResponseMessage> policy)
=> Configure(options => options.HttpErrorPolicy = policy); => Configure(options => options.HttpErrorPolicy = policy);
/// <summary> /// <summary>
@ -63,7 +62,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="obj">The object to compare with the current object.</param> /// <param name="obj">The object to compare with the current object.</param>
/// <returns><c>true</c> if the specified object is equal to the current object; otherwise, false.</returns> /// <returns><c>true</c> if the specified object is equal to the current object; otherwise, false.</returns>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals([CanBeNull] object obj) => base.Equals(obj); public override bool Equals(object? obj) => base.Equals(obj);
/// <summary> /// <summary>
/// Serves as the default hash function. /// Serves as the default hash function.
@ -77,6 +76,6 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <returns>A string that represents the current object.</returns> /// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString(); public override string? ToString() => base.ToString();
} }
} }

13
src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpConfiguration.cs

@ -7,7 +7,6 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Http; using Microsoft.Extensions.Http;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -23,11 +22,11 @@ namespace OpenIddict.Validation.SystemNetHttp
#if !SUPPORTS_SERVICE_PROVIDER_IN_HTTP_MESSAGE_HANDLER_BUILDER #if !SUPPORTS_SERVICE_PROVIDER_IN_HTTP_MESSAGE_HANDLER_BUILDER
private readonly IServiceProvider _provider; private readonly IServiceProvider _provider;
public OpenIddictValidationSystemNetHttpConfiguration([NotNull] IServiceProvider provider) public OpenIddictValidationSystemNetHttpConfiguration(IServiceProvider provider)
=> _provider = provider; => _provider = provider;
#endif #endif
public void Configure([NotNull] OpenIddictValidationOptions options) public void Configure(OpenIddictValidationOptions options)
{ {
if (options == null) if (options == null)
{ {
@ -38,10 +37,10 @@ namespace OpenIddict.Validation.SystemNetHttp
options.Handlers.AddRange(OpenIddictValidationSystemNetHttpHandlers.DefaultHandlers); options.Handlers.AddRange(OpenIddictValidationSystemNetHttpHandlers.DefaultHandlers);
} }
public void Configure([NotNull] HttpClientFactoryOptions options) public void Configure(HttpClientFactoryOptions options)
=> Debug.Fail("This infrastructure method shouldn't be called."); => Debug.Fail("This infrastructure method shouldn't be called.");
public void Configure([CanBeNull] string name, [NotNull] HttpClientFactoryOptions options) public void Configure(string name, HttpClientFactoryOptions options)
{ {
if (options == null) if (options == null)
{ {
@ -58,8 +57,8 @@ namespace OpenIddict.Validation.SystemNetHttp
options.HttpClientActions.Add(client => options.HttpClientActions.Add(client =>
{ {
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue( client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(
productName: assembly.Name, productName: assembly.Name!,
productVersion: assembly.Version.ToString())); productVersion: assembly.Version!.ToString()));
}); });
options.HttpMessageHandlerBuilderActions.Add(builder => options.HttpMessageHandlerBuilderActions.Add(builder =>

6
src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpExtensions.cs

@ -6,7 +6,6 @@
using System; using System;
using System.Linq; using System.Linq;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Http; using Microsoft.Extensions.Http;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -28,7 +27,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="builder">The services builder used by OpenIddict to register new services.</param> /// <param name="builder">The services builder used by OpenIddict to register new services.</param>
/// <remarks>This extension can be safely called multiple times.</remarks> /// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public static OpenIddictValidationSystemNetHttpBuilder UseSystemNetHttp([NotNull] this OpenIddictValidationBuilder builder) public static OpenIddictValidationSystemNetHttpBuilder UseSystemNetHttp(this OpenIddictValidationBuilder builder)
{ {
if (builder == null) if (builder == null)
{ {
@ -62,8 +61,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <remarks>This extension can be safely called multiple times.</remarks> /// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
public static OpenIddictValidationBuilder UseSystemNetHttp( public static OpenIddictValidationBuilder UseSystemNetHttp(
[NotNull] this OpenIddictValidationBuilder builder, this OpenIddictValidationBuilder builder, Action<OpenIddictValidationSystemNetHttpBuilder> configuration)
[NotNull] Action<OpenIddictValidationSystemNetHttpBuilder> configuration)
{ {
if (builder == null) if (builder == null)
{ {

3
src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlerFilters.cs

@ -7,7 +7,6 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using static OpenIddict.Validation.OpenIddictValidationEvents; using static OpenIddict.Validation.OpenIddictValidationEvents;
namespace OpenIddict.Validation.SystemNetHttp namespace OpenIddict.Validation.SystemNetHttp
@ -20,7 +19,7 @@ namespace OpenIddict.Validation.SystemNetHttp
/// </summary> /// </summary>
public class RequireHttpMetadataAddress : IOpenIddictValidationHandlerFilter<BaseContext> public class RequireHttpMetadataAddress : IOpenIddictValidationHandlerFilter<BaseContext>
{ {
public ValueTask<bool> IsActiveAsync([NotNull] BaseContext context) public ValueTask<bool> IsActiveAsync(BaseContext context)
{ {
if (context == null) if (context == null)
{ {

9
src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHandlers.Introspection.cs

@ -6,11 +6,11 @@
using System; using System;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Abstractions.OpenIddictConstants;
using static OpenIddict.Validation.OpenIddictValidationEvents; using static OpenIddict.Validation.OpenIddictValidationEvents;
using static OpenIddict.Validation.SystemNetHttp.OpenIddictValidationSystemNetHttpHandlerFilters; using static OpenIddict.Validation.SystemNetHttp.OpenIddictValidationSystemNetHttpHandlerFilters;
@ -52,13 +52,16 @@ namespace OpenIddict.Validation.SystemNetHttp
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
public async ValueTask HandleAsync([NotNull] PrepareIntrospectionRequestContext context) /// <inheritdoc/>
public async ValueTask HandleAsync(PrepareIntrospectionRequestContext context)
{ {
if (context == null) if (context == null)
{ {
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
Debug.Assert(context.Request != null, SR.GetResourceString(SR.ID5008));
// This handler only applies to System.Net.Http requests. If the HTTP request cannot be resolved, // This handler only applies to System.Net.Http requests. If the HTTP request cannot be resolved,
// this may indicate that the request was incorrectly processed by another client stack. // this may indicate that the request was incorrectly processed by another client stack.
var request = context.Transaction.GetHttpRequestMessage(); var request = context.Transaction.GetHttpRequestMessage();
@ -97,7 +100,7 @@ namespace OpenIddict.Validation.SystemNetHttp
context.Request.ClientId = context.Request.ClientSecret = null; context.Request.ClientId = context.Request.ClientSecret = null;
} }
static string EscapeDataString(string value) static string? EscapeDataString(string? value)
{ {
if (string.IsNullOrEmpty(value)) if (string.IsNullOrEmpty(value))
{ {

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

@ -8,12 +8,12 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Net.Http.Json; using System.Net.Http.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using OpenIddict.Abstractions; using OpenIddict.Abstractions;
using static OpenIddict.Validation.OpenIddictValidationEvents; using static OpenIddict.Validation.OpenIddictValidationEvents;
using static OpenIddict.Validation.SystemNetHttp.OpenIddictValidationSystemNetHttpHandlerFilters; using static OpenIddict.Validation.SystemNetHttp.OpenIddictValidationSystemNetHttpHandlerFilters;
@ -45,7 +45,8 @@ namespace OpenIddict.Validation.SystemNetHttp
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
public ValueTask HandleAsync([NotNull] TContext context) /// <inheritdoc/>
public ValueTask HandleAsync(TContext context)
{ {
if (context == null) if (context == null)
{ {
@ -57,7 +58,7 @@ namespace OpenIddict.Validation.SystemNetHttp
request.Headers.AcceptCharset.Add(new StringWithQualityHeaderValue("utf-8")); request.Headers.AcceptCharset.Add(new StringWithQualityHeaderValue("utf-8"));
// Store the HttpRequestMessage in the transaction properties. // Store the HttpRequestMessage in the transaction properties.
context.Transaction.Properties[typeof(HttpRequestMessage).FullName] = request; context.Transaction.Properties[typeof(HttpRequestMessage).FullName!] = request;
return default; return default;
} }
@ -79,7 +80,8 @@ namespace OpenIddict.Validation.SystemNetHttp
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
public ValueTask HandleAsync([NotNull] TContext context) /// <inheritdoc/>
public ValueTask HandleAsync(TContext context)
{ {
if (context == null) if (context == null)
{ {
@ -91,7 +93,7 @@ namespace OpenIddict.Validation.SystemNetHttp
request.Headers.AcceptCharset.Add(new StringWithQualityHeaderValue("utf-8")); request.Headers.AcceptCharset.Add(new StringWithQualityHeaderValue("utf-8"));
// Store the HttpRequestMessage in the transaction properties. // Store the HttpRequestMessage in the transaction properties.
context.Transaction.Properties[typeof(HttpRequestMessage).FullName] = request; context.Transaction.Properties[typeof(HttpRequestMessage).FullName!] = request;
return default; return default;
} }
@ -113,13 +115,16 @@ namespace OpenIddict.Validation.SystemNetHttp
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
public async ValueTask HandleAsync([NotNull] TContext context) /// <inheritdoc/>
public async ValueTask HandleAsync(TContext context)
{ {
if (context == null) if (context == null)
{ {
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
Debug.Assert(context.Transaction.Request != null, SR.GetResourceString(SR.ID5008));
// This handler only applies to System.Net.Http requests. If the HTTP request cannot be resolved, // This handler only applies to System.Net.Http requests. If the HTTP request cannot be resolved,
// this may indicate that the request was incorrectly processed by another client stack. // this may indicate that the request was incorrectly processed by another client stack.
var request = context.Transaction.GetHttpRequestMessage(); var request = context.Transaction.GetHttpRequestMessage();
@ -132,8 +137,8 @@ namespace OpenIddict.Validation.SystemNetHttp
// query strings from existing key/value pairs. To work around this limitation, // query strings from existing key/value pairs. To work around this limitation,
// a FormUrlEncodedContent is instantiated and used to manually create the URL. // a FormUrlEncodedContent is instantiated and used to manually create the URL.
using var content = new FormUrlEncodedContent( using var content = new FormUrlEncodedContent(
from parameter in context.Request.GetParameters() from parameter in context.Transaction.Request.GetParameters()
let values = (string[]) parameter.Value let values = (string[]?) parameter.Value
where values != null where values != null
from value in values from value in values
select new KeyValuePair<string, string>(parameter.Key, value)); select new KeyValuePair<string, string>(parameter.Key, value));
@ -163,13 +168,16 @@ namespace OpenIddict.Validation.SystemNetHttp
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
public ValueTask HandleAsync([NotNull] TContext context) /// <inheritdoc/>
public ValueTask HandleAsync(TContext context)
{ {
if (context == null) if (context == null)
{ {
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
Debug.Assert(context.Transaction.Request != null, SR.GetResourceString(SR.ID5008));
// This handler only applies to System.Net.Http requests. If the HTTP request cannot be resolved, // This handler only applies to System.Net.Http requests. If the HTTP request cannot be resolved,
// this may indicate that the request was incorrectly processed by another client stack. // this may indicate that the request was incorrectly processed by another client stack.
var request = context.Transaction.GetHttpRequestMessage(); var request = context.Transaction.GetHttpRequestMessage();
@ -179,8 +187,8 @@ namespace OpenIddict.Validation.SystemNetHttp
} }
request.Content = new FormUrlEncodedContent( request.Content = new FormUrlEncodedContent(
from parameter in context.Request.GetParameters() from parameter in context.Transaction.Request.GetParameters()
let values = (string[]) parameter.Value let values = (string[]?) parameter.Value
where values != null where values != null
from value in values from value in values
select new KeyValuePair<string, string>(parameter.Key, value)); select new KeyValuePair<string, string>(parameter.Key, value));
@ -196,7 +204,7 @@ namespace OpenIddict.Validation.SystemNetHttp
{ {
private readonly IHttpClientFactory _factory; private readonly IHttpClientFactory _factory;
public SendHttpRequest([NotNull] IHttpClientFactory factory) public SendHttpRequest(IHttpClientFactory factory)
=> _factory = factory; => _factory = factory;
/// <summary> /// <summary>
@ -210,7 +218,8 @@ namespace OpenIddict.Validation.SystemNetHttp
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
public async ValueTask HandleAsync([NotNull] TContext context) /// <inheritdoc/>
public async ValueTask HandleAsync(TContext context)
{ {
if (context == null) if (context == null)
{ {
@ -239,7 +248,7 @@ namespace OpenIddict.Validation.SystemNetHttp
} }
// Store the HttpResponseMessage in the transaction properties. // Store the HttpResponseMessage in the transaction properties.
context.Transaction.Properties[typeof(HttpResponseMessage).FullName] = response; context.Transaction.Properties[typeof(HttpResponseMessage).FullName!] = response;
} }
} }
@ -259,7 +268,8 @@ namespace OpenIddict.Validation.SystemNetHttp
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
public async ValueTask HandleAsync([NotNull] TContext context) /// <inheritdoc/>
public async ValueTask HandleAsync(TContext context)
{ {
if (context == null) if (context == null)
{ {
@ -279,7 +289,7 @@ namespace OpenIddict.Validation.SystemNetHttp
// Note: ReadFromJsonAsync() automatically validates the content type and the content encoding // Note: ReadFromJsonAsync() automatically validates the content type and the content encoding
// and transcode the response stream if a non-UTF-8 response is returned by the remote server. // and transcode the response stream if a non-UTF-8 response is returned by the remote server.
context.Response = await response.Content.ReadFromJsonAsync<OpenIddictResponse>(); context.Transaction.Response = await response.Content.ReadFromJsonAsync<OpenIddictResponse>();
} }
} }
} }

9
src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpHelpers.cs

@ -4,7 +4,6 @@
* the license and the contributors participating to this project. * the license and the contributors participating to this project.
*/ */
using JetBrains.Annotations;
using OpenIddict.Validation; using OpenIddict.Validation;
namespace System.Net.Http namespace System.Net.Http
@ -19,15 +18,15 @@ namespace System.Net.Http
/// </summary> /// </summary>
/// <param name="transaction">The transaction instance.</param> /// <param name="transaction">The transaction instance.</param>
/// <returns>The <see cref="HttpRequestMessage"/> instance or <c>null</c> if it couldn't be found.</returns> /// <returns>The <see cref="HttpRequestMessage"/> instance or <c>null</c> if it couldn't be found.</returns>
public static HttpRequestMessage GetHttpRequestMessage([NotNull] this OpenIddictValidationTransaction transaction) public static HttpRequestMessage? GetHttpRequestMessage(this OpenIddictValidationTransaction transaction)
=> transaction.GetProperty<HttpRequestMessage>(typeof(HttpRequestMessage).FullName); => transaction.GetProperty<HttpRequestMessage>(typeof(HttpRequestMessage).FullName!);
/// <summary> /// <summary>
/// Gets the <see cref="HttpResponseMessage"/> associated with the current context. /// Gets the <see cref="HttpResponseMessage"/> associated with the current context.
/// </summary> /// </summary>
/// <param name="transaction">The transaction instance.</param> /// <param name="transaction">The transaction instance.</param>
/// <returns>The <see cref="HttpResponseMessage"/> instance or <c>null</c> if it couldn't be found.</returns> /// <returns>The <see cref="HttpResponseMessage"/> instance or <c>null</c> if it couldn't be found.</returns>
public static HttpResponseMessage GetHttpResponseMessage([NotNull] this OpenIddictValidationTransaction transaction) public static HttpResponseMessage? GetHttpResponseMessage(this OpenIddictValidationTransaction transaction)
=> transaction.GetProperty<HttpResponseMessage>(typeof(HttpResponseMessage).FullName); => transaction.GetProperty<HttpResponseMessage>(typeof(HttpResponseMessage).FullName!);
} }
} }

2
src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpOptions.cs

@ -20,7 +20,7 @@ namespace OpenIddict.Validation.SystemNetHttp
/// <summary> /// <summary>
/// Gets or sets the HTTP Polly error policy used by the internal OpenIddict HTTP clients. /// Gets or sets the HTTP Polly error policy used by the internal OpenIddict HTTP clients.
/// </summary> /// </summary>
public IAsyncPolicy<HttpResponseMessage> HttpErrorPolicy { get; set; } public IAsyncPolicy<HttpResponseMessage>? HttpErrorPolicy { get; set; }
= HttpPolicyExtensions.HandleTransientHttpError() = HttpPolicyExtensions.HandleTransientHttpError()
.OrResult(response => response.StatusCode == HttpStatusCode.NotFound) .OrResult(response => response.StatusCode == HttpStatusCode.NotFound)
.WaitAndRetryAsync(4, attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt))); .WaitAndRetryAsync(4, attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)));

3
src/OpenIddict.Validation/IOpenIddictValidationDispatcher.cs

@ -5,13 +5,12 @@
*/ */
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using static OpenIddict.Validation.OpenIddictValidationEvents; using static OpenIddict.Validation.OpenIddictValidationEvents;
namespace OpenIddict.Validation namespace OpenIddict.Validation
{ {
public interface IOpenIddictValidationDispatcher public interface IOpenIddictValidationDispatcher
{ {
ValueTask DispatchAsync<TContext>([NotNull] TContext context) where TContext : BaseContext; ValueTask DispatchAsync<TContext>(TContext context) where TContext : BaseContext;
} }
} }

3
src/OpenIddict.Validation/IOpenIddictValidationHandler.cs

@ -5,7 +5,6 @@
*/ */
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using static OpenIddict.Validation.OpenIddictValidationEvents; using static OpenIddict.Validation.OpenIddictValidationEvents;
namespace OpenIddict.Validation namespace OpenIddict.Validation
@ -23,6 +22,6 @@ namespace OpenIddict.Validation
/// <returns> /// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation. /// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
ValueTask HandleAsync([NotNull] TContext context); ValueTask HandleAsync(TContext context);
} }
} }

3
src/OpenIddict.Validation/IOpenIddictValidationHandlerFilter.cs

@ -5,13 +5,12 @@
*/ */
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using static OpenIddict.Validation.OpenIddictValidationEvents; using static OpenIddict.Validation.OpenIddictValidationEvents;
namespace OpenIddict.Validation namespace OpenIddict.Validation
{ {
public interface IOpenIddictValidationHandlerFilter<in TContext> where TContext : BaseContext public interface IOpenIddictValidationHandlerFilter<in TContext> where TContext : BaseContext
{ {
ValueTask<bool> IsActiveAsync([NotNull] TContext context); ValueTask<bool> IsActiveAsync(TContext context);
} }
} }

1
src/OpenIddict.Validation/OpenIddict.Validation.csproj

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net461;net472;netcoreapp2.1;netcoreapp3.1;netstandard2.0;netstandard2.1</TargetFrameworks> <TargetFrameworks>net461;net472;netcoreapp2.1;netcoreapp3.1;netstandard2.0;netstandard2.1</TargetFrameworks>
<Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>

49
src/OpenIddict.Validation/OpenIddictValidationBuilder.cs

@ -11,7 +11,6 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
@ -30,7 +29,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// Initializes a new instance of <see cref="OpenIddictValidationBuilder"/>. /// Initializes a new instance of <see cref="OpenIddictValidationBuilder"/>.
/// </summary> /// </summary>
/// <param name="services">The services collection.</param> /// <param name="services">The services collection.</param>
public OpenIddictValidationBuilder([NotNull] IServiceCollection services) public OpenIddictValidationBuilder(IServiceCollection services)
=> Services = services ?? throw new ArgumentNullException(nameof(services)); => Services = services ?? throw new ArgumentNullException(nameof(services));
/// <summary> /// <summary>
@ -47,7 +46,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
[EditorBrowsable(EditorBrowsableState.Advanced)] [EditorBrowsable(EditorBrowsableState.Advanced)]
public OpenIddictValidationBuilder AddEventHandler<TContext>( public OpenIddictValidationBuilder AddEventHandler<TContext>(
[NotNull] Action<OpenIddictValidationHandlerDescriptor.Builder<TContext>> configuration) Action<OpenIddictValidationHandlerDescriptor.Builder<TContext>> configuration)
where TContext : OpenIddictValidationEvents.BaseContext where TContext : OpenIddictValidationEvents.BaseContext
{ {
if (configuration == null) if (configuration == null)
@ -70,7 +69,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="descriptor">The handler descriptor.</param> /// <param name="descriptor">The handler descriptor.</param>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
[EditorBrowsable(EditorBrowsableState.Advanced)] [EditorBrowsable(EditorBrowsableState.Advanced)]
public OpenIddictValidationBuilder AddEventHandler([NotNull] OpenIddictValidationHandlerDescriptor descriptor) public OpenIddictValidationBuilder AddEventHandler(OpenIddictValidationHandlerDescriptor descriptor)
{ {
if (descriptor == null) if (descriptor == null)
{ {
@ -89,7 +88,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="descriptor">The descriptor corresponding to the handler to remove.</param> /// <param name="descriptor">The descriptor corresponding to the handler to remove.</param>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
[EditorBrowsable(EditorBrowsableState.Advanced)] [EditorBrowsable(EditorBrowsableState.Advanced)]
public OpenIddictValidationBuilder RemoveEventHandler([NotNull] OpenIddictValidationHandlerDescriptor descriptor) public OpenIddictValidationBuilder RemoveEventHandler(OpenIddictValidationHandlerDescriptor descriptor)
{ {
if (descriptor == null) if (descriptor == null)
{ {
@ -118,7 +117,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="configuration">The delegate used to configure the OpenIddict options.</param> /// <param name="configuration">The delegate used to configure the OpenIddict options.</param>
/// <remarks>This extension can be safely called multiple times.</remarks> /// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public OpenIddictValidationBuilder Configure([NotNull] Action<OpenIddictValidationOptions> configuration) public OpenIddictValidationBuilder Configure(Action<OpenIddictValidationOptions> configuration)
{ {
if (configuration == null) if (configuration == null)
{ {
@ -135,7 +134,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <param name="credentials">The encrypting credentials.</param> /// <param name="credentials">The encrypting credentials.</param>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public OpenIddictValidationBuilder AddEncryptionCredentials([NotNull] EncryptingCredentials credentials) public OpenIddictValidationBuilder AddEncryptionCredentials(EncryptingCredentials credentials)
{ {
if (credentials == null) if (credentials == null)
{ {
@ -150,7 +149,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <param name="key">The security key.</param> /// <param name="key">The security key.</param>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public OpenIddictValidationBuilder AddEncryptionKey([NotNull] SecurityKey key) public OpenIddictValidationBuilder AddEncryptionKey(SecurityKey key)
{ {
if (key == null) if (key == null)
{ {
@ -184,7 +183,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <param name="certificate">The encryption certificate.</param> /// <param name="certificate">The encryption certificate.</param>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public OpenIddictValidationBuilder AddEncryptionCertificate([NotNull] X509Certificate2 certificate) public OpenIddictValidationBuilder AddEncryptionCertificate(X509Certificate2 certificate)
{ {
if (certificate == null) if (certificate == null)
{ {
@ -218,7 +217,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="password">The password used to open the certificate.</param> /// <param name="password">The password used to open the certificate.</param>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public OpenIddictValidationBuilder AddEncryptionCertificate( public OpenIddictValidationBuilder AddEncryptionCertificate(
[NotNull] Assembly assembly, [NotNull] string resource, [NotNull] string password) Assembly assembly, string resource, string password)
#if SUPPORTS_EPHEMERAL_KEY_SETS #if SUPPORTS_EPHEMERAL_KEY_SETS
// Note: ephemeral key sets are currently not supported on macOS. // Note: ephemeral key sets are currently not supported on macOS.
=> AddEncryptionCertificate(assembly, resource, password, RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? => AddEncryptionCertificate(assembly, resource, password, RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ?
@ -237,8 +236,8 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="flags">An enumeration of flags indicating how and where to store the private key of the certificate.</param> /// <param name="flags">An enumeration of flags indicating how and where to store the private key of the certificate.</param>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public OpenIddictValidationBuilder AddEncryptionCertificate( public OpenIddictValidationBuilder AddEncryptionCertificate(
[NotNull] Assembly assembly, [NotNull] string resource, Assembly assembly, string resource,
[NotNull] string password, X509KeyStorageFlags flags) string password, X509KeyStorageFlags flags)
{ {
if (assembly == null) if (assembly == null)
{ {
@ -270,7 +269,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="stream">The stream containing the certificate.</param> /// <param name="stream">The stream containing the certificate.</param>
/// <param name="password">The password used to open the certificate.</param> /// <param name="password">The password used to open the certificate.</param>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public OpenIddictValidationBuilder AddEncryptionCertificate([NotNull] Stream stream, [NotNull] string password) public OpenIddictValidationBuilder AddEncryptionCertificate(Stream stream, string password)
#if SUPPORTS_EPHEMERAL_KEY_SETS #if SUPPORTS_EPHEMERAL_KEY_SETS
// Note: ephemeral key sets are currently not supported on macOS. // Note: ephemeral key sets are currently not supported on macOS.
=> AddEncryptionCertificate(stream, password, RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? => AddEncryptionCertificate(stream, password, RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ?
@ -293,7 +292,7 @@ namespace Microsoft.Extensions.DependencyInjection
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope",
Justification = "The X.509 certificate is attached to the server options.")] Justification = "The X.509 certificate is attached to the server options.")]
public OpenIddictValidationBuilder AddEncryptionCertificate( public OpenIddictValidationBuilder AddEncryptionCertificate(
[NotNull] Stream stream, [NotNull] string password, X509KeyStorageFlags flags) Stream stream, string password, X509KeyStorageFlags flags)
{ {
if (stream == null) if (stream == null)
{ {
@ -316,7 +315,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <param name="thumbprint">The thumbprint of the certificate used to identify it in the X.509 store.</param> /// <param name="thumbprint">The thumbprint of the certificate used to identify it in the X.509 store.</param>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public OpenIddictValidationBuilder AddEncryptionCertificate([NotNull] string thumbprint) public OpenIddictValidationBuilder AddEncryptionCertificate(string thumbprint)
{ {
if (string.IsNullOrEmpty(thumbprint)) if (string.IsNullOrEmpty(thumbprint))
{ {
@ -350,7 +349,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="location">The location of the X.509 store.</param> /// <param name="location">The location of the X.509 store.</param>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public OpenIddictValidationBuilder AddEncryptionCertificate( public OpenIddictValidationBuilder AddEncryptionCertificate(
[NotNull] string thumbprint, StoreName name, StoreLocation location) string thumbprint, StoreName name, StoreLocation location)
{ {
if (string.IsNullOrEmpty(thumbprint)) if (string.IsNullOrEmpty(thumbprint))
{ {
@ -378,7 +377,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <param name="audiences">The audiences valid for this resource server.</param> /// <param name="audiences">The audiences valid for this resource server.</param>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public OpenIddictValidationBuilder AddAudiences([NotNull] params string[] audiences) public OpenIddictValidationBuilder AddAudiences(params string[] audiences)
{ {
if (audiences == null) if (audiences == null)
{ {
@ -419,7 +418,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <param name="configuration">The server configuration.</param> /// <param name="configuration">The server configuration.</param>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public OpenIddictValidationBuilder SetConfiguration([NotNull] OpenIdConnectConfiguration configuration) public OpenIddictValidationBuilder SetConfiguration(OpenIdConnectConfiguration configuration)
{ {
if (configuration == null) if (configuration == null)
{ {
@ -435,7 +434,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <param name="identifier">The client identifier.</param> /// <param name="identifier">The client identifier.</param>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public OpenIddictValidationBuilder SetClientId([NotNull] string identifier) public OpenIddictValidationBuilder SetClientId(string identifier)
{ {
if (string.IsNullOrEmpty(identifier)) if (string.IsNullOrEmpty(identifier))
{ {
@ -451,7 +450,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <param name="secret">The client secret.</param> /// <param name="secret">The client secret.</param>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public OpenIddictValidationBuilder SetClientSecret([NotNull] string secret) public OpenIddictValidationBuilder SetClientSecret(string secret)
{ {
if (string.IsNullOrEmpty(secret)) if (string.IsNullOrEmpty(secret))
{ {
@ -467,7 +466,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <param name="address">The issuer address.</param> /// <param name="address">The issuer address.</param>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public OpenIddictValidationBuilder SetIssuer([NotNull] Uri address) public OpenIddictValidationBuilder SetIssuer(Uri address)
{ {
if (address == null) if (address == null)
{ {
@ -483,14 +482,14 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <param name="address">The issuer address.</param> /// <param name="address">The issuer address.</param>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public OpenIddictValidationBuilder SetIssuer([NotNull] string address) public OpenIddictValidationBuilder SetIssuer(string address)
{ {
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(address))
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID1125), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID1125), nameof(address));
} }
if (!Uri.TryCreate(address, UriKind.Absolute, out Uri uri) || !uri.IsWellFormedOriginalString()) if (!Uri.TryCreate(address, UriKind.Absolute, out Uri? uri) || !uri.IsWellFormedOriginalString())
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID1126), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID1126), nameof(address));
} }
@ -511,7 +510,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="obj">The object to compare with the current object.</param> /// <param name="obj">The object to compare with the current object.</param>
/// <returns><c>true</c> if the specified object is equal to the current object; otherwise, false.</returns> /// <returns><c>true</c> if the specified object is equal to the current object; otherwise, false.</returns>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals([CanBeNull] object obj) => base.Equals(obj); public override bool Equals(object? obj) => base.Equals(obj);
/// <summary> /// <summary>
/// Serves as the default hash function. /// Serves as the default hash function.
@ -525,6 +524,6 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
/// <returns>A string that represents the current object.</returns> /// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString(); public override string? ToString() => base.ToString();
} }
} }

72
src/OpenIddict.Validation/OpenIddictValidationConfiguration.cs

@ -6,7 +6,6 @@
using System; using System;
using System.Linq; using System.Linq;
using JetBrains.Annotations;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Protocols; using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Protocols.OpenIdConnect;
@ -23,7 +22,7 @@ namespace OpenIddict.Validation
{ {
private readonly OpenIddictValidationService _service; private readonly OpenIddictValidationService _service;
public OpenIddictValidationConfiguration([NotNull] OpenIddictValidationService service) public OpenIddictValidationConfiguration(OpenIddictValidationService service)
=> _service = service; => _service = service;
/// <summary> /// <summary>
@ -32,7 +31,7 @@ namespace OpenIddict.Validation
/// </summary> /// </summary>
/// <param name="name">The name of the options instance to configure, if applicable.</param> /// <param name="name">The name of the options instance to configure, if applicable.</param>
/// <param name="options">The options instance to initialize.</param> /// <param name="options">The options instance to initialize.</param>
public void PostConfigure([CanBeNull] string name, [NotNull] OpenIddictValidationOptions options) public void PostConfigure(string name, OpenIddictValidationOptions options)
{ {
if (options == null) if (options == null)
{ {
@ -91,55 +90,52 @@ namespace OpenIddict.Validation
throw new InvalidOperationException(SR.GetResourceString(SR.ID1086)); throw new InvalidOperationException(SR.GetResourceString(SR.ID1086));
} }
if (options.Configuration == null && options.ConfigurationManager == null) if (options.ConfigurationManager == null)
{ {
if (!options.Handlers.Any(descriptor => descriptor.ContextType == typeof(ApplyConfigurationRequestContext)) || if (options.Configuration != null)
!options.Handlers.Any(descriptor => descriptor.ContextType == typeof(ApplyCryptographyRequestContext)))
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID1134));
}
if (options.MetadataAddress == null)
{ {
options.MetadataAddress = new Uri(".well-known/openid-configuration", UriKind.Relative); options.ConfigurationManager = new StaticConfigurationManager<OpenIdConnectConfiguration>(options.Configuration);
} }
if (!options.MetadataAddress.IsAbsoluteUri) else
{ {
if (options.Issuer == null || !options.Issuer.IsAbsoluteUri) if (!options.Handlers.Any(descriptor => descriptor.ContextType == typeof(ApplyConfigurationRequestContext)) ||
!options.Handlers.Any(descriptor => descriptor.ContextType == typeof(ApplyCryptographyRequestContext)))
{ {
throw new InvalidOperationException(SR.GetResourceString(SR.ID1135)); throw new InvalidOperationException(SR.GetResourceString(SR.ID1134));
} }
if (!string.IsNullOrEmpty(options.Issuer.Fragment) || !string.IsNullOrEmpty(options.Issuer.Query)) if (options.MetadataAddress == null)
{ {
throw new InvalidOperationException(SR.GetResourceString(SR.ID1136)); options.MetadataAddress = new Uri(".well-known/openid-configuration", UriKind.Relative);
} }
if (!options.Issuer.OriginalString.EndsWith("/")) if (!options.MetadataAddress.IsAbsoluteUri)
{ {
options.Issuer = new Uri(options.Issuer.OriginalString + "/", UriKind.Absolute); if (options.Issuer == null || !options.Issuer.IsAbsoluteUri)
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID1135));
}
if (!string.IsNullOrEmpty(options.Issuer.Fragment) || !string.IsNullOrEmpty(options.Issuer.Query))
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID1136));
}
if (!options.Issuer.OriginalString.EndsWith("/"))
{
options.Issuer = new Uri(options.Issuer.OriginalString + "/", UriKind.Absolute);
}
if (options.MetadataAddress.OriginalString.StartsWith("/"))
{
options.MetadataAddress = new Uri(options.MetadataAddress.OriginalString.Substring(
1, options.MetadataAddress.OriginalString.Length - 1), UriKind.Relative);
}
options.MetadataAddress = new Uri(options.Issuer, options.MetadataAddress);
} }
if (options.MetadataAddress.OriginalString.StartsWith("/"))
{
options.MetadataAddress = new Uri(options.MetadataAddress.OriginalString.Substring(
1, options.MetadataAddress.OriginalString.Length - 1), UriKind.Relative);
}
options.MetadataAddress = new Uri(options.Issuer, options.MetadataAddress);
}
}
if (options.ConfigurationManager == null)
{
if (options.Configuration != null)
{
options.ConfigurationManager = new StaticConfigurationManager<OpenIdConnectConfiguration>(options.Configuration);
}
else
{
options.ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>( options.ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(
options.MetadataAddress.AbsoluteUri, new OpenIddictValidationRetriever(_service)) options.MetadataAddress.AbsoluteUri, new OpenIddictValidationRetriever(_service))
{ {

9
src/OpenIddict.Validation/OpenIddictValidationDispatcher.cs

@ -7,7 +7,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using static OpenIddict.Validation.OpenIddictValidationEvents; using static OpenIddict.Validation.OpenIddictValidationEvents;
@ -25,16 +24,16 @@ namespace OpenIddict.Validation
/// Creates a new instance of the <see cref="OpenIddictValidationDispatcher"/> class. /// Creates a new instance of the <see cref="OpenIddictValidationDispatcher"/> class.
/// </summary> /// </summary>
public OpenIddictValidationDispatcher( public OpenIddictValidationDispatcher(
[NotNull] ILogger<OpenIddictValidationDispatcher> logger, ILogger<OpenIddictValidationDispatcher> logger,
[NotNull] IOptionsMonitor<OpenIddictValidationOptions> options, IOptionsMonitor<OpenIddictValidationOptions> options,
[NotNull] IServiceProvider provider) IServiceProvider provider)
{ {
_logger = logger; _logger = logger;
_options = options; _options = options;
_provider = provider; _provider = provider;
} }
public async ValueTask DispatchAsync<TContext>([NotNull] TContext context) where TContext : BaseContext public async ValueTask DispatchAsync<TContext>(TContext context) where TContext : BaseContext
{ {
if (context == null) if (context == null)
{ {

126
src/OpenIddict.Validation/OpenIddictValidationEvents.Discovery.cs

@ -4,9 +4,9 @@
* the license and the contributors participating to this project. * the license and the contributors participating to this project.
*/ */
using JetBrains.Annotations;
using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using OpenIddict.Abstractions;
namespace OpenIddict.Validation namespace OpenIddict.Validation
{ {
@ -21,10 +21,19 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="PrepareConfigurationRequestContext"/> class. /// Creates a new instance of the <see cref="PrepareConfigurationRequestContext"/> class.
/// </summary> /// </summary>
public PrepareConfigurationRequestContext([NotNull] OpenIddictValidationTransaction transaction) public PrepareConfigurationRequestContext(OpenIddictValidationTransaction transaction)
: base(transaction) : base(transaction)
{ {
} }
/// <summary>
/// Gets or sets the request.
/// </summary>
public OpenIddictRequest Request
{
get => Transaction.Request!;
set => Transaction.Request = value;
}
} }
/// <summary> /// <summary>
@ -36,10 +45,19 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="ApplyConfigurationRequestContext"/> class. /// Creates a new instance of the <see cref="ApplyConfigurationRequestContext"/> class.
/// </summary> /// </summary>
public ApplyConfigurationRequestContext([NotNull] OpenIddictValidationTransaction transaction) public ApplyConfigurationRequestContext(OpenIddictValidationTransaction transaction)
: base(transaction) : base(transaction)
{ {
} }
/// <summary>
/// Gets or sets the request.
/// </summary>
public OpenIddictRequest Request
{
get => Transaction.Request!;
set => Transaction.Request = value;
}
} }
/// <summary> /// <summary>
@ -51,10 +69,28 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="ExtractConfigurationResponseContext"/> class. /// Creates a new instance of the <see cref="ExtractConfigurationResponseContext"/> class.
/// </summary> /// </summary>
public ExtractConfigurationResponseContext([NotNull] OpenIddictValidationTransaction transaction) public ExtractConfigurationResponseContext(OpenIddictValidationTransaction transaction)
: base(transaction) : base(transaction)
{ {
} }
/// <summary>
/// Gets or sets the request.
/// </summary>
public OpenIddictRequest Request
{
get => Transaction.Request!;
set => Transaction.Request = value;
}
/// <summary>
/// Gets or sets the response, or <c>null</c> if it wasn't extracted yet.
/// </summary>
public OpenIddictResponse? Response
{
get => Transaction.Response;
set => Transaction.Response = value;
}
} }
/// <summary> /// <summary>
@ -65,11 +101,29 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="HandleConfigurationResponseContext"/> class. /// Creates a new instance of the <see cref="HandleConfigurationResponseContext"/> class.
/// </summary> /// </summary>
public HandleConfigurationResponseContext([NotNull] OpenIddictValidationTransaction transaction) public HandleConfigurationResponseContext(OpenIddictValidationTransaction transaction)
: base(transaction) : base(transaction)
{ {
} }
/// <summary>
/// Gets or sets the request.
/// </summary>
public OpenIddictRequest Request
{
get => Transaction.Request!;
set => Transaction.Request = value;
}
/// <summary>
/// Gets or sets the response.
/// </summary>
public OpenIddictResponse Response
{
get => Transaction.Response!;
set => Transaction.Response = value;
}
/// <summary> /// <summary>
/// Gets the OpenID Connect configuration. /// Gets the OpenID Connect configuration.
/// </summary> /// </summary>
@ -85,10 +139,19 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="PrepareCryptographyRequestContext"/> class. /// Creates a new instance of the <see cref="PrepareCryptographyRequestContext"/> class.
/// </summary> /// </summary>
public PrepareCryptographyRequestContext([NotNull] OpenIddictValidationTransaction transaction) public PrepareCryptographyRequestContext(OpenIddictValidationTransaction transaction)
: base(transaction) : base(transaction)
{ {
} }
/// <summary>
/// Gets or sets the request.
/// </summary>
public OpenIddictRequest Request
{
get => Transaction.Request!;
set => Transaction.Request = value;
}
} }
/// <summary> /// <summary>
@ -100,10 +163,19 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="ApplyCryptographyRequestContext"/> class. /// Creates a new instance of the <see cref="ApplyCryptographyRequestContext"/> class.
/// </summary> /// </summary>
public ApplyCryptographyRequestContext([NotNull] OpenIddictValidationTransaction transaction) public ApplyCryptographyRequestContext(OpenIddictValidationTransaction transaction)
: base(transaction) : base(transaction)
{ {
} }
/// <summary>
/// Gets or sets the request.
/// </summary>
public OpenIddictRequest Request
{
get => Transaction.Request!;
set => Transaction.Request = value;
}
} }
/// <summary> /// <summary>
@ -115,10 +187,28 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="ExtractCryptographyResponseContext"/> class. /// Creates a new instance of the <see cref="ExtractCryptographyResponseContext"/> class.
/// </summary> /// </summary>
public ExtractCryptographyResponseContext([NotNull] OpenIddictValidationTransaction transaction) public ExtractCryptographyResponseContext(OpenIddictValidationTransaction transaction)
: base(transaction) : base(transaction)
{ {
} }
/// <summary>
/// Gets or sets the request.
/// </summary>
public OpenIddictRequest Request
{
get => Transaction.Request!;
set => Transaction.Request = value;
}
/// <summary>
/// Gets or sets the response, or <c>null</c> if it wasn't extracted yet.
/// </summary>
public OpenIddictResponse? Response
{
get => Transaction.Response;
set => Transaction.Response = value;
}
} }
/// <summary> /// <summary>
@ -129,11 +219,29 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="HandleCryptographyResponseContext"/> class. /// Creates a new instance of the <see cref="HandleCryptographyResponseContext"/> class.
/// </summary> /// </summary>
public HandleCryptographyResponseContext([NotNull] OpenIddictValidationTransaction transaction) public HandleCryptographyResponseContext(OpenIddictValidationTransaction transaction)
: base(transaction) : base(transaction)
{ {
} }
/// <summary>
/// Gets or sets the request.
/// </summary>
public OpenIddictRequest Request
{
get => Transaction.Request!;
set => Transaction.Request = value;
}
/// <summary>
/// Gets or sets the response.
/// </summary>
public OpenIddictResponse Response
{
get => Transaction.Response!;
set => Transaction.Response = value;
}
/// <summary> /// <summary>
/// Gets the security keys. /// Gets the security keys.
/// </summary> /// </summary>

74
src/OpenIddict.Validation/OpenIddictValidationEvents.Introspection.cs

@ -5,7 +5,7 @@
*/ */
using System.Security.Claims; using System.Security.Claims;
using JetBrains.Annotations; using OpenIddict.Abstractions;
namespace OpenIddict.Validation namespace OpenIddict.Validation
{ {
@ -20,20 +20,29 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="PrepareIntrospectionRequestContext"/> class. /// Creates a new instance of the <see cref="PrepareIntrospectionRequestContext"/> class.
/// </summary> /// </summary>
public PrepareIntrospectionRequestContext([NotNull] OpenIddictValidationTransaction transaction) public PrepareIntrospectionRequestContext(OpenIddictValidationTransaction transaction)
: base(transaction) : base(transaction)
{ {
} }
/// <summary>
/// Gets or sets the request.
/// </summary>
public OpenIddictRequest Request
{
get => Transaction.Request!;
set => Transaction.Request = value;
}
/// <summary> /// <summary>
/// Gets or sets the token sent to the introspection endpoint. /// Gets or sets the token sent to the introspection endpoint.
/// </summary> /// </summary>
public string Token { get; set; } public string? Token { get; set; }
/// <summary> /// <summary>
/// Gets or sets the token type sent to the introspection endpoint. /// Gets or sets the token type sent to the introspection endpoint.
/// </summary> /// </summary>
public string TokenType { get; set; } public string? TokenType { get; set; }
} }
/// <summary> /// <summary>
@ -45,10 +54,19 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="ApplyIntrospectionRequestContext"/> class. /// Creates a new instance of the <see cref="ApplyIntrospectionRequestContext"/> class.
/// </summary> /// </summary>
public ApplyIntrospectionRequestContext([NotNull] OpenIddictValidationTransaction transaction) public ApplyIntrospectionRequestContext(OpenIddictValidationTransaction transaction)
: base(transaction) : base(transaction)
{ {
} }
/// <summary>
/// Gets or sets the request.
/// </summary>
public OpenIddictRequest Request
{
get => Transaction.Request!;
set => Transaction.Request = value;
}
} }
/// <summary> /// <summary>
@ -60,10 +78,28 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="ExtractIntrospectionResponseContext"/> class. /// Creates a new instance of the <see cref="ExtractIntrospectionResponseContext"/> class.
/// </summary> /// </summary>
public ExtractIntrospectionResponseContext([NotNull] OpenIddictValidationTransaction transaction) public ExtractIntrospectionResponseContext(OpenIddictValidationTransaction transaction)
: base(transaction) : base(transaction)
{ {
} }
/// <summary>
/// Gets or sets the request.
/// </summary>
public OpenIddictRequest Request
{
get => Transaction.Request!;
set => Transaction.Request = value;
}
/// <summary>
/// Gets or sets the response, or <c>null</c> if it wasn't extracted yet.
/// </summary>
public OpenIddictResponse? Response
{
get => Transaction.Response;
set => Transaction.Response = value;
}
} }
/// <summary> /// <summary>
@ -74,25 +110,43 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="HandleIntrospectionResponseContext"/> class. /// Creates a new instance of the <see cref="HandleIntrospectionResponseContext"/> class.
/// </summary> /// </summary>
public HandleIntrospectionResponseContext([NotNull] OpenIddictValidationTransaction transaction) public HandleIntrospectionResponseContext(OpenIddictValidationTransaction transaction)
: base(transaction) : base(transaction)
{ {
} }
/// <summary>
/// Gets or sets the request.
/// </summary>
public OpenIddictRequest Request
{
get => Transaction.Request!;
set => Transaction.Request = value;
}
/// <summary>
/// Gets or sets the response.
/// </summary>
public OpenIddictResponse Response
{
get => Transaction.Response!;
set => Transaction.Response = value;
}
/// <summary> /// <summary>
/// Gets or sets the token sent to the introspection endpoint. /// Gets or sets the token sent to the introspection endpoint.
/// </summary> /// </summary>
public string Token { get; set; } public string? Token { get; set; }
/// <summary> /// <summary>
/// Gets or sets the token type sent to the introspection endpoint. /// Gets or sets the token type sent to the introspection endpoint.
/// </summary> /// </summary>
public string TokenType { get; set; } public string? TokenType { get; set; }
/// <summary> /// <summary>
/// Gets or sets the principal containing the claims resolved from the introspection response. /// Gets or sets the principal containing the claims resolved from the introspection response.
/// </summary> /// </summary>
public ClaimsPrincipal Principal { get; set; } public ClaimsPrincipal? Principal { get; set; }
} }
} }
} }

102
src/OpenIddict.Validation/OpenIddictValidationEvents.cs

@ -7,7 +7,6 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Security.Claims; using System.Security.Claims;
using JetBrains.Annotations;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using OpenIddict.Abstractions; using OpenIddict.Abstractions;
@ -25,7 +24,7 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="BaseContext"/> class. /// Creates a new instance of the <see cref="BaseContext"/> class.
/// </summary> /// </summary>
protected BaseContext([NotNull] OpenIddictValidationTransaction transaction) protected BaseContext(OpenIddictValidationTransaction transaction)
=> Transaction = transaction ?? throw new ArgumentNullException(nameof(transaction)); => Transaction = transaction ?? throw new ArgumentNullException(nameof(transaction));
/// <summary> /// <summary>
@ -45,7 +44,7 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Gets or sets the issuer address associated with the current transaction, if available. /// Gets or sets the issuer address associated with the current transaction, if available.
/// </summary> /// </summary>
public Uri Issuer public Uri? Issuer
{ {
get => Transaction.Issuer; get => Transaction.Issuer;
set => Transaction.Issuer = value; set => Transaction.Issuer = value;
@ -65,24 +64,6 @@ namespace OpenIddict.Validation
/// Gets the OpenIddict validation options. /// Gets the OpenIddict validation options.
/// </summary> /// </summary>
public OpenIddictValidationOptions Options => Transaction.Options; public OpenIddictValidationOptions Options => Transaction.Options;
/// <summary>
/// Gets or sets the OpenIddict request or <c>null</c> if it couldn't be extracted.
/// </summary>
public OpenIddictRequest Request
{
get => Transaction.Request;
set => Transaction.Request = value;
}
/// <summary>
/// Gets or sets the OpenIddict response, if applicable.
/// </summary>
public OpenIddictResponse Response
{
get => Transaction.Response;
set => Transaction.Response = value;
}
} }
/// <summary> /// <summary>
@ -94,7 +75,7 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="BaseRequestContext"/> class. /// Creates a new instance of the <see cref="BaseRequestContext"/> class.
/// </summary> /// </summary>
protected BaseRequestContext([NotNull] OpenIddictValidationTransaction transaction) protected BaseRequestContext(OpenIddictValidationTransaction transaction)
: base(transaction) : base(transaction)
{ {
} }
@ -133,7 +114,7 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="BaseRequestContext"/> class. /// Creates a new instance of the <see cref="BaseRequestContext"/> class.
/// </summary> /// </summary>
protected BaseExternalContext([NotNull] OpenIddictValidationTransaction transaction) protected BaseExternalContext(OpenIddictValidationTransaction transaction)
: base(transaction) : base(transaction)
{ {
} }
@ -141,7 +122,7 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Gets or sets the address of the external endpoint to communicate with. /// Gets or sets the address of the external endpoint to communicate with.
/// </summary> /// </summary>
public Uri Address { get; set; } public Uri? Address { get; set; }
} }
/// <summary> /// <summary>
@ -153,7 +134,7 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="BaseValidatingContext"/> class. /// Creates a new instance of the <see cref="BaseValidatingContext"/> class.
/// </summary> /// </summary>
protected BaseValidatingContext([NotNull] OpenIddictValidationTransaction transaction) protected BaseValidatingContext(OpenIddictValidationTransaction transaction)
: base(transaction) : base(transaction)
{ {
} }
@ -166,17 +147,17 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Gets or sets the "error" parameter returned to the client application. /// Gets or sets the "error" parameter returned to the client application.
/// </summary> /// </summary>
public string Error { get; private set; } public string? Error { get; private set; }
/// <summary> /// <summary>
/// Gets or sets the "error_description" parameter returned to the client application. /// Gets or sets the "error_description" parameter returned to the client application.
/// </summary> /// </summary>
public string ErrorDescription { get; private set; } public string? ErrorDescription { get; private set; }
/// <summary> /// <summary>
/// Gets or sets the "error_uri" parameter returned to the client application. /// Gets or sets the "error_uri" parameter returned to the client application.
/// </summary> /// </summary>
public string ErrorUri { get; private set; } public string? ErrorUri { get; private set; }
/// <summary> /// <summary>
/// Rejects the request. /// Rejects the request.
@ -187,7 +168,7 @@ namespace OpenIddict.Validation
/// Rejects the request. /// Rejects the request.
/// </summary> /// </summary>
/// <param name="error">The "error" parameter returned to the client application.</param> /// <param name="error">The "error" parameter returned to the client application.</param>
public virtual void Reject(string error) public virtual void Reject(string? error)
{ {
Error = error; Error = error;
@ -199,7 +180,7 @@ namespace OpenIddict.Validation
/// </summary> /// </summary>
/// <param name="error">The "error" parameter returned to the client application.</param> /// <param name="error">The "error" parameter returned to the client application.</param>
/// <param name="description">The "error_description" parameter returned to the client application.</param> /// <param name="description">The "error_description" parameter returned to the client application.</param>
public virtual void Reject(string error, string description) public virtual void Reject(string? error, string? description)
{ {
Error = error; Error = error;
ErrorDescription = description; ErrorDescription = description;
@ -213,7 +194,7 @@ namespace OpenIddict.Validation
/// <param name="error">The "error" parameter returned to the client application.</param> /// <param name="error">The "error" parameter returned to the client application.</param>
/// <param name="description">The "error_description" parameter returned to the client application.</param> /// <param name="description">The "error_description" parameter returned to the client application.</param>
/// <param name="uri">The "error_uri" parameter returned to the client application.</param> /// <param name="uri">The "error_uri" parameter returned to the client application.</param>
public virtual void Reject(string error, string description, string uri) public virtual void Reject(string? error, string? description, string? uri)
{ {
Error = error; Error = error;
ErrorDescription = description; ErrorDescription = description;
@ -231,7 +212,7 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="ProcessRequestContext"/> class. /// Creates a new instance of the <see cref="ProcessRequestContext"/> class.
/// </summary> /// </summary>
public ProcessRequestContext([NotNull] OpenIddictValidationTransaction transaction) public ProcessRequestContext(OpenIddictValidationTransaction transaction)
: base(transaction) : base(transaction)
{ {
} }
@ -245,10 +226,28 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="ProcessErrorContext"/> class. /// Creates a new instance of the <see cref="ProcessErrorContext"/> class.
/// </summary> /// </summary>
public ProcessErrorContext([NotNull] OpenIddictValidationTransaction transaction) public ProcessErrorContext(OpenIddictValidationTransaction transaction)
: base(transaction) : base(transaction)
{ {
} }
/// <summary>
/// Gets or sets the request, or <c>null</c> if it couldn't be extracted.
/// </summary>
public OpenIddictRequest? Request
{
get => Transaction.Request;
set => Transaction.Request = value;
}
/// <summary>
/// Gets or sets the response.
/// </summary>
public OpenIddictResponse Response
{
get => Transaction.Response!;
set => Transaction.Response = value;
}
} }
/// <summary> /// <summary>
@ -259,25 +258,34 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="ProcessAuthenticationContext"/> class. /// Creates a new instance of the <see cref="ProcessAuthenticationContext"/> class.
/// </summary> /// </summary>
public ProcessAuthenticationContext([NotNull] OpenIddictValidationTransaction transaction) public ProcessAuthenticationContext(OpenIddictValidationTransaction transaction)
: base(transaction) : base(transaction)
{ {
} }
/// <summary>
/// Gets or sets the request.
/// </summary>
public OpenIddictRequest Request
{
get => Transaction.Request!;
set => Transaction.Request = value;
}
/// <summary> /// <summary>
/// Gets or sets the security principal. /// Gets or sets the security principal.
/// </summary> /// </summary>
public ClaimsPrincipal Principal { get; set; } public ClaimsPrincipal? Principal { get; set; }
/// <summary> /// <summary>
/// Gets or sets the token to validate. /// Gets or sets the token to validate.
/// </summary> /// </summary>
public string Token { get; set; } public string? Token { get; set; }
/// <summary> /// <summary>
/// Gets or sets the expected type of the token. /// Gets or sets the expected type of the token.
/// </summary> /// </summary>
public string TokenType { get; set; } public string? TokenType { get; set; }
} }
/// <summary> /// <summary>
@ -288,10 +296,28 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="ProcessChallengeContext"/> class. /// Creates a new instance of the <see cref="ProcessChallengeContext"/> class.
/// </summary> /// </summary>
public ProcessChallengeContext([NotNull] OpenIddictValidationTransaction transaction) public ProcessChallengeContext(OpenIddictValidationTransaction transaction)
: base(transaction) : base(transaction)
{ {
} }
/// <summary>
/// Gets or sets the request.
/// </summary>
public OpenIddictRequest Request
{
get => Transaction.Request!;
set => Transaction.Request = value;
}
/// <summary>
/// Gets or sets the response.
/// </summary>
public OpenIddictResponse Response
{
get => Transaction.Response!;
set => Transaction.Response = value;
}
} }
} }
} }

7
src/OpenIddict.Validation/OpenIddictValidationExtensions.cs

@ -6,7 +6,6 @@
using System; using System;
using System.Linq; using System.Linq;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
@ -30,7 +29,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <param name="builder">The services builder used by OpenIddict to register new services.</param> /// <param name="builder">The services builder used by OpenIddict to register new services.</param>
/// <remarks>This extension can be safely called multiple times.</remarks> /// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictValidationBuilder"/>.</returns>
public static OpenIddictValidationBuilder AddValidation([NotNull] this OpenIddictBuilder builder) public static OpenIddictValidationBuilder AddValidation(this OpenIddictBuilder builder)
{ {
if (builder == null) if (builder == null)
{ {
@ -81,8 +80,8 @@ namespace Microsoft.Extensions.DependencyInjection
/// <remarks>This extension can be safely called multiple times.</remarks> /// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns> /// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
public static OpenIddictBuilder AddValidation( public static OpenIddictBuilder AddValidation(
[NotNull] this OpenIddictBuilder builder, this OpenIddictBuilder builder,
[NotNull] Action<OpenIddictValidationBuilder> configuration) Action<OpenIddictValidationBuilder> configuration)
{ {
if (builder == null) if (builder == null)
{ {

7
src/OpenIddict.Validation/OpenIddictValidationFactory.cs

@ -5,7 +5,6 @@
*/ */
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -23,9 +22,9 @@ namespace OpenIddict.Validation
/// Creates a new instance of the <see cref="OpenIddictValidationFactory"/> class. /// Creates a new instance of the <see cref="OpenIddictValidationFactory"/> class.
/// </summary> /// </summary>
public OpenIddictValidationFactory( public OpenIddictValidationFactory(
[NotNull] IStringLocalizer<OpenIddictResources> localizer, IStringLocalizer<OpenIddictResources> localizer,
[NotNull] ILogger<OpenIddictValidationDispatcher> logger, ILogger<OpenIddictValidationDispatcher> logger,
[NotNull] IOptionsMonitor<OpenIddictValidationOptions> options) IOptionsMonitor<OpenIddictValidationOptions> options)
{ {
_localizer = localizer; _localizer = localizer;
_logger = logger; _logger = logger;

5
src/OpenIddict.Validation/OpenIddictValidationHandler.cs

@ -6,7 +6,6 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using static OpenIddict.Validation.OpenIddictValidationEvents; using static OpenIddict.Validation.OpenIddictValidationEvents;
namespace OpenIddict.Validation namespace OpenIddict.Validation
@ -23,7 +22,7 @@ namespace OpenIddict.Validation
/// Creates a new event using the specified handler delegate. /// Creates a new event using the specified handler delegate.
/// </summary> /// </summary>
/// <param name="handler">The event handler delegate.</param> /// <param name="handler">The event handler delegate.</param>
public OpenIddictValidationHandler([NotNull] Func<TContext, ValueTask> handler) public OpenIddictValidationHandler(Func<TContext, ValueTask> handler)
=> _handler = handler ?? throw new ArgumentNullException(nameof(handler)); => _handler = handler ?? throw new ArgumentNullException(nameof(handler));
/// <summary> /// <summary>
@ -33,7 +32,7 @@ namespace OpenIddict.Validation
/// <returns> /// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation. /// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
public ValueTask HandleAsync([NotNull] TContext context) public ValueTask HandleAsync(TContext context)
=> _handler(context ?? throw new ArgumentNullException(nameof(context))); => _handler(context ?? throw new ArgumentNullException(nameof(context)));
} }
} }

15
src/OpenIddict.Validation/OpenIddictValidationHandlerDescriptor.cs

@ -10,7 +10,6 @@ using System.Collections.Immutable;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using static OpenIddict.Validation.OpenIddictValidationEvents; using static OpenIddict.Validation.OpenIddictValidationEvents;
using SR = OpenIddict.Abstractions.OpenIddictResources; using SR = OpenIddict.Abstractions.OpenIddictResources;
@ -31,7 +30,7 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Gets the context type associated with the event. /// Gets the context type associated with the event.
/// </summary> /// </summary>
public Type ContextType { get; private set; } public Type ContextType { get; private set; } = default!;
/// <summary> /// <summary>
/// Gets the list of filters responsible of excluding the handler /// Gets the list of filters responsible of excluding the handler
@ -47,7 +46,7 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Gets the service descriptor associated with the handler. /// Gets the service descriptor associated with the handler.
/// </summary> /// </summary>
public ServiceDescriptor ServiceDescriptor { get; private set; } public ServiceDescriptor ServiceDescriptor { get; private set; } = default!;
/// <summary> /// <summary>
/// Gets the type associated with the handler. /// Gets the type associated with the handler.
@ -68,7 +67,7 @@ namespace OpenIddict.Validation
/// <typeparam name="TContext">The event context type.</typeparam> /// <typeparam name="TContext">The event context type.</typeparam>
public class Builder<TContext> where TContext : BaseContext public class Builder<TContext> where TContext : BaseContext
{ {
private ServiceDescriptor _descriptor; private ServiceDescriptor? _descriptor;
private readonly List<Type> _filterTypes = new List<Type>(); private readonly List<Type> _filterTypes = new List<Type>();
private int _order; private int _order;
private OpenIddictValidationHandlerType _type; private OpenIddictValidationHandlerType _type;
@ -78,7 +77,7 @@ namespace OpenIddict.Validation
/// </summary> /// </summary>
/// <param name="type">The event handler filter type.</param> /// <param name="type">The event handler filter type.</param>
/// <returns>The builder instance, so that calls can be easily chained.</returns> /// <returns>The builder instance, so that calls can be easily chained.</returns>
public Builder<TContext> AddFilter([NotNull] Type type) public Builder<TContext> AddFilter(Type type)
{ {
if (type == null) if (type == null)
{ {
@ -109,7 +108,7 @@ namespace OpenIddict.Validation
/// </summary> /// </summary>
/// <param name="descriptor">The service descriptor.</param> /// <param name="descriptor">The service descriptor.</param>
/// <returns>The builder instance, so that calls can be easily chained.</returns> /// <returns>The builder instance, so that calls can be easily chained.</returns>
public Builder<TContext> SetServiceDescriptor([NotNull] ServiceDescriptor descriptor) public Builder<TContext> SetServiceDescriptor(ServiceDescriptor descriptor)
{ {
if (descriptor == null) if (descriptor == null)
{ {
@ -161,7 +160,7 @@ namespace OpenIddict.Validation
/// </summary> /// </summary>
/// <param name="handler">The handler instance.</param> /// <param name="handler">The handler instance.</param>
/// <returns>The builder instance, so that calls can be easily chained.</returns> /// <returns>The builder instance, so that calls can be easily chained.</returns>
public Builder<TContext> UseInlineHandler([NotNull] Func<TContext, ValueTask> handler) public Builder<TContext> UseInlineHandler(Func<TContext, ValueTask> handler)
{ {
if (handler == null) if (handler == null)
{ {
@ -197,7 +196,7 @@ namespace OpenIddict.Validation
/// <typeparam name="THandler">The handler type.</typeparam> /// <typeparam name="THandler">The handler type.</typeparam>
/// <param name="handler">The handler instance.</param> /// <param name="handler">The handler instance.</param>
/// <returns>The builder instance, so that calls can be easily chained.</returns> /// <returns>The builder instance, so that calls can be easily chained.</returns>
public Builder<TContext> UseSingletonHandler<THandler>([NotNull] THandler handler) public Builder<TContext> UseSingletonHandler<THandler>(THandler handler)
where THandler : IOpenIddictValidationHandler<TContext> where THandler : IOpenIddictValidationHandler<TContext>
{ {
if (handler == null) if (handler == null)

9
src/OpenIddict.Validation/OpenIddictValidationHandlerFilters.cs

@ -7,7 +7,6 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using static OpenIddict.Validation.OpenIddictValidationEvents; using static OpenIddict.Validation.OpenIddictValidationEvents;
namespace OpenIddict.Validation namespace OpenIddict.Validation
@ -20,7 +19,7 @@ namespace OpenIddict.Validation
/// </summary> /// </summary>
public class RequireAuthorizationEntryValidationEnabled : IOpenIddictValidationHandlerFilter<BaseContext> public class RequireAuthorizationEntryValidationEnabled : IOpenIddictValidationHandlerFilter<BaseContext>
{ {
public ValueTask<bool> IsActiveAsync([NotNull] BaseContext context) public ValueTask<bool> IsActiveAsync(BaseContext context)
{ {
if (context == null) if (context == null)
{ {
@ -36,7 +35,7 @@ namespace OpenIddict.Validation
/// </summary> /// </summary>
public class RequireLocalValidation : IOpenIddictValidationHandlerFilter<BaseContext> public class RequireLocalValidation : IOpenIddictValidationHandlerFilter<BaseContext>
{ {
public ValueTask<bool> IsActiveAsync([NotNull] BaseContext context) public ValueTask<bool> IsActiveAsync(BaseContext context)
{ {
if (context == null) if (context == null)
{ {
@ -52,7 +51,7 @@ namespace OpenIddict.Validation
/// </summary> /// </summary>
public class RequireIntrospectionValidation : IOpenIddictValidationHandlerFilter<BaseContext> public class RequireIntrospectionValidation : IOpenIddictValidationHandlerFilter<BaseContext>
{ {
public ValueTask<bool> IsActiveAsync([NotNull] BaseContext context) public ValueTask<bool> IsActiveAsync(BaseContext context)
{ {
if (context == null) if (context == null)
{ {
@ -68,7 +67,7 @@ namespace OpenIddict.Validation
/// </summary> /// </summary>
public class RequireTokenEntryValidationEnabled : IOpenIddictValidationHandlerFilter<BaseContext> public class RequireTokenEntryValidationEnabled : IOpenIddictValidationHandlerFilter<BaseContext>
{ {
public ValueTask<bool> IsActiveAsync([NotNull] BaseContext context) public ValueTask<bool> IsActiveAsync(BaseContext context)
{ {
if (context == null) if (context == null)
{ {

73
src/OpenIddict.Validation/OpenIddictValidationHandlers.Discovery.cs

@ -7,7 +7,6 @@
using System; using System;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Abstractions.OpenIddictConstants;
using static OpenIddict.Validation.OpenIddictValidationEvents; using static OpenIddict.Validation.OpenIddictValidationEvents;
@ -49,14 +48,8 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(HandleConfigurationResponseContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleConfigurationResponseContext context)
{ {
if (context == null) if (context == null)
{ {
@ -65,7 +58,7 @@ namespace OpenIddict.Validation
// The issuer returned in the discovery document must exactly match the URL used to access it. // The issuer returned in the discovery document must exactly match the URL used to access it.
// See https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationValidation. // See https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationValidation.
var issuer = (string) context.Response[Metadata.Issuer]; var issuer = (string?) context.Response[Metadata.Issuer];
if (string.IsNullOrEmpty(issuer)) if (string.IsNullOrEmpty(issuer))
{ {
context.Reject( context.Reject(
@ -75,7 +68,7 @@ namespace OpenIddict.Validation
return default; return default;
} }
if (!Uri.TryCreate(issuer, UriKind.Absolute, out Uri address)) if (!Uri.TryCreate(issuer, UriKind.Absolute, out Uri? address))
{ {
context.Reject( context.Reject(
error: Errors.ServerError, error: Errors.ServerError,
@ -114,14 +107,8 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(HandleConfigurationResponseContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleConfigurationResponseContext context)
{ {
if (context == null) if (context == null)
{ {
@ -130,7 +117,7 @@ namespace OpenIddict.Validation
// Note: the jwks_uri node is required by the OpenID Connect discovery specification. // Note: the jwks_uri node is required by the OpenID Connect discovery specification.
// See https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationValidation. // See https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationValidation.
var address = (string) context.Response[Metadata.JwksUri]; var address = (string?) context.Response[Metadata.JwksUri];
if (string.IsNullOrEmpty(address)) if (string.IsNullOrEmpty(address))
{ {
context.Reject( context.Reject(
@ -170,21 +157,15 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(HandleConfigurationResponseContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleConfigurationResponseContext context)
{ {
if (context == null) if (context == null)
{ {
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
var address = (string) context.Response[Metadata.IntrospectionEndpoint]; var address = (string?) context.Response[Metadata.IntrospectionEndpoint];
if (!string.IsNullOrEmpty(address) && !Uri.IsWellFormedUriString(address, UriKind.Absolute)) if (!string.IsNullOrEmpty(address) && !Uri.IsWellFormedUriString(address, UriKind.Absolute))
{ {
context.Reject( context.Reject(
@ -201,7 +182,7 @@ namespace OpenIddict.Validation
{ {
foreach (var method in methods.GetUnnamedParameters()) foreach (var method in methods.GetUnnamedParameters())
{ {
var value = (string) method; var value = (string?) method;
if (string.IsNullOrEmpty(value)) if (string.IsNullOrEmpty(value))
{ {
continue; continue;
@ -230,14 +211,8 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(HandleCryptographyResponseContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleCryptographyResponseContext context)
{ {
if (context == null) if (context == null)
{ {
@ -259,7 +234,7 @@ namespace OpenIddict.Validation
// Note: the "use" parameter is defined as optional by the specification. // Note: the "use" parameter is defined as optional by the specification.
// To prevent key swapping attacks, OpenIddict requires that this parameter // To prevent key swapping attacks, OpenIddict requires that this parameter
// be present and will ignore keys that don't include a "use" parameter. // be present and will ignore keys that don't include a "use" parameter.
var use = (string) keys[index][JsonWebKeyParameterNames.Use]; var use = (string?) keys[index][JsonWebKeyParameterNames.Use];
if (string.IsNullOrEmpty(use)) if (string.IsNullOrEmpty(use))
{ {
continue; continue;
@ -271,21 +246,21 @@ namespace OpenIddict.Validation
continue; continue;
} }
var key = (string) keys[index][JsonWebKeyParameterNames.Kty] switch var key = (string?) keys[index][JsonWebKeyParameterNames.Kty] switch
{ {
JsonWebAlgorithmsKeyTypes.RSA => new JsonWebKey JsonWebAlgorithmsKeyTypes.RSA => new JsonWebKey
{ {
Kty = JsonWebAlgorithmsKeyTypes.RSA, Kty = JsonWebAlgorithmsKeyTypes.RSA,
E = (string) keys[index][JsonWebKeyParameterNames.E], E = (string?) keys[index][JsonWebKeyParameterNames.E],
N = (string) keys[index][JsonWebKeyParameterNames.N] N = (string?) keys[index][JsonWebKeyParameterNames.N]
}, },
JsonWebAlgorithmsKeyTypes.EllipticCurve => new JsonWebKey JsonWebAlgorithmsKeyTypes.EllipticCurve => new JsonWebKey
{ {
Kty = JsonWebAlgorithmsKeyTypes.EllipticCurve, Kty = JsonWebAlgorithmsKeyTypes.EllipticCurve,
Crv = (string) keys[index][JsonWebKeyParameterNames.Crv], Crv = (string?) keys[index][JsonWebKeyParameterNames.Crv],
X = (string) keys[index][JsonWebKeyParameterNames.X], X = (string?) keys[index][JsonWebKeyParameterNames.X],
Y = (string) keys[index][JsonWebKeyParameterNames.Y] Y = (string?) keys[index][JsonWebKeyParameterNames.Y]
}, },
_ => null _ => null
@ -300,15 +275,15 @@ namespace OpenIddict.Validation
return default; return default;
} }
key.KeyId = (string) keys[index][JsonWebKeyParameterNames.Kid]; key.KeyId = (string?) keys[index][JsonWebKeyParameterNames.Kid];
key.X5t = (string) keys[index][JsonWebKeyParameterNames.X5t]; key.X5t = (string?) keys[index][JsonWebKeyParameterNames.X5t];
key.X5tS256 = (string) keys[index][JsonWebKeyParameterNames.X5tS256]; key.X5tS256 = (string?) keys[index][JsonWebKeyParameterNames.X5tS256];
if (keys[index].TryGetNamedParameter(JsonWebKeyParameterNames.X5c, out var chain)) if (keys[index].TryGetNamedParameter(JsonWebKeyParameterNames.X5c, out var chain))
{ {
foreach (var certificate in chain.GetNamedParameters()) foreach (var certificate in chain.GetNamedParameters())
{ {
var value = (string) certificate.Value; var value = (string?) certificate.Value;
if (string.IsNullOrEmpty(value)) if (string.IsNullOrEmpty(value))
{ {
context.Reject( context.Reject(

79
src/OpenIddict.Validation/OpenIddictValidationHandlers.Introspection.cs

@ -10,7 +10,6 @@ using System.Globalization;
using System.Security.Claims; using System.Security.Claims;
using System.Text.Json; using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.JsonWebTokens;
using OpenIddict.Abstractions; using OpenIddict.Abstractions;
using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Abstractions.OpenIddictConstants;
@ -55,14 +54,8 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(PrepareIntrospectionRequestContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] PrepareIntrospectionRequestContext context)
{ {
if (context == null) if (context == null)
{ {
@ -91,14 +84,8 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(PrepareIntrospectionRequestContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] PrepareIntrospectionRequestContext context)
{ {
if (context == null) if (context == null)
{ {
@ -127,14 +114,8 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(HandleIntrospectionResponseContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleIntrospectionResponseContext context)
{ {
if (context == null) if (context == null)
{ {
@ -185,14 +166,8 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(HandleIntrospectionResponseContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleIntrospectionResponseContext context)
{ {
if (context == null) if (context == null)
{ {
@ -306,14 +281,8 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(HandleIntrospectionResponseContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleIntrospectionResponseContext context)
{ {
if (context == null) if (context == null)
{ {
@ -322,10 +291,10 @@ namespace OpenIddict.Validation
// The issuer claim is optional. If it's not null or empty, validate it to // The issuer claim is optional. If it's not null or empty, validate it to
// ensure it matches the issuer registered in the server configuration. // ensure it matches the issuer registered in the server configuration.
var issuer = (string) context.Response[Claims.Issuer]; var issuer = (string?) context.Response[Claims.Issuer];
if (!string.IsNullOrEmpty(issuer)) if (!string.IsNullOrEmpty(issuer))
{ {
if (!Uri.TryCreate(issuer, UriKind.Absolute, out Uri uri)) if (!Uri.TryCreate(issuer, UriKind.Absolute, out Uri? uri))
{ {
context.Reject( context.Reject(
error: Errors.ServerError, error: Errors.ServerError,
@ -363,14 +332,8 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(HandleIntrospectionResponseContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleIntrospectionResponseContext context)
{ {
if (context == null) if (context == null)
{ {
@ -382,7 +345,7 @@ namespace OpenIddict.Validation
// introspected token is of the expected type and prevent token substitution attacks. // introspected token is of the expected type and prevent token substitution attacks.
if (!string.IsNullOrEmpty(context.TokenType)) if (!string.IsNullOrEmpty(context.TokenType))
{ {
var usage = (string) context.Response[Claims.TokenUsage]; var usage = (string?) context.Response[Claims.TokenUsage];
if (!string.IsNullOrEmpty(usage) && if (!string.IsNullOrEmpty(usage) &&
!string.Equals(usage, context.TokenType, StringComparison.OrdinalIgnoreCase)) !string.Equals(usage, context.TokenType, StringComparison.OrdinalIgnoreCase))
{ {
@ -413,14 +376,8 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(HandleIntrospectionResponseContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] HandleIntrospectionResponseContext context)
{ {
if (context == null) if (context == null)
{ {
@ -437,7 +394,7 @@ namespace OpenIddict.Validation
// Resolve the issuer that will be attached to the claims created by this handler. // Resolve the issuer that will be attached to the claims created by this handler.
// Note: at this stage, the optional issuer extracted from the response is assumed // Note: at this stage, the optional issuer extracted from the response is assumed
// to be valid, as it is guarded against unknown values by the ValidateIssuer handler. // to be valid, as it is guarded against unknown values by the ValidateIssuer handler.
var issuer = (string) context.Response[Claims.Issuer] ?? context.Issuer?.AbsoluteUri ?? ClaimsIdentity.DefaultIssuer; var issuer = (string?) context.Response[Claims.Issuer] ?? context.Issuer?.AbsoluteUri ?? ClaimsIdentity.DefaultIssuer;
foreach (var parameter in context.Response.GetParameters()) foreach (var parameter in context.Response.GetParameters())
{ {

151
src/OpenIddict.Validation/OpenIddictValidationHandlers.cs

@ -7,11 +7,11 @@
using System; using System;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Security.Claims; using System.Security.Claims;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using OpenIddict.Abstractions; using OpenIddict.Abstractions;
@ -66,14 +66,8 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(ProcessAuthenticationContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context)
{ {
if (context == null) if (context == null)
{ {
@ -110,7 +104,7 @@ namespace OpenIddict.Validation
public ValidateReferenceTokenIdentifier() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1138)); public ValidateReferenceTokenIdentifier() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1138));
public ValidateReferenceTokenIdentifier([NotNull] IOpenIddictTokenManager tokenManager) public ValidateReferenceTokenIdentifier(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager; => _tokenManager = tokenManager;
/// <summary> /// <summary>
@ -125,7 +119,8 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
public async ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context) /// <inheritdoc/>
public async ValueTask HandleAsync(ProcessAuthenticationContext context)
{ {
if (context == null) if (context == null)
{ {
@ -187,14 +182,8 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public async ValueTask HandleAsync(ProcessAuthenticationContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public async ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context)
{ {
if (context == null) if (context == null)
{ {
@ -295,7 +284,7 @@ namespace OpenIddict.Validation
{ {
private readonly OpenIddictValidationService _service; private readonly OpenIddictValidationService _service;
public IntrospectToken([NotNull] OpenIddictValidationService service) public IntrospectToken(OpenIddictValidationService service)
=> _service = service; => _service = service;
/// <summary> /// <summary>
@ -309,14 +298,8 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public async ValueTask HandleAsync(ProcessAuthenticationContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public async ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context)
{ {
if (context == null) if (context == null)
{ {
@ -329,11 +312,13 @@ namespace OpenIddict.Validation
return; return;
} }
Debug.Assert(!string.IsNullOrEmpty(context.Token), SR.GetResourceString(SR.ID5010));
var configuration = await context.Options.ConfigurationManager.GetConfigurationAsync(default) ?? var configuration = await context.Options.ConfigurationManager.GetConfigurationAsync(default) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID1139)); throw new InvalidOperationException(SR.GetResourceString(SR.ID1139));
if (string.IsNullOrEmpty(configuration.IntrospectionEndpoint) || if (string.IsNullOrEmpty(configuration.IntrospectionEndpoint) ||
!Uri.TryCreate(configuration.IntrospectionEndpoint, UriKind.Absolute, out Uri address) || !Uri.TryCreate(configuration.IntrospectionEndpoint, UriKind.Absolute, out Uri? address) ||
!address.IsWellFormedOriginalString()) !address.IsWellFormedOriginalString())
{ {
context.Reject( context.Reject(
@ -385,14 +370,8 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(ProcessAuthenticationContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context)
{ {
if (context == null) if (context == null)
{ {
@ -436,14 +415,8 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(ProcessAuthenticationContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context)
{ {
if (context == null) if (context == null)
{ {
@ -540,7 +513,7 @@ namespace OpenIddict.Validation
public RestoreReferenceTokenProperties() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1138)); public RestoreReferenceTokenProperties() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1138));
public RestoreReferenceTokenProperties([NotNull] IOpenIddictTokenManager tokenManager) public RestoreReferenceTokenProperties(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager; => _tokenManager = tokenManager;
/// <summary> /// <summary>
@ -555,7 +528,8 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
public async ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context) /// <inheritdoc/>
public async ValueTask HandleAsync(ProcessAuthenticationContext context)
{ {
if (context == null) if (context == null)
{ {
@ -567,12 +541,13 @@ namespace OpenIddict.Validation
return; return;
} }
if (!context.Transaction.Properties.TryGetValue(Properties.ReferenceTokenIdentifier, out var identifier)) var identifier = context.Transaction.GetProperty<string>(Properties.ReferenceTokenIdentifier);
if (string.IsNullOrEmpty(identifier))
{ {
return; return;
} }
var token = await _tokenManager.FindByIdAsync((string) identifier); var token = await _tokenManager.FindByIdAsync(identifier);
if (token == null) if (token == null)
{ {
throw new InvalidOperationException(SR.GetResourceString(SR.ID1020)); throw new InvalidOperationException(SR.GetResourceString(SR.ID1020));
@ -603,14 +578,8 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(ProcessAuthenticationContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context)
{ {
if (context == null) if (context == null)
{ {
@ -663,20 +632,16 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(ProcessAuthenticationContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context)
{ {
if (context == null) if (context == null)
{ {
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
Debug.Assert(context.Principal != null, SR.GetResourceString(SR.ID5006));
var date = context.Principal.GetExpirationDate(); var date = context.Principal.GetExpirationDate();
if (date.HasValue && date.Value < DateTimeOffset.UtcNow) if (date.HasValue && date.Value < DateTimeOffset.UtcNow)
{ {
@ -709,20 +674,16 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(ProcessAuthenticationContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context)
{ {
if (context == null) if (context == null)
{ {
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
Debug.Assert(context.Principal != null, SR.GetResourceString(SR.ID5006));
// If no explicit audience has been configured, // If no explicit audience has been configured,
// skip the default audience validation. // skip the default audience validation.
if (context.Options.Audiences.Count == 0) if (context.Options.Audiences.Count == 0)
@ -770,7 +731,7 @@ namespace OpenIddict.Validation
public ValidateTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1138)); public ValidateTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1138));
public ValidateTokenEntry([NotNull] IOpenIddictTokenManager tokenManager) public ValidateTokenEntry(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager; => _tokenManager = tokenManager;
/// <summary> /// <summary>
@ -785,13 +746,16 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
public async ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context) /// <inheritdoc/>
public async ValueTask HandleAsync(ProcessAuthenticationContext context)
{ {
if (context == null) if (context == null)
{ {
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
Debug.Assert(context.Principal != null, SR.GetResourceString(SR.ID5006));
var identifier = context.Principal.GetTokenId(); var identifier = context.Principal.GetTokenId();
if (string.IsNullOrEmpty(identifier)) if (string.IsNullOrEmpty(identifier))
{ {
@ -830,7 +794,7 @@ namespace OpenIddict.Validation
public ValidateAuthorizationEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1141)); public ValidateAuthorizationEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID1141));
public ValidateAuthorizationEntry([NotNull] IOpenIddictAuthorizationManager authorizationManager) public ValidateAuthorizationEntry(IOpenIddictAuthorizationManager authorizationManager)
=> _authorizationManager = authorizationManager; => _authorizationManager = authorizationManager;
/// <summary> /// <summary>
@ -845,13 +809,16 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
public async ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context) /// <inheritdoc/>
public async ValueTask HandleAsync(ProcessAuthenticationContext context)
{ {
if (context == null) if (context == null)
{ {
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
Debug.Assert(context.Principal != null, SR.GetResourceString(SR.ID5006));
var identifier = context.Principal.GetAuthorizationId(); var identifier = context.Principal.GetAuthorizationId();
if (string.IsNullOrEmpty(identifier)) if (string.IsNullOrEmpty(identifier))
{ {
@ -887,14 +854,8 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(ProcessChallengeContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] ProcessChallengeContext context)
{ {
if (context == null) if (context == null)
{ {
@ -917,7 +878,7 @@ namespace OpenIddict.Validation
// to inform the client that the user is not allowed to perform the requested action. // to inform the client that the user is not allowed to perform the requested action.
var notification = context.Transaction.GetProperty<ProcessAuthenticationContext>( var notification = context.Transaction.GetProperty<ProcessAuthenticationContext>(
typeof(ProcessAuthenticationContext).FullName); typeof(ProcessAuthenticationContext).FullName!);
if (!string.IsNullOrEmpty(notification?.Error)) if (!string.IsNullOrEmpty(notification?.Error))
{ {
@ -951,26 +912,20 @@ namespace OpenIddict.Validation
.SetType(OpenIddictValidationHandlerType.BuiltIn) .SetType(OpenIddictValidationHandlerType.BuiltIn)
.Build(); .Build();
/// <summary> /// <inheritdoc/>
/// Processes the event. public ValueTask HandleAsync(TContext context)
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync([NotNull] TContext context)
{ {
if (context == null) if (context == null)
{ {
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(context));
} }
if (!string.IsNullOrEmpty(context.Response.Error)) if (!string.IsNullOrEmpty(context.Transaction.Response?.Error))
{ {
context.Reject( context.Reject(
error: context.Response.Error, error: context.Transaction.Response.Error,
description: context.Response.ErrorDescription, description: context.Transaction.Response.ErrorDescription,
uri: context.Response.ErrorUri); uri: context.Transaction.Response.ErrorUri);
return default; return default;
} }

9
src/OpenIddict.Validation/OpenIddictValidationHelpers.cs

@ -5,7 +5,6 @@
*/ */
using System; using System;
using JetBrains.Annotations;
using SR = OpenIddict.Abstractions.OpenIddictResources; using SR = OpenIddict.Abstractions.OpenIddictResources;
namespace OpenIddict.Validation namespace OpenIddict.Validation
@ -22,8 +21,8 @@ namespace OpenIddict.Validation
/// <param name="transaction">The validation transaction.</param> /// <param name="transaction">The validation transaction.</param>
/// <param name="name">The property name.</param> /// <param name="name">The property name.</param>
/// <returns>The property value or <c>null</c> if it couldn't be found.</returns> /// <returns>The property value or <c>null</c> if it couldn't be found.</returns>
public static TProperty GetProperty<TProperty>( public static TProperty? GetProperty<TProperty>(
[NotNull] this OpenIddictValidationTransaction transaction, [NotNull] string name) where TProperty : class this OpenIddictValidationTransaction transaction, string name) where TProperty : class
{ {
if (transaction == null) if (transaction == null)
{ {
@ -52,8 +51,8 @@ namespace OpenIddict.Validation
/// <param name="value">The property value.</param> /// <param name="value">The property value.</param>
/// <returns>The validation transaction, so that calls can be easily chained.</returns> /// <returns>The validation transaction, so that calls can be easily chained.</returns>
public static OpenIddictValidationTransaction SetProperty<TProperty>( public static OpenIddictValidationTransaction SetProperty<TProperty>(
[NotNull] this OpenIddictValidationTransaction transaction, this OpenIddictValidationTransaction transaction,
[NotNull] string name, [CanBeNull] TProperty value) where TProperty : class string name, TProperty? value) where TProperty : class
{ {
if (transaction == null) if (transaction == null)
{ {

12
src/OpenIddict.Validation/OpenIddictValidationOptions.cs

@ -60,12 +60,12 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Gets or sets the client identifier sent to the authorization server when using remote validation. /// Gets or sets the client identifier sent to the authorization server when using remote validation.
/// </summary> /// </summary>
public string ClientId { get; set; } public string? ClientId { get; set; }
/// <summary> /// <summary>
/// Gets or sets the client secret sent to the authorization server when using remote validation. /// Gets or sets the client secret sent to the authorization server when using remote validation.
/// </summary> /// </summary>
public string ClientSecret { get; set; } public string? ClientSecret { get; set; }
/// <summary> /// <summary>
/// Gets or sets a boolean indicating whether a database call is made /// Gets or sets a boolean indicating whether a database call is made
@ -86,24 +86,24 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Gets or sets the absolute URL of the OAuth 2.0/OpenID Connect server. /// Gets or sets the absolute URL of the OAuth 2.0/OpenID Connect server.
/// </summary> /// </summary>
public Uri Issuer { get; set; } public Uri? Issuer { get; set; }
/// <summary> /// <summary>
/// Gets or sets the URL of the OAuth 2.0/OpenID Connect server discovery endpoint. /// Gets or sets the URL of the OAuth 2.0/OpenID Connect server discovery endpoint.
/// When the URL is relative, <see cref="Issuer"/> must be set and absolute. /// When the URL is relative, <see cref="Issuer"/> must be set and absolute.
/// </summary> /// </summary>
public Uri MetadataAddress { get; set; } public Uri? MetadataAddress { get; set; }
/// <summary> /// <summary>
/// Gets or sets the OAuth 2.0/OpenID Connect static server configuration, if applicable. /// Gets or sets the OAuth 2.0/OpenID Connect static server configuration, if applicable.
/// </summary> /// </summary>
public OpenIdConnectConfiguration Configuration { get; set; } public OpenIdConnectConfiguration? Configuration { get; set; }
/// <summary> /// <summary>
/// Gets or sets the configuration manager used to retrieve /// Gets or sets the configuration manager used to retrieve
/// and cache the OAuth 2.0/OpenID Connect server configuration. /// and cache the OAuth 2.0/OpenID Connect server configuration.
/// </summary> /// </summary>
public IConfigurationManager<OpenIdConnectConfiguration> ConfigurationManager { get; set; } public IConfigurationManager<OpenIdConnectConfiguration> ConfigurationManager { get; set; } = default!;
/// <summary> /// <summary>
/// Gets the intended audiences of this resource server. /// Gets the intended audiences of this resource server.

5
src/OpenIddict.Validation/OpenIddictValidationRetriever.cs

@ -7,7 +7,6 @@
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.IdentityModel.Protocols; using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using SR = OpenIddict.Abstractions.OpenIddictResources; using SR = OpenIddict.Abstractions.OpenIddictResources;
@ -22,7 +21,7 @@ namespace OpenIddict.Validation
/// Creates a new instance of the <see cref="OpenIddictValidationRetriever"/> class. /// Creates a new instance of the <see cref="OpenIddictValidationRetriever"/> class.
/// </summary> /// </summary>
/// <param name="service">The validation service.</param> /// <param name="service">The validation service.</param>
public OpenIddictValidationRetriever([NotNull] OpenIddictValidationService service) public OpenIddictValidationRetriever(OpenIddictValidationService service)
=> _service = service; => _service = service;
/// <summary> /// <summary>
@ -39,7 +38,7 @@ namespace OpenIddict.Validation
throw new ArgumentException(SR.GetResourceString(SR.ID1142), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID1142), nameof(address));
} }
if (!Uri.TryCreate(address, UriKind.Absolute, out Uri uri) || !uri.IsWellFormedOriginalString()) if (!Uri.TryCreate(address, UriKind.Absolute, out Uri? uri) || !uri.IsWellFormedOriginalString())
{ {
throw new ArgumentException(SR.GetResourceString(SR.ID1143), nameof(address)); throw new ArgumentException(SR.GetResourceString(SR.ID1143), nameof(address));
} }

29
src/OpenIddict.Validation/OpenIddictValidationService.cs

@ -5,10 +5,10 @@
*/ */
using System; using System;
using System.Diagnostics;
using System.Security.Claims; using System.Security.Claims;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
@ -27,7 +27,7 @@ namespace OpenIddict.Validation
/// Creates a new instance of the <see cref="OpenIddictValidationService"/> class. /// Creates a new instance of the <see cref="OpenIddictValidationService"/> class.
/// </summary> /// </summary>
/// <param name="provider">The service provider.</param> /// <param name="provider">The service provider.</param>
public OpenIddictValidationService([NotNull] IServiceProvider provider) public OpenIddictValidationService(IServiceProvider provider)
=> _provider = provider; => _provider = provider;
/// <summary> /// <summary>
@ -36,8 +36,7 @@ namespace OpenIddict.Validation
/// <param name="address">The address of the remote metadata endpoint.</param> /// <param name="address">The address of the remote metadata endpoint.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The OpenID Connect server configuration retrieved from the remote server.</returns> /// <returns>The OpenID Connect server configuration retrieved from the remote server.</returns>
public async ValueTask<OpenIdConnectConfiguration> GetConfigurationAsync( public async ValueTask<OpenIdConnectConfiguration> GetConfigurationAsync(Uri address, CancellationToken cancellationToken = default)
[NotNull] Uri address, CancellationToken cancellationToken = default)
{ {
if (address == null) if (address == null)
{ {
@ -132,6 +131,8 @@ namespace OpenIddict.Validation
context.Error, context.ErrorDescription, context.ErrorUri); context.Error, context.ErrorDescription, context.ErrorUri);
} }
Debug.Assert(context.Response != null, SR.GetResourceString(SR.ID5007));
return context.Response; return context.Response;
} }
@ -176,8 +177,7 @@ namespace OpenIddict.Validation
/// <param name="address">The address of the remote metadata endpoint.</param> /// <param name="address">The address of the remote metadata endpoint.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The security keys retrieved from the remote server.</returns> /// <returns>The security keys retrieved from the remote server.</returns>
public async ValueTask<JsonWebKeySet> GetSecurityKeysAsync( public async ValueTask<JsonWebKeySet> GetSecurityKeysAsync(Uri address, CancellationToken cancellationToken = default)
[NotNull] Uri address, CancellationToken cancellationToken = default)
{ {
if (address == null) if (address == null)
{ {
@ -273,6 +273,8 @@ namespace OpenIddict.Validation
context.Error, context.ErrorDescription, context.ErrorUri); context.Error, context.ErrorDescription, context.ErrorUri);
} }
Debug.Assert(context.Response != null, SR.GetResourceString(SR.ID5007));
return context.Response; return context.Response;
} }
@ -318,8 +320,7 @@ namespace OpenIddict.Validation
/// <param name="token">The token to introspect.</param> /// <param name="token">The token to introspect.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The claims principal created from the claim retrieved from the remote server.</returns> /// <returns>The claims principal created from the claim retrieved from the remote server.</returns>
public ValueTask<ClaimsPrincipal> IntrospectTokenAsync( public ValueTask<ClaimsPrincipal> IntrospectTokenAsync(Uri address, string token, CancellationToken cancellationToken = default)
[NotNull] Uri address, [NotNull] string token, CancellationToken cancellationToken = default)
=> IntrospectTokenAsync(address, token, type: null, cancellationToken); => IntrospectTokenAsync(address, token, type: null, cancellationToken);
/// <summary> /// <summary>
@ -331,8 +332,7 @@ namespace OpenIddict.Validation
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The claims principal created from the claim retrieved from the remote server.</returns> /// <returns>The claims principal created from the claim retrieved from the remote server.</returns>
public async ValueTask<ClaimsPrincipal> IntrospectTokenAsync( public async ValueTask<ClaimsPrincipal> IntrospectTokenAsync(
[NotNull] Uri address, [NotNull] string token, Uri address, string token, string? type, CancellationToken cancellationToken = default)
[CanBeNull] string type, CancellationToken cancellationToken = default)
{ {
if (address == null) if (address == null)
{ {
@ -434,6 +434,8 @@ namespace OpenIddict.Validation
context.Error, context.ErrorDescription, context.ErrorUri); context.Error, context.ErrorDescription, context.ErrorUri);
} }
Debug.Assert(context.Response != null, SR.GetResourceString(SR.ID5007));
return context.Response; return context.Response;
} }
@ -456,6 +458,8 @@ namespace OpenIddict.Validation
context.Error, context.ErrorDescription, context.ErrorUri); context.Error, context.ErrorDescription, context.ErrorUri);
} }
Debug.Assert(context.Principal != null, SR.GetResourceString(SR.ID5006));
return context.Principal; return context.Principal;
} }
} }
@ -480,8 +484,7 @@ namespace OpenIddict.Validation
/// <param name="token">The access token to validate.</param> /// <param name="token">The access token to validate.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The principal containing the claims extracted from the token.</returns> /// <returns>The principal containing the claims extracted from the token.</returns>
public async ValueTask<ClaimsPrincipal> ValidateAccessTokenAsync( public async ValueTask<ClaimsPrincipal> ValidateAccessTokenAsync(string token, CancellationToken cancellationToken = default)
[NotNull] string token, CancellationToken cancellationToken = default)
{ {
if (string.IsNullOrEmpty(token)) if (string.IsNullOrEmpty(token))
{ {
@ -518,6 +521,8 @@ namespace OpenIddict.Validation
context.Error, context.ErrorDescription, context.ErrorUri); context.Error, context.ErrorDescription, context.ErrorUri);
} }
Debug.Assert(context.Principal != null, SR.GetResourceString(SR.ID5006));
return context.Principal; return context.Principal;
} }

16
src/OpenIddict.Validation/OpenIddictValidationTransaction.cs

@ -25,37 +25,37 @@ namespace OpenIddict.Validation
/// <summary> /// <summary>
/// Gets or sets the issuer address associated with the current transaction, if available. /// Gets or sets the issuer address associated with the current transaction, if available.
/// </summary> /// </summary>
public Uri Issuer { get; set; } public Uri? Issuer { get; set; }
/// <summary> /// <summary>
/// Gets or sets the localizer associated with the current request. /// Gets or sets the localizer associated with the current request.
/// </summary> /// </summary>
public IStringLocalizer Localizer { get; set; } public IStringLocalizer Localizer { get; set; } = default!;
/// <summary> /// <summary>
/// Gets or sets the logger associated with the current request. /// Gets or sets the logger associated with the current request.
/// </summary> /// </summary>
public ILogger Logger { get; set; } public ILogger Logger { get; set; } = default!;
/// <summary> /// <summary>
/// Gets or sets the options associated with the current request. /// Gets or sets the options associated with the current request.
/// </summary> /// </summary>
public OpenIddictValidationOptions Options { get; set; } public OpenIddictValidationOptions Options { get; set; } = default!;
/// <summary> /// <summary>
/// Gets the additional properties associated with the current request. /// Gets the additional properties associated with the current request.
/// </summary> /// </summary>
public IDictionary<string, object> Properties { get; } public IDictionary<string, object?> Properties { get; }
= new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase);
/// <summary> /// <summary>
/// Gets or sets the current OpenID Connect request. /// Gets or sets the current OpenID Connect request.
/// </summary> /// </summary>
public OpenIddictRequest Request { get; set; } public OpenIddictRequest? Request { get; set; }
/// <summary> /// <summary>
/// Gets or sets the current OpenID Connect response being returned. /// Gets or sets the current OpenID Connect response being returned.
/// </summary> /// </summary>
public OpenIddictResponse Response { get; set; } public OpenIddictResponse? Response { get; set; }
} }
} }

Loading…
Cancel
Save