Browse Source

React to the removal of the !! operator in C# 11

pull/1424/head
Kévin Chalet 4 years ago
parent
commit
7222d95025
  1. 7
      global.json
  2. 7
      sandbox/OpenIddict.Sandbox.AspNetCore.Server/Helpers/AsyncEnumerableExtensions.cs
  3. 12
      shared/OpenIddict.Extensions/Helpers/OpenIddictHelpers.cs
  4. 4
      src/OpenIddict.Abstractions/OpenIddictBuilder.cs
  5. 23
      src/OpenIddict.Abstractions/OpenIddictExtensions.cs
  6. 38
      src/OpenIddict.Abstractions/Primitives/OpenIddictConverter.cs
  7. 400
      src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs
  8. 42
      src/OpenIddict.Abstractions/Primitives/OpenIddictMessage.cs
  9. 7
      src/OpenIddict.Abstractions/Primitives/OpenIddictParameter.cs
  10. 11
      src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreBuilder.cs
  11. 21
      src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreConfiguration.cs
  12. 19
      src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreExtensions.cs
  13. 16
      src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandler.cs
  14. 56
      src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandlerFilters.cs
  15. 7
      src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandlers.Authentication.cs
  16. 92
      src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandlers.cs
  17. 56
      src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHelpers.cs
  18. 11
      src/OpenIddict.Client.Owin/OpenIddictClientOwinBuilder.cs
  19. 14
      src/OpenIddict.Client.Owin/OpenIddictClientOwinConfiguration.cs
  20. 19
      src/OpenIddict.Client.Owin/OpenIddictClientOwinExtensions.cs
  21. 8
      src/OpenIddict.Client.Owin/OpenIddictClientOwinHandler.cs
  22. 41
      src/OpenIddict.Client.Owin/OpenIddictClientOwinHandlerFilters.cs
  23. 7
      src/OpenIddict.Client.Owin/OpenIddictClientOwinHandlers.Authentication.cs
  24. 85
      src/OpenIddict.Client.Owin/OpenIddictClientOwinHandlers.cs
  25. 67
      src/OpenIddict.Client.Owin/OpenIddictClientOwinHelpers.cs
  26. 10
      src/OpenIddict.Client.Owin/OpenIddictClientOwinMiddleware.cs
  27. 7
      src/OpenIddict.Client.Owin/OpenIddictClientOwinMiddlewareFactory.cs
  28. 11
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpBuilder.cs
  29. 18
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpConfiguration.cs
  30. 19
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpExtensions.cs
  31. 14
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlerFilters.cs
  32. 7
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Exchange.cs
  33. 14
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Userinfo.cs
  34. 58
      src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.cs
  35. 153
      src/OpenIddict.Client/OpenIddictClientBuilder.cs
  36. 9
      src/OpenIddict.Client/OpenIddictClientConfiguration.cs
  37. 19
      src/OpenIddict.Client/OpenIddictClientDispatcher.cs
  38. 4
      src/OpenIddict.Client/OpenIddictClientEvents.cs
  39. 19
      src/OpenIddict.Client/OpenIddictClientExtensions.cs
  40. 8
      src/OpenIddict.Client/OpenIddictClientFactory.cs
  41. 7
      src/OpenIddict.Client/OpenIddictClientHandler.cs
  42. 65
      src/OpenIddict.Client/OpenIddictClientHandlerDescriptor.cs
  43. 209
      src/OpenIddict.Client/OpenIddictClientHandlerFilters.cs
  44. 91
      src/OpenIddict.Client/OpenIddictClientHandlers.Authentication.cs
  45. 105
      src/OpenIddict.Client/OpenIddictClientHandlers.Discovery.cs
  46. 7
      src/OpenIddict.Client/OpenIddictClientHandlers.Exchange.cs
  47. 49
      src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs
  48. 14
      src/OpenIddict.Client/OpenIddictClientHandlers.Userinfo.cs
  49. 481
      src/OpenIddict.Client/OpenIddictClientHandlers.cs
  50. 14
      src/OpenIddict.Client/OpenIddictClientHelpers.cs
  51. 7
      src/OpenIddict.Client/OpenIddictClientRetriever.cs
  52. 53
      src/OpenIddict.Client/OpenIddictClientService.cs
  53. 43
      src/OpenIddict.Core/Caches/OpenIddictApplicationCache.cs
  54. 43
      src/OpenIddict.Core/Caches/OpenIddictAuthorizationCache.cs
  55. 45
      src/OpenIddict.Core/Caches/OpenIddictScopeCache.cs
  56. 43
      src/OpenIddict.Core/Caches/OpenIddictTokenCache.cs
  57. 332
      src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs
  58. 275
      src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
  59. 276
      src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs
  60. 323
      src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs
  61. 123
      src/OpenIddict.Core/OpenIddictCoreBuilder.cs
  62. 19
      src/OpenIddict.Core/OpenIddictCoreExtensions.cs
  63. 4
      src/OpenIddict.Core/Resolvers/OpenIddictApplicationStoreResolver.cs
  64. 4
      src/OpenIddict.Core/Resolvers/OpenIddictAuthorizationStoreResolver.cs
  65. 4
      src/OpenIddict.Core/Resolvers/OpenIddictScopeStoreResolver.cs
  66. 4
      src/OpenIddict.Core/Resolvers/OpenIddictTokenStoreResolver.cs
  67. 18
      src/OpenIddict.EntityFramework/OpenIddictEntityFrameworkBuilder.cs
  68. 19
      src/OpenIddict.EntityFramework/OpenIddictEntityFrameworkExtensions.cs
  69. 14
      src/OpenIddict.EntityFramework/OpenIddictEntityFrameworkHelpers.cs
  70. 12
      src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkApplicationStoreResolver.cs
  71. 12
      src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkAuthorizationStoreResolver.cs
  72. 12
      src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkScopeStoreResolver.cs
  73. 12
      src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkTokenStoreResolver.cs
  74. 249
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkApplicationStore.cs
  75. 198
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkAuthorizationStore.cs
  76. 187
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkScopeStore.cs
  77. 280
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkTokenStore.cs
  78. 7
      src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictEntityFrameworkCoreApplicationConfiguration.cs
  79. 7
      src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictEntityFrameworkCoreAuthorizationConfiguration.cs
  80. 7
      src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictEntityFrameworkCoreScopeConfiguration.cs
  81. 7
      src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictEntityFrameworkCoreTokenConfiguration.cs
  82. 18
      src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreBuilder.cs
  83. 12
      src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreCustomizer.cs
  84. 19
      src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreExtensions.cs
  85. 29
      src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreHelpers.cs
  86. 12
      src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreApplicationStoreResolver.cs
  87. 12
      src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreAuthorizationStoreResolver.cs
  88. 12
      src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreScopeStoreResolver.cs
  89. 12
      src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreTokenStoreResolver.cs
  90. 255
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreApplicationStore.cs
  91. 196
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreAuthorizationStore.cs
  92. 193
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreScopeStore.cs
  93. 282
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreTokenStore.cs
  94. 18
      src/OpenIddict.MongoDb/OpenIddictMongoDbBuilder.cs
  95. 8
      src/OpenIddict.MongoDb/OpenIddictMongoDbContext.cs
  96. 19
      src/OpenIddict.MongoDb/OpenIddictMongoDbExtensions.cs
  97. 18
      src/OpenIddict.MongoDb/OpenIddictMongoDbHelpers.cs
  98. 4
      src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbApplicationStoreResolver.cs
  99. 4
      src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbAuthorizationStoreResolver.cs
  100. 4
      src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbScopeStoreResolver.cs

7
global.json

@ -1,17 +1,16 @@
{
"sdk": {
"version": "7.0.100-preview.2.22153.17"
"version": "6.0.202"
},
"tools": {
"dotnet": "7.0.100-preview.2.22153.17",
"dotnet": "6.0.202",
"runtimes": {
"aspnetcore": [
"2.1.28",
"3.1.16",
"5.0.7",
"6.0.0"
"5.0.7"
]
}
},

7
sandbox/OpenIddict.Sandbox.AspNetCore.Server/Helpers/AsyncEnumerableExtensions.cs

@ -2,8 +2,13 @@
public static class AsyncEnumerableExtensions
{
public static Task<List<T>> ToListAsync<T>(this IAsyncEnumerable<T> source!!)
public static Task<List<T>> ToListAsync<T>(this IAsyncEnumerable<T> source)
{
if (source is null)
{
throw new ArgumentNullException(nameof(source));
}
return ExecuteAsync();
async Task<List<T>> ExecuteAsync()

12
shared/OpenIddict.Extensions/Helpers/OpenIddictHelpers.cs

@ -20,8 +20,18 @@ internal static class OpenIddictHelpers
/// <param name="type">The type to introspect.</param>
/// <param name="definition">The generic type definition.</param>
/// <returns>A <see cref="Type"/> instance if the base type was found, <see langword="null"/> otherwise.</returns>
public static IEnumerable<Type> FindGenericBaseTypes(Type type!!, Type definition!!)
public static IEnumerable<Type> FindGenericBaseTypes(Type type, Type definition)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
if (definition is null)
{
throw new ArgumentNullException(nameof(definition));
}
if (!definition.IsGenericTypeDefinition)
{
throw new ArgumentException(SR.GetResourceString(SR.ID0263), nameof(definition));

4
src/OpenIddict.Abstractions/OpenIddictBuilder.cs

@ -17,8 +17,8 @@ public class OpenIddictBuilder
/// Initializes a new instance of <see cref="OpenIddictBuilder"/>.
/// </summary>
/// <param name="services">The services collection.</param>
public OpenIddictBuilder(IServiceCollection services!!)
=> Services = services;
public OpenIddictBuilder(IServiceCollection services)
=> Services = services ?? throw new ArgumentNullException(nameof(services));
/// <summary>
/// Gets the services collection.

23
src/OpenIddict.Abstractions/OpenIddictExtensions.cs

@ -17,8 +17,15 @@ public static class OpenIddictExtensions
/// <param name="services">The services collection.</param>
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
public static OpenIddictBuilder AddOpenIddict(this IServiceCollection services!!)
=> new OpenIddictBuilder(services);
public static OpenIddictBuilder AddOpenIddict(this IServiceCollection services)
{
if (services is null)
{
throw new ArgumentNullException(nameof(services));
}
return new OpenIddictBuilder(services);
}
/// <summary>
/// Provides a common entry point for registering the OpenIddict services.
@ -27,8 +34,18 @@ public static class OpenIddictExtensions
/// <param name="configuration">The configuration delegate used to register new services.</param>
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="IServiceCollection"/>.</returns>
public static IServiceCollection AddOpenIddict(this IServiceCollection services!!, Action<OpenIddictBuilder> configuration!!)
public static IServiceCollection AddOpenIddict(this IServiceCollection services, Action<OpenIddictBuilder> configuration)
{
if (services is null)
{
throw new ArgumentNullException(nameof(services));
}
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
configuration(services.AddOpenIddict());
return services;

38
src/OpenIddict.Abstractions/Primitives/OpenIddictConverter.cs

@ -19,10 +19,17 @@ public class OpenIddictConverter : JsonConverter<OpenIddictMessage>
/// </summary>
/// <param name="typeToConvert">The type to convert.</param>
/// <returns><see langword="true"/> if the type is supported, <see langword="false"/> otherwise.</returns>
public override bool CanConvert(Type typeToConvert!!)
=> typeToConvert == typeof(OpenIddictMessage) ||
typeToConvert == typeof(OpenIddictRequest) ||
typeToConvert == typeof(OpenIddictResponse);
public override bool CanConvert(Type typeToConvert)
{
if (typeToConvert is null)
{
throw new ArgumentNullException(nameof(typeToConvert));
}
return typeToConvert == typeof(OpenIddictMessage) ||
typeToConvert == typeof(OpenIddictRequest) ||
typeToConvert == typeof(OpenIddictResponse);
}
/// <summary>
/// Deserializes an <see cref="OpenIddictMessage"/> instance.
@ -31,8 +38,13 @@ public class OpenIddictConverter : JsonConverter<OpenIddictMessage>
/// <param name="typeToConvert">The type of the deserialized instance.</param>
/// <param name="options">The JSON serializer options.</param>
/// <returns>The deserialized <see cref="OpenIddictMessage"/> instance.</returns>
public override OpenIddictMessage Read(ref Utf8JsonReader reader, Type typeToConvert!!, JsonSerializerOptions options)
public override OpenIddictMessage Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (typeToConvert is null)
{
throw new ArgumentNullException(nameof(typeToConvert));
}
using var document = JsonDocument.ParseValue(ref reader);
return typeToConvert == typeof(OpenIddictMessage) ? new OpenIddictMessage(document.RootElement.Clone()) :
@ -47,6 +59,18 @@ public class OpenIddictConverter : JsonConverter<OpenIddictMessage>
/// <param name="writer">The JSON writer.</param>
/// <param name="value">The instance.</param>
/// <param name="options">The JSON serializer options.</param>
public override void Write(Utf8JsonWriter writer!!, OpenIddictMessage value!!, JsonSerializerOptions options)
=> value.WriteTo(writer);
public override void Write(Utf8JsonWriter writer, OpenIddictMessage value, JsonSerializerOptions options)
{
if (writer is null)
{
throw new ArgumentNullException(nameof(writer));
}
if (value is null)
{
throw new ArgumentNullException(nameof(value));
}
value.WriteTo(writer);
}
}

400
src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs

@ -25,37 +25,70 @@ public static class OpenIddictExtensions
/// Extracts the authentication context class values from an <see cref="OpenIddictRequest"/>.
/// </summary>
/// <param name="request">The <see cref="OpenIddictRequest"/> instance.</param>
public static ImmutableArray<string> GetAcrValues(this OpenIddictRequest request!!)
=> GetValues(request.AcrValues, Separators.Space);
public static ImmutableArray<string> GetAcrValues(this OpenIddictRequest request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
return GetValues(request.AcrValues, Separators.Space);
}
/// <summary>
/// Extracts the prompt values from an <see cref="OpenIddictRequest"/>.
/// </summary>
/// <param name="request">The <see cref="OpenIddictRequest"/> instance.</param>
public static ImmutableArray<string> GetPrompts(this OpenIddictRequest request!!)
=> GetValues(request.Prompt, Separators.Space);
public static ImmutableArray<string> GetPrompts(this OpenIddictRequest request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
return GetValues(request.Prompt, Separators.Space);
}
/// <summary>
/// Extracts the response types from an <see cref="OpenIddictRequest"/>.
/// </summary>
/// <param name="request">The <see cref="OpenIddictRequest"/> instance.</param>
public static ImmutableArray<string> GetResponseTypes(this OpenIddictRequest request!!)
=> GetValues(request.ResponseType, Separators.Space);
public static ImmutableArray<string> GetResponseTypes(this OpenIddictRequest request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
return GetValues(request.ResponseType, Separators.Space);
}
/// <summary>
/// Extracts the scopes from an <see cref="OpenIddictRequest"/>.
/// </summary>
/// <param name="request">The <see cref="OpenIddictRequest"/> instance.</param>
public static ImmutableArray<string> GetScopes(this OpenIddictRequest request!!)
=> GetValues(request.Scope, Separators.Space);
public static ImmutableArray<string> GetScopes(this OpenIddictRequest request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
return GetValues(request.Scope, Separators.Space);
}
/// <summary>
/// Determines whether the requested authentication context class values contain the specified item.
/// </summary>
/// <param name="request">The <see cref="OpenIddictRequest"/> instance.</param>
/// <param name="value">The component to look for in the parameter.</param>
public static bool HasAcrValue(this OpenIddictRequest request!!, string value)
public static bool HasAcrValue(this OpenIddictRequest request, string value)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
if (string.IsNullOrEmpty(value))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0177), nameof(value));
@ -69,8 +102,13 @@ public static class OpenIddictExtensions
/// </summary>
/// <param name="request">The <see cref="OpenIddictRequest"/> instance.</param>
/// <param name="prompt">The component to look for in the parameter.</param>
public static bool HasPrompt(this OpenIddictRequest request!!, string prompt)
public static bool HasPrompt(this OpenIddictRequest request, string prompt)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
if (string.IsNullOrEmpty(prompt))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0178), nameof(prompt));
@ -84,8 +122,13 @@ public static class OpenIddictExtensions
/// </summary>
/// <param name="request">The <see cref="OpenIddictRequest"/> instance.</param>
/// <param name="type">The component to look for in the parameter.</param>
public static bool HasResponseType(this OpenIddictRequest request!!, string type)
public static bool HasResponseType(this OpenIddictRequest request, string type)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0179), nameof(type));
@ -99,8 +142,13 @@ public static class OpenIddictExtensions
/// </summary>
/// <param name="request">The <see cref="OpenIddictRequest"/> instance.</param>
/// <param name="scope">The component to look for in the parameter.</param>
public static bool HasScope(this OpenIddictRequest request!!, string scope)
public static bool HasScope(this OpenIddictRequest request, string scope)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
if (string.IsNullOrEmpty(scope))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0180), nameof(scope));
@ -115,8 +163,13 @@ public static class OpenIddictExtensions
/// </summary>
/// <param name="request">The <see cref="OpenIddictRequest"/> instance.</param>
/// <returns><see langword="true"/> if the request is a response_type=none request, <see langword="false"/> otherwise.</returns>
public static bool IsNoneFlow(this OpenIddictRequest request!!)
public static bool IsNoneFlow(this OpenIddictRequest request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
if (string.IsNullOrEmpty(request.ResponseType))
{
return false;
@ -137,8 +190,13 @@ public static class OpenIddictExtensions
/// </summary>
/// <param name="request">The <see cref="OpenIddictRequest"/> instance.</param>
/// <returns><see langword="true"/> if the request is a code flow request, <see langword="false"/> otherwise.</returns>
public static bool IsAuthorizationCodeFlow(this OpenIddictRequest request!!)
public static bool IsAuthorizationCodeFlow(this OpenIddictRequest request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
if (string.IsNullOrEmpty(request.ResponseType))
{
return false;
@ -160,8 +218,13 @@ public static class OpenIddictExtensions
/// </summary>
/// <param name="request">The <see cref="OpenIddictRequest"/> instance.</param>
/// <returns><see langword="true"/> if the request is an implicit flow request, <see langword="false"/> otherwise.</returns>
public static bool IsImplicitFlow(this OpenIddictRequest request!!)
public static bool IsImplicitFlow(this OpenIddictRequest request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
if (string.IsNullOrEmpty(request.ResponseType))
{
return false;
@ -209,8 +272,13 @@ public static class OpenIddictExtensions
/// </summary>
/// <param name="request">The <see cref="OpenIddictRequest"/> instance.</param>
/// <returns><see langword="true"/> if the request is an hybrid flow request, <see langword="false"/> otherwise.</returns>
public static bool IsHybridFlow(this OpenIddictRequest request!!)
public static bool IsHybridFlow(this OpenIddictRequest request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
if (string.IsNullOrEmpty(request.ResponseType))
{
return false;
@ -271,8 +339,13 @@ public static class OpenIddictExtensions
/// <see langword="true"/> if the request specified the fragment response mode or if
/// it's the default value for the requested flow, <see langword="false"/> otherwise.
/// </returns>
public static bool IsFragmentResponseMode(this OpenIddictRequest request!!)
public static bool IsFragmentResponseMode(this OpenIddictRequest request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
if (string.Equals(request.ResponseMode, ResponseModes.Fragment, StringComparison.Ordinal))
{
return true;
@ -299,8 +372,13 @@ public static class OpenIddictExtensions
/// <see langword="true"/> if the request specified the query response mode or if
/// it's the default value for the requested flow, <see langword="false"/> otherwise.
/// </returns>
public static bool IsQueryResponseMode(this OpenIddictRequest request!!)
public static bool IsQueryResponseMode(this OpenIddictRequest request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
if (string.Equals(request.ResponseMode, ResponseModes.Query, StringComparison.Ordinal))
{
return true;
@ -326,8 +404,15 @@ public static class OpenIddictExtensions
/// <see langword="true"/> if the request specified the form post response mode or if
/// it's the default value for the requested flow, <see langword="false"/> otherwise.
/// </returns>
public static bool IsFormPostResponseMode(this OpenIddictRequest request!!)
=> string.Equals(request.ResponseMode, ResponseModes.FormPost, StringComparison.Ordinal);
public static bool IsFormPostResponseMode(this OpenIddictRequest request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
return string.Equals(request.ResponseMode, ResponseModes.FormPost, StringComparison.Ordinal);
}
/// <summary>
/// Determines whether the "grant_type" parameter corresponds to the authorization code grant.
@ -335,8 +420,15 @@ public static class OpenIddictExtensions
/// </summary>
/// <param name="request">The <see cref="OpenIddictRequest"/> instance.</param>
/// <returns><see langword="true"/> if the request is a code grant request, <see langword="false"/> otherwise.</returns>
public static bool IsAuthorizationCodeGrantType(this OpenIddictRequest request!!)
=> string.Equals(request.GrantType, GrantTypes.AuthorizationCode, StringComparison.Ordinal);
public static bool IsAuthorizationCodeGrantType(this OpenIddictRequest request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
return string.Equals(request.GrantType, GrantTypes.AuthorizationCode, StringComparison.Ordinal);
}
/// <summary>
/// Determines whether the "grant_type" parameter corresponds to the client credentials grant.
@ -344,8 +436,15 @@ public static class OpenIddictExtensions
/// </summary>
/// <param name="request">The <see cref="OpenIddictRequest"/> instance.</param>
/// <returns><see langword="true"/> if the request is a client credentials grant request, <see langword="false"/> otherwise.</returns>
public static bool IsClientCredentialsGrantType(this OpenIddictRequest request!!)
=> string.Equals(request.GrantType, GrantTypes.ClientCredentials, StringComparison.Ordinal);
public static bool IsClientCredentialsGrantType(this OpenIddictRequest request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
return string.Equals(request.GrantType, GrantTypes.ClientCredentials, StringComparison.Ordinal);
}
/// <summary>
/// Determines whether the "grant_type" parameter corresponds to the device code grant.
@ -353,8 +452,15 @@ public static class OpenIddictExtensions
/// </summary>
/// <param name="request">The <see cref="OpenIddictRequest"/> instance.</param>
/// <returns><see langword="true"/> if the request is a device code grant request, <see langword="false"/> otherwise.</returns>
public static bool IsDeviceCodeGrantType(this OpenIddictRequest request!!)
=> string.Equals(request.GrantType, GrantTypes.DeviceCode, StringComparison.Ordinal);
public static bool IsDeviceCodeGrantType(this OpenIddictRequest request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
return string.Equals(request.GrantType, GrantTypes.DeviceCode, StringComparison.Ordinal);
}
/// <summary>
/// Determines whether the "grant_type" parameter corresponds to the password grant.
@ -362,8 +468,15 @@ public static class OpenIddictExtensions
/// </summary>
/// <param name="request">The <see cref="OpenIddictRequest"/> instance.</param>
/// <returns><see langword="true"/> if the request is a password grant request, <see langword="false"/> otherwise.</returns>
public static bool IsPasswordGrantType(this OpenIddictRequest request!!)
=> string.Equals(request.GrantType, GrantTypes.Password, StringComparison.Ordinal);
public static bool IsPasswordGrantType(this OpenIddictRequest request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
return string.Equals(request.GrantType, GrantTypes.Password, StringComparison.Ordinal);
}
/// <summary>
/// Determines whether the "grant_type" parameter corresponds to the refresh token grant.
@ -371,16 +484,28 @@ public static class OpenIddictExtensions
/// </summary>
/// <param name="request">The <see cref="OpenIddictRequest"/> instance.</param>
/// <returns><see langword="true"/> if the request is a refresh token grant request, <see langword="false"/> otherwise.</returns>
public static bool IsRefreshTokenGrantType(this OpenIddictRequest request!!)
=> string.Equals(request.GrantType, GrantTypes.RefreshToken, StringComparison.Ordinal);
public static bool IsRefreshTokenGrantType(this OpenIddictRequest request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
return string.Equals(request.GrantType, GrantTypes.RefreshToken, StringComparison.Ordinal);
}
/// <summary>
/// Gets the destinations associated with a claim.
/// </summary>
/// <param name="claim">The <see cref="Claim"/> instance.</param>
/// <returns>The destinations associated with the claim.</returns>
public static ImmutableArray<string> GetDestinations(this Claim claim!!)
public static ImmutableArray<string> GetDestinations(this Claim claim)
{
if (claim is null)
{
throw new ArgumentNullException(nameof(claim));
}
claim.Properties.TryGetValue(Properties.Destinations, out string? destinations);
if (string.IsNullOrEmpty(destinations))
@ -410,8 +535,13 @@ public static class OpenIddictExtensions
/// </summary>
/// <param name="claim">The <see cref="Claim"/> instance.</param>
/// <param name="destination">The required destination.</param>
public static bool HasDestination(this Claim claim!!, string destination)
public static bool HasDestination(this Claim claim, string destination)
{
if (claim is null)
{
throw new ArgumentNullException(nameof(claim));
}
if (string.IsNullOrEmpty(destination))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0181), nameof(destination));
@ -443,8 +573,13 @@ public static class OpenIddictExtensions
/// </summary>
/// <param name="claim">The <see cref="Claim"/> instance.</param>
/// <param name="destinations">The destinations.</param>
public static Claim SetDestinations(this Claim claim!!, ImmutableArray<string> destinations)
public static Claim SetDestinations(this Claim claim, ImmutableArray<string> destinations)
{
if (claim is null)
{
throw new ArgumentNullException(nameof(claim));
}
if (destinations.IsDefaultOrEmpty)
{
claim.Properties.Remove(Properties.Destinations);
@ -452,7 +587,7 @@ public static class OpenIddictExtensions
return claim;
}
if (destinations.Any(string.IsNullOrEmpty))
if (destinations.Any(destination => string.IsNullOrEmpty(destination)))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0182), nameof(destinations));
}
@ -500,8 +635,13 @@ public static class OpenIddictExtensions
/// </summary>
/// <param name="principal">The principal.</param>
/// <returns>The destinations, returned as a flattened dictionary.</returns>
public static ImmutableDictionary<string, string[]> GetDestinations(this ClaimsPrincipal principal!!)
public static ImmutableDictionary<string, string[]> GetDestinations(this ClaimsPrincipal principal)
{
if (principal is null)
{
throw new ArgumentNullException(nameof(principal));
}
var builder = ImmutableDictionary.CreateBuilder<string, string[]>(StringComparer.Ordinal);
foreach (var group in principal.Claims.GroupBy(claim => claim.Type))
@ -533,8 +673,18 @@ public static class OpenIddictExtensions
/// <param name="principal">The principal.</param>
/// <param name="destinations">The destinations, as a flattened dictionary.</param>
/// <returns>The principal.</returns>
public static ClaimsPrincipal SetDestinations(this ClaimsPrincipal principal!!, ImmutableDictionary<string, string[]> destinations!!)
public static ClaimsPrincipal SetDestinations(this ClaimsPrincipal principal, ImmutableDictionary<string, string[]> destinations)
{
if (principal is null)
{
throw new ArgumentNullException(nameof(principal));
}
if (destinations is null)
{
throw new ArgumentNullException(nameof(destinations));
}
foreach (var destination in destinations)
{
foreach (var claim in principal.Claims.Where(claim => claim.Type == destination.Key))
@ -554,8 +704,18 @@ public static class OpenIddictExtensions
/// The delegate filtering the claims: return <see langword="true"/>
/// to accept the claim, <see langword="false"/> to remove it.
/// </param>
public static ClaimsIdentity Clone(this ClaimsIdentity identity!!, Func<Claim, bool> filter!!)
public static ClaimsIdentity Clone(this ClaimsIdentity identity, Func<Claim, bool> filter)
{
if (identity is null)
{
throw new ArgumentNullException(nameof(identity));
}
if (filter is null)
{
throw new ArgumentNullException(nameof(filter));
}
var clone = identity.Clone();
// Note: make sure to call ToList() to avoid modifying
@ -584,8 +744,18 @@ public static class OpenIddictExtensions
/// The delegate filtering the claims: return <see langword="true"/>
/// to accept the claim, <see langword="false"/> to remove it.
/// </param>
public static ClaimsPrincipal Clone(this ClaimsPrincipal principal!!, Func<Claim, bool> filter!!)
public static ClaimsPrincipal Clone(this ClaimsPrincipal principal, Func<Claim, bool> filter)
{
if (principal is null)
{
throw new ArgumentNullException(nameof(principal));
}
if (filter is null)
{
throw new ArgumentNullException(nameof(filter));
}
var clone = new ClaimsPrincipal();
foreach (var identity in principal.Identities)
@ -602,8 +772,13 @@ public static class OpenIddictExtensions
/// <param name="identity">The identity.</param>
/// <param name="type">The type associated with the claim.</param>
/// <param name="value">The value associated with the claim.</param>
public static ClaimsIdentity AddClaim(this ClaimsIdentity identity!!, string type, string value)
public static ClaimsIdentity AddClaim(this ClaimsIdentity identity, string type, string value)
{
if (identity is null)
{
throw new ArgumentNullException(nameof(identity));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0184), nameof(type));
@ -625,8 +800,13 @@ public static class OpenIddictExtensions
/// <param name="type">The type associated with the claim.</param>
/// <param name="value">The value associated with the claim.</param>
/// <param name="destinations">The destinations associated with the claim.</param>
public static ClaimsIdentity AddClaim(this ClaimsIdentity identity!!, string type, string value, ImmutableArray<string> destinations)
public static ClaimsIdentity AddClaim(this ClaimsIdentity identity, string type, string value, ImmutableArray<string> destinations)
{
if (identity is null)
{
throw new ArgumentNullException(nameof(identity));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0184), nameof(type));
@ -657,8 +837,13 @@ public static class OpenIddictExtensions
/// <param name="identity">The identity.</param>
/// <param name="type">The type associated with the claim.</param>
/// <returns>The claim value.</returns>
public static string? GetClaim(this ClaimsIdentity identity!!, string type)
public static string? GetClaim(this ClaimsIdentity identity, string type)
{
if (identity is null)
{
throw new ArgumentNullException(nameof(identity));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0184), nameof(type));
@ -673,8 +858,13 @@ public static class OpenIddictExtensions
/// <param name="principal">The principal.</param>
/// <param name="type">The type associated with the claim.</param>
/// <returns>The claim value.</returns>
public static string? GetClaim(this ClaimsPrincipal principal!!, string type)
public static string? GetClaim(this ClaimsPrincipal principal, string type)
{
if (principal is null)
{
throw new ArgumentNullException(nameof(principal));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0184), nameof(type));
@ -689,8 +879,13 @@ public static class OpenIddictExtensions
/// <param name="identity">The identity.</param>
/// <param name="type">The type associated with the claims.</param>
/// <returns>The claim values.</returns>
public static ImmutableArray<string> GetClaims(this ClaimsIdentity identity!!, string type)
public static ImmutableArray<string> GetClaims(this ClaimsIdentity identity, string type)
{
if (identity is null)
{
throw new ArgumentNullException(nameof(identity));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0184), nameof(type));
@ -705,8 +900,13 @@ public static class OpenIddictExtensions
/// <param name="identity">The claims identity.</param>
/// <param name="type">The claim type.</param>
/// <returns><see langword="true"/> if the identity contains at least one claim of the specified type.</returns>
public static bool HasClaim(this ClaimsIdentity identity!!, string type)
public static bool HasClaim(this ClaimsIdentity identity, string type)
{
if (identity is null)
{
throw new ArgumentNullException(nameof(identity));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0184), nameof(type));
@ -721,8 +921,13 @@ public static class OpenIddictExtensions
/// <param name="principal">The principal.</param>
/// <param name="type">The type associated with the claims.</param>
/// <returns>The claim values.</returns>
public static ImmutableArray<string> GetClaims(this ClaimsPrincipal principal!!, string type)
public static ImmutableArray<string> GetClaims(this ClaimsPrincipal principal, string type)
{
if (principal is null)
{
throw new ArgumentNullException(nameof(principal));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0184), nameof(type));
@ -737,8 +942,13 @@ public static class OpenIddictExtensions
/// <param name="principal">The claims principal.</param>
/// <param name="type">The claim type.</param>
/// <returns><see langword="true"/> if the principal contains at least one claim of the specified type.</returns>
public static bool HasClaim(this ClaimsPrincipal principal!!, string type)
public static bool HasClaim(this ClaimsPrincipal principal, string type)
{
if (principal is null)
{
throw new ArgumentNullException(nameof(principal));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0184), nameof(type));
@ -753,8 +963,13 @@ public static class OpenIddictExtensions
/// <param name="identity">The identity.</param>
/// <param name="type">The type associated with the claims.</param>
/// <returns>The claims identity.</returns>
public static ClaimsIdentity RemoveClaims(this ClaimsIdentity identity!!, string type)
public static ClaimsIdentity RemoveClaims(this ClaimsIdentity identity, string type)
{
if (identity is null)
{
throw new ArgumentNullException(nameof(identity));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0184), nameof(type));
@ -774,8 +989,13 @@ public static class OpenIddictExtensions
/// <param name="principal">The principal.</param>
/// <param name="type">The type associated with the claims.</param>
/// <returns>The claims identity.</returns>
public static ClaimsPrincipal RemoveClaims(this ClaimsPrincipal principal!!, string type)
public static ClaimsPrincipal RemoveClaims(this ClaimsPrincipal principal, string type)
{
if (principal is null)
{
throw new ArgumentNullException(nameof(principal));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0184), nameof(type));
@ -799,8 +1019,13 @@ public static class OpenIddictExtensions
/// <param name="type">The type associated with the claims.</param>
/// <param name="value">The claim value.</param>
/// <returns>The claims identity.</returns>
public static ClaimsIdentity SetClaims(this ClaimsIdentity identity!!, string type, string? value)
public static ClaimsIdentity SetClaims(this ClaimsIdentity identity, string type, string? value)
{
if (identity is null)
{
throw new ArgumentNullException(nameof(identity));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0184), nameof(type));
@ -823,8 +1048,13 @@ public static class OpenIddictExtensions
/// <param name="type">The type associated with the claims.</param>
/// <param name="value">The claim value.</param>
/// <returns>The claims identity.</returns>
public static ClaimsPrincipal SetClaim(this ClaimsPrincipal principal!!, string type, string? value)
public static ClaimsPrincipal SetClaim(this ClaimsPrincipal principal, string type, string? value)
{
if (principal is null)
{
throw new ArgumentNullException(nameof(principal));
}
if (principal.Identity is not ClaimsIdentity identity)
{
throw new ArgumentException(SR.GetResourceString(SR.ID0286), nameof(principal));
@ -852,8 +1082,13 @@ public static class OpenIddictExtensions
/// <param name="type">The type associated with the claims.</param>
/// <param name="values">The claim values.</param>
/// <returns>The claims identity.</returns>
public static ClaimsIdentity SetClaims(this ClaimsIdentity identity!!, string type, ImmutableArray<string> values)
public static ClaimsIdentity SetClaims(this ClaimsIdentity identity, string type, ImmutableArray<string> values)
{
if (identity is null)
{
throw new ArgumentNullException(nameof(identity));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0184), nameof(type));
@ -876,8 +1111,13 @@ public static class OpenIddictExtensions
/// <param name="type">The type associated with the claims.</param>
/// <param name="values">The claim values.</param>
/// <returns>The claims identity.</returns>
public static ClaimsPrincipal SetClaims(this ClaimsPrincipal principal!!, string type, ImmutableArray<string> values)
public static ClaimsPrincipal SetClaims(this ClaimsPrincipal principal, string type, ImmutableArray<string> values)
{
if (principal is null)
{
throw new ArgumentNullException(nameof(principal));
}
if (principal.Identity is not ClaimsIdentity identity)
{
throw new ArgumentException(SR.GetResourceString(SR.ID0286), nameof(principal));
@ -903,8 +1143,13 @@ public static class OpenIddictExtensions
/// </summary>
/// <param name="principal">The claims principal.</param>
/// <returns>The creation date or <see langword="null"/> if the claim cannot be found.</returns>
public static DateTimeOffset? GetCreationDate(this ClaimsPrincipal principal!!)
public static DateTimeOffset? GetCreationDate(this ClaimsPrincipal principal)
{
if (principal is null)
{
throw new ArgumentNullException(nameof(principal));
}
var claim = principal.FindFirst(Claims.Private.CreationDate);
if (claim is null)
{
@ -924,8 +1169,13 @@ public static class OpenIddictExtensions
/// </summary>
/// <param name="principal">The claims principal.</param>
/// <returns>The expiration date or <see langword="null"/> if the claim cannot be found.</returns>
public static DateTimeOffset? GetExpirationDate(this ClaimsPrincipal principal!!)
public static DateTimeOffset? GetExpirationDate(this ClaimsPrincipal principal)
{
if (principal is null)
{
throw new ArgumentNullException(nameof(principal));
}
var claim = principal.FindFirst(Claims.Private.ExpirationDate);
if (claim is null)
{
@ -1058,8 +1308,13 @@ public static class OpenIddictExtensions
/// <param name="principal">The claims principal.</param>
/// <param name="audience">The audience.</param>
/// <returns><see langword="true"/> if the principal contains the given audience.</returns>
public static bool HasAudience(this ClaimsPrincipal principal!!, string audience)
public static bool HasAudience(this ClaimsPrincipal principal, string audience)
{
if (principal is null)
{
throw new ArgumentNullException(nameof(principal));
}
if (string.IsNullOrEmpty(audience))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0186), nameof(audience));
@ -1074,8 +1329,13 @@ public static class OpenIddictExtensions
/// <param name="principal">The claims principal.</param>
/// <param name="presenter">The presenter.</param>
/// <returns><see langword="true"/> if the principal contains the given presenter.</returns>
public static bool HasPresenter(this ClaimsPrincipal principal!!, string presenter)
public static bool HasPresenter(this ClaimsPrincipal principal, string presenter)
{
if (principal is null)
{
throw new ArgumentNullException(nameof(principal));
}
if (string.IsNullOrEmpty(presenter))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0187), nameof(presenter));
@ -1090,8 +1350,13 @@ public static class OpenIddictExtensions
/// <param name="principal">The claims principal.</param>
/// <param name="resource">The resource.</param>
/// <returns><see langword="true"/> if the principal contains the given resource.</returns>
public static bool HasResource(this ClaimsPrincipal principal!!, string resource)
public static bool HasResource(this ClaimsPrincipal principal, string resource)
{
if (principal is null)
{
throw new ArgumentNullException(nameof(principal));
}
if (string.IsNullOrEmpty(resource))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0062), nameof(resource));
@ -1106,8 +1371,13 @@ public static class OpenIddictExtensions
/// <param name="principal">The claims principal.</param>
/// <param name="scope">The scope.</param>
/// <returns><see langword="true"/> if the principal contains the given scope.</returns>
public static bool HasScope(this ClaimsPrincipal principal!!, string scope)
public static bool HasScope(this ClaimsPrincipal principal, string scope)
{
if (principal is null)
{
throw new ArgumentNullException(nameof(principal));
}
if (string.IsNullOrEmpty(scope))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0180), nameof(scope));
@ -1122,8 +1392,13 @@ public static class OpenIddictExtensions
/// <param name="principal">The claims principal.</param>
/// <param name="type">The token type.</param>
/// <returns><see langword="true"/> if the token type matches the specified type.</returns>
public static bool HasTokenType(this ClaimsPrincipal principal!!, string type)
public static bool HasTokenType(this ClaimsPrincipal principal, string type)
{
if (principal is null)
{
throw new ArgumentNullException(nameof(principal));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0188), nameof(type));
@ -1477,8 +1752,13 @@ public static class OpenIddictExtensions
return false;
}
private static TimeSpan? GetLifetime(ClaimsPrincipal principal!!, string type)
private static TimeSpan? GetLifetime(ClaimsPrincipal principal, string type)
{
if (principal is null)
{
throw new ArgumentNullException(nameof(principal));
}
var value = principal.GetClaim(type);
if (string.IsNullOrEmpty(value))
{

42
src/OpenIddict.Abstractions/Primitives/OpenIddictMessage.cs

@ -74,8 +74,13 @@ public class OpenIddictMessage
/// </summary>
/// <param name="parameters">The message parameters.</param>
/// <remarks>Parameters with a null or empty key are always ignored.</remarks>
public OpenIddictMessage(JsonObject parameters!!)
public OpenIddictMessage(JsonObject parameters)
{
if (parameters is null)
{
throw new ArgumentNullException(nameof(parameters));
}
foreach (var parameter in parameters)
{
// Ignore parameters whose name is null or empty.
@ -101,8 +106,13 @@ public class OpenIddictMessage
/// </summary>
/// <param name="parameters">The message parameters.</param>
/// <remarks>Parameters with a null or empty key are always ignored.</remarks>
public OpenIddictMessage(IEnumerable<KeyValuePair<string, OpenIddictParameter>> parameters!!)
public OpenIddictMessage(IEnumerable<KeyValuePair<string, OpenIddictParameter>> parameters)
{
if (parameters is null)
{
throw new ArgumentNullException(nameof(parameters));
}
foreach (var parameter in parameters)
{
// Ignore parameters whose name is null or empty.
@ -120,8 +130,13 @@ public class OpenIddictMessage
/// </summary>
/// <param name="parameters">The message parameters.</param>
/// <remarks>Parameters with a null or empty key are always ignored.</remarks>
public OpenIddictMessage(IEnumerable<KeyValuePair<string, string?>> parameters!!)
public OpenIddictMessage(IEnumerable<KeyValuePair<string, string?>> parameters)
{
if (parameters is null)
{
throw new ArgumentNullException(nameof(parameters));
}
foreach (var parameter in parameters.GroupBy(parameter => parameter.Key))
{
// Ignore parameters whose name is null or empty.
@ -150,8 +165,13 @@ public class OpenIddictMessage
/// </summary>
/// <param name="parameters">The message parameters.</param>
/// <remarks>Parameters with a null or empty key are always ignored.</remarks>
public OpenIddictMessage(IEnumerable<KeyValuePair<string, string?[]?>> parameters!!)
public OpenIddictMessage(IEnumerable<KeyValuePair<string, string?[]?>> parameters)
{
if (parameters is null)
{
throw new ArgumentNullException(nameof(parameters));
}
foreach (var parameter in parameters)
{
// Ignore parameters whose name is null or empty.
@ -178,8 +198,13 @@ public class OpenIddictMessage
/// </summary>
/// <param name="parameters">The message parameters.</param>
/// <remarks>Parameters with a null or empty key are always ignored.</remarks>
public OpenIddictMessage(IEnumerable<KeyValuePair<string, StringValues>> parameters!!)
public OpenIddictMessage(IEnumerable<KeyValuePair<string, StringValues>> parameters)
{
if (parameters is null)
{
throw new ArgumentNullException(nameof(parameters));
}
foreach (var parameter in parameters)
{
// Ignore parameters whose name is null or empty.
@ -387,8 +412,13 @@ public class OpenIddictMessage
/// Writes the message to the specified JSON writer.
/// </summary>
/// <param name="writer">The UTF-8 JSON writer.</param>
public void WriteTo(Utf8JsonWriter writer!!)
public void WriteTo(Utf8JsonWriter writer)
{
if (writer is null)
{
throw new ArgumentNullException(nameof(writer));
}
writer.WriteStartObject();
foreach (var parameter in Parameters)

7
src/OpenIddict.Abstractions/Primitives/OpenIddictParameter.cs

@ -695,8 +695,13 @@ public readonly struct OpenIddictParameter : IEquatable<OpenIddictParameter>
/// Writes the parameter value to the specified JSON writer.
/// </summary>
/// <param name="writer">The UTF-8 JSON writer.</param>
public void WriteTo(Utf8JsonWriter writer!!)
public void WriteTo(Utf8JsonWriter writer)
{
if (writer is null)
{
throw new ArgumentNullException(nameof(writer));
}
switch (Value)
{
// Note: undefined JsonElement values are assimilated to null values.

11
src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreBuilder.cs

@ -20,8 +20,8 @@ public class OpenIddictClientAspNetCoreBuilder
/// Initializes a new instance of <see cref="OpenIddictClientAspNetCoreBuilder"/>.
/// </summary>
/// <param name="services">The services collection.</param>
public OpenIddictClientAspNetCoreBuilder(IServiceCollection services!!)
=> Services = services;
public OpenIddictClientAspNetCoreBuilder(IServiceCollection services)
=> Services = services ?? throw new ArgumentNullException(nameof(services));
/// <summary>
/// Gets the services collection.
@ -35,8 +35,13 @@ public class OpenIddictClientAspNetCoreBuilder
/// <param name="configuration">The delegate used to configure the OpenIddict options.</param>
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictClientAspNetCoreBuilder"/>.</returns>
public OpenIddictClientAspNetCoreBuilder Configure(Action<OpenIddictClientAspNetCoreOptions> configuration!!)
public OpenIddictClientAspNetCoreBuilder Configure(Action<OpenIddictClientAspNetCoreOptions> configuration)
{
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
Services.Configure(configuration);
return this;

21
src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreConfiguration.cs

@ -19,8 +19,13 @@ public class OpenIddictClientAspNetCoreConfiguration : IConfigureOptions<Authent
/// Registers the OpenIddict client handler in the global authentication options.
/// </summary>
/// <param name="options">The options instance to initialize.</param>
public void Configure(AuthenticationOptions options!!)
public void Configure(AuthenticationOptions options)
{
if (options is null)
{
throw new ArgumentNullException(nameof(options));
}
// If a handler was already registered and the type doesn't correspond to the OpenIddict handler, throw an exception.
if (options.SchemeMap.TryGetValue(OpenIddictClientAspNetCoreDefaults.AuthenticationScheme, out var builder) &&
builder.HandlerType != typeof(OpenIddictClientAspNetCoreHandler))
@ -32,8 +37,13 @@ public class OpenIddictClientAspNetCoreConfiguration : IConfigureOptions<Authent
OpenIddictClientAspNetCoreDefaults.AuthenticationScheme, displayName: null);
}
public void Configure(OpenIddictClientOptions options!!)
public void Configure(OpenIddictClientOptions options)
{
if (options is null)
{
throw new ArgumentNullException(nameof(options));
}
// Register the built-in event handlers used by the OpenIddict ASP.NET Core client components.
options.Handlers.AddRange(OpenIddictClientAspNetCoreHandlers.DefaultHandlers);
}
@ -43,8 +53,13 @@ public class OpenIddictClientAspNetCoreConfiguration : IConfigureOptions<Authent
/// </summary>
/// <param name="name">The authentication scheme associated with the handler instance.</param>
/// <param name="options">The options instance to initialize.</param>
public void PostConfigure(string name, AuthenticationOptions options!!)
public void PostConfigure(string name, AuthenticationOptions options)
{
if (options is null)
{
throw new ArgumentNullException(nameof(options));
}
if (!TryValidate(options.SchemeMap, options.DefaultAuthenticateScheme) ||
!TryValidate(options.SchemeMap, options.DefaultScheme) ||
!TryValidate(options.SchemeMap, options.DefaultSignInScheme) ||

19
src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreExtensions.cs

@ -22,8 +22,13 @@ public static class OpenIddictClientAspNetCoreExtensions
/// <param name="builder">The services builder used by OpenIddict to register new services.</param>
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictClientAspNetCoreBuilder"/>.</returns>
public static OpenIddictClientAspNetCoreBuilder UseAspNetCore(this OpenIddictClientBuilder builder!!)
public static OpenIddictClientAspNetCoreBuilder UseAspNetCore(this OpenIddictClientBuilder builder)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Services.AddAuthentication();
builder.Services.TryAddScoped<OpenIddictClientAspNetCoreHandler>();
@ -59,8 +64,18 @@ public static class OpenIddictClientAspNetCoreExtensions
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
public static OpenIddictClientBuilder UseAspNetCore(
this OpenIddictClientBuilder builder!!, Action<OpenIddictClientAspNetCoreBuilder> configuration!!)
this OpenIddictClientBuilder builder, Action<OpenIddictClientAspNetCoreBuilder> configuration)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
configuration(builder.UseAspNetCore());
return builder;

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

@ -27,16 +27,16 @@ public class OpenIddictClientAspNetCoreHandler : AuthenticationHandler<OpenIddic
/// Creates a new instance of the <see cref="OpenIddictClientAspNetCoreHandler"/> class.
/// </summary>
public OpenIddictClientAspNetCoreHandler(
IOpenIddictClientDispatcher dispatcher!!,
IOpenIddictClientFactory factory!!,
IOptionsMonitor<OpenIddictClientAspNetCoreOptions> options!!,
ILoggerFactory logger!!,
UrlEncoder encoder!!,
ISystemClock clock!!)
IOpenIddictClientDispatcher dispatcher,
IOpenIddictClientFactory factory,
IOptionsMonitor<OpenIddictClientAspNetCoreOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock)
: base(options, logger, encoder, clock)
{
_dispatcher = dispatcher;
_factory = factory;
_dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
_factory = factory ?? throw new ArgumentNullException(nameof(factory));
}
/// <inheritdoc/>

56
src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandlerFilters.cs

@ -24,11 +24,18 @@ public static class OpenIddictClientAspNetCoreHandlerFilters
{
private readonly IOptionsMonitor<OpenIddictClientAspNetCoreOptions> _options;
public RequireRedirectionEndpointPassthroughEnabled(IOptionsMonitor<OpenIddictClientAspNetCoreOptions> options!!)
=> _options = options;
public RequireRedirectionEndpointPassthroughEnabled(IOptionsMonitor<OpenIddictClientAspNetCoreOptions> options)
=> _options = options ?? throw new ArgumentNullException(nameof(options));
public ValueTask<bool> IsActiveAsync(BaseContext context!!)
=> new(_options.CurrentValue.EnableRedirectionEndpointPassthrough);
public ValueTask<bool> IsActiveAsync(BaseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(_options.CurrentValue.EnableRedirectionEndpointPassthrough);
}
}
/// <summary>
@ -38,11 +45,18 @@ public static class OpenIddictClientAspNetCoreHandlerFilters
{
private readonly IOptionsMonitor<OpenIddictClientAspNetCoreOptions> _options;
public RequireErrorPassthroughEnabled(IOptionsMonitor<OpenIddictClientAspNetCoreOptions> options!!)
=> _options = options;
public RequireErrorPassthroughEnabled(IOptionsMonitor<OpenIddictClientAspNetCoreOptions> options)
=> _options = options ?? throw new ArgumentNullException(nameof(options));
public ValueTask<bool> IsActiveAsync(BaseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
public ValueTask<bool> IsActiveAsync(BaseContext context!!)
=> new(_options.CurrentValue.EnableErrorPassthrough);
return new(_options.CurrentValue.EnableErrorPassthrough);
}
}
/// <summary>
@ -50,8 +64,15 @@ public static class OpenIddictClientAspNetCoreHandlerFilters
/// </summary>
public class RequireHttpRequest : IOpenIddictClientHandlerFilter<BaseContext>
{
public ValueTask<bool> IsActiveAsync(BaseContext context!!)
=> new(context.Transaction.GetHttpRequest() is not null);
public ValueTask<bool> IsActiveAsync(BaseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(context.Transaction.GetHttpRequest() is not null);
}
}
/// <summary>
@ -61,10 +82,17 @@ public static class OpenIddictClientAspNetCoreHandlerFilters
{
private readonly IOptionsMonitor<OpenIddictClientAspNetCoreOptions> _options;
public RequireStatusCodePagesIntegrationEnabled(IOptionsMonitor<OpenIddictClientAspNetCoreOptions> options!!)
=> _options = options;
public RequireStatusCodePagesIntegrationEnabled(IOptionsMonitor<OpenIddictClientAspNetCoreOptions> options)
=> _options = options ?? throw new ArgumentNullException(nameof(options));
public ValueTask<bool> IsActiveAsync(BaseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
public ValueTask<bool> IsActiveAsync(BaseContext context!!)
=> new(_options.CurrentValue.EnableStatusCodePagesIntegration);
return new(_options.CurrentValue.EnableStatusCodePagesIntegration);
}
}
}

7
src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandlers.Authentication.cs

@ -57,8 +57,13 @@ public static partial class OpenIddictClientAspNetCoreHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ApplyAuthorizationRequestContext context!!)
public ValueTask HandleAsync(ApplyAuthorizationRequestContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// 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.
var response = context.Transaction.GetHttpRequest()?.HttpContext.Response ??

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

@ -61,8 +61,13 @@ public static partial class OpenIddictClientAspNetCoreHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessRequestContext context!!)
public ValueTask HandleAsync(ProcessRequestContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// 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.
var request = context.Transaction.GetHttpRequest() ??
@ -145,8 +150,13 @@ public static partial class OpenIddictClientAspNetCoreHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(TContext context!!)
public async ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// 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.
var request = context.Transaction.GetHttpRequest() ??
@ -210,8 +220,8 @@ public static partial class OpenIddictClientAspNetCoreHandlers
{
private readonly IOptionsMonitor<OpenIddictClientAspNetCoreOptions> _options;
public ValidateCorrelationCookie(IOptionsMonitor<OpenIddictClientAspNetCoreOptions> options!!)
=> _options = options;
public ValidateCorrelationCookie(IOptionsMonitor<OpenIddictClientAspNetCoreOptions> options)
=> _options = options ?? throw new ArgumentNullException(nameof(options));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -226,8 +236,13 @@ public static partial class OpenIddictClientAspNetCoreHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.StateTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// This handler only applies to ASP.NET Core requests. If the HTTP context cannot be resolved,
@ -299,8 +314,13 @@ public static partial class OpenIddictClientAspNetCoreHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessChallengeContext context!!)
public ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
var properties = context.Transaction.GetProperty<AuthenticationProperties>(typeof(AuthenticationProperties).FullName!);
if (properties is null)
{
@ -356,8 +376,8 @@ public static partial class OpenIddictClientAspNetCoreHandlers
{
private readonly IOptionsMonitor<OpenIddictClientAspNetCoreOptions> _options;
public GenerateCorrelationCookie(IOptionsMonitor<OpenIddictClientAspNetCoreOptions> options!!)
=> _options = options;
public GenerateCorrelationCookie(IOptionsMonitor<OpenIddictClientAspNetCoreOptions> options)
=> _options = options ?? throw new ArgumentNullException(nameof(options));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -372,8 +392,13 @@ public static partial class OpenIddictClientAspNetCoreHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessChallengeContext context!!)
public ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// Note: using a correlation cookie serves as an antiforgery protection as the request will
// always be rejected if a cookie corresponding to the request forgery protection claim
// persisted in the state token cannot be found. This protection is considered essential
@ -437,8 +462,13 @@ public static partial class OpenIddictClientAspNetCoreHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(TContext context!!)
public ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
context.SkipRequest();
return default;
@ -463,8 +493,13 @@ public static partial class OpenIddictClientAspNetCoreHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(TContext context!!)
public ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// 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.
var response = context.Transaction.GetHttpRequest()?.HttpContext.Response ??
@ -501,8 +536,13 @@ public static partial class OpenIddictClientAspNetCoreHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(TContext context!!)
public ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// 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.
var response = context.Transaction.GetHttpRequest()?.HttpContext.Response ??
@ -540,8 +580,13 @@ public static partial class OpenIddictClientAspNetCoreHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(TContext context!!)
public ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Transaction.Response is not null, SR.GetResourceString(SR.ID4007));
if (string.IsNullOrEmpty(context.Transaction.Response.Error))
@ -575,8 +620,13 @@ public static partial class OpenIddictClientAspNetCoreHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(TContext context!!)
public ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// 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.
var response = context.Transaction.GetHttpRequest()?.HttpContext.Response ??
@ -626,8 +676,13 @@ public static partial class OpenIddictClientAspNetCoreHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(TContext context!!)
public async ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// 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.
var response = context.Transaction.GetHttpRequest()?.HttpContext.Response ??
@ -695,8 +750,13 @@ public static partial class OpenIddictClientAspNetCoreHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(TContext context!!)
public ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
context.Logger.LogInformation(SR.GetResourceString(SR.ID6145));
context.HandleRequest();

56
src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHelpers.cs

@ -19,32 +19,68 @@ public static class OpenIddictClientAspNetCoreHelpers
/// </summary>
/// <param name="transaction">The transaction instance.</param>
/// <returns>The <see cref="HttpRequest"/> instance or <see langword="null"/> if it couldn't be found.</returns>
public static HttpRequest? GetHttpRequest(this OpenIddictClientTransaction transaction!!)
=> transaction.Properties.TryGetValue(typeof(HttpRequest).FullName!, out object? property) &&
property is WeakReference<HttpRequest> reference &&
reference.TryGetTarget(out HttpRequest? request) ? request : null;
public static HttpRequest? GetHttpRequest(this OpenIddictClientTransaction transaction)
{
if (transaction is null)
{
throw new ArgumentNullException(nameof(transaction));
}
if (!transaction.Properties.TryGetValue(typeof(HttpRequest).FullName!, out object? property))
{
return null;
}
if (property is WeakReference<HttpRequest> reference && reference.TryGetTarget(out HttpRequest? request))
{
return request;
}
return null;
}
/// <summary>
/// Retrieves the <see cref="OpenIddictClientEndpointType"/> instance stored in <see cref="BaseContext"/>.
/// </summary>
/// <param name="context">The context instance.</param>
/// <returns>The <see cref="OpenIddictClientEndpointType"/>.</returns>
public static OpenIddictClientEndpointType GetOpenIddictClientEndpointType(this HttpContext context!!)
=> context.Features.Get<OpenIddictClientAspNetCoreFeature>()?.Transaction?.EndpointType ?? default;
public static OpenIddictClientEndpointType GetOpenIddictClientEndpointType(this HttpContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return context.Features.Get<OpenIddictClientAspNetCoreFeature>()?.Transaction?.EndpointType ?? default;
}
/// <summary>
/// Retrieves the <see cref="OpenIddictRequest"/> instance stored in <see cref="BaseContext"/>.
/// </summary>
/// <param name="context">The context instance.</param>
/// <returns>The <see cref="OpenIddictRequest"/> instance or <see langword="null"/> if it couldn't be found.</returns>
public static OpenIddictRequest? GetOpenIddictClientRequest(this HttpContext context!!)
=> context.Features.Get<OpenIddictClientAspNetCoreFeature>()?.Transaction?.Request;
public static OpenIddictRequest? GetOpenIddictClientRequest(this HttpContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return context.Features.Get<OpenIddictClientAspNetCoreFeature>()?.Transaction?.Request;
}
/// <summary>
/// Retrieves the <see cref="OpenIddictResponse"/> instance stored in <see cref="BaseContext"/>.
/// </summary>
/// <param name="context">The context instance.</param>
/// <returns>The <see cref="OpenIddictResponse"/> instance or <see langword="null"/> if it couldn't be found.</returns>
public static OpenIddictResponse? GetOpenIddictClientResponse(this HttpContext context!!)
=> context.Features.Get<OpenIddictClientAspNetCoreFeature>()?.Transaction?.Response;
public static OpenIddictResponse? GetOpenIddictClientResponse(this HttpContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return context.Features.Get<OpenIddictClientAspNetCoreFeature>()?.Transaction?.Response;
}
}

11
src/OpenIddict.Client.Owin/OpenIddictClientOwinBuilder.cs

@ -20,8 +20,8 @@ public class OpenIddictClientOwinBuilder
/// Initializes a new instance of <see cref="OpenIddictClientOwinBuilder"/>.
/// </summary>
/// <param name="services">The services collection.</param>
public OpenIddictClientOwinBuilder(IServiceCollection services!!)
=> Services = services;
public OpenIddictClientOwinBuilder(IServiceCollection services)
=> Services = services ?? throw new ArgumentNullException(nameof(services));
/// <summary>
/// Gets the services collection.
@ -35,8 +35,13 @@ public class OpenIddictClientOwinBuilder
/// <param name="configuration">The delegate used to configure the OpenIddict options.</param>
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictClientOwinBuilder"/>.</returns>
public OpenIddictClientOwinBuilder Configure(Action<OpenIddictClientOwinOptions> configuration!!)
public OpenIddictClientOwinBuilder Configure(Action<OpenIddictClientOwinOptions> configuration)
{
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
Services.Configure(configuration);
return this;

14
src/OpenIddict.Client.Owin/OpenIddictClientOwinConfiguration.cs

@ -14,14 +14,24 @@ namespace OpenIddict.Client.Owin;
public class OpenIddictClientOwinConfiguration : IConfigureOptions<OpenIddictClientOptions>,
IPostConfigureOptions<OpenIddictClientOwinOptions>
{
public void Configure(OpenIddictClientOptions options!!)
public void Configure(OpenIddictClientOptions options)
{
if (options is null)
{
throw new ArgumentNullException(nameof(options));
}
// Register the built-in event handlers used by the OpenIddict OWIN Client components.
options.Handlers.AddRange(OpenIddictClientOwinHandlers.DefaultHandlers);
}
public void PostConfigure(string name, OpenIddictClientOwinOptions options!!)
public void PostConfigure(string name, OpenIddictClientOwinOptions options)
{
if (options is null)
{
throw new ArgumentNullException(nameof(options));
}
if (options.AuthenticationMode is AuthenticationMode.Active)
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0314));

19
src/OpenIddict.Client.Owin/OpenIddictClientOwinExtensions.cs

@ -22,8 +22,13 @@ public static class OpenIddictClientOwinExtensions
/// <param name="builder">The services builder used by OpenIddict to register new services.</param>
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictClientOwinBuilder"/>.</returns>
public static OpenIddictClientOwinBuilder UseOwin(this OpenIddictClientBuilder builder!!)
public static OpenIddictClientOwinBuilder UseOwin(this OpenIddictClientBuilder builder)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Services.AddWebEncoders();
// Note: unlike regular OWIN middleware, the OpenIddict client middleware is registered
@ -59,8 +64,18 @@ public static class OpenIddictClientOwinExtensions
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
public static OpenIddictClientBuilder UseOwin(
this OpenIddictClientBuilder builder!!, Action<OpenIddictClientOwinBuilder> configuration!!)
this OpenIddictClientBuilder builder, Action<OpenIddictClientOwinBuilder> configuration)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
configuration(builder.UseOwin());
return builder;

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

@ -26,11 +26,11 @@ public class OpenIddictClientOwinHandler : AuthenticationHandler<OpenIddictClien
/// <param name="dispatcher">The OpenIddict client dispatcher used by this instance.</param>
/// <param name="factory">The OpenIddict client factory used by this instance.</param>
public OpenIddictClientOwinHandler(
IOpenIddictClientDispatcher dispatcher!!,
IOpenIddictClientFactory factory!!)
IOpenIddictClientDispatcher dispatcher,
IOpenIddictClientFactory factory)
{
_dispatcher = dispatcher;
_factory = factory;
_dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
_factory = factory ?? throw new ArgumentNullException(nameof(factory));
}
/// <inheritdoc/>

41
src/OpenIddict.Client.Owin/OpenIddictClientOwinHandlerFilters.cs

@ -24,11 +24,18 @@ public static class OpenIddictClientOwinHandlerFilters
{
private readonly IOptionsMonitor<OpenIddictClientOwinOptions> _options;
public RequireRedirectionEndpointPassthroughEnabled(IOptionsMonitor<OpenIddictClientOwinOptions> options!!)
=> _options = options;
public RequireRedirectionEndpointPassthroughEnabled(IOptionsMonitor<OpenIddictClientOwinOptions> options)
=> _options = options ?? throw new ArgumentNullException(nameof(options));
public ValueTask<bool> IsActiveAsync(BaseContext context!!)
=> new(_options.CurrentValue.EnableRedirectionEndpointPassthrough);
public ValueTask<bool> IsActiveAsync(BaseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(_options.CurrentValue.EnableRedirectionEndpointPassthrough);
}
}
/// <summary>
@ -38,11 +45,18 @@ public static class OpenIddictClientOwinHandlerFilters
{
private readonly IOptionsMonitor<OpenIddictClientOwinOptions> _options;
public RequireErrorPassthroughEnabled(IOptionsMonitor<OpenIddictClientOwinOptions> options!!)
=> _options = options;
public RequireErrorPassthroughEnabled(IOptionsMonitor<OpenIddictClientOwinOptions> options)
=> _options = options ?? throw new ArgumentNullException(nameof(options));
public ValueTask<bool> IsActiveAsync(BaseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
public ValueTask<bool> IsActiveAsync(BaseContext context!!)
=> new(_options.CurrentValue.EnableErrorPassthrough);
return new(_options.CurrentValue.EnableErrorPassthrough);
}
}
/// <summary>
@ -50,7 +64,14 @@ public static class OpenIddictClientOwinHandlerFilters
/// </summary>
public class RequireOwinRequest : IOpenIddictClientHandlerFilter<BaseContext>
{
public ValueTask<bool> IsActiveAsync(BaseContext context!!)
=> new(context.Transaction.GetOwinRequest() is not null);
public ValueTask<bool> IsActiveAsync(BaseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(context.Transaction.GetOwinRequest() is not null);
}
}
}

7
src/OpenIddict.Client.Owin/OpenIddictClientOwinHandlers.Authentication.cs

@ -55,8 +55,13 @@ public static partial class OpenIddictClientOwinHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ApplyAuthorizationRequestContext context!!)
public ValueTask HandleAsync(ApplyAuthorizationRequestContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// This handler only applies to OWIN requests. If the HTTP context cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack.
var response = context.Transaction.GetOwinRequest()?.Context.Response ??

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

@ -58,8 +58,13 @@ public static partial class OpenIddictClientOwinHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessRequestContext context!!)
public ValueTask HandleAsync(ProcessRequestContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// 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.
var request = context.Transaction.GetOwinRequest() ??
@ -142,8 +147,13 @@ public static partial class OpenIddictClientOwinHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(TContext context!!)
public async ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// 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.
var request = context.Transaction.GetOwinRequest() ??
@ -207,8 +217,8 @@ public static partial class OpenIddictClientOwinHandlers
{
private readonly IOptionsMonitor<OpenIddictClientOwinOptions> _options;
public ValidateCorrelationCookie(IOptionsMonitor<OpenIddictClientOwinOptions> options!!)
=> _options = options;
public ValidateCorrelationCookie(IOptionsMonitor<OpenIddictClientOwinOptions> options)
=> _options = options ?? throw new ArgumentNullException(nameof(options));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -223,8 +233,13 @@ public static partial class OpenIddictClientOwinHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.StateTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// This handler only applies to OWIN requests. If the HTTP context cannot be resolved,
@ -305,8 +320,13 @@ public static partial class OpenIddictClientOwinHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessChallengeContext context!!)
public ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
var properties = context.Transaction.GetProperty<AuthenticationProperties>(typeof(AuthenticationProperties).FullName!);
if (properties is null)
{
@ -343,8 +363,8 @@ public static partial class OpenIddictClientOwinHandlers
{
private readonly IOptionsMonitor<OpenIddictClientOwinOptions> _options;
public GenerateCorrelationCookie(IOptionsMonitor<OpenIddictClientOwinOptions> options!!)
=> _options = options;
public GenerateCorrelationCookie(IOptionsMonitor<OpenIddictClientOwinOptions> options)
=> _options = options ?? throw new ArgumentNullException(nameof(options));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -359,8 +379,13 @@ public static partial class OpenIddictClientOwinHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessChallengeContext context!!)
public ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// Note: using a correlation cookie serves as an antiforgery protection as the request will
// always be rejected if a cookie corresponding to the request forgery protection claim
// persisted in the state token cannot be found. This protection is considered essential
@ -433,8 +458,13 @@ public static partial class OpenIddictClientOwinHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(TContext context!!)
public ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
context.SkipRequest();
return default;
@ -459,8 +489,13 @@ public static partial class OpenIddictClientOwinHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(TContext context!!)
public ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// This handler only applies to OWIN requests. If the HTTP context cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack.
var response = context.Transaction.GetOwinRequest()?.Context.Response ??
@ -497,8 +532,13 @@ public static partial class OpenIddictClientOwinHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(TContext context!!)
public ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// This handler only applies to OWIN requests. If the HTTP context cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack.
var response = context.Transaction.GetOwinRequest()?.Context.Response ??
@ -536,8 +576,13 @@ public static partial class OpenIddictClientOwinHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(TContext context!!)
public ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Transaction.Response is not null, SR.GetResourceString(SR.ID4007));
if (string.IsNullOrEmpty(context.Transaction.Response.Error))
@ -570,8 +615,13 @@ public static partial class OpenIddictClientOwinHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(TContext context!!)
public async ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// This handler only applies to OWIN requests. If the HTTP context cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack.
var response = context.Transaction.GetOwinRequest()?.Context.Response ??
@ -639,8 +689,13 @@ public static partial class OpenIddictClientOwinHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(TContext context!!)
public ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
context.Logger.LogInformation(SR.GetResourceString(SR.ID6145));
context.HandleRequest();

67
src/OpenIddict.Client.Owin/OpenIddictClientOwinHelpers.cs

@ -21,40 +21,83 @@ public static class OpenIddictClientOwinHelpers
/// </summary>
/// <param name="app">The application builder used to register middleware instances.</param>
/// <returns>The <see cref="IAppBuilder"/>.</returns>
public static IAppBuilder UseOpenIddictClient(this IAppBuilder app!!)
=> app.Use<OpenIddictClientOwinMiddlewareFactory>();
public static IAppBuilder UseOpenIddictClient(this IAppBuilder app)
{
if (app is null)
{
throw new ArgumentNullException(nameof(app));
}
return app.Use<OpenIddictClientOwinMiddlewareFactory>();
}
/// <summary>
/// Retrieves the <see cref="IOwinRequest"/> instance stored in the <see cref="OpenIddictClientTransaction"/> properties.
/// </summary>
/// <param name="transaction">The transaction instance.</param>
/// <returns>The <see cref="IOwinRequest"/> instance or <see langword="null"/> if it couldn't be found.</returns>
public static IOwinRequest? GetOwinRequest(this OpenIddictClientTransaction transaction!!)
=> transaction.Properties.TryGetValue(typeof(IOwinRequest).FullName!, out object? property) &&
property is WeakReference<IOwinRequest> reference &&
reference.TryGetTarget(out IOwinRequest? request) ? request : null;
public static IOwinRequest? GetOwinRequest(this OpenIddictClientTransaction transaction)
{
if (transaction is null)
{
throw new ArgumentNullException(nameof(transaction));
}
if (!transaction.Properties.TryGetValue(typeof(IOwinRequest).FullName!, out object? property))
{
return null;
}
if (property is WeakReference<IOwinRequest> reference && reference.TryGetTarget(out IOwinRequest? request))
{
return request;
}
return null;
}
/// <summary>
/// Retrieves the <see cref="OpenIddictClientEndpointType"/> instance stored in <see cref="BaseContext"/>.
/// </summary>
/// <param name="context">The context instance.</param>
/// <returns>The <see cref="OpenIddictClientEndpointType"/>.</returns>
public static OpenIddictClientEndpointType GetOpenIddictClientEndpointType(this IOwinContext context!!)
=> context.Get<OpenIddictClientTransaction>(typeof(OpenIddictClientTransaction).FullName)?.EndpointType ?? default;
public static OpenIddictClientEndpointType GetOpenIddictClientEndpointType(this IOwinContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return context.Get<OpenIddictClientTransaction>(typeof(OpenIddictClientTransaction).FullName)?.EndpointType ?? default;
}
/// <summary>
/// Retrieves the <see cref="OpenIddictRequest"/> instance stored in <see cref="BaseContext"/>.
/// </summary>
/// <param name="context">The context instance.</param>
/// <returns>The <see cref="OpenIddictRequest"/> instance or <see langword="null"/> if it couldn't be found.</returns>
public static OpenIddictRequest? GetOpenIddictClientRequest(this IOwinContext context!!)
=> context.Get<OpenIddictClientTransaction>(typeof(OpenIddictClientTransaction).FullName)?.Request;
public static OpenIddictRequest? GetOpenIddictClientRequest(this IOwinContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return context.Get<OpenIddictClientTransaction>(typeof(OpenIddictClientTransaction).FullName)?.Request;
}
/// <summary>
/// Retrieves the <see cref="OpenIddictResponse"/> instance stored in <see cref="BaseContext"/>.
/// </summary>
/// <param name="context">The context instance.</param>
/// <returns>The <see cref="OpenIddictResponse"/> instance or <see langword="null"/> if it couldn't be found.</returns>
public static OpenIddictResponse? GetOpenIddictClientResponse(this IOwinContext context!!)
=> context.Get<OpenIddictClientTransaction>(typeof(OpenIddictClientTransaction).FullName)?.Response;
public static OpenIddictResponse? GetOpenIddictClientResponse(this IOwinContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return context.Get<OpenIddictClientTransaction>(typeof(OpenIddictClientTransaction).FullName)?.Response;
}
}

10
src/OpenIddict.Client.Owin/OpenIddictClientOwinMiddleware.cs

@ -29,13 +29,13 @@ public class OpenIddictClientOwinMiddleware : AuthenticationMiddleware<OpenIddic
/// <param name="factory">The OpenIddict client factory.</param>
public OpenIddictClientOwinMiddleware(
OwinMiddleware? next,
IOptionsMonitor<OpenIddictClientOwinOptions> options!!,
IOpenIddictClientDispatcher dispatcher!!,
IOpenIddictClientFactory factory!!)
IOptionsMonitor<OpenIddictClientOwinOptions> options,
IOpenIddictClientDispatcher dispatcher,
IOpenIddictClientFactory factory)
: base(next, options.CurrentValue)
{
_dispatcher = dispatcher;
_factory = factory;
_dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
_factory = factory ?? throw new ArgumentNullException(nameof(factory));
}
/// <summary>

7
src/OpenIddict.Client.Owin/OpenIddictClientOwinMiddlewareFactory.cs

@ -33,8 +33,13 @@ public class OpenIddictClientOwinMiddlewareFactory : OwinMiddleware
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public override Task Invoke(IOwinContext context!!)
public override Task Invoke(IOwinContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
var provider = context.Get<IServiceProvider>(typeof(IServiceProvider).FullName) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0316));

11
src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpBuilder.cs

@ -19,8 +19,8 @@ public class OpenIddictClientSystemNetHttpBuilder
/// Initializes a new instance of <see cref="OpenIddictClientBuilder"/>.
/// </summary>
/// <param name="services">The services collection.</param>
public OpenIddictClientSystemNetHttpBuilder(IServiceCollection services!!)
=> Services = services;
public OpenIddictClientSystemNetHttpBuilder(IServiceCollection services)
=> Services = services ?? throw new ArgumentNullException(nameof(services));
/// <summary>
/// Gets the services collection.
@ -34,8 +34,13 @@ public class OpenIddictClientSystemNetHttpBuilder
/// <param name="configuration">The delegate used to configure the OpenIddict options.</param>
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictClientSystemNetHttpBuilder"/>.</returns>
public OpenIddictClientSystemNetHttpBuilder Configure(Action<OpenIddictClientSystemNetHttpOptions> configuration!!)
public OpenIddictClientSystemNetHttpBuilder Configure(Action<OpenIddictClientSystemNetHttpOptions> configuration)
{
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
Services.Configure(configuration);
return this;

18
src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpConfiguration.cs

@ -21,12 +21,17 @@ public class OpenIddictClientSystemNetHttpConfiguration : IConfigureOptions<Open
#if !SUPPORTS_SERVICE_PROVIDER_IN_HTTP_MESSAGE_HANDLER_BUILDER
private readonly IServiceProvider _serviceProvider;
public OpenIddictClientSystemNetHttpConfiguration(IServiceProvider serviceProvider!!)
=> _serviceProvider = serviceProvider;
public OpenIddictClientSystemNetHttpConfiguration(IServiceProvider serviceProvider)
=> _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
#endif
public void Configure(OpenIddictClientOptions options!!)
public void Configure(OpenIddictClientOptions options)
{
if (options is null)
{
throw new ArgumentNullException(nameof(options));
}
// Register the built-in event handlers used by the OpenIddict System.Net.Http client components.
options.Handlers.AddRange(OpenIddictClientSystemNetHttpHandlers.DefaultHandlers);
}
@ -34,8 +39,13 @@ public class OpenIddictClientSystemNetHttpConfiguration : IConfigureOptions<Open
public void Configure(HttpClientFactoryOptions options)
=> Debug.Fail("This infrastructure method shouldn't be called.");
public void Configure(string name, HttpClientFactoryOptions options!!)
public void Configure(string name, HttpClientFactoryOptions options)
{
if (options is null)
{
throw new ArgumentNullException(nameof(options));
}
var assembly = typeof(OpenIddictClientSystemNetHttpOptions).Assembly.GetName();
if (!string.Equals(name, assembly.Name, StringComparison.Ordinal))

19
src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpExtensions.cs

@ -23,8 +23,13 @@ public static class OpenIddictClientSystemNetHttpExtensions
/// <param name="builder">The services builder used by OpenIddict to register new services.</param>
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
public static OpenIddictClientSystemNetHttpBuilder UseSystemNetHttp(this OpenIddictClientBuilder builder!!)
public static OpenIddictClientSystemNetHttpBuilder UseSystemNetHttp(this OpenIddictClientBuilder builder)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Services.AddHttpClient();
// Register the built-in validation event handlers used by the OpenIddict System.Net.Http components.
@ -52,8 +57,18 @@ public static class OpenIddictClientSystemNetHttpExtensions
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
public static OpenIddictClientBuilder UseSystemNetHttp(
this OpenIddictClientBuilder builder!!, Action<OpenIddictClientSystemNetHttpBuilder> configuration!!)
this OpenIddictClientBuilder builder, Action<OpenIddictClientSystemNetHttpBuilder> configuration)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
configuration(builder.UseSystemNetHttp());
return builder;

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

@ -16,8 +16,16 @@ public static class OpenIddictClientSystemNetHttpHandlerFilters
/// </summary>
public class RequireHttpMetadataAddress : IOpenIddictClientHandlerFilter<BaseExternalContext>
{
public ValueTask<bool> IsActiveAsync(BaseExternalContext context!!)
=> new(string.Equals(context.Address?.Scheme, Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase) ||
string.Equals(context.Address?.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase));
public ValueTask<bool> IsActiveAsync(BaseExternalContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(
string.Equals(context.Address?.Scheme, Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase) ||
string.Equals(context.Address?.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase));
}
}
}

7
src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpHandlers.Exchange.cs

@ -48,8 +48,13 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(PrepareTokenRequestContext context!!)
public async ValueTask HandleAsync(PrepareTokenRequestContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Request is not null, SR.GetResourceString(SR.ID4008));
// This handler only applies to System.Net.Http requests. If the HTTP request cannot be resolved,

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

@ -47,8 +47,13 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(PrepareUserinfoRequestContext context!!)
public ValueTask HandleAsync(PrepareUserinfoRequestContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Request is not null, SR.GetResourceString(SR.ID4008));
// This handler only applies to System.Net.Http requests. If the HTTP request cannot be resolved,
@ -83,8 +88,13 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ExtractUserinfoResponseContext context!!)
public async ValueTask HandleAsync(ExtractUserinfoResponseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// This handler only applies to System.Net.Http requests. If the HTTP response cannot be resolved,
// this may indicate that the request was incorrectly processed by another client stack.
var response = context.Transaction.GetHttpResponseMessage() ??

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

@ -41,8 +41,13 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
/// <inheritdoc/>
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope",
Justification = "The HTTP request message is disposed later by a dedicated handler.")]
public ValueTask HandleAsync(TContext context!!)
public ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
var request = new HttpRequestMessage(HttpMethod.Get, context.Address)
{
Headers =
@ -78,8 +83,13 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
/// <inheritdoc/>
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope",
Justification = "The HTTP request message is disposed later by a dedicated handler.")]
public ValueTask HandleAsync(TContext context!!)
public ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
var request = new HttpRequestMessage(HttpMethod.Post, context.Address)
{
Headers =
@ -113,8 +123,13 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(TContext context!!)
public ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Transaction.Request is not null, SR.GetResourceString(SR.ID4008));
// This handler only applies to System.Net.Http requests. If the HTTP request cannot be resolved,
@ -171,8 +186,13 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(TContext context!!)
public ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Transaction.Request is not null, SR.GetResourceString(SR.ID4008));
// This handler only applies to System.Net.Http requests. If the HTTP request cannot be resolved,
@ -200,7 +220,7 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
private readonly IHttpClientFactory _factory;
public SendHttpRequest(IHttpClientFactory factory)
=> _factory = factory;
=> _factory = factory ?? throw new ArgumentNullException(nameof(factory));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -214,8 +234,13 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(TContext context!!)
public async ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// 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.
var request = context.Transaction.GetHttpRequestMessage() ??
@ -254,8 +279,13 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(TContext context!!)
public ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// 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.
var request = context.Transaction.GetHttpRequestMessage() ??
@ -287,8 +317,13 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(TContext context!!)
public async ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// This handler only applies to System.Net.Http requests. If the HTTP response cannot be resolved,
// this may indicate that the request was incorrectly processed by another client stack.
var response = context.Transaction.GetHttpResponseMessage() ??
@ -320,8 +355,13 @@ public static partial class OpenIddictClientSystemNetHttpHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(TContext context!!)
public ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// This handler only applies to System.Net.Http requests. If the HTTP response cannot be resolved,
// this may indicate that the request was incorrectly processed by another client stack.
var response = context.Transaction.GetHttpResponseMessage() ??

153
src/OpenIddict.Client/OpenIddictClientBuilder.cs

@ -25,8 +25,8 @@ public class OpenIddictClientBuilder
/// Initializes a new instance of <see cref="OpenIddictClientBuilder"/>.
/// </summary>
/// <param name="services">The services collection.</param>
public OpenIddictClientBuilder(IServiceCollection services!!)
=> Services = services;
public OpenIddictClientBuilder(IServiceCollection services)
=> Services = services ?? throw new ArgumentNullException(nameof(services));
/// <summary>
/// Gets the services collection.
@ -42,9 +42,14 @@ public class OpenIddictClientBuilder
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public OpenIddictClientBuilder AddEventHandler<TContext>(
Action<OpenIddictClientHandlerDescriptor.Builder<TContext>> configuration!!)
Action<OpenIddictClientHandlerDescriptor.Builder<TContext>> configuration)
where TContext : OpenIddictClientEvents.BaseContext
{
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
// Note: handlers registered using this API are assumed to be custom handlers by default.
var builder = OpenIddictClientHandlerDescriptor.CreateBuilder<TContext>()
.SetType(OpenIddictClientHandlerType.Custom);
@ -60,8 +65,13 @@ public class OpenIddictClientBuilder
/// <param name="descriptor">The handler descriptor.</param>
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public OpenIddictClientBuilder AddEventHandler(OpenIddictClientHandlerDescriptor descriptor!!)
public OpenIddictClientBuilder AddEventHandler(OpenIddictClientHandlerDescriptor descriptor)
{
if (descriptor is null)
{
throw new ArgumentNullException(nameof(descriptor));
}
// Register the handler in the services collection.
Services.Add(descriptor.ServiceDescriptor);
@ -74,8 +84,13 @@ public class OpenIddictClientBuilder
/// <param name="descriptor">The descriptor corresponding to the handler to remove.</param>
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public OpenIddictClientBuilder RemoveEventHandler(OpenIddictClientHandlerDescriptor descriptor!!)
public OpenIddictClientBuilder RemoveEventHandler(OpenIddictClientHandlerDescriptor descriptor)
{
if (descriptor is null)
{
throw new ArgumentNullException(nameof(descriptor));
}
Services.RemoveAll(descriptor.ServiceDescriptor.ServiceType);
Services.PostConfigure<OpenIddictClientOptions>(options =>
@ -98,8 +113,13 @@ public class OpenIddictClientBuilder
/// <param name="configuration">The delegate used to configure the OpenIddict options.</param>
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
public OpenIddictClientBuilder Configure(Action<OpenIddictClientOptions> configuration!!)
public OpenIddictClientBuilder Configure(Action<OpenIddictClientOptions> configuration)
{
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
Services.Configure(configuration);
return this;
@ -110,16 +130,28 @@ public class OpenIddictClientBuilder
/// </summary>
/// <param name="credentials">The encrypting credentials.</param>
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
public OpenIddictClientBuilder AddEncryptionCredentials(EncryptingCredentials credentials!!)
=> Configure(options => options.EncryptionCredentials.Add(credentials));
public OpenIddictClientBuilder AddEncryptionCredentials(EncryptingCredentials credentials)
{
if (credentials is null)
{
throw new ArgumentNullException(nameof(credentials));
}
return Configure(options => options.EncryptionCredentials.Add(credentials));
}
/// <summary>
/// Registers an encryption key.
/// </summary>
/// <param name="key">The security key.</param>
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
public OpenIddictClientBuilder AddEncryptionKey(SecurityKey key!!)
public OpenIddictClientBuilder AddEncryptionKey(SecurityKey key)
{
if (key is null)
{
throw new ArgumentNullException(nameof(key));
}
// If the encryption key is an asymmetric security key, ensure it has a private key.
if (key is AsymmetricSecurityKey asymmetricSecurityKey &&
asymmetricSecurityKey.PrivateKeyStatus is PrivateKeyStatus.DoesNotExist)
@ -161,8 +193,13 @@ public class OpenIddictClientBuilder
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope",
Justification = "The X.509 certificate is attached to the client options.")]
public OpenIddictClientBuilder AddDevelopmentEncryptionCertificate(X500DistinguishedName subject!!)
public OpenIddictClientBuilder AddDevelopmentEncryptionCertificate(X500DistinguishedName subject)
{
if (subject is null)
{
throw new ArgumentNullException(nameof(subject));
}
using var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadWrite);
@ -317,8 +354,13 @@ public class OpenIddictClientBuilder
/// </summary>
/// <param name="certificate">The encryption certificate.</param>
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
public OpenIddictClientBuilder AddEncryptionCertificate(X509Certificate2 certificate!!)
public OpenIddictClientBuilder AddEncryptionCertificate(X509Certificate2 certificate)
{
if (certificate is null)
{
throw new ArgumentNullException(nameof(certificate));
}
// If the certificate is a X.509v3 certificate that specifies at least one
// key usage, ensure that the certificate key can be used for key encryption.
if (certificate.Version >= 3)
@ -364,9 +406,14 @@ public class OpenIddictClientBuilder
/// <param name="flags">An enumeration of flags indicating how and where to store the private key of the certificate.</param>
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
public OpenIddictClientBuilder AddEncryptionCertificate(
Assembly assembly!!, string resource,
Assembly assembly, string resource,
string? password, X509KeyStorageFlags flags)
{
if (assembly is null)
{
throw new ArgumentNullException(nameof(assembly));
}
if (string.IsNullOrEmpty(resource))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0062), nameof(resource));
@ -406,8 +453,13 @@ public class OpenIddictClientBuilder
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope",
Justification = "The X.509 certificate is attached to the client options.")]
public OpenIddictClientBuilder AddEncryptionCertificate(Stream stream!!, string? password, X509KeyStorageFlags flags)
public OpenIddictClientBuilder AddEncryptionCertificate(Stream stream, string? password, X509KeyStorageFlags flags)
{
if (stream is null)
{
throw new ArgumentNullException(nameof(stream));
}
using var buffer = new MemoryStream();
stream.CopyTo(buffer);
@ -470,16 +522,28 @@ public class OpenIddictClientBuilder
/// </summary>
/// <param name="credentials">The signing credentials.</param>
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
public OpenIddictClientBuilder AddSigningCredentials(SigningCredentials credentials!!)
=> Configure(options => options.SigningCredentials.Add(credentials));
public OpenIddictClientBuilder AddSigningCredentials(SigningCredentials credentials)
{
if (credentials is null)
{
throw new ArgumentNullException(nameof(credentials));
}
return Configure(options => options.SigningCredentials.Add(credentials));
}
/// <summary>
/// Registers a signing key.
/// </summary>
/// <param name="key">The security key.</param>
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
public OpenIddictClientBuilder AddSigningKey(SecurityKey key!!)
public OpenIddictClientBuilder AddSigningKey(SecurityKey key)
{
if (key is null)
{
throw new ArgumentNullException(nameof(key));
}
// If the signing key is an asymmetric security key, ensure it has a private key.
if (key is AsymmetricSecurityKey asymmetricSecurityKey &&
asymmetricSecurityKey.PrivateKeyStatus is PrivateKeyStatus.DoesNotExist)
@ -539,8 +603,13 @@ public class OpenIddictClientBuilder
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope",
Justification = "The X.509 certificate is attached to the client options.")]
public OpenIddictClientBuilder AddDevelopmentSigningCertificate(X500DistinguishedName subject!!)
public OpenIddictClientBuilder AddDevelopmentSigningCertificate(X500DistinguishedName subject)
{
if (subject is null)
{
throw new ArgumentNullException(nameof(subject));
}
using var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadWrite);
@ -713,8 +782,13 @@ public class OpenIddictClientBuilder
/// </summary>
/// <param name="certificate">The signing certificate.</param>
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
public OpenIddictClientBuilder AddSigningCertificate(X509Certificate2 certificate!!)
public OpenIddictClientBuilder AddSigningCertificate(X509Certificate2 certificate)
{
if (certificate is null)
{
throw new ArgumentNullException(nameof(certificate));
}
// If the certificate is a X.509v3 certificate that specifies at least
// one key usage, ensure that the certificate key can be used for signing.
if (certificate.Version >= 3)
@ -760,9 +834,14 @@ public class OpenIddictClientBuilder
/// <param name="flags">An enumeration of flags indicating how and where to store the private key of the certificate.</param>
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
public OpenIddictClientBuilder AddSigningCertificate(
Assembly assembly!!, string resource,
Assembly assembly, string resource,
string? password, X509KeyStorageFlags flags)
{
if (assembly is null)
{
throw new ArgumentNullException(nameof(assembly));
}
if (string.IsNullOrEmpty(resource))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0062), nameof(resource));
@ -802,8 +881,13 @@ public class OpenIddictClientBuilder
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope",
Justification = "The X.509 certificate is attached to the client options.")]
public OpenIddictClientBuilder AddSigningCertificate(Stream stream!!, string? password, X509KeyStorageFlags flags)
public OpenIddictClientBuilder AddSigningCertificate(Stream stream, string? password, X509KeyStorageFlags flags)
{
if (stream is null)
{
throw new ArgumentNullException(nameof(stream));
}
using var buffer = new MemoryStream();
stream.CopyTo(buffer);
@ -866,8 +950,15 @@ public class OpenIddictClientBuilder
/// </summary>
/// <param name="registration">The client registration.</param>
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
public OpenIddictClientBuilder AddRegistration(OpenIddictClientRegistration registration!!)
=> Configure(options => options.Registrations.Add(registration));
public OpenIddictClientBuilder AddRegistration(OpenIddictClientRegistration registration)
{
if (registration is null)
{
throw new ArgumentNullException(nameof(registration));
}
return Configure(options => options.Registrations.Add(registration));
}
/// <summary>
/// Sets the relative or absolute URLs associated to the redirection endpoint.
@ -876,8 +967,15 @@ public class OpenIddictClientBuilder
/// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
public OpenIddictClientBuilder SetRedirectionEndpointUris(params string[] addresses!!)
=> SetRedirectionEndpointUris(addresses.Select(address => new Uri(address, UriKind.RelativeOrAbsolute)).ToArray());
public OpenIddictClientBuilder SetRedirectionEndpointUris(params string[] addresses)
{
if (addresses is null)
{
throw new ArgumentNullException(nameof(addresses));
}
return SetRedirectionEndpointUris(addresses.Select(address => new Uri(address, UriKind.RelativeOrAbsolute)).ToArray());
}
/// <summary>
/// Sets the relative or absolute URLs associated to the redirection endpoint.
@ -886,8 +984,13 @@ public class OpenIddictClientBuilder
/// </summary>
/// <param name="addresses">The addresses associated to the endpoint.</param>
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
public OpenIddictClientBuilder SetRedirectionEndpointUris(params Uri[] addresses!!)
public OpenIddictClientBuilder SetRedirectionEndpointUris(params Uri[] addresses)
{
if (addresses is null)
{
throw new ArgumentNullException(nameof(addresses));
}
if (addresses.Any(address => !address.IsWellFormedOriginalString()))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0072), nameof(addresses));

9
src/OpenIddict.Client/OpenIddictClientConfiguration.cs

@ -19,7 +19,7 @@ public class OpenIddictClientConfiguration : IPostConfigureOptions<OpenIddictCli
private readonly OpenIddictClientService _service;
public OpenIddictClientConfiguration(OpenIddictClientService service)
=> _service = service;
=> _service = service ?? throw new ArgumentNullException(nameof(service));
/// <summary>
/// Populates the default OpenIddict client options and ensures
@ -27,8 +27,13 @@ public class OpenIddictClientConfiguration : IPostConfigureOptions<OpenIddictCli
/// </summary>
/// <param name="name">The authentication scheme associated with the handler instance.</param>
/// <param name="options">The options instance to initialize.</param>
public void PostConfigure(string name, OpenIddictClientOptions options!!)
public void PostConfigure(string name, OpenIddictClientOptions options)
{
if (options is null)
{
throw new ArgumentNullException(nameof(options));
}
if (options.JsonWebTokenHandler is null)
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0075));

19
src/OpenIddict.Client/OpenIddictClientDispatcher.cs

@ -19,17 +19,22 @@ public class OpenIddictClientDispatcher : IOpenIddictClientDispatcher
/// Creates a new instance of the <see cref="OpenIddictClientDispatcher"/> class.
/// </summary>
public OpenIddictClientDispatcher(
ILogger<OpenIddictClientDispatcher> logger!!,
IOptionsMonitor<OpenIddictClientOptions> options!!,
IServiceProvider provider!!)
ILogger<OpenIddictClientDispatcher> logger,
IOptionsMonitor<OpenIddictClientOptions> options,
IServiceProvider provider)
{
_logger = logger;
_options = options;
_provider = provider;
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_options = options ?? throw new ArgumentNullException(nameof(options));
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
}
public async ValueTask DispatchAsync<TContext>(TContext context!!) where TContext : BaseContext
public async ValueTask DispatchAsync<TContext>(TContext context) where TContext : BaseContext
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
await foreach (var handler in GetHandlersAsync())
{
try

4
src/OpenIddict.Client/OpenIddictClientEvents.cs

@ -21,8 +21,8 @@ public static partial class OpenIddictClientEvents
/// <summary>
/// Creates a new instance of the <see cref="BaseContext"/> class.
/// </summary>
protected BaseContext(OpenIddictClientTransaction transaction!!)
=> Transaction = transaction;
protected BaseContext(OpenIddictClientTransaction transaction)
=> Transaction = transaction ?? throw new ArgumentNullException(nameof(transaction));
/// <summary>
/// Gets the environment associated with the current request being processed.

19
src/OpenIddict.Client/OpenIddictClientExtensions.cs

@ -21,8 +21,13 @@ public static class OpenIddictClientExtensions
/// <param name="builder">The services builder used by OpenIddict to register new services.</param>
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictClientBuilder"/>.</returns>
public static OpenIddictClientBuilder AddClient(this OpenIddictBuilder builder!!)
public static OpenIddictClientBuilder AddClient(this OpenIddictBuilder builder)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Services.AddLogging();
builder.Services.AddOptions();
@ -69,8 +74,18 @@ public static class OpenIddictClientExtensions
/// <param name="configuration">The configuration delegate used to configure the client services.</param>
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
public static OpenIddictBuilder AddClient(this OpenIddictBuilder builder!!, Action<OpenIddictClientBuilder> configuration!!)
public static OpenIddictBuilder AddClient(this OpenIddictBuilder builder, Action<OpenIddictClientBuilder> configuration)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
configuration(builder.AddClient());
return builder;

8
src/OpenIddict.Client/OpenIddictClientFactory.cs

@ -18,11 +18,11 @@ public class OpenIddictClientFactory : IOpenIddictClientFactory
/// Creates a new instance of the <see cref="OpenIddictClientFactory"/> class.
/// </summary>
public OpenIddictClientFactory(
ILogger<OpenIddictClientDispatcher> logger!!,
IOptionsMonitor<OpenIddictClientOptions> options!!)
ILogger<OpenIddictClientDispatcher> logger,
IOptionsMonitor<OpenIddictClientOptions> options)
{
_logger = logger;
_options = options;
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_options = options ?? throw new ArgumentNullException(nameof(options));
}
public ValueTask<OpenIddictClientTransaction> CreateTransactionAsync()

7
src/OpenIddict.Client/OpenIddictClientHandler.cs

@ -18,8 +18,8 @@ public class OpenIddictClientHandler<TContext> : IOpenIddictClientHandler<TConte
/// Creates a new event using the specified handler delegate.
/// </summary>
/// <param name="handler">The event handler delegate.</param>
public OpenIddictClientHandler(Func<TContext, ValueTask> handler!!)
=> _handler = handler;
public OpenIddictClientHandler(Func<TContext, ValueTask> handler)
=> _handler = handler ?? throw new ArgumentNullException(nameof(handler));
/// <summary>
/// Processes the event.
@ -28,5 +28,6 @@ public class OpenIddictClientHandler<TContext> : IOpenIddictClientHandler<TConte
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public ValueTask HandleAsync(TContext context!!) => _handler(context);
public ValueTask HandleAsync(TContext context)
=> _handler(context ?? throw new ArgumentNullException(nameof(context)));
}

65
src/OpenIddict.Client/OpenIddictClientHandlerDescriptor.cs

@ -72,8 +72,13 @@ public class OpenIddictClientHandlerDescriptor
/// </summary>
/// <param name="type">The event handler filter type.</param>
/// <returns>The builder instance, so that calls can be easily chained.</returns>
public Builder<TContext> AddFilter(Type type!!)
public Builder<TContext> AddFilter(Type type)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
if (!typeof(IOpenIddictClientHandlerFilter<>).MakeGenericType(typeof(TContext)).IsAssignableFrom(type))
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0104));
@ -99,8 +104,13 @@ public class OpenIddictClientHandlerDescriptor
/// <param name="descriptor">The existing descriptor properties are copied from.</param>
/// <remarks>All the properties previously set on this instance are automatically replaced.</remarks>
/// <returns>The builder instance, so that calls can be easily chained.</returns>
public Builder<TContext> Import(OpenIddictClientHandlerDescriptor descriptor!!)
public Builder<TContext> Import(OpenIddictClientHandlerDescriptor descriptor)
{
if (descriptor is null)
{
throw new ArgumentNullException(nameof(descriptor));
}
if (descriptor.ContextType != typeof(TContext))
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0284));
@ -120,8 +130,13 @@ public class OpenIddictClientHandlerDescriptor
/// </summary>
/// <param name="descriptor">The service descriptor.</param>
/// <returns>The builder instance, so that calls can be easily chained.</returns>
public Builder<TContext> SetServiceDescriptor(ServiceDescriptor descriptor!!)
public Builder<TContext> SetServiceDescriptor(ServiceDescriptor descriptor)
{
if (descriptor is null)
{
throw new ArgumentNullException(nameof(descriptor));
}
var type = descriptor.ServiceType;
if (!typeof(IOpenIddictClientHandler<>).MakeGenericType(typeof(TContext)).IsAssignableFrom(type))
{
@ -167,8 +182,15 @@ public class OpenIddictClientHandlerDescriptor
/// </summary>
/// <param name="handler">The handler instance.</param>
/// <returns>The builder instance, so that calls can be easily chained.</returns>
public Builder<TContext> UseInlineHandler(Func<TContext, ValueTask> handler!!)
=> UseSingletonHandler(new OpenIddictClientHandler<TContext>(handler));
public Builder<TContext> UseInlineHandler(Func<TContext, ValueTask> handler)
{
if (handler is null)
{
throw new ArgumentNullException(nameof(handler));
}
return UseSingletonHandler(new OpenIddictClientHandler<TContext>(handler));
}
/// <summary>
/// Configures the descriptor to use the specified scoped handler.
@ -186,10 +208,17 @@ public class OpenIddictClientHandlerDescriptor
/// <typeparam name="THandler">The handler type.</typeparam>
/// <param name="factory">The factory used to create the handler.</param>
/// <returns>The builder instance, so that calls can be easily chained.</returns>
public Builder<TContext> UseScopedHandler<THandler>(Func<IServiceProvider, object> factory!!)
public Builder<TContext> UseScopedHandler<THandler>(Func<IServiceProvider, object> factory)
where THandler : IOpenIddictClientHandler<TContext>
=> SetServiceDescriptor(new ServiceDescriptor(
{
if (factory is null)
{
throw new ArgumentNullException(nameof(factory));
}
return SetServiceDescriptor(new ServiceDescriptor(
typeof(THandler), factory, ServiceLifetime.Scoped));
}
/// <summary>
/// Configures the descriptor to use the specified singleton handler.
@ -207,10 +236,17 @@ public class OpenIddictClientHandlerDescriptor
/// <typeparam name="THandler">The handler type.</typeparam>
/// <param name="factory">The factory used to create the handler.</param>
/// <returns>The builder instance, so that calls can be easily chained.</returns>
public Builder<TContext> UseSingletonHandler<THandler>(Func<IServiceProvider, object> factory!!)
public Builder<TContext> UseSingletonHandler<THandler>(Func<IServiceProvider, object> factory)
where THandler : IOpenIddictClientHandler<TContext>
=> SetServiceDescriptor(new ServiceDescriptor(
{
if (factory is null)
{
throw new ArgumentNullException(nameof(factory));
}
return SetServiceDescriptor(new ServiceDescriptor(
typeof(THandler), factory, ServiceLifetime.Singleton));
}
/// <summary>
/// Configures the descriptor to use the specified singleton handler.
@ -218,9 +254,16 @@ public class OpenIddictClientHandlerDescriptor
/// <typeparam name="THandler">The handler type.</typeparam>
/// <param name="handler">The handler instance.</param>
/// <returns>The builder instance, so that calls can be easily chained.</returns>
public Builder<TContext> UseSingletonHandler<THandler>(THandler handler!!)
public Builder<TContext> UseSingletonHandler<THandler>(THandler handler)
where THandler : IOpenIddictClientHandler<TContext>
=> SetServiceDescriptor(new ServiceDescriptor(typeof(THandler), handler));
{
if (handler is null)
{
throw new ArgumentNullException(nameof(handler));
}
return SetServiceDescriptor(new ServiceDescriptor(typeof(THandler), handler));
}
/// <summary>
/// Build a new descriptor instance, based on the parameters that were previously set.

209
src/OpenIddict.Client/OpenIddictClientHandlerFilters.cs

@ -17,8 +17,15 @@ public static class OpenIddictClientHandlerFilters
/// </summary>
public class RequireAuthorizationCodeOrImplicitGrantType : IOpenIddictClientHandlerFilter<ProcessChallengeContext>
{
public ValueTask<bool> IsActiveAsync(ProcessChallengeContext context!!)
=> new(context.GrantType is GrantTypes.AuthorizationCode or GrantTypes.Implicit);
public ValueTask<bool> IsActiveAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(context.GrantType is GrantTypes.AuthorizationCode or GrantTypes.Implicit);
}
}
/// <summary>
@ -26,8 +33,15 @@ public static class OpenIddictClientHandlerFilters
/// </summary>
public class RequireAuthorizationCodeValidated : IOpenIddictClientHandlerFilter<ProcessAuthenticationContext>
{
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context!!)
=> new(context.ValidateAuthorizationCode);
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(context.ValidateAuthorizationCode);
}
}
/// <summary>
@ -35,8 +49,15 @@ public static class OpenIddictClientHandlerFilters
/// </summary>
public class RequireBackchannelAccessTokenValidated : IOpenIddictClientHandlerFilter<ProcessAuthenticationContext>
{
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context!!)
=> new(context.ValidateBackchannelAccessToken);
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(context.ValidateBackchannelAccessToken);
}
}
/// <summary>
@ -44,8 +65,15 @@ public static class OpenIddictClientHandlerFilters
/// </summary>
public class RequireBackchannelIdentityTokenPrincipal : IOpenIddictClientHandlerFilter<ProcessAuthenticationContext>
{
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context!!)
=> new(context.BackchannelIdentityTokenPrincipal is not null);
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(context.BackchannelIdentityTokenPrincipal is not null);
}
}
/// <summary>
@ -53,8 +81,15 @@ public static class OpenIddictClientHandlerFilters
/// </summary>
public class RequireBackchannelIdentityTokenValidated : IOpenIddictClientHandlerFilter<ProcessAuthenticationContext>
{
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context!!)
=> new(context.ValidateBackchannelIdentityToken);
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(context.ValidateBackchannelIdentityToken);
}
}
/// <summary>
@ -62,8 +97,15 @@ public static class OpenIddictClientHandlerFilters
/// </summary>
public class RequireFrontchannelAccessTokenValidated : IOpenIddictClientHandlerFilter<ProcessAuthenticationContext>
{
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context!!)
=> new(context.ValidateFrontchannelAccessToken);
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(context.ValidateFrontchannelAccessToken);
}
}
/// <summary>
@ -71,8 +113,15 @@ public static class OpenIddictClientHandlerFilters
/// </summary>
public class RequireFrontchannelIdentityTokenPrincipal : IOpenIddictClientHandlerFilter<ProcessAuthenticationContext>
{
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context!!)
=> new(context.FrontchannelIdentityTokenPrincipal is not null);
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(context.FrontchannelIdentityTokenPrincipal is not null);
}
}
/// <summary>
@ -80,8 +129,15 @@ public static class OpenIddictClientHandlerFilters
/// </summary>
public class RequireFrontchannelIdentityTokenValidated : IOpenIddictClientHandlerFilter<ProcessAuthenticationContext>
{
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context!!)
=> new(context.ValidateFrontchannelIdentityToken);
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(context.ValidateFrontchannelIdentityToken);
}
}
/// <summary>
@ -89,8 +145,15 @@ public static class OpenIddictClientHandlerFilters
/// </summary>
public class RequireRedirectionRequest : IOpenIddictClientHandlerFilter<BaseContext>
{
public ValueTask<bool> IsActiveAsync(BaseContext context!!)
=> new(context.EndpointType is OpenIddictClientEndpointType.Redirection);
public ValueTask<bool> IsActiveAsync(BaseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(context.EndpointType is OpenIddictClientEndpointType.Redirection);
}
}
/// <summary>
@ -98,8 +161,15 @@ public static class OpenIddictClientHandlerFilters
/// </summary>
public class RequireRefreshTokenValidated : IOpenIddictClientHandlerFilter<ProcessAuthenticationContext>
{
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context!!)
=> new(context.ValidateRefreshToken);
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(context.ValidateRefreshToken);
}
}
/// <summary>
@ -107,8 +177,15 @@ public static class OpenIddictClientHandlerFilters
/// </summary>
public class RequireStateTokenGenerated : IOpenIddictClientHandlerFilter<ProcessChallengeContext>
{
public ValueTask<bool> IsActiveAsync(ProcessChallengeContext context!!)
=> new(context.GenerateStateToken);
public ValueTask<bool> IsActiveAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(context.GenerateStateToken);
}
}
/// <summary>
@ -116,8 +193,15 @@ public static class OpenIddictClientHandlerFilters
/// </summary>
public class RequireStateTokenPrincipal : IOpenIddictClientHandlerFilter<ProcessAuthenticationContext>
{
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context!!)
=> new(context.StateTokenPrincipal is not null);
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(context.StateTokenPrincipal is not null);
}
}
/// <summary>
@ -125,8 +209,15 @@ public static class OpenIddictClientHandlerFilters
/// </summary>
public class RequireStateTokenValidated : IOpenIddictClientHandlerFilter<ProcessAuthenticationContext>
{
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context!!)
=> new(context.ValidateStateToken);
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(context.ValidateStateToken);
}
}
/// <summary>
@ -134,8 +225,15 @@ public static class OpenIddictClientHandlerFilters
/// </summary>
public class RequireTokenRequest : IOpenIddictClientHandlerFilter<ProcessAuthenticationContext>
{
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context!!)
=> new(context.TokenRequest is not null);
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(context.TokenRequest is not null);
}
}
/// <summary>
@ -143,8 +241,15 @@ public static class OpenIddictClientHandlerFilters
/// </summary>
public class RequireTokenResponse : IOpenIddictClientHandlerFilter<ProcessAuthenticationContext>
{
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context!!)
=> new(context.TokenResponse is not null);
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(context.TokenResponse is not null);
}
}
/// <summary>
@ -152,8 +257,15 @@ public static class OpenIddictClientHandlerFilters
/// </summary>
public class RequireUserinfoRequest : IOpenIddictClientHandlerFilter<ProcessAuthenticationContext>
{
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context!!)
=> new(context.UserinfoRequest is not null);
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(context.UserinfoRequest is not null);
}
}
/// <summary>
@ -161,8 +273,15 @@ public static class OpenIddictClientHandlerFilters
/// </summary>
public class RequireUserinfoResponse : IOpenIddictClientHandlerFilter<ProcessAuthenticationContext>
{
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context!!)
=> new(context.UserinfoResponse is not null);
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(context.UserinfoResponse is not null);
}
}
/// <summary>
@ -170,8 +289,15 @@ public static class OpenIddictClientHandlerFilters
/// </summary>
public class RequireUserinfoTokenExtracted : IOpenIddictClientHandlerFilter<ProcessAuthenticationContext>
{
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context!!)
=> new(context.ExtractUserinfoToken);
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(context.ExtractUserinfoToken);
}
}
/// <summary>
@ -179,7 +305,14 @@ public static class OpenIddictClientHandlerFilters
/// </summary>
public class RequireUserinfoTokenPrincipal : IOpenIddictClientHandlerFilter<ProcessAuthenticationContext>
{
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context!!)
=> new(context.UserinfoTokenPrincipal is not null);
public ValueTask<bool> IsActiveAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return new(context.UserinfoTokenPrincipal is not null);
}
}
}

91
src/OpenIddict.Client/OpenIddictClientHandlers.Authentication.cs

@ -51,8 +51,8 @@ public static partial class OpenIddictClientHandlers
{
private readonly IOpenIddictClientDispatcher _dispatcher;
public PrepareAuthorizationRequest(IOpenIddictClientDispatcher dispatcher!!)
=> _dispatcher = dispatcher;
public PrepareAuthorizationRequest(IOpenIddictClientDispatcher dispatcher)
=> _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -65,8 +65,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessChallengeContext context!!)
public async ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
var notification = new PrepareAuthorizationRequestContext(context.Transaction);
await _dispatcher.DispatchAsync(notification);
@ -91,8 +96,8 @@ public static partial class OpenIddictClientHandlers
{
private readonly IOpenIddictClientDispatcher _dispatcher;
public ApplyAuthorizationRequest(IOpenIddictClientDispatcher dispatcher!!)
=> _dispatcher = dispatcher;
public ApplyAuthorizationRequest(IOpenIddictClientDispatcher dispatcher)
=> _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -105,8 +110,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessChallengeContext context!!)
public async ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
var notification = new ApplyAuthorizationRequestContext(context.Transaction);
await _dispatcher.DispatchAsync(notification);
@ -139,8 +149,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ApplyAuthorizationRequestContext context!!)
public async ValueTask HandleAsync(ApplyAuthorizationRequestContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
var configuration = await context.Registration.ConfigurationManager.GetConfigurationAsync(default) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0140));
@ -168,8 +183,8 @@ public static partial class OpenIddictClientHandlers
{
private readonly IOpenIddictClientDispatcher _dispatcher;
public ExtractRedirectionRequest(IOpenIddictClientDispatcher dispatcher!!)
=> _dispatcher = dispatcher;
public ExtractRedirectionRequest(IOpenIddictClientDispatcher dispatcher)
=> _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -182,8 +197,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessRequestContext context!!)
public async ValueTask HandleAsync(ProcessRequestContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
var notification = new ExtractRedirectionRequestContext(context.Transaction);
await _dispatcher.DispatchAsync(notification);
@ -224,8 +244,8 @@ public static partial class OpenIddictClientHandlers
{
private readonly IOpenIddictClientDispatcher _dispatcher;
public ValidateRedirectionRequest(IOpenIddictClientDispatcher dispatcher!!)
=> _dispatcher = dispatcher;
public ValidateRedirectionRequest(IOpenIddictClientDispatcher dispatcher)
=> _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -239,8 +259,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessRequestContext context!!)
public async ValueTask HandleAsync(ProcessRequestContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
var notification = new ValidateRedirectionRequestContext(context.Transaction);
await _dispatcher.DispatchAsync(notification);
@ -276,8 +301,8 @@ public static partial class OpenIddictClientHandlers
{
private readonly IOpenIddictClientDispatcher _dispatcher;
public HandleRedirectionRequest(IOpenIddictClientDispatcher dispatcher!!)
=> _dispatcher = dispatcher;
public HandleRedirectionRequest(IOpenIddictClientDispatcher dispatcher)
=> _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -290,8 +315,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessRequestContext context!!)
public async ValueTask HandleAsync(ProcessRequestContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
var notification = new HandleRedirectionRequestContext(context.Transaction);
await _dispatcher.DispatchAsync(notification);
@ -327,8 +357,8 @@ public static partial class OpenIddictClientHandlers
{
private readonly IOpenIddictClientDispatcher _dispatcher;
public ApplyRedirectionResponse(IOpenIddictClientDispatcher dispatcher!!)
=> _dispatcher = dispatcher;
public ApplyRedirectionResponse(IOpenIddictClientDispatcher dispatcher)
=> _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -342,8 +372,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(TContext context!!)
public async ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
var notification = new ApplyRedirectionResponseContext(context.Transaction);
await _dispatcher.DispatchAsync(notification);
@ -379,8 +414,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(PrepareAuthorizationRequestContext context!!)
public ValueTask HandleAsync(PrepareAuthorizationRequestContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// When the response mode corresponds to the default mode assigned to the selected
// response type, the specification explicitly recommends omitting the response mode.
// As such, this handler is expected to remove the mode parameter in the following cases:
@ -411,8 +451,8 @@ public static partial class OpenIddictClientHandlers
{
private readonly IOpenIddictClientDispatcher _dispatcher;
public ValidateTokens(IOpenIddictClientDispatcher dispatcher!!)
=> _dispatcher = dispatcher;
public ValidateTokens(IOpenIddictClientDispatcher dispatcher)
=> _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -425,8 +465,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ValidateRedirectionRequestContext context!!)
public async ValueTask HandleAsync(ValidateRedirectionRequestContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
var notification = new ProcessAuthenticationContext(context.Transaction);
await _dispatcher.DispatchAsync(notification);

105
src/OpenIddict.Client/OpenIddictClientHandlers.Discovery.cs

@ -56,8 +56,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(HandleConfigurationResponseContext context!!)
public ValueTask HandleAsync(HandleConfigurationResponseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
foreach (var parameter in context.Response.GetParameters())
{
if (!ValidateParameterType(parameter.Key, parameter.Value))
@ -139,8 +144,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(HandleConfigurationResponseContext context!!)
public ValueTask HandleAsync(HandleConfigurationResponseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// 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#ProviderConfigurationClient.
var issuer = (string?) context.Response[Metadata.Issuer];
@ -186,8 +196,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(HandleConfigurationResponseContext context!!)
public ValueTask HandleAsync(HandleConfigurationResponseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// Note: the authorization_endpoint node is required by the OpenID Connect discovery specification
// but is optional in the OAuth 2.0 authorization server metadata specification. To make OpenIddict
// compatible with the newer OAuth 2.0 specification, null/empty and missing values are allowed here.
@ -233,8 +248,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(HandleConfigurationResponseContext context!!)
public ValueTask HandleAsync(HandleConfigurationResponseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// Note: the jwks_uri node is required by the OpenID Connect discovery specification.
// See https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationClient.
var address = (string?) context.Response[Metadata.JwksUri];
@ -280,8 +300,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(HandleConfigurationResponseContext context!!)
public ValueTask HandleAsync(HandleConfigurationResponseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
var address = (string?) context.Response[Metadata.TokenEndpoint];
if (!string.IsNullOrEmpty(address))
{
@ -318,8 +343,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(HandleConfigurationResponseContext context!!)
public ValueTask HandleAsync(HandleConfigurationResponseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
var address = (string?) context.Response[Metadata.UserinfoEndpoint];
if (!string.IsNullOrEmpty(address))
{
@ -356,8 +386,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(HandleConfigurationResponseContext context!!)
public ValueTask HandleAsync(HandleConfigurationResponseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// Resolve the grant types supported by the authorization endpoint, if available.
var types = context.Response[Metadata.GrantTypesSupported]?.GetUnnamedParameters();
if (types is { Count: > 0 })
@ -393,8 +428,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(HandleConfigurationResponseContext context!!)
public ValueTask HandleAsync(HandleConfigurationResponseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// Resolve the response modes supported by the authorization endpoint, if available.
var modes = context.Response[Metadata.ResponseModesSupported]?.GetUnnamedParameters();
if (modes is { Count: > 0 })
@ -430,8 +470,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(HandleConfigurationResponseContext context!!)
public ValueTask HandleAsync(HandleConfigurationResponseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// Resolve the response types supported by the authorization endpoint, if available.
var types = context.Response[Metadata.ResponseTypesSupported]?.GetUnnamedParameters();
if (types is { Count: > 0 })
@ -467,8 +512,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(HandleConfigurationResponseContext context!!)
public ValueTask HandleAsync(HandleConfigurationResponseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// Resolve the code challenge methods supported by the authorization endpoint, if available.
var methods = context.Response[Metadata.CodeChallengeMethodsSupported]?.GetUnnamedParameters();
if (methods is { Count: > 0 })
@ -504,8 +554,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(HandleConfigurationResponseContext context!!)
public ValueTask HandleAsync(HandleConfigurationResponseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// Resolve the scopes supported by the remote server, if available.
var scopes = context.Response[Metadata.ScopesSupported]?.GetUnnamedParameters();
if (scopes is { Count: > 0 })
@ -542,8 +597,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(HandleConfigurationResponseContext context!!)
public ValueTask HandleAsync(HandleConfigurationResponseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
context.Configuration.AuthorizationResponseIssParameterSupported = (bool?)
context.Response[Metadata.AuthorizationResponseIssParameterSupported];
@ -568,8 +628,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(HandleConfigurationResponseContext context!!)
public ValueTask HandleAsync(HandleConfigurationResponseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// Resolve the client authentication methods supported by the token endpoint, if available.
var methods = context.Response[Metadata.TokenEndpointAuthMethodsSupported]?.GetUnnamedParameters();
if (methods is { Count: > 0 })
@ -605,8 +670,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(HandleCryptographyResponseContext context!!)
public ValueTask HandleAsync(HandleCryptographyResponseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
foreach (var parameter in context.Response.GetParameters())
{
if (!ValidateParameterType(parameter.Key, parameter.Value))
@ -670,8 +740,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(HandleCryptographyResponseContext context!!)
public ValueTask HandleAsync(HandleCryptographyResponseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
var keys = context.Response[JsonWebKeySetParameterNames.Keys]?.GetUnnamedParameters();
if (keys is not { Count: > 0 })
{

7
src/OpenIddict.Client/OpenIddictClientHandlers.Exchange.cs

@ -36,8 +36,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(HandleTokenResponseContext context!!)
public ValueTask HandleAsync(HandleTokenResponseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
foreach (var parameter in context.Response.GetParameters())
{
if (!ValidateParameterType(parameter.Key, parameter.Value))

49
src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs

@ -50,8 +50,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ValidateTokenContext context!!)
public async ValueTask HandleAsync(ValidateTokenContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// The OpenIddict client is expected to validate tokens it creates (e.g state tokens) and
// tokens that are created by one or multiple authorization servers (e.g identity tokens).
//
@ -157,8 +162,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ValidateTokenContext context!!)
public async ValueTask HandleAsync(ValidateTokenContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// If a principal was already attached, don't overwrite it.
if (context.Principal is not null)
{
@ -268,8 +278,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ValidateTokenContext context!!)
public ValueTask HandleAsync(ValidateTokenContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// Note: only map the private claims from fully trusted tokens.
if (context.Principal is null || !context.Principal.HasTokenType(TokenTypeHints.StateToken))
{
@ -320,8 +335,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ValidateTokenContext context!!)
public ValueTask HandleAsync(ValidateTokenContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.Principal is null)
{
context.Reject(
@ -367,8 +387,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ValidateTokenContext context!!)
public ValueTask HandleAsync(ValidateTokenContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
var date = context.Principal.GetExpirationDate();
@ -402,8 +427,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(GenerateTokenContext context!!)
public ValueTask HandleAsync(GenerateTokenContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
context.SecurityTokenHandler = context.Options.JsonWebTokenHandler;
context.EncryptionCredentials = context.Options.EncryptionCredentials.First();
@ -429,8 +459,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(GenerateTokenContext context!!)
public ValueTask HandleAsync(GenerateTokenContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// If a token was already attached by another handler, don't overwrite it.
if (!string.IsNullOrEmpty(context.Token))
{

14
src/OpenIddict.Client/OpenIddictClientHandlers.Userinfo.cs

@ -39,8 +39,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(HandleUserinfoResponseContext context!!)
public ValueTask HandleAsync(HandleUserinfoResponseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// Ignore the response instance if a userinfo token was extracted.
if (!string.IsNullOrEmpty(context.UserinfoToken))
{
@ -96,8 +101,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(HandleUserinfoResponseContext context!!)
public async ValueTask HandleAsync(HandleUserinfoResponseContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// Ignore the response instance if a userinfo token was extracted.
if (!string.IsNullOrEmpty(context.UserinfoToken))
{

481
src/OpenIddict.Client/OpenIddictClientHandlers.cs

@ -127,8 +127,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// Authentication demands can be triggered from the redirection endpoint
// to handle authorization callbacks but also from unknown endpoints
// when using the refresh token grant, to perform a token refresh dance.
@ -179,8 +184,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
(context.ExtractStateToken,
context.RequireStateToken,
context.ValidateStateToken) = context.EndpointType switch
@ -215,8 +225,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
context.StateToken = context.EndpointType switch
{
OpenIddictClientEndpointType.Redirection when context.ExtractStateToken
@ -245,8 +260,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.RequireStateToken && string.IsNullOrEmpty(context.StateToken))
{
context.Reject(
@ -268,8 +288,8 @@ public static partial class OpenIddictClientHandlers
{
private readonly IOpenIddictClientDispatcher _dispatcher;
public ValidateStateToken(IOpenIddictClientDispatcher dispatcher!!)
=> _dispatcher = dispatcher;
public ValidateStateToken(IOpenIddictClientDispatcher dispatcher)
=> _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -283,8 +303,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public async ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.StateTokenPrincipal is not null ||
string.IsNullOrEmpty(context.StateToken))
{
@ -341,8 +366,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.StateTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Retrieve the client definition using the authorization server stored in the state token.
@ -391,8 +421,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public async ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013));
var configuration = await context.Registration.ConfigurationManager.GetConfigurationAsync(default) ??
@ -477,8 +512,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
var (error, description, uri) = (
(string?) context.Request[Parameters.Error],
(string?) context.Request[Parameters.ErrorDescription],
@ -516,8 +556,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.StateTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Resolve the negotiated grant type from the state token.
@ -564,8 +609,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.StateTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Resolve the negotiated response type from the state token.
@ -591,8 +641,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
(context.ExtractAuthorizationCode,
context.RequireAuthorizationCode,
context.ValidateAuthorizationCode) = context.GrantType switch
@ -668,8 +723,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
context.AuthorizationCode = context.EndpointType switch
{
OpenIddictClientEndpointType.Redirection when context.ExtractAuthorizationCode
@ -714,8 +774,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
if ((context.RequireAuthorizationCode && string.IsNullOrEmpty(context.AuthorizationCode)) ||
(context.RequireFrontchannelAccessToken && string.IsNullOrEmpty(context.FrontchannelAccessToken)) ||
(context.RequireFrontchannelIdentityToken && string.IsNullOrEmpty(context.FrontchannelIdentityToken)))
@ -739,8 +804,8 @@ public static partial class OpenIddictClientHandlers
{
private readonly IOpenIddictClientDispatcher _dispatcher;
public ValidateFrontchannelIdentityToken(IOpenIddictClientDispatcher dispatcher!!)
=> _dispatcher = dispatcher;
public ValidateFrontchannelIdentityToken(IOpenIddictClientDispatcher dispatcher)
=> _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -754,8 +819,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public async ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.FrontchannelIdentityTokenPrincipal is not null ||
string.IsNullOrEmpty(context.FrontchannelIdentityToken))
{
@ -812,8 +882,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.FrontchannelIdentityTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
foreach (var group in context.FrontchannelIdentityTokenPrincipal.Claims
@ -943,8 +1018,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.FrontchannelIdentityTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Note: while an identity token typically contains a single audience represented
@ -983,8 +1063,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.FrontchannelIdentityTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Note: the "azp" claim is optional, but if it's present, it MUST match the client identifier of the application.
@ -1022,8 +1107,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.FrontchannelIdentityTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.StateTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
@ -1080,8 +1170,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.FrontchannelIdentityTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Resolve the signing algorithm used to sign the identity token. If the private
@ -1200,8 +1295,8 @@ public static partial class OpenIddictClientHandlers
{
private readonly IOpenIddictClientDispatcher _dispatcher;
public ValidateFrontchannelAccessToken(IOpenIddictClientDispatcher dispatcher!!)
=> _dispatcher = dispatcher;
public ValidateFrontchannelAccessToken(IOpenIddictClientDispatcher dispatcher)
=> _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -1215,8 +1310,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public async ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.FrontchannelAccessTokenPrincipal is not null ||
string.IsNullOrEmpty(context.FrontchannelAccessToken))
{
@ -1265,8 +1365,8 @@ public static partial class OpenIddictClientHandlers
{
private readonly IOpenIddictClientDispatcher _dispatcher;
public ValidateAuthorizationCode(IOpenIddictClientDispatcher dispatcher!!)
=> _dispatcher = dispatcher;
public ValidateAuthorizationCode(IOpenIddictClientDispatcher dispatcher)
=> _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -1280,8 +1380,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public async ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.AuthorizationCodePrincipal is not null ||
string.IsNullOrEmpty(context.AuthorizationCode))
{
@ -1337,8 +1442,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
(context.ExtractBackchannelAccessToken,
context.RequireBackchannelAccessToken,
context.ValidateBackchannelAccessToken) = context.GrantType switch
@ -1424,8 +1534,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public async ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
if (!context.ExtractBackchannelAccessToken &&
!context.ExtractBackchannelIdentityToken &&
!context.ExtractRefreshToken)
@ -1465,8 +1580,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
if (!context.ExtractBackchannelAccessToken &&
!context.ExtractBackchannelIdentityToken &&
!context.ExtractRefreshToken)
@ -1530,7 +1650,7 @@ public static partial class OpenIddictClientHandlers
private readonly OpenIddictClientService _service;
public SendTokenRequest(OpenIddictClientService service)
=> _service = service;
=> _service = service ?? throw new ArgumentNullException(nameof(service));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -1543,8 +1663,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public async ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.TokenRequest is not null, SR.GetResourceString(SR.ID4008));
// Ensure the token endpoint is present and is a valid absolute URL.
@ -1575,8 +1700,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.TokenResponse is not null, SR.GetResourceString(SR.ID4007));
if (!string.IsNullOrEmpty(context.TokenResponse.Error))
@ -1609,8 +1739,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.TokenResponse is not null, SR.GetResourceString(SR.ID4007));
context.BackchannelAccessToken = context.ExtractBackchannelAccessToken switch
@ -1651,8 +1786,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
if ((context.RequireBackchannelAccessToken && string.IsNullOrEmpty(context.BackchannelAccessToken)) ||
(context.RequireBackchannelIdentityToken && string.IsNullOrEmpty(context.BackchannelIdentityToken)) ||
(context.RequireRefreshToken && string.IsNullOrEmpty(context.RefreshToken)))
@ -1676,8 +1816,8 @@ public static partial class OpenIddictClientHandlers
{
private readonly IOpenIddictClientDispatcher _dispatcher;
public ValidateBackchannelIdentityToken(IOpenIddictClientDispatcher dispatcher!!)
=> _dispatcher = dispatcher;
public ValidateBackchannelIdentityToken(IOpenIddictClientDispatcher dispatcher)
=> _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -1691,8 +1831,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public async ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.BackchannelIdentityTokenPrincipal is not null ||
string.IsNullOrEmpty(context.BackchannelIdentityToken))
{
@ -1749,8 +1894,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.BackchannelIdentityTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
foreach (var group in context.BackchannelIdentityTokenPrincipal.Claims
@ -1880,8 +2030,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.BackchannelIdentityTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Note: while an identity token typically contains a single audience represented
@ -1920,8 +2075,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.BackchannelIdentityTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
// Note: the "azp" claim is optional, but if it's present, it MUST match the client identifier of the application.
@ -1959,8 +2119,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.BackchannelIdentityTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
Debug.Assert(context.StateTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
@ -2017,8 +2182,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.BackchannelIdentityTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
Debug.Assert(!string.IsNullOrEmpty(context.BackchannelAccessToken), SR.GetResourceString(SR.ID4010));
@ -2110,8 +2280,8 @@ public static partial class OpenIddictClientHandlers
{
private readonly IOpenIddictClientDispatcher _dispatcher;
public ValidateBackchannelAccessToken(IOpenIddictClientDispatcher dispatcher!!)
=> _dispatcher = dispatcher;
public ValidateBackchannelAccessToken(IOpenIddictClientDispatcher dispatcher)
=> _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -2125,8 +2295,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public async ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.BackchannelAccessTokenPrincipal is not null ||
string.IsNullOrEmpty(context.BackchannelAccessToken))
{
@ -2175,8 +2350,8 @@ public static partial class OpenIddictClientHandlers
{
private readonly IOpenIddictClientDispatcher _dispatcher;
public ValidateRefreshToken(IOpenIddictClientDispatcher dispatcher!!)
=> _dispatcher = dispatcher;
public ValidateRefreshToken(IOpenIddictClientDispatcher dispatcher)
=> _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -2190,8 +2365,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public async ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.RefreshTokenPrincipal is not null ||
string.IsNullOrEmpty(context.RefreshToken))
{
@ -2247,8 +2427,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public async ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
var configuration = await context.Registration.ConfigurationManager.GetConfigurationAsync(default) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0140));
@ -2282,8 +2467,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public async ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
var configuration = await context.Registration.ConfigurationManager.GetConfigurationAsync(default) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0140));
@ -2335,8 +2525,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// Attach a new request instance if necessary.
context.UserinfoRequest ??= new OpenIddictRequest();
@ -2365,7 +2560,7 @@ public static partial class OpenIddictClientHandlers
private readonly OpenIddictClientService _service;
public SendUserinfoRequest(OpenIddictClientService service)
=> _service = service;
=> _service = service ?? throw new ArgumentNullException(nameof(service));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -2378,8 +2573,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public async ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.UserinfoRequest is not null, SR.GetResourceString(SR.ID4008));
// Ensure the userinfo endpoint is present and is a valid absolute URL.
@ -2414,8 +2614,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.UserinfoResponse is not null, SR.GetResourceString(SR.ID4007));
if (!string.IsNullOrEmpty(context.UserinfoResponse.Error))
@ -2448,8 +2653,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.RequireUserinfoToken && string.IsNullOrEmpty(context.UserinfoToken))
{
context.Reject(
@ -2471,8 +2681,8 @@ public static partial class OpenIddictClientHandlers
{
private readonly IOpenIddictClientDispatcher _dispatcher;
public ValidateUserinfoToken(IOpenIddictClientDispatcher dispatcher!!)
=> _dispatcher = dispatcher;
public ValidateUserinfoToken(IOpenIddictClientDispatcher dispatcher)
=> _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -2486,8 +2696,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public async ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.UserinfoTokenPrincipal is not null ||
string.IsNullOrEmpty(context.UserinfoToken))
{
@ -2544,8 +2759,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public async ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.UserinfoTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
var configuration = await context.Registration.ConfigurationManager.GetConfigurationAsync(default) ??
@ -2612,8 +2832,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessAuthenticationContext context!!)
public async ValueTask HandleAsync(ProcessAuthenticationContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.UserinfoTokenPrincipal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
var configuration = await context.Registration.ConfigurationManager.GetConfigurationAsync(default) ??
@ -2692,8 +2917,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessChallengeContext context!!)
public ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// If an explicit grant type was specified, ensure it is supported by OpenIddict.
if (!string.IsNullOrEmpty(context.GrantType) &&
context.GrantType is not (GrantTypes.AuthorizationCode or GrantTypes.Implicit))
@ -2731,8 +2961,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessChallengeContext context!!)
public ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// Note: if the static registration cannot be found in the options, this may indicate
// the client was removed after the authorization dance started and thus, can no longer
// be used to authenticate users. In this case, throw an exception to abort the flow.
@ -2761,8 +2996,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessChallengeContext context!!)
public async ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// If an explicit grant type was specified, don't overwrite it.
if (!string.IsNullOrEmpty(context.GrantType))
{
@ -2846,8 +3086,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessChallengeContext context!!)
public ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// In OpenIddict, per-authorization demand values are stored in an encrypted and signed token
// called "state token", that allows flowing per-authorization demand data like the issuer
// targeted by the authorization demand or secret values like the code verifier used to
@ -2885,8 +3130,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessChallengeContext context!!)
public async ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// If an explicit response type was specified, don't overwrite it.
if (!string.IsNullOrEmpty(context.ResponseType))
{
@ -3078,8 +3328,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessChallengeContext context!!)
public async ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// If an explicit response type was specified, don't overwrite it.
if (!string.IsNullOrEmpty(context.ResponseMode))
{
@ -3185,8 +3440,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessChallengeContext context!!)
public ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
context.ClientId ??= context.Registration.ClientId;
return default;
@ -3209,8 +3469,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessChallengeContext context!!)
public ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// Unlike OpenID Connect, OAuth 2.0 and 2.1 don't require specifying a redirect_uri.
// To keep OpenIddict compatible with OAuth 2.0/2.1 deployments, the redirect_uri
// is not required for OAuth 2.0 requests but an exception will be thrown later
@ -3237,8 +3502,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessChallengeContext context!!)
public async ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// If an explicit set of scopes was specified, don't overwrite it.
if (context.Scopes.Count > 0)
{
@ -3284,8 +3554,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessChallengeContext context!!)
public ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// Generate a new crypto-secure random identifier that will
// be used as the non-guessable part of the state token.
var data = new byte[256 / 8];
@ -3317,8 +3592,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessChallengeContext context!!)
public async ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
var configuration = await context.Registration.ConfigurationManager.GetConfigurationAsync(default) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0140));
@ -3362,8 +3642,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessChallengeContext context!!)
public async ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// Don't attach a code challenge method if no authorization code is requested as some implementations
// (like OpenIddict server) are known to eagerly block authorization requests that specify an invalid
// code_challenge/code_challenge_method/response_type combination (e.g response_type=id_token).
@ -3464,8 +3749,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessChallengeContext context!!)
public ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
Debug.Assert(context.Issuer is { IsAbsoluteUri: true }, SR.GetResourceString(SR.ID4013));
Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006));
@ -3556,8 +3846,8 @@ public static partial class OpenIddictClientHandlers
{
private readonly IOpenIddictClientDispatcher _dispatcher;
public GenerateStateToken(IOpenIddictClientDispatcher dispatcher!!)
=> _dispatcher = dispatcher;
public GenerateStateToken(IOpenIddictClientDispatcher dispatcher)
=> _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
@ -3571,8 +3861,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public async ValueTask HandleAsync(ProcessChallengeContext context!!)
public async ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
var notification = new GenerateTokenContext(context.Transaction)
{
Principal = context.StateTokenPrincipal!,
@ -3623,8 +3918,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessChallengeContext context!!)
public ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// While OAuth 2.0/2.1 allows sending an authorization request without a redirect_uri,
// doing so is illegal in OpenID Connect and such requests will always be rejected.
// To make that requirement explicit, an exception is proactively thrown here.
@ -3653,8 +3953,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessChallengeContext context!!)
public ValueTask HandleAsync(ProcessChallengeContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// Note: while the exact order of the parameters has typically no effect on how requests
// are handled by an authorization server, client_id and redirect_uri are deliberately
// set first so that they appear early in the URL (when GET requests are used), making
@ -3709,8 +4014,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(TContext context!!)
public ValueTask HandleAsync(TContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
if (!string.IsNullOrEmpty(context.Transaction.Response?.Error))
{
context.Reject(
@ -3741,8 +4051,13 @@ public static partial class OpenIddictClientHandlers
.Build();
/// <inheritdoc/>
public ValueTask HandleAsync(ProcessErrorContext context!!)
public ValueTask HandleAsync(ProcessErrorContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
context.Response.Error = context.Error;
context.Response.ErrorDescription = context.ErrorDescription;
context.Response.ErrorUri = context.ErrorUri;

14
src/OpenIddict.Client/OpenIddictClientHelpers.cs

@ -19,8 +19,13 @@ public static class OpenIddictClientHelpers
/// <param name="name">The property name.</param>
/// <returns>The property value or <see langword="null"/> if it couldn't be found.</returns>
public static TProperty? GetProperty<TProperty>(
this OpenIddictClientTransaction transaction!!, string name) where TProperty : class
this OpenIddictClientTransaction transaction, string name) where TProperty : class
{
if (transaction is null)
{
throw new ArgumentNullException(nameof(transaction));
}
if (string.IsNullOrEmpty(name))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0106), nameof(name));
@ -43,9 +48,14 @@ public static class OpenIddictClientHelpers
/// <param name="value">The property value.</param>
/// <returns>The client transaction, so that calls can be easily chained.</returns>
public static OpenIddictClientTransaction SetProperty<TProperty>(
this OpenIddictClientTransaction transaction!!,
this OpenIddictClientTransaction transaction,
string name, TProperty? value) where TProperty : class
{
if (transaction is null)
{
throw new ArgumentNullException(nameof(transaction));
}
if (string.IsNullOrEmpty(name))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0106), nameof(name));

7
src/OpenIddict.Client/OpenIddictClientRetriever.cs

@ -16,8 +16,8 @@ public class OpenIddictClientRetriever : IConfigurationRetriever<OpenIddictConfi
/// Creates a new instance of the <see cref="OpenIddictClientRetriever"/> class.
/// </summary>
/// <param name="service">The validation service.</param>
public OpenIddictClientRetriever(OpenIddictClientService service!!)
=> _service = service;
public OpenIddictClientRetriever(OpenIddictClientService service)
=> _service = service ?? throw new ArgumentNullException(nameof(service));
/// <summary>
/// Retrieves the OpenID Connect server configuration from the specified address.
@ -26,8 +26,7 @@ public class OpenIddictClientRetriever : IConfigurationRetriever<OpenIddictConfi
/// <param name="retriever">The retriever used by IdentityModel.</param>
/// <param name="cancel">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>
async Task<OpenIddictConfiguration> IConfigurationRetriever<OpenIddictConfiguration>.GetConfigurationAsync(
string address, IDocumentRetriever retriever, CancellationToken cancel)
async Task<OpenIddictConfiguration> IConfigurationRetriever<OpenIddictConfiguration>.GetConfigurationAsync(string address, IDocumentRetriever retriever, CancellationToken cancel)
{
if (string.IsNullOrEmpty(address))
{

53
src/OpenIddict.Client/OpenIddictClientService.cs

@ -19,8 +19,8 @@ public class OpenIddictClientService
/// Creates a new instance of the <see cref="OpenIddictClientService"/> class.
/// </summary>
/// <param name="provider">The service provider.</param>
public OpenIddictClientService(IServiceProvider provider!!)
=> _provider = provider;
public OpenIddictClientService(IServiceProvider provider)
=> _provider = provider ?? throw new ArgumentNullException(nameof(provider));
/// <summary>
/// Retrieves the OpenID Connect server configuration from the specified address.
@ -28,9 +28,14 @@ public class OpenIddictClientService
/// <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>
/// <returns>The OpenID Connect server configuration retrieved from the remote server.</returns>
public async ValueTask<OpenIddictConfiguration> GetConfigurationAsync(Uri address!!, CancellationToken cancellationToken = default)
public async ValueTask<OpenIddictConfiguration> GetConfigurationAsync(Uri address, CancellationToken cancellationToken = default)
{
if (!address.IsAbsoluteUri)
if (address is null)
{
throw new ArgumentNullException(nameof(address));
}
if (!address.IsAbsoluteUri || !address.IsWellFormedOriginalString())
{
throw new ArgumentException(SR.GetResourceString(SR.ID0144), nameof(address));
}
@ -162,9 +167,14 @@ public class OpenIddictClientService
/// <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>
/// <returns>The security keys retrieved from the remote server.</returns>
public async ValueTask<JsonWebKeySet> GetSecurityKeysAsync(Uri address!!, CancellationToken cancellationToken = default)
public async ValueTask<JsonWebKeySet> GetSecurityKeysAsync(Uri address, CancellationToken cancellationToken = default)
{
if (!address.IsAbsoluteUri)
if (address is null)
{
throw new ArgumentNullException(nameof(address));
}
if (!address.IsAbsoluteUri || !address.IsWellFormedOriginalString())
{
throw new ArgumentException(SR.GetResourceString(SR.ID0144), nameof(address));
}
@ -299,8 +309,13 @@ public class OpenIddictClientService
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The response and a merged principal containing the claims extracted from the tokens and userinfo response.</returns>
public async ValueTask<(OpenIddictResponse Response, ClaimsPrincipal Principal)> RefreshTokensAsync(
OpenIddictClientRegistration registration!!, string token, CancellationToken cancellationToken = default)
OpenIddictClientRegistration registration, string token, CancellationToken cancellationToken = default)
{
if (registration is null)
{
throw new ArgumentNullException(nameof(registration));
}
if (string.IsNullOrEmpty(token))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0156), nameof(token));
@ -418,8 +433,18 @@ public class OpenIddictClientService
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The token response.</returns>
public async ValueTask<OpenIddictResponse> SendTokenRequestAsync(
OpenIddictClientRegistration registration!!, Uri address!!, OpenIddictRequest request, CancellationToken cancellationToken = default)
OpenIddictClientRegistration registration, Uri address, OpenIddictRequest request, CancellationToken cancellationToken = default)
{
if (registration is null)
{
throw new ArgumentNullException(nameof(registration));
}
if (address is null)
{
throw new ArgumentNullException(nameof(address));
}
if (!address.IsAbsoluteUri || !address.IsWellFormedOriginalString())
{
throw new ArgumentException(SR.GetResourceString(SR.ID0144), nameof(address));
@ -562,8 +587,18 @@ public class OpenIddictClientService
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The response and the principal extracted from the userinfo response or the userinfo token.</returns>
public async ValueTask<(OpenIddictResponse Response, (ClaimsPrincipal? Principal, string? Token))> SendUserinfoRequestAsync(
OpenIddictClientRegistration registration!!, Uri address!!, OpenIddictRequest request, CancellationToken cancellationToken = default)
OpenIddictClientRegistration registration, Uri address, OpenIddictRequest request, CancellationToken cancellationToken = default)
{
if (registration is null)
{
throw new ArgumentNullException(nameof(registration));
}
if (address is null)
{
throw new ArgumentNullException(nameof(address));
}
if (!address.IsAbsoluteUri || !address.IsWellFormedOriginalString())
{
throw new ArgumentException(SR.GetResourceString(SR.ID0144), nameof(address));

43
src/OpenIddict.Core/Caches/OpenIddictApplicationCache.cs

@ -24,21 +24,26 @@ public class OpenIddictApplicationCache<TApplication> : IOpenIddictApplicationCa
private readonly IOpenIddictApplicationStore<TApplication> _store;
public OpenIddictApplicationCache(
IOptionsMonitor<OpenIddictCoreOptions> options!!,
IOpenIddictApplicationStoreResolver resolver!!)
IOptionsMonitor<OpenIddictCoreOptions> options,
IOpenIddictApplicationStoreResolver resolver)
{
_cache = new MemoryCache(new MemoryCacheOptions
{
SizeLimit = options.CurrentValue.EntityCacheLimit
SizeLimit = (options ?? throw new ArgumentNullException(nameof(options))).CurrentValue.EntityCacheLimit
});
_signals = new ConcurrentDictionary<string, CancellationTokenSource>(StringComparer.Ordinal);
_store = resolver.Get<TApplication>();
_store = (resolver ?? throw new ArgumentNullException(nameof(resolver))).Get<TApplication>();
}
/// <inheritdoc/>
public async ValueTask AddAsync(TApplication application!!, CancellationToken cancellationToken)
public async ValueTask AddAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
_cache.Remove(new
{
Method = nameof(FindByClientIdAsync),
@ -244,8 +249,13 @@ public class OpenIddictApplicationCache<TApplication> : IOpenIddictApplicationCa
}
/// <inheritdoc/>
public async ValueTask RemoveAsync(TApplication application!!, CancellationToken cancellationToken)
public async ValueTask RemoveAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
var identifier = await _store.GetIdAsync(application, cancellationToken);
if (string.IsNullOrEmpty(identifier))
{
@ -266,8 +276,13 @@ public class OpenIddictApplicationCache<TApplication> : IOpenIddictApplicationCa
/// <param name="application">The application to store in the cache entry, if applicable.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
protected virtual async ValueTask CreateEntryAsync(object key!!, TApplication? application, CancellationToken cancellationToken)
protected virtual async ValueTask CreateEntryAsync(object key, TApplication? application, CancellationToken cancellationToken)
{
if (key is null)
{
throw new ArgumentNullException(nameof(key));
}
using var entry = _cache.CreateEntry(key);
if (application is not null)
@ -288,8 +303,13 @@ public class OpenIddictApplicationCache<TApplication> : IOpenIddictApplicationCa
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
protected virtual async ValueTask CreateEntryAsync(
object key!!, ImmutableArray<TApplication> applications, CancellationToken cancellationToken)
object key, ImmutableArray<TApplication> applications, CancellationToken cancellationToken)
{
if (key is null)
{
throw new ArgumentNullException(nameof(key));
}
using var entry = _cache.CreateEntry(key);
foreach (var application in applications)
@ -313,8 +333,13 @@ public class OpenIddictApplicationCache<TApplication> : IOpenIddictApplicationCa
/// whose result returns an expiration signal for the specified application.
/// </returns>
protected virtual async ValueTask<IChangeToken> CreateExpirationSignalAsync(
TApplication application!!, CancellationToken cancellationToken)
TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
var identifier = await _store.GetIdAsync(application, cancellationToken);
if (string.IsNullOrEmpty(identifier))
{

43
src/OpenIddict.Core/Caches/OpenIddictAuthorizationCache.cs

@ -24,21 +24,26 @@ public class OpenIddictAuthorizationCache<TAuthorization> : IOpenIddictAuthoriza
private readonly IOpenIddictAuthorizationStore<TAuthorization> _store;
public OpenIddictAuthorizationCache(
IOptionsMonitor<OpenIddictCoreOptions> options!!,
IOpenIddictAuthorizationStoreResolver resolver!!)
IOptionsMonitor<OpenIddictCoreOptions> options,
IOpenIddictAuthorizationStoreResolver resolver)
{
_cache = new MemoryCache(new MemoryCacheOptions
{
SizeLimit = options.CurrentValue.EntityCacheLimit
SizeLimit = (options ?? throw new ArgumentNullException(nameof(options))).CurrentValue.EntityCacheLimit
});
_signals = new ConcurrentDictionary<string, CancellationTokenSource>(StringComparer.Ordinal);
_store = resolver.Get<TAuthorization>();
_store = (resolver ?? throw new ArgumentNullException(nameof(resolver))).Get<TAuthorization>();
}
/// <inheritdoc/>
public async ValueTask AddAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
public async ValueTask AddAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
_cache.Remove(new
{
Method = nameof(FindAsync),
@ -420,8 +425,13 @@ public class OpenIddictAuthorizationCache<TAuthorization> : IOpenIddictAuthoriza
}
/// <inheritdoc/>
public async ValueTask RemoveAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
public async ValueTask RemoveAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
var identifier = await _store.GetIdAsync(authorization, cancellationToken);
if (string.IsNullOrEmpty(identifier))
{
@ -442,8 +452,13 @@ public class OpenIddictAuthorizationCache<TAuthorization> : IOpenIddictAuthoriza
/// <param name="authorization">The authorization to store in the cache entry, if applicable.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
protected virtual async ValueTask CreateEntryAsync(object key!!, TAuthorization? authorization, CancellationToken cancellationToken)
protected virtual async ValueTask CreateEntryAsync(object key, TAuthorization? authorization, CancellationToken cancellationToken)
{
if (key is null)
{
throw new ArgumentNullException(nameof(key));
}
using var entry = _cache.CreateEntry(key);
if (authorization is not null)
@ -464,8 +479,13 @@ public class OpenIddictAuthorizationCache<TAuthorization> : IOpenIddictAuthoriza
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
protected virtual async ValueTask CreateEntryAsync(
object key!!, ImmutableArray<TAuthorization> authorizations, CancellationToken cancellationToken)
object key, ImmutableArray<TAuthorization> authorizations, CancellationToken cancellationToken)
{
if (key is null)
{
throw new ArgumentNullException(nameof(key));
}
using var entry = _cache.CreateEntry(key);
foreach (var authorization in authorizations)
@ -489,8 +509,13 @@ public class OpenIddictAuthorizationCache<TAuthorization> : IOpenIddictAuthoriza
/// whose result returns an expiration signal for the specified authorization.
/// </returns>
protected virtual async ValueTask<IChangeToken> CreateExpirationSignalAsync(
TAuthorization authorization!!, CancellationToken cancellationToken)
TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
var identifier = await _store.GetIdAsync(authorization, cancellationToken);
if (string.IsNullOrEmpty(identifier))
{

45
src/OpenIddict.Core/Caches/OpenIddictScopeCache.cs

@ -24,21 +24,26 @@ public class OpenIddictScopeCache<TScope> : IOpenIddictScopeCache<TScope>, IDisp
private readonly IOpenIddictScopeStore<TScope> _store;
public OpenIddictScopeCache(
IOptionsMonitor<OpenIddictCoreOptions> options!!,
IOpenIddictScopeStoreResolver resolver!!)
IOptionsMonitor<OpenIddictCoreOptions> options,
IOpenIddictScopeStoreResolver resolver)
{
_cache = new MemoryCache(new MemoryCacheOptions
{
SizeLimit = options.CurrentValue.EntityCacheLimit
SizeLimit = (options ?? throw new ArgumentNullException(nameof(options))).CurrentValue.EntityCacheLimit
});
_signals = new ConcurrentDictionary<string, CancellationTokenSource>(StringComparer.Ordinal);
_store = resolver.Get<TScope>();
_store = (resolver ?? throw new ArgumentNullException(nameof(resolver))).Get<TScope>();
}
/// <inheritdoc/>
public async ValueTask AddAsync(TScope scope!!, CancellationToken cancellationToken)
public async ValueTask AddAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
_cache.Remove(new
{
Method = nameof(FindByIdAsync),
@ -155,7 +160,7 @@ public class OpenIddictScopeCache<TScope> : IOpenIddictScopeCache<TScope>, IDisp
/// <inheritdoc/>
public IAsyncEnumerable<TScope> FindByNamesAsync(ImmutableArray<string> names, CancellationToken cancellationToken)
{
if (names.Any(string.IsNullOrEmpty))
if (names.Any(name => string.IsNullOrEmpty(name)))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0203), nameof(names));
}
@ -217,8 +222,13 @@ public class OpenIddictScopeCache<TScope> : IOpenIddictScopeCache<TScope>, IDisp
}
/// <inheritdoc/>
public async ValueTask RemoveAsync(TScope scope!!, CancellationToken cancellationToken)
public async ValueTask RemoveAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
var identifier = await _store.GetIdAsync(scope, cancellationToken);
if (string.IsNullOrEmpty(identifier))
{
@ -239,8 +249,13 @@ public class OpenIddictScopeCache<TScope> : IOpenIddictScopeCache<TScope>, IDisp
/// <param name="scope">The scope to store in the cache entry, if applicable.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
protected virtual async ValueTask CreateEntryAsync(object key!!, TScope? scope, CancellationToken cancellationToken)
protected virtual async ValueTask CreateEntryAsync(object key, TScope? scope, CancellationToken cancellationToken)
{
if (key is null)
{
throw new ArgumentNullException(nameof(key));
}
using var entry = _cache.CreateEntry(key);
if (scope is not null)
@ -261,8 +276,13 @@ public class OpenIddictScopeCache<TScope> : IOpenIddictScopeCache<TScope>, IDisp
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
protected virtual async ValueTask CreateEntryAsync(
object key!!, ImmutableArray<TScope> scopes, CancellationToken cancellationToken)
object key, ImmutableArray<TScope> scopes, CancellationToken cancellationToken)
{
if (key is null)
{
throw new ArgumentNullException(nameof(key));
}
using var entry = _cache.CreateEntry(key);
foreach (var scope in scopes)
@ -285,8 +305,13 @@ public class OpenIddictScopeCache<TScope> : IOpenIddictScopeCache<TScope>, IDisp
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation,
/// whose result returns an expiration signal for the specified scope.
/// </returns>
protected virtual async ValueTask<IChangeToken> CreateExpirationSignalAsync(TScope scope!!, CancellationToken cancellationToken)
protected virtual async ValueTask<IChangeToken> CreateExpirationSignalAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
var identifier = await _store.GetIdAsync(scope, cancellationToken);
if (string.IsNullOrEmpty(identifier))
{

43
src/OpenIddict.Core/Caches/OpenIddictTokenCache.cs

@ -24,21 +24,26 @@ public class OpenIddictTokenCache<TToken> : IOpenIddictTokenCache<TToken>, IDisp
private readonly IOpenIddictTokenStore<TToken> _store;
public OpenIddictTokenCache(
IOptionsMonitor<OpenIddictCoreOptions> options!!,
IOpenIddictTokenStoreResolver resolver!!)
IOptionsMonitor<OpenIddictCoreOptions> options,
IOpenIddictTokenStoreResolver resolver)
{
_cache = new MemoryCache(new MemoryCacheOptions
{
SizeLimit = options.CurrentValue.EntityCacheLimit
SizeLimit = (options ?? throw new ArgumentNullException(nameof(options))).CurrentValue.EntityCacheLimit
});
_signals = new ConcurrentDictionary<string, CancellationTokenSource>(StringComparer.Ordinal);
_store = resolver.Get<TToken>();
_store = (resolver ?? throw new ArgumentNullException(nameof(resolver))).Get<TToken>();
}
/// <inheritdoc/>
public async ValueTask AddAsync(TToken token!!, CancellationToken cancellationToken)
public async ValueTask AddAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
_cache.Remove(new
{
Method = nameof(FindAsync),
@ -472,8 +477,13 @@ public class OpenIddictTokenCache<TToken> : IOpenIddictTokenCache<TToken>, IDisp
}
/// <inheritdoc/>
public async ValueTask RemoveAsync(TToken token!!, CancellationToken cancellationToken)
public async ValueTask RemoveAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
var identifier = await _store.GetIdAsync(token, cancellationToken);
if (string.IsNullOrEmpty(identifier))
{
@ -494,8 +504,13 @@ public class OpenIddictTokenCache<TToken> : IOpenIddictTokenCache<TToken>, IDisp
/// <param name="token">The token to store in the cache entry, if applicable.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
protected virtual async ValueTask CreateEntryAsync(object key!!, TToken? token, CancellationToken cancellationToken)
protected virtual async ValueTask CreateEntryAsync(object key, TToken? token, CancellationToken cancellationToken)
{
if (key is null)
{
throw new ArgumentNullException(nameof(key));
}
using var entry = _cache.CreateEntry(key);
if (token is not null)
@ -516,8 +531,13 @@ public class OpenIddictTokenCache<TToken> : IOpenIddictTokenCache<TToken>, IDisp
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
protected virtual async ValueTask CreateEntryAsync(
object key!!, ImmutableArray<TToken> tokens, CancellationToken cancellationToken)
object key, ImmutableArray<TToken> tokens, CancellationToken cancellationToken)
{
if (key is null)
{
throw new ArgumentNullException(nameof(key));
}
using var entry = _cache.CreateEntry(key);
foreach (var token in tokens)
@ -540,8 +560,13 @@ public class OpenIddictTokenCache<TToken> : IOpenIddictTokenCache<TToken>, IDisp
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation,
/// whose result returns an expiration signal for the specified token.
/// </returns>
protected virtual async ValueTask<IChangeToken> CreateExpirationSignalAsync(TToken token!!, CancellationToken cancellationToken)
protected virtual async ValueTask<IChangeToken> CreateExpirationSignalAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
var identifier = await _store.GetIdAsync(token, cancellationToken);
if (string.IsNullOrEmpty(identifier))
{

332
src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs

@ -41,15 +41,15 @@ namespace OpenIddict.Core;
public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplicationManager where TApplication : class
{
public OpenIddictApplicationManager(
IOpenIddictApplicationCache<TApplication> cache!!,
ILogger<OpenIddictApplicationManager<TApplication>> logger!!,
IOptionsMonitor<OpenIddictCoreOptions> options!!,
IOpenIddictApplicationStoreResolver resolver!!)
IOpenIddictApplicationCache<TApplication> cache,
ILogger<OpenIddictApplicationManager<TApplication>> logger,
IOptionsMonitor<OpenIddictCoreOptions> options,
IOpenIddictApplicationStoreResolver resolver)
{
Cache = cache;
Logger = logger;
Options = options;
Store = resolver.Get<TApplication>();
Cache = cache ?? throw new ArgumentNullException(nameof(cache));
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
Options = options ?? throw new ArgumentNullException(nameof(options));
Store = (resolver ?? throw new ArgumentNullException(nameof(resolver))).Get<TApplication>();
}
/// <summary>
@ -94,8 +94,15 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// whose result returns the number of applications that match the specified query.
/// </returns>
public virtual ValueTask<long> CountAsync<TResult>(
Func<IQueryable<TApplication>, IQueryable<TResult>> query!!, CancellationToken cancellationToken = default)
=> Store.CountAsync(query, cancellationToken);
Func<IQueryable<TApplication>, IQueryable<TResult>> query, CancellationToken cancellationToken = default)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return Store.CountAsync(query, cancellationToken);
}
/// <summary>
/// Creates a new application.
@ -119,8 +126,13 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask CreateAsync(TApplication application!!, string? secret, CancellationToken cancellationToken = default)
public virtual async ValueTask CreateAsync(TApplication application, string? secret, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (!string.IsNullOrEmpty(await Store.GetClientSecretAsync(application, cancellationToken)))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0206), nameof(application));
@ -189,8 +201,13 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// whose result returns the unique identifier associated with the application.
/// </returns>
public virtual async ValueTask<TApplication> CreateAsync(
OpenIddictApplicationDescriptor descriptor!!, CancellationToken cancellationToken = default)
OpenIddictApplicationDescriptor descriptor, CancellationToken cancellationToken = default)
{
if (descriptor is null)
{
throw new ArgumentNullException(nameof(descriptor));
}
var application = await Store.InstantiateAsync(cancellationToken) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0208));
@ -218,8 +235,13 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask DeleteAsync(TApplication application!!, CancellationToken cancellationToken = default)
public virtual async ValueTask DeleteAsync(TApplication application, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (!Options.CurrentValue.DisableEntityCaching)
{
await Cache.RemoveAsync(application, cancellationToken);
@ -398,8 +420,15 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// whose result returns the first element returned when executing the query.
/// </returns>
public virtual ValueTask<TResult?> GetAsync<TResult>(
Func<IQueryable<TApplication>, IQueryable<TResult>> query!!, CancellationToken cancellationToken = default)
=> GetAsync(static (applications, query) => query(applications), query, cancellationToken);
Func<IQueryable<TApplication>, IQueryable<TResult>> query, CancellationToken cancellationToken = default)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return GetAsync(static (applications, query) => query(applications), query, cancellationToken);
}
/// <summary>
/// Executes the specified query and returns the first element.
@ -414,9 +443,16 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// whose result returns the first element returned when executing the query.
/// </returns>
public virtual ValueTask<TResult?> GetAsync<TState, TResult>(
Func<IQueryable<TApplication>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TApplication>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken = default)
=> Store.GetAsync(query, state, cancellationToken);
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return Store.GetAsync(query, state, cancellationToken);
}
/// <summary>
/// Retrieves the client identifier associated with an application.
@ -428,8 +464,15 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// whose result returns the client identifier associated with the application.
/// </returns>
public virtual ValueTask<string?> GetClientIdAsync(
TApplication application!!, CancellationToken cancellationToken = default)
=> Store.GetClientIdAsync(application, cancellationToken);
TApplication application, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
return Store.GetClientIdAsync(application, cancellationToken);
}
/// <summary>
/// Retrieves the client type associated with an application.
@ -441,8 +484,15 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// whose result returns the client type of the application (by default, "public").
/// </returns>
public virtual ValueTask<string?> GetClientTypeAsync(
TApplication application!!, CancellationToken cancellationToken = default)
=> Store.GetClientTypeAsync(application, cancellationToken);
TApplication application, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
return Store.GetClientTypeAsync(application, cancellationToken);
}
/// <summary>
/// Retrieves the consent type associated with an application.
@ -454,8 +504,13 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// whose result returns the consent type of the application (by default, "explicit").
/// </returns>
public virtual async ValueTask<string?> GetConsentTypeAsync(
TApplication application!!, CancellationToken cancellationToken = default)
TApplication application, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
var type = await Store.GetConsentTypeAsync(application, cancellationToken);
if (string.IsNullOrEmpty(type))
{
@ -475,8 +530,15 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// whose result returns the display name associated with the application.
/// </returns>
public virtual ValueTask<string?> GetDisplayNameAsync(
TApplication application!!, CancellationToken cancellationToken = default)
=> Store.GetDisplayNameAsync(application, cancellationToken);
TApplication application, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
return Store.GetDisplayNameAsync(application, cancellationToken);
}
/// <summary>
/// Retrieves the localized display names associated with an application.
@ -488,9 +550,21 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// whose result returns all the localized display names associated with the application.
/// </returns>
public virtual async ValueTask<ImmutableDictionary<CultureInfo, string>> GetDisplayNamesAsync(
TApplication application!!, CancellationToken cancellationToken = default)
=> await Store.GetDisplayNamesAsync(application, cancellationToken) is { Count: > 0 } names ?
names : ImmutableDictionary.Create<CultureInfo, string>();
TApplication application, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
var names = await Store.GetDisplayNamesAsync(application, cancellationToken);
if (names is null || names.Count == 0)
{
return ImmutableDictionary.Create<CultureInfo, string>();
}
return names;
}
/// <summary>
/// Retrieves the unique identifier associated with an application.
@ -501,8 +575,15 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the unique identifier associated with the application.
/// </returns>
public virtual ValueTask<string?> GetIdAsync(TApplication application!!, CancellationToken cancellationToken = default)
=> Store.GetIdAsync(application, cancellationToken);
public virtual ValueTask<string?> GetIdAsync(TApplication application, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
return Store.GetIdAsync(application, cancellationToken);
}
/// <summary>
/// Retrieves the localized display name associated with an application
@ -532,8 +613,18 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// whose result returns the matching localized display name associated with the application.
/// </returns>
public virtual async ValueTask<string?> GetLocalizedDisplayNameAsync(
TApplication application!!, CultureInfo culture!!, CancellationToken cancellationToken = default)
TApplication application, CultureInfo culture, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (culture is null)
{
throw new ArgumentNullException(nameof(culture));
}
var names = await Store.GetDisplayNamesAsync(application, cancellationToken);
if (names is not { Count: > 0 })
{
@ -565,8 +656,15 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// whose result returns all the permissions associated with the application.
/// </returns>
public virtual ValueTask<ImmutableArray<string>> GetPermissionsAsync(
TApplication application!!, CancellationToken cancellationToken = default)
=> Store.GetPermissionsAsync(application, cancellationToken);
TApplication application, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
return Store.GetPermissionsAsync(application, cancellationToken);
}
/// <summary>
/// Retrieves the logout callback addresses associated with an application.
@ -578,8 +676,15 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// whose result returns all the post_logout_redirect_uri associated with the application.
/// </returns>
public virtual ValueTask<ImmutableArray<string>> GetPostLogoutRedirectUrisAsync(
TApplication application!!, CancellationToken cancellationToken = default)
=> Store.GetPostLogoutRedirectUrisAsync(application, cancellationToken);
TApplication application, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
return Store.GetPostLogoutRedirectUrisAsync(application, cancellationToken);
}
/// <summary>
/// Retrieves the additional properties associated with an application.
@ -591,8 +696,15 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// whose result returns all the additional properties associated with the application.
/// </returns>
public virtual ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(
TApplication application!!, CancellationToken cancellationToken = default)
=> Store.GetPropertiesAsync(application, cancellationToken);
TApplication application, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
return Store.GetPropertiesAsync(application, cancellationToken);
}
/// <summary>
/// Retrieves the callback addresses associated with an application.
@ -604,8 +716,15 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// whose result returns all the redirect_uri associated with the application.
/// </returns>
public virtual ValueTask<ImmutableArray<string>> GetRedirectUrisAsync(
TApplication application!!, CancellationToken cancellationToken = default)
=> Store.GetRedirectUrisAsync(application, cancellationToken);
TApplication application, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
return Store.GetRedirectUrisAsync(application, cancellationToken);
}
/// <summary>
/// Retrieves the requirements associated with an application.
@ -617,8 +736,15 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// whose result returns all the requirements associated with the application.
/// </returns>
public virtual ValueTask<ImmutableArray<string>> GetRequirementsAsync(
TApplication application!!, CancellationToken cancellationToken = default)
=> Store.GetRequirementsAsync(application, cancellationToken);
TApplication application, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
return Store.GetRequirementsAsync(application, cancellationToken);
}
/// <summary>
/// Determines whether a given application has the specified client type.
@ -628,8 +754,13 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><see langword="true"/> if the application has the specified client type, <see langword="false"/> otherwise.</returns>
public virtual async ValueTask<bool> HasClientTypeAsync(
TApplication application!!, string type, CancellationToken cancellationToken = default)
TApplication application, string type, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0209), nameof(type));
@ -646,8 +777,13 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><see langword="true"/> if the application has the specified consent type, <see langword="false"/> otherwise.</returns>
public virtual async ValueTask<bool> HasConsentTypeAsync(
TApplication application!!, string type, CancellationToken cancellationToken = default)
TApplication application, string type, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0210), nameof(type));
@ -664,8 +800,13 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><see langword="true"/> if the application has been granted the specified permission, <see langword="false"/> otherwise.</returns>
public virtual async ValueTask<bool> HasPermissionAsync(
TApplication application!!, string permission, CancellationToken cancellationToken = default)
TApplication application, string permission, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (string.IsNullOrEmpty(permission))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0211), nameof(permission));
@ -682,8 +823,13 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><see langword="true"/> if the requirement has been enforced for the specified application, <see langword="false"/> otherwise.</returns>
public virtual async ValueTask<bool> HasRequirementAsync(
TApplication application!!, string requirement, CancellationToken cancellationToken = default)
TApplication application, string requirement, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (string.IsNullOrEmpty(requirement))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0212), nameof(requirement));
@ -711,8 +857,15 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>All the elements returned when executing the specified query.</returns>
public virtual IAsyncEnumerable<TResult> ListAsync<TResult>(
Func<IQueryable<TApplication>, IQueryable<TResult>> query!!, CancellationToken cancellationToken = default)
=> ListAsync(static (applications, query) => query(applications), query, cancellationToken);
Func<IQueryable<TApplication>, IQueryable<TResult>> query, CancellationToken cancellationToken = default)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return ListAsync(static (applications, query) => query(applications), query, cancellationToken);
}
/// <summary>
/// Executes the specified query and returns all the corresponding elements.
@ -724,9 +877,16 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>All the elements returned when executing the specified query.</returns>
public virtual IAsyncEnumerable<TResult> ListAsync<TState, TResult>(
Func<IQueryable<TApplication>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TApplication>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken = default)
=> Store.ListAsync(query, state, cancellationToken);
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return Store.ListAsync(query, state, cancellationToken);
}
/// <summary>
/// Populates the application using the specified descriptor.
@ -737,9 +897,19 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask PopulateAsync(TApplication application!!,
OpenIddictApplicationDescriptor descriptor!!, CancellationToken cancellationToken = default)
public virtual async ValueTask PopulateAsync(TApplication application,
OpenIddictApplicationDescriptor descriptor, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (descriptor is null)
{
throw new ArgumentNullException(nameof(descriptor));
}
await Store.SetClientIdAsync(application, descriptor.ClientId, cancellationToken);
await Store.SetClientSecretAsync(application, descriptor.ClientSecret, cancellationToken);
await Store.SetClientTypeAsync(application, descriptor.Type, cancellationToken);
@ -765,9 +935,19 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask PopulateAsync(
OpenIddictApplicationDescriptor descriptor!!,
TApplication application!!, CancellationToken cancellationToken = default)
OpenIddictApplicationDescriptor descriptor,
TApplication application, CancellationToken cancellationToken = default)
{
if (descriptor is null)
{
throw new ArgumentNullException(nameof(descriptor));
}
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
descriptor.ClientId = await Store.GetClientIdAsync(application, cancellationToken);
descriptor.ClientSecret = await Store.GetClientSecretAsync(application, cancellationToken);
descriptor.ConsentType = await Store.GetConsentTypeAsync(application, cancellationToken);
@ -835,8 +1015,13 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask UpdateAsync(TApplication application!!, CancellationToken cancellationToken = default)
public virtual async ValueTask UpdateAsync(TApplication application, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
var results = await GetValidationResultsAsync(application, cancellationToken);
if (results.Any(result => result != ValidationResult.Success))
{
@ -885,8 +1070,13 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask UpdateAsync(TApplication application!!, string? secret, CancellationToken cancellationToken = default)
public virtual async ValueTask UpdateAsync(TApplication application, string? secret, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (string.IsNullOrEmpty(secret))
{
await Store.SetClientSecretAsync(application, null, cancellationToken);
@ -910,9 +1100,19 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask UpdateAsync(TApplication application!!,
OpenIddictApplicationDescriptor descriptor!!, CancellationToken cancellationToken = default)
public virtual async ValueTask UpdateAsync(TApplication application,
OpenIddictApplicationDescriptor descriptor, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (descriptor is null)
{
throw new ArgumentNullException(nameof(descriptor));
}
// Store the original client secret for later comparison.
var comparand = await Store.GetClientSecretAsync(application, cancellationToken);
await PopulateAsync(application, descriptor, cancellationToken);
@ -936,8 +1136,13 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The validation error encountered when validating the application.</returns>
public virtual async IAsyncEnumerable<ValidationResult> ValidateAsync(
TApplication application!!, [EnumeratorCancellation] CancellationToken cancellationToken = default)
TApplication application, [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
// Ensure the client_id is not null or empty and is not already used for a different application.
var identifier = await Store.GetClientIdAsync(application, cancellationToken);
if (string.IsNullOrEmpty(identifier))
@ -1046,8 +1251,12 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// whose result returns a boolean indicating whether the client secret was valid.
/// </returns>
public virtual async ValueTask<bool> ValidateClientSecretAsync(
TApplication application!!, string secret, CancellationToken cancellationToken = default)
TApplication application, string secret, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (string.IsNullOrEmpty(secret))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0216), nameof(secret));
@ -1089,8 +1298,13 @@ public class OpenIddictApplicationManager<TApplication> : IOpenIddictApplication
/// whose result returns a boolean indicating whether the redirect_uri was valid.
/// </returns>
public virtual async ValueTask<bool> ValidateRedirectUriAsync(
TApplication application!!, string address, CancellationToken cancellationToken = default)
TApplication application, string address, CancellationToken cancellationToken = default)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (string.IsNullOrEmpty(address))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(address));

275
src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs

@ -28,15 +28,15 @@ namespace OpenIddict.Core;
public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthorizationManager where TAuthorization : class
{
public OpenIddictAuthorizationManager(
IOpenIddictAuthorizationCache<TAuthorization> cache!!,
ILogger<OpenIddictAuthorizationManager<TAuthorization>> logger!!,
IOptionsMonitor<OpenIddictCoreOptions> options!!,
IOpenIddictAuthorizationStoreResolver resolver!!)
IOpenIddictAuthorizationCache<TAuthorization> cache,
ILogger<OpenIddictAuthorizationManager<TAuthorization>> logger,
IOptionsMonitor<OpenIddictCoreOptions> options,
IOpenIddictAuthorizationStoreResolver resolver)
{
Cache = cache;
Logger = logger;
Options = options;
Store = resolver.Get<TAuthorization>();
Cache = cache ?? throw new ArgumentNullException(nameof(cache));
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
Options = options ?? throw new ArgumentNullException(nameof(options));
Store = (resolver ?? throw new ArgumentNullException(nameof(resolver))).Get<TAuthorization>();
}
/// <summary>
@ -81,8 +81,15 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// whose result returns the number of authorizations that match the specified query.
/// </returns>
public virtual ValueTask<long> CountAsync<TResult>(
Func<IQueryable<TAuthorization>, IQueryable<TResult>> query!!, CancellationToken cancellationToken = default)
=> Store.CountAsync(query, cancellationToken);
Func<IQueryable<TAuthorization>, IQueryable<TResult>> query, CancellationToken cancellationToken = default)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return Store.CountAsync(query, cancellationToken);
}
/// <summary>
/// Creates a new authorization.
@ -92,8 +99,13 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask CreateAsync(TAuthorization authorization!!, CancellationToken cancellationToken = default)
public virtual async ValueTask CreateAsync(TAuthorization authorization, CancellationToken cancellationToken = default)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
// If no status was explicitly specified, assume that the authorization is valid.
if (string.IsNullOrEmpty(await Store.GetStatusAsync(authorization, cancellationToken)))
{
@ -145,8 +157,13 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation, whose result returns the authorization.
/// </returns>
public virtual async ValueTask<TAuthorization> CreateAsync(
OpenIddictAuthorizationDescriptor descriptor!!, CancellationToken cancellationToken = default)
OpenIddictAuthorizationDescriptor descriptor, CancellationToken cancellationToken = default)
{
if (descriptor is null)
{
throw new ArgumentNullException(nameof(descriptor));
}
var authorization = await Store.InstantiateAsync(cancellationToken) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0220));
@ -169,9 +186,14 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation, whose result returns the authorization.
/// </returns>
public virtual ValueTask<TAuthorization> CreateAsync(
ClaimsPrincipal principal!!, string subject, string client,
ClaimsPrincipal principal, string subject, string client,
string type, ImmutableArray<string> scopes, CancellationToken cancellationToken = default)
{
if (principal is null)
{
throw new ArgumentNullException(nameof(principal));
}
if (string.IsNullOrEmpty(subject))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0198), nameof(subject));
@ -210,8 +232,13 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask DeleteAsync(TAuthorization authorization!!, CancellationToken cancellationToken = default)
public virtual async ValueTask DeleteAsync(TAuthorization authorization, CancellationToken cancellationToken = default)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (!Options.CurrentValue.DisableEntityCaching)
{
await Cache.RemoveAsync(authorization, cancellationToken);
@ -584,8 +611,15 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// whose result returns the application identifier associated with the authorization.
/// </returns>
public virtual ValueTask<string?> GetApplicationIdAsync(
TAuthorization authorization!!, CancellationToken cancellationToken = default)
=> Store.GetApplicationIdAsync(authorization, cancellationToken);
TAuthorization authorization, CancellationToken cancellationToken = default)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
return Store.GetApplicationIdAsync(authorization, cancellationToken);
}
/// <summary>
/// Executes the specified query and returns the first element.
@ -598,8 +632,15 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// whose result returns the first element returned when executing the query.
/// </returns>
public virtual ValueTask<TResult?> GetAsync<TResult>(
Func<IQueryable<TAuthorization>, IQueryable<TResult>> query!!, CancellationToken cancellationToken = default)
=> GetAsync(static (authorizations, query) => query(authorizations), query, cancellationToken);
Func<IQueryable<TAuthorization>, IQueryable<TResult>> query, CancellationToken cancellationToken = default)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return GetAsync(static (authorizations, query) => query(authorizations), query, cancellationToken);
}
/// <summary>
/// Executes the specified query and returns the first element.
@ -614,9 +655,16 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// whose result returns the first element returned when executing the query.
/// </returns>
public virtual ValueTask<TResult?> GetAsync<TState, TResult>(
Func<IQueryable<TAuthorization>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TAuthorization>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken = default)
=> Store.GetAsync(query, state, cancellationToken);
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return Store.GetAsync(query, state, cancellationToken);
}
/// <summary>
/// Retrieves the creation date associated with an authorization.
@ -628,8 +676,15 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// whose result returns the creation date associated with the specified authorization.
/// </returns>
public virtual ValueTask<DateTimeOffset?> GetCreationDateAsync(
TAuthorization authorization!!, CancellationToken cancellationToken = default)
=> Store.GetCreationDateAsync(authorization, cancellationToken);
TAuthorization authorization, CancellationToken cancellationToken = default)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
return Store.GetCreationDateAsync(authorization, cancellationToken);
}
/// <summary>
/// Retrieves the unique identifier associated with an authorization.
@ -640,8 +695,15 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the unique identifier associated with the authorization.
/// </returns>
public virtual ValueTask<string?> GetIdAsync(TAuthorization authorization!!, CancellationToken cancellationToken = default)
=> Store.GetIdAsync(authorization, cancellationToken);
public virtual ValueTask<string?> GetIdAsync(TAuthorization authorization, CancellationToken cancellationToken = default)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
return Store.GetIdAsync(authorization, cancellationToken);
}
/// <summary>
/// Retrieves the additional properties associated with an authorization.
@ -653,8 +715,15 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// whose result returns all the additional properties associated with the authorization.
/// </returns>
public virtual ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(
TAuthorization authorization!!, CancellationToken cancellationToken = default)
=> Store.GetPropertiesAsync(authorization, cancellationToken);
TAuthorization authorization, CancellationToken cancellationToken = default)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
return Store.GetPropertiesAsync(authorization, cancellationToken);
}
/// <summary>
/// Retrieves the scopes associated with an authorization.
@ -666,8 +735,15 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// whose result returns the scopes associated with the specified authorization.
/// </returns>
public virtual ValueTask<ImmutableArray<string>> GetScopesAsync(
TAuthorization authorization!!, CancellationToken cancellationToken = default)
=> Store.GetScopesAsync(authorization, cancellationToken);
TAuthorization authorization, CancellationToken cancellationToken = default)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
return Store.GetScopesAsync(authorization, cancellationToken);
}
/// <summary>
/// Retrieves the status associated with an authorization.
@ -679,8 +755,15 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// whose result returns the status associated with the specified authorization.
/// </returns>
public virtual ValueTask<string?> GetStatusAsync(
TAuthorization authorization!!, CancellationToken cancellationToken = default)
=> Store.GetStatusAsync(authorization, cancellationToken);
TAuthorization authorization, CancellationToken cancellationToken = default)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
return Store.GetStatusAsync(authorization, cancellationToken);
}
/// <summary>
/// Retrieves the subject associated with an authorization.
@ -692,8 +775,15 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// whose result returns the subject associated with the specified authorization.
/// </returns>
public virtual ValueTask<string?> GetSubjectAsync(
TAuthorization authorization!!, CancellationToken cancellationToken = default)
=> Store.GetSubjectAsync(authorization, cancellationToken);
TAuthorization authorization, CancellationToken cancellationToken = default)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
return Store.GetSubjectAsync(authorization, cancellationToken);
}
/// <summary>
/// Retrieves the type associated with an authorization.
@ -705,8 +795,15 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// whose result returns the type associated with the specified authorization.
/// </returns>
public virtual ValueTask<string?> GetTypeAsync(
TAuthorization authorization!!, CancellationToken cancellationToken = default)
=> Store.GetTypeAsync(authorization, cancellationToken);
TAuthorization authorization, CancellationToken cancellationToken = default)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
return Store.GetTypeAsync(authorization, cancellationToken);
}
/// <summary>
/// Determines whether the specified scopes are included in the authorization.
@ -715,10 +812,17 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// <param name="scopes">The scopes.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><see langword="true"/> if the scopes are included in the authorization, <see langword="false"/> otherwise.</returns>
public virtual async ValueTask<bool> HasScopesAsync(TAuthorization authorization!!,
public virtual async ValueTask<bool> HasScopesAsync(TAuthorization authorization,
ImmutableArray<string> scopes, CancellationToken cancellationToken = default)
=> new HashSet<string>(await Store.GetScopesAsync(
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
return new HashSet<string>(await Store.GetScopesAsync(
authorization, cancellationToken), StringComparer.Ordinal).IsSupersetOf(scopes);
}
/// <summary>
/// Determines whether a given authorization has the specified status.
@ -727,9 +831,14 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// <param name="status">The expected status.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><see langword="true"/> if the authorization has the specified status, <see langword="false"/> otherwise.</returns>
public virtual async ValueTask<bool> HasStatusAsync(TAuthorization authorization!!,
public virtual async ValueTask<bool> HasStatusAsync(TAuthorization authorization,
string status, CancellationToken cancellationToken = default)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (string.IsNullOrEmpty(status))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0199), nameof(status));
@ -746,8 +855,13 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><see langword="true"/> if the authorization has the specified type, <see langword="false"/> otherwise.</returns>
public virtual async ValueTask<bool> HasTypeAsync(
TAuthorization authorization!!, string type, CancellationToken cancellationToken = default)
TAuthorization authorization, string type, CancellationToken cancellationToken = default)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0200), nameof(type));
@ -775,8 +889,15 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>All the elements returned when executing the specified query.</returns>
public virtual IAsyncEnumerable<TResult> ListAsync<TResult>(
Func<IQueryable<TAuthorization>, IQueryable<TResult>> query!!, CancellationToken cancellationToken = default)
=> ListAsync(static (authorizations, query) => query(authorizations), query, cancellationToken);
Func<IQueryable<TAuthorization>, IQueryable<TResult>> query, CancellationToken cancellationToken = default)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return ListAsync(static (authorizations, query) => query(authorizations), query, cancellationToken);
}
/// <summary>
/// Executes the specified query and returns all the corresponding elements.
@ -788,9 +909,16 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>All the elements returned when executing the specified query.</returns>
public virtual IAsyncEnumerable<TResult> ListAsync<TState, TResult>(
Func<IQueryable<TAuthorization>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TAuthorization>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken = default)
=> Store.ListAsync(query, state, cancellationToken);
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return Store.ListAsync(query, state, cancellationToken);
}
/// <summary>
/// Populates the authorization using the specified descriptor.
@ -801,9 +929,19 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask PopulateAsync(TAuthorization authorization!!,
OpenIddictAuthorizationDescriptor descriptor!!, CancellationToken cancellationToken = default)
public virtual async ValueTask PopulateAsync(TAuthorization authorization,
OpenIddictAuthorizationDescriptor descriptor, CancellationToken cancellationToken = default)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (descriptor is null)
{
throw new ArgumentNullException(nameof(descriptor));
}
await Store.SetApplicationIdAsync(authorization, descriptor.ApplicationId, cancellationToken);
await Store.SetCreationDateAsync(authorization, descriptor.CreationDate, cancellationToken);
await Store.SetPropertiesAsync(authorization, descriptor.Properties.ToImmutableDictionary(), cancellationToken);
@ -823,9 +961,19 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask PopulateAsync(
OpenIddictAuthorizationDescriptor descriptor!!,
TAuthorization authorization!!, CancellationToken cancellationToken = default)
OpenIddictAuthorizationDescriptor descriptor,
TAuthorization authorization, CancellationToken cancellationToken = default)
{
if (descriptor is null)
{
throw new ArgumentNullException(nameof(descriptor));
}
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
descriptor.ApplicationId = await Store.GetApplicationIdAsync(authorization, cancellationToken);
descriptor.CreationDate = await Store.GetCreationDateAsync(authorization, cancellationToken);
descriptor.Scopes.Clear();
@ -863,8 +1011,13 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// <param name="authorization">The authorization to revoke.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><see langword="true"/> if the authorization was successfully revoked, <see langword="false"/> otherwise.</returns>
public virtual async ValueTask<bool> TryRevokeAsync(TAuthorization authorization!!, CancellationToken cancellationToken = default)
public virtual async ValueTask<bool> TryRevokeAsync(TAuthorization authorization, CancellationToken cancellationToken = default)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
var status = await Store.GetStatusAsync(authorization, cancellationToken);
if (string.Equals(status, Statuses.Revoked, StringComparison.OrdinalIgnoreCase))
{
@ -905,8 +1058,13 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask UpdateAsync(TAuthorization authorization!!, CancellationToken cancellationToken = default)
public virtual async ValueTask UpdateAsync(TAuthorization authorization, CancellationToken cancellationToken = default)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
var results = await GetValidationResultsAsync(authorization, cancellationToken);
if (results.Any(result => result != ValidationResult.Success))
{
@ -953,9 +1111,19 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask UpdateAsync(TAuthorization authorization!!,
OpenIddictAuthorizationDescriptor descriptor!!, CancellationToken cancellationToken = default)
public virtual async ValueTask UpdateAsync(TAuthorization authorization,
OpenIddictAuthorizationDescriptor descriptor, CancellationToken cancellationToken = default)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (descriptor is null)
{
throw new ArgumentNullException(nameof(descriptor));
}
await PopulateAsync(authorization, descriptor, cancellationToken);
await UpdateAsync(authorization, cancellationToken);
}
@ -967,8 +1135,13 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The validation error encountered when validating the authorization.</returns>
public virtual async IAsyncEnumerable<ValidationResult> ValidateAsync(
TAuthorization authorization!!, [EnumeratorCancellation] CancellationToken cancellationToken = default)
TAuthorization authorization, [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
var type = await Store.GetTypeAsync(authorization, cancellationToken);
if (string.IsNullOrEmpty(type))
{

276
src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs

@ -27,15 +27,15 @@ namespace OpenIddict.Core;
public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TScope : class
{
public OpenIddictScopeManager(
IOpenIddictScopeCache<TScope> cache!!,
ILogger<OpenIddictScopeManager<TScope>> logger!!,
IOptionsMonitor<OpenIddictCoreOptions> options!!,
IOpenIddictScopeStoreResolver resolver!!)
IOpenIddictScopeCache<TScope> cache,
ILogger<OpenIddictScopeManager<TScope>> logger,
IOptionsMonitor<OpenIddictCoreOptions> options,
IOpenIddictScopeStoreResolver resolver)
{
Cache = cache;
Logger = logger;
Options = options;
Store = resolver.Get<TScope>();
Cache = cache ?? throw new ArgumentNullException(nameof(cache));
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
Options = options ?? throw new ArgumentNullException(nameof(options));
Store = (resolver ?? throw new ArgumentNullException(nameof(resolver))).Get<TScope>();
}
/// <summary>
@ -80,8 +80,15 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// whose result returns the number of scopes that match the specified query.
/// </returns>
public virtual ValueTask<long> CountAsync<TResult>(
Func<IQueryable<TScope>, IQueryable<TResult>> query!!, CancellationToken cancellationToken = default)
=> Store.CountAsync(query, cancellationToken);
Func<IQueryable<TScope>, IQueryable<TResult>> query, CancellationToken cancellationToken = default)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return Store.CountAsync(query, cancellationToken);
}
/// <summary>
/// Creates a new scope.
@ -91,8 +98,13 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask CreateAsync(TScope scope!!, CancellationToken cancellationToken = default)
public virtual async ValueTask CreateAsync(TScope scope, CancellationToken cancellationToken = default)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
var results = await GetValidationResultsAsync(scope, cancellationToken);
if (results.Any(result => result != ValidationResult.Success))
{
@ -138,8 +150,13 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation, whose result returns the scope.
/// </returns>
public virtual async ValueTask<TScope> CreateAsync(
OpenIddictScopeDescriptor descriptor!!, CancellationToken cancellationToken = default)
OpenIddictScopeDescriptor descriptor, CancellationToken cancellationToken = default)
{
if (descriptor is null)
{
throw new ArgumentNullException(nameof(descriptor));
}
var scope = await Store.InstantiateAsync(cancellationToken) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0223));
@ -157,8 +174,13 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask DeleteAsync(TScope scope!!, CancellationToken cancellationToken = default)
public virtual async ValueTask DeleteAsync(TScope scope, CancellationToken cancellationToken = default)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
if (!Options.CurrentValue.DisableEntityCaching)
{
await Cache.RemoveAsync(scope, cancellationToken);
@ -251,7 +273,7 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
public virtual IAsyncEnumerable<TScope> FindByNamesAsync(
ImmutableArray<string> names, CancellationToken cancellationToken = default)
{
if (names.Any(string.IsNullOrEmpty))
if (names.Any(name => string.IsNullOrEmpty(name)))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0203), nameof(names));
}
@ -336,8 +358,15 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// whose result returns the first element returned when executing the query.
/// </returns>
public virtual ValueTask<TResult?> GetAsync<TResult>(
Func<IQueryable<TScope>, IQueryable<TResult>> query!!, CancellationToken cancellationToken = default)
=> GetAsync(static (scopes, query) => query(scopes), query, cancellationToken);
Func<IQueryable<TScope>, IQueryable<TResult>> query, CancellationToken cancellationToken = default)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return GetAsync(static (scopes, query) => query(scopes), query, cancellationToken);
}
/// <summary>
/// Executes the specified query and returns the first element.
@ -352,9 +381,16 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// whose result returns the first element returned when executing the query.
/// </returns>
public virtual ValueTask<TResult?> GetAsync<TState, TResult>(
Func<IQueryable<TScope>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TScope>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken = default)
=> Store.GetAsync(query, state, cancellationToken);
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return Store.GetAsync(query, state, cancellationToken);
}
/// <summary>
/// Retrieves the description associated with a scope.
@ -365,8 +401,15 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the description associated with the specified scope.
/// </returns>
public virtual ValueTask<string?> GetDescriptionAsync(TScope scope!!, CancellationToken cancellationToken = default)
=> Store.GetDescriptionAsync(scope, cancellationToken);
public virtual ValueTask<string?> GetDescriptionAsync(TScope scope, CancellationToken cancellationToken = default)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
return Store.GetDescriptionAsync(scope, cancellationToken);
}
/// <summary>
/// Retrieves the localized descriptions associated with an scope.
@ -378,9 +421,21 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// whose result returns all the localized descriptions associated with the scope.
/// </returns>
public virtual async ValueTask<ImmutableDictionary<CultureInfo, string>> GetDescriptionsAsync(
TScope scope!!, CancellationToken cancellationToken = default)
=> await Store.GetDescriptionsAsync(scope, cancellationToken) is { Count: > 0 } descriptions ?
descriptions : ImmutableDictionary.Create<CultureInfo, string>();
TScope scope, CancellationToken cancellationToken = default)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
var descriptions = await Store.GetDescriptionsAsync(scope, cancellationToken);
if (descriptions is null || descriptions.Count == 0)
{
return ImmutableDictionary.Create<CultureInfo, string>();
}
return descriptions;
}
/// <summary>
/// Retrieves the display name associated with a scope.
@ -391,8 +446,15 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the display name associated with the scope.
/// </returns>
public virtual ValueTask<string?> GetDisplayNameAsync(TScope scope!!, CancellationToken cancellationToken = default)
=> Store.GetDisplayNameAsync(scope, cancellationToken);
public virtual ValueTask<string?> GetDisplayNameAsync(TScope scope, CancellationToken cancellationToken = default)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
return Store.GetDisplayNameAsync(scope, cancellationToken);
}
/// <summary>
/// Retrieves the localized display names associated with an scope.
@ -404,9 +466,21 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// whose result returns all the localized display names associated with the scope.
/// </returns>
public virtual async ValueTask<ImmutableDictionary<CultureInfo, string>> GetDisplayNamesAsync(
TScope scope!!, CancellationToken cancellationToken = default)
=> await Store.GetDisplayNamesAsync(scope, cancellationToken) is { Count: > 0 } names ?
names : ImmutableDictionary.Create<CultureInfo, string>();
TScope scope, CancellationToken cancellationToken = default)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
var names = await Store.GetDisplayNamesAsync(scope, cancellationToken);
if (names is null || names.Count == 0)
{
return ImmutableDictionary.Create<CultureInfo, string>();
}
return names;
}
/// <summary>
/// Retrieves the unique identifier associated with a scope.
@ -417,8 +491,15 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the unique identifier associated with the scope.
/// </returns>
public virtual ValueTask<string?> GetIdAsync(TScope scope!!, CancellationToken cancellationToken = default)
=> Store.GetIdAsync(scope, cancellationToken);
public virtual ValueTask<string?> GetIdAsync(TScope scope, CancellationToken cancellationToken = default)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
return Store.GetIdAsync(scope, cancellationToken);
}
/// <summary>
/// Retrieves the localized display name associated with an scope
@ -447,8 +528,18 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// whose result returns the matching display name associated with the scope.
/// </returns>
public virtual async ValueTask<string?> GetLocalizedDisplayNameAsync(
TScope scope!!, CultureInfo culture!!, CancellationToken cancellationToken = default)
TScope scope, CultureInfo culture, CancellationToken cancellationToken = default)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
if (culture is null)
{
throw new ArgumentNullException(nameof(culture));
}
var names = await Store.GetDisplayNamesAsync(scope, cancellationToken);
if (names is not { Count: > 0 })
{
@ -497,8 +588,18 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// whose result returns the matching localized description associated with the scope.
/// </returns>
public virtual async ValueTask<string?> GetLocalizedDescriptionAsync(
TScope scope!!, CultureInfo culture!!, CancellationToken cancellationToken = default)
TScope scope, CultureInfo culture, CancellationToken cancellationToken = default)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
if (culture is null)
{
throw new ArgumentNullException(nameof(culture));
}
var descriptions = await Store.GetDescriptionsAsync(scope, cancellationToken);
if (descriptions is not { Count: > 0 })
{
@ -529,8 +630,15 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the name associated with the specified scope.
/// </returns>
public virtual ValueTask<string?> GetNameAsync(TScope scope!!, CancellationToken cancellationToken = default)
=> Store.GetNameAsync(scope, cancellationToken);
public virtual ValueTask<string?> GetNameAsync(TScope scope, CancellationToken cancellationToken = default)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
return Store.GetNameAsync(scope, cancellationToken);
}
/// <summary>
/// Retrieves the additional properties associated with a scope.
@ -542,8 +650,15 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// whose result returns all the additional properties associated with the scope.
/// </returns>
public virtual ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(
TScope scope!!, CancellationToken cancellationToken = default)
=> Store.GetPropertiesAsync(scope, cancellationToken);
TScope scope, CancellationToken cancellationToken = default)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
return Store.GetPropertiesAsync(scope, cancellationToken);
}
/// <summary>
/// Retrieves the resources associated with a scope.
@ -555,8 +670,15 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// whose result returns all the resources associated with the scope.
/// </returns>
public virtual ValueTask<ImmutableArray<string>> GetResourcesAsync(
TScope scope!!, CancellationToken cancellationToken = default)
=> Store.GetResourcesAsync(scope, cancellationToken);
TScope scope, CancellationToken cancellationToken = default)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
return Store.GetResourcesAsync(scope, cancellationToken);
}
/// <summary>
/// Executes the specified query and returns all the corresponding elements.
@ -577,8 +699,15 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>All the elements returned when executing the specified query.</returns>
public virtual IAsyncEnumerable<TResult> ListAsync<TResult>(
Func<IQueryable<TScope>, IQueryable<TResult>> query!!, CancellationToken cancellationToken = default)
=> ListAsync(static (scopes, query) => query(scopes), query, cancellationToken);
Func<IQueryable<TScope>, IQueryable<TResult>> query, CancellationToken cancellationToken = default)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return ListAsync(static (scopes, query) => query(scopes), query, cancellationToken);
}
/// <summary>
/// Executes the specified query and returns all the corresponding elements.
@ -590,9 +719,16 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>All the elements returned when executing the specified query.</returns>
public virtual IAsyncEnumerable<TResult> ListAsync<TState, TResult>(
Func<IQueryable<TScope>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TScope>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken = default)
=> Store.ListAsync(query, state, cancellationToken);
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return Store.ListAsync(query, state, cancellationToken);
}
/// <summary>
/// Lists all the resources associated with the specified scopes.
@ -625,9 +761,19 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask PopulateAsync(TScope scope!!,
OpenIddictScopeDescriptor descriptor!!, CancellationToken cancellationToken = default)
public virtual async ValueTask PopulateAsync(TScope scope,
OpenIddictScopeDescriptor descriptor, CancellationToken cancellationToken = default)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
if (descriptor is null)
{
throw new ArgumentNullException(nameof(descriptor));
}
await Store.SetDescriptionAsync(scope, descriptor.Description, cancellationToken);
await Store.SetDescriptionsAsync(scope, descriptor.Descriptions.ToImmutableDictionary(), cancellationToken);
await Store.SetDisplayNameAsync(scope, descriptor.DisplayName, cancellationToken);
@ -647,9 +793,19 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask PopulateAsync(
OpenIddictScopeDescriptor descriptor!!,
TScope scope!!, CancellationToken cancellationToken = default)
OpenIddictScopeDescriptor descriptor,
TScope scope, CancellationToken cancellationToken = default)
{
if (descriptor is null)
{
throw new ArgumentNullException(nameof(descriptor));
}
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
descriptor.Description = await Store.GetDescriptionAsync(scope, cancellationToken);
descriptor.DisplayName = await Store.GetDisplayNameAsync(scope, cancellationToken);
descriptor.Name = await Store.GetNameAsync(scope, cancellationToken);
@ -683,8 +839,13 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask UpdateAsync(TScope scope!!, CancellationToken cancellationToken = default)
public virtual async ValueTask UpdateAsync(TScope scope, CancellationToken cancellationToken = default)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
var results = await GetValidationResultsAsync(scope, cancellationToken);
if (results.Any(result => result != ValidationResult.Success))
{
@ -731,9 +892,19 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask UpdateAsync(TScope scope!!,
OpenIddictScopeDescriptor descriptor!!, CancellationToken cancellationToken = default)
public virtual async ValueTask UpdateAsync(TScope scope,
OpenIddictScopeDescriptor descriptor, CancellationToken cancellationToken = default)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
if (descriptor is null)
{
throw new ArgumentNullException(nameof(descriptor));
}
await PopulateAsync(scope, descriptor, cancellationToken);
await UpdateAsync(scope, cancellationToken);
}
@ -745,8 +916,13 @@ public class OpenIddictScopeManager<TScope> : IOpenIddictScopeManager where TSco
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The validation error encountered when validating the scope.</returns>
public virtual async IAsyncEnumerable<ValidationResult> ValidateAsync(
TScope scope!!, [EnumeratorCancellation] CancellationToken cancellationToken = default)
TScope scope, [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
// Ensure the name is not null or empty, does not contain a
// space and is not already used for a different scope entity.
var name = await Store.GetNameAsync(scope, cancellationToken);

323
src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs

@ -28,15 +28,15 @@ namespace OpenIddict.Core;
public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TToken : class
{
public OpenIddictTokenManager(
IOpenIddictTokenCache<TToken> cache!!,
ILogger<OpenIddictTokenManager<TToken>> logger!!,
IOptionsMonitor<OpenIddictCoreOptions> options!!,
IOpenIddictTokenStoreResolver resolver!!)
IOpenIddictTokenCache<TToken> cache,
ILogger<OpenIddictTokenManager<TToken>> logger,
IOptionsMonitor<OpenIddictCoreOptions> options,
IOpenIddictTokenStoreResolver resolver)
{
Cache = cache;
Logger = logger;
Options = options;
Store = resolver.Get<TToken>();
Cache = cache ?? throw new ArgumentNullException(nameof(cache));
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
Options = options ?? throw new ArgumentNullException(nameof(options));
Store = (resolver ?? throw new ArgumentNullException(nameof(resolver))).Get<TToken>();
}
/// <summary>
@ -81,8 +81,15 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// whose result returns the number of tokens that match the specified query.
/// </returns>
public virtual ValueTask<long> CountAsync<TResult>(
Func<IQueryable<TToken>, IQueryable<TResult>> query!!, CancellationToken cancellationToken = default)
=> Store.CountAsync(query, cancellationToken);
Func<IQueryable<TToken>, IQueryable<TResult>> query, CancellationToken cancellationToken = default)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return Store.CountAsync(query, cancellationToken);
}
/// <summary>
/// Creates a new token.
@ -92,8 +99,13 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask CreateAsync(TToken token!!, CancellationToken cancellationToken = default)
public virtual async ValueTask CreateAsync(TToken token, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
// If no status was explicitly specified, assume that the token is valid.
if (string.IsNullOrEmpty(await Store.GetStatusAsync(token, cancellationToken)))
{
@ -153,8 +165,13 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation, whose result returns the token.
/// </returns>
public virtual async ValueTask<TToken> CreateAsync(
OpenIddictTokenDescriptor descriptor!!, CancellationToken cancellationToken = default)
OpenIddictTokenDescriptor descriptor, CancellationToken cancellationToken = default)
{
if (descriptor is null)
{
throw new ArgumentNullException(nameof(descriptor));
}
var token = await Store.InstantiateAsync(cancellationToken) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0226));
@ -172,8 +189,13 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask DeleteAsync(TToken token!!, CancellationToken cancellationToken = default)
public virtual async ValueTask DeleteAsync(TToken token, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
if (!Options.CurrentValue.DisableEntityCaching)
{
await Cache.RemoveAsync(token, cancellationToken);
@ -554,8 +576,15 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the application identifier associated with the token.
/// </returns>
public virtual ValueTask<string?> GetApplicationIdAsync(TToken token!!, CancellationToken cancellationToken = default)
=> Store.GetApplicationIdAsync(token, cancellationToken);
public virtual ValueTask<string?> GetApplicationIdAsync(TToken token, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return Store.GetApplicationIdAsync(token, cancellationToken);
}
/// <summary>
/// Executes the specified query and returns the first element.
@ -568,8 +597,15 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// whose result returns the first element returned when executing the query.
/// </returns>
public virtual ValueTask<TResult?> GetAsync<TResult>(
Func<IQueryable<TToken>, IQueryable<TResult>> query!!, CancellationToken cancellationToken = default)
=> GetAsync(static (tokens, query) => query(tokens), query, cancellationToken);
Func<IQueryable<TToken>, IQueryable<TResult>> query, CancellationToken cancellationToken = default)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return GetAsync(static (tokens, query) => query(tokens), query, cancellationToken);
}
/// <summary>
/// Executes the specified query and returns the first element.
@ -584,9 +620,16 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// whose result returns the first element returned when executing the query.
/// </returns>
public virtual ValueTask<TResult?> GetAsync<TState, TResult>(
Func<IQueryable<TToken>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TToken>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken = default)
=> Store.GetAsync(query, state, cancellationToken);
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return Store.GetAsync(query, state, cancellationToken);
}
/// <summary>
/// Retrieves the optional authorization identifier associated with a token.
@ -597,8 +640,15 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the authorization identifier associated with the token.
/// </returns>
public virtual ValueTask<string?> GetAuthorizationIdAsync(TToken token!!, CancellationToken cancellationToken = default)
=> Store.GetAuthorizationIdAsync(token, cancellationToken);
public virtual ValueTask<string?> GetAuthorizationIdAsync(TToken token, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return Store.GetAuthorizationIdAsync(token, cancellationToken);
}
/// <summary>
/// Retrieves the creation date associated with a token.
@ -609,8 +659,15 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the creation date associated with the specified token.
/// </returns>
public virtual ValueTask<DateTimeOffset?> GetCreationDateAsync(TToken token!!, CancellationToken cancellationToken = default)
=> Store.GetCreationDateAsync(token, cancellationToken);
public virtual ValueTask<DateTimeOffset?> GetCreationDateAsync(TToken token, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return Store.GetCreationDateAsync(token, cancellationToken);
}
/// <summary>
/// Retrieves the expiration date associated with a token.
@ -621,8 +678,15 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the expiration date associated with the specified token.
/// </returns>
public virtual ValueTask<DateTimeOffset?> GetExpirationDateAsync(TToken token!!, CancellationToken cancellationToken = default)
=> Store.GetExpirationDateAsync(token, cancellationToken);
public virtual ValueTask<DateTimeOffset?> GetExpirationDateAsync(TToken token, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return Store.GetExpirationDateAsync(token, cancellationToken);
}
/// <summary>
/// Retrieves the unique identifier associated with a token.
@ -633,8 +697,15 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the unique identifier associated with the token.
/// </returns>
public virtual ValueTask<string?> GetIdAsync(TToken token!!, CancellationToken cancellationToken = default)
=> Store.GetIdAsync(token, cancellationToken);
public virtual ValueTask<string?> GetIdAsync(TToken token, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return Store.GetIdAsync(token, cancellationToken);
}
/// <summary>
/// Retrieves the payload associated with a token.
@ -645,8 +716,15 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the payload associated with the specified token.
/// </returns>
public virtual ValueTask<string?> GetPayloadAsync(TToken token!!, CancellationToken cancellationToken = default)
=> Store.GetPayloadAsync(token, cancellationToken);
public virtual ValueTask<string?> GetPayloadAsync(TToken token, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return Store.GetPayloadAsync(token, cancellationToken);
}
/// <summary>
/// Retrieves the additional properties associated with a token.
@ -658,8 +736,15 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// whose result returns all the additional properties associated with the token.
/// </returns>
public virtual ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(
TToken token!!, CancellationToken cancellationToken = default)
=> Store.GetPropertiesAsync(token, cancellationToken);
TToken token, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return Store.GetPropertiesAsync(token, cancellationToken);
}
/// <summary>
/// Retrieves the redemption date associated with a token.
@ -670,8 +755,15 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the redemption date associated with the specified token.
/// </returns>
public virtual ValueTask<DateTimeOffset?> GetRedemptionDateAsync(TToken token!!, CancellationToken cancellationToken = default)
=> Store.GetRedemptionDateAsync(token, cancellationToken);
public virtual ValueTask<DateTimeOffset?> GetRedemptionDateAsync(TToken token, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return Store.GetRedemptionDateAsync(token, cancellationToken);
}
/// <summary>
/// Retrieves the reference identifier associated with a token.
@ -684,8 +776,15 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the reference identifier associated with the specified token.
/// </returns>
public virtual ValueTask<string?> GetReferenceIdAsync(TToken token!!, CancellationToken cancellationToken = default)
=> Store.GetReferenceIdAsync(token, cancellationToken);
public virtual ValueTask<string?> GetReferenceIdAsync(TToken token, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return Store.GetReferenceIdAsync(token, cancellationToken);
}
/// <summary>
/// Retrieves the status associated with a token.
@ -696,8 +795,15 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the status associated with the specified token.
/// </returns>
public virtual ValueTask<string?> GetStatusAsync(TToken token!!, CancellationToken cancellationToken = default)
=> Store.GetStatusAsync(token, cancellationToken);
public virtual ValueTask<string?> GetStatusAsync(TToken token, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return Store.GetStatusAsync(token, cancellationToken);
}
/// <summary>
/// Retrieves the subject associated with a token.
@ -708,8 +814,15 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the subject associated with the specified token.
/// </returns>
public virtual ValueTask<string?> GetSubjectAsync(TToken token!!, CancellationToken cancellationToken = default)
=> Store.GetSubjectAsync(token, cancellationToken);
public virtual ValueTask<string?> GetSubjectAsync(TToken token, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return Store.GetSubjectAsync(token, cancellationToken);
}
/// <summary>
/// Retrieves the token type associated with a token.
@ -720,8 +833,15 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the token type associated with the specified token.
/// </returns>
public virtual ValueTask<string?> GetTypeAsync(TToken token!!, CancellationToken cancellationToken = default)
=> Store.GetTypeAsync(token, cancellationToken);
public virtual ValueTask<string?> GetTypeAsync(TToken token, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return Store.GetTypeAsync(token, cancellationToken);
}
/// <summary>
/// Determines whether a given token has the specified status.
@ -730,8 +850,13 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// <param name="status">The expected status.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><see langword="true"/> if the token has the specified status, <see langword="false"/> otherwise.</returns>
public virtual async ValueTask<bool> HasStatusAsync(TToken token!!, string status, CancellationToken cancellationToken = default)
public virtual async ValueTask<bool> HasStatusAsync(TToken token, string status, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
if (string.IsNullOrEmpty(status))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0199), nameof(status));
@ -747,8 +872,13 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// <param name="type">The expected type.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><see langword="true"/> if the token has the specified type, <see langword="false"/> otherwise.</returns>
public virtual async ValueTask<bool> HasTypeAsync(TToken token!!, string type, CancellationToken cancellationToken = default)
public virtual async ValueTask<bool> HasTypeAsync(TToken token, string type, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0200), nameof(type));
@ -764,8 +894,13 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// <param name="types">The expected types.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><see langword="true"/> if the token has any of the specified types, <see langword="false"/> otherwise.</returns>
public virtual async ValueTask<bool> HasTypeAsync(TToken token!!, ImmutableArray<string> types, CancellationToken cancellationToken = default)
public virtual async ValueTask<bool> HasTypeAsync(TToken token, ImmutableArray<string> types, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
var type = await Store.GetTypeAsync(token, cancellationToken);
if (string.IsNullOrEmpty(type))
{
@ -802,8 +937,15 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>All the elements returned when executing the specified query.</returns>
public virtual IAsyncEnumerable<TResult> ListAsync<TResult>(
Func<IQueryable<TToken>, IQueryable<TResult>> query!!, CancellationToken cancellationToken = default)
=> ListAsync(static (tokens, query) => query(tokens), query, cancellationToken);
Func<IQueryable<TToken>, IQueryable<TResult>> query, CancellationToken cancellationToken = default)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return ListAsync(static (tokens, query) => query(tokens), query, cancellationToken);
}
/// <summary>
/// Executes the specified query and returns all the corresponding elements.
@ -815,9 +957,16 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>All the elements returned when executing the specified query.</returns>
public virtual IAsyncEnumerable<TResult> ListAsync<TState, TResult>(
Func<IQueryable<TToken>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TToken>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken = default)
=> Store.ListAsync(query, state, cancellationToken);
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return Store.ListAsync(query, state, cancellationToken);
}
/// <summary>
/// Populates the token using the specified descriptor.
@ -828,9 +977,19 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask PopulateAsync(TToken token!!,
OpenIddictTokenDescriptor descriptor!!, CancellationToken cancellationToken = default)
public virtual async ValueTask PopulateAsync(TToken token,
OpenIddictTokenDescriptor descriptor, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
if (descriptor is null)
{
throw new ArgumentNullException(nameof(descriptor));
}
await Store.SetApplicationIdAsync(token, descriptor.ApplicationId, cancellationToken);
await Store.SetAuthorizationIdAsync(token, descriptor.AuthorizationId, cancellationToken);
await Store.SetCreationDateAsync(token, descriptor.CreationDate, cancellationToken);
@ -854,9 +1013,19 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask PopulateAsync(
OpenIddictTokenDescriptor descriptor!!,
TToken token!!, CancellationToken cancellationToken = default)
OpenIddictTokenDescriptor descriptor,
TToken token, CancellationToken cancellationToken = default)
{
if (descriptor is null)
{
throw new ArgumentNullException(nameof(descriptor));
}
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
descriptor.ApplicationId = await Store.GetApplicationIdAsync(token, cancellationToken);
descriptor.AuthorizationId = await Store.GetAuthorizationIdAsync(token, cancellationToken);
descriptor.CreationDate = await Store.GetCreationDateAsync(token, cancellationToken);
@ -886,15 +1055,19 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// </returns>
public virtual ValueTask PruneAsync(DateTimeOffset threshold, CancellationToken cancellationToken = default)
=> Store.PruneAsync(threshold, cancellationToken);
/// <summary>
/// Tries to redeem a token.
/// </summary>
/// <param name="token">The token to redeem.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><see langword="true"/> if the token was successfully redemeed, <see langword="false"/> otherwise.</returns>
public virtual async ValueTask<bool> TryRedeemAsync(TToken token!!, CancellationToken cancellationToken = default)
public virtual async ValueTask<bool> TryRedeemAsync(TToken token, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
// If the token doesn't have a redemption date attached, this likely means it's
// the first time the token is redeemed. In this case, attach the current date.
if (await Store.GetRedemptionDateAsync(token, cancellationToken) is null)
@ -934,8 +1107,13 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// <param name="token">The token to reject.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><see langword="true"/> if the token was successfully redemeed, <see langword="false"/> otherwise.</returns>
public virtual async ValueTask<bool> TryRejectAsync(TToken token!!, CancellationToken cancellationToken = default)
public virtual async ValueTask<bool> TryRejectAsync(TToken token, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
await Store.SetStatusAsync(token, Statuses.Rejected, cancellationToken);
try
@ -968,8 +1146,13 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// <param name="token">The token to revoke.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><see langword="true"/> if the token was successfully revoked, <see langword="false"/> otherwise.</returns>
public virtual async ValueTask<bool> TryRevokeAsync(TToken token!!, CancellationToken cancellationToken = default)
public virtual async ValueTask<bool> TryRevokeAsync(TToken token, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
await Store.SetStatusAsync(token, Statuses.Revoked, cancellationToken);
try
@ -1004,8 +1187,13 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask UpdateAsync(TToken token!!, CancellationToken cancellationToken = default)
public virtual async ValueTask UpdateAsync(TToken token, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
var results = await GetValidationResultsAsync(token, cancellationToken);
if (results.Any(result => result != ValidationResult.Success))
{
@ -1052,9 +1240,19 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public virtual async ValueTask UpdateAsync(TToken token!!,
OpenIddictTokenDescriptor descriptor!!, CancellationToken cancellationToken = default)
public virtual async ValueTask UpdateAsync(TToken token,
OpenIddictTokenDescriptor descriptor, CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
if (descriptor is null)
{
throw new ArgumentNullException(nameof(descriptor));
}
// Store the original reference identifier for later comparison.
var comparand = await Store.GetReferenceIdAsync(token, cancellationToken);
await PopulateAsync(token, descriptor, cancellationToken);
@ -1077,8 +1275,13 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The validation error encountered when validating the token.</returns>
public virtual async IAsyncEnumerable<ValidationResult> ValidateAsync(
TToken token!!, [EnumeratorCancellation] CancellationToken cancellationToken = default)
TToken token, [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
// If a reference identifier was associated with the token,
// ensure it's not already used for a different token.
var identifier = await Store.GetReferenceIdAsync(token, cancellationToken);

123
src/OpenIddict.Core/OpenIddictCoreBuilder.cs

@ -20,8 +20,8 @@ public class OpenIddictCoreBuilder
/// Initializes a new instance of <see cref="OpenIddictCoreBuilder"/>.
/// </summary>
/// <param name="services">The services collection.</param>
public OpenIddictCoreBuilder(IServiceCollection services!!)
=> Services = services;
public OpenIddictCoreBuilder(IServiceCollection services)
=> Services = services ?? throw new ArgumentNullException(nameof(services));
/// <summary>
/// Gets the services collection.
@ -35,8 +35,13 @@ public class OpenIddictCoreBuilder
/// <param name="configuration">The delegate used to configure the OpenIddict options.</param>
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
public OpenIddictCoreBuilder Configure(Action<OpenIddictCoreOptions> configuration!!)
public OpenIddictCoreBuilder Configure(Action<OpenIddictCoreOptions> configuration)
{
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
Services.Configure(configuration);
return this;
@ -64,8 +69,13 @@ public class OpenIddictCoreBuilder
/// <param name="type">The type of the custom store.</param>
/// <param name="lifetime">The lifetime of the registered service.</param>
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
public OpenIddictCoreBuilder AddApplicationStore(Type type!!, ServiceLifetime lifetime = ServiceLifetime.Scoped)
public OpenIddictCoreBuilder AddApplicationStore(Type type, ServiceLifetime lifetime = ServiceLifetime.Scoped)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(IOpenIddictApplicationStore<>)) ??
throw new ArgumentException(SR.GetResourceString(SR.ID0232), nameof(type));
@ -112,8 +122,13 @@ public class OpenIddictCoreBuilder
/// <param name="type">The type of the custom store.</param>
/// <param name="lifetime">The lifetime of the registered service.</param>
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
public OpenIddictCoreBuilder AddAuthorizationStore(Type type!!, ServiceLifetime lifetime = ServiceLifetime.Scoped)
public OpenIddictCoreBuilder AddAuthorizationStore(Type type, ServiceLifetime lifetime = ServiceLifetime.Scoped)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(IOpenIddictAuthorizationStore<>)) ??
throw new ArgumentException(SR.GetResourceString(SR.ID0232), nameof(type));
@ -160,8 +175,13 @@ public class OpenIddictCoreBuilder
/// <param name="type">The type of the custom store.</param>
/// <param name="lifetime">The lifetime of the registered service.</param>
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
public OpenIddictCoreBuilder AddScopeStore(Type type!!, ServiceLifetime lifetime = ServiceLifetime.Scoped)
public OpenIddictCoreBuilder AddScopeStore(Type type, ServiceLifetime lifetime = ServiceLifetime.Scoped)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(IOpenIddictScopeStore<>)) ??
throw new ArgumentException(SR.GetResourceString(SR.ID0232), nameof(type));
@ -208,8 +228,13 @@ public class OpenIddictCoreBuilder
/// <param name="type">The type of the custom store.</param>
/// <param name="lifetime">The lifetime of the registered service.</param>
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
public OpenIddictCoreBuilder AddTokenStore(Type type!!, ServiceLifetime lifetime = ServiceLifetime.Scoped)
public OpenIddictCoreBuilder AddTokenStore(Type type, ServiceLifetime lifetime = ServiceLifetime.Scoped)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(IOpenIddictTokenStore<>)) ??
throw new ArgumentException(SR.GetResourceString(SR.ID0232), nameof(type));
@ -254,8 +279,13 @@ public class OpenIddictCoreBuilder
/// </summary>
/// <param name="type">The type of the custom manager.</param>
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
public OpenIddictCoreBuilder ReplaceApplicationManager(Type type!!)
public OpenIddictCoreBuilder ReplaceApplicationManager(Type type)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(OpenIddictApplicationManager<>)) ??
throw new ArgumentException(SR.GetResourceString(SR.ID0232), nameof(type));
@ -303,8 +333,13 @@ public class OpenIddictCoreBuilder
/// <param name="lifetime">The lifetime of the registered service.</param>
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
public OpenIddictCoreBuilder ReplaceApplicationStoreResolver(
Type type!!, ServiceLifetime lifetime = ServiceLifetime.Scoped)
Type type, ServiceLifetime lifetime = ServiceLifetime.Scoped)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
if (!typeof(IOpenIddictApplicationStoreResolver).IsAssignableFrom(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0232), nameof(type));
@ -335,8 +370,13 @@ public class OpenIddictCoreBuilder
/// </summary>
/// <param name="type">The type of the custom manager.</param>
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
public OpenIddictCoreBuilder ReplaceAuthorizationManager(Type type!!)
public OpenIddictCoreBuilder ReplaceAuthorizationManager(Type type)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(OpenIddictAuthorizationManager<>)) ??
throw new ArgumentException(SR.GetResourceString(SR.ID0232), nameof(type));
@ -384,8 +424,13 @@ public class OpenIddictCoreBuilder
/// <param name="lifetime">The lifetime of the registered service.</param>
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
public OpenIddictCoreBuilder ReplaceAuthorizationStoreResolver(
Type type!!, ServiceLifetime lifetime = ServiceLifetime.Scoped)
Type type, ServiceLifetime lifetime = ServiceLifetime.Scoped)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
if (!typeof(IOpenIddictAuthorizationStoreResolver).IsAssignableFrom(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0232), nameof(type));
@ -416,8 +461,13 @@ public class OpenIddictCoreBuilder
/// </summary>
/// <param name="type">The type of the custom manager.</param>
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
public OpenIddictCoreBuilder ReplaceScopeManager(Type type!!)
public OpenIddictCoreBuilder ReplaceScopeManager(Type type)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(OpenIddictScopeManager<>)) ??
throw new ArgumentException(SR.GetResourceString(SR.ID0232), nameof(type));
@ -465,8 +515,13 @@ public class OpenIddictCoreBuilder
/// <param name="lifetime">The lifetime of the registered service.</param>
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
public OpenIddictCoreBuilder ReplaceScopeStoreResolver(
Type type!!, ServiceLifetime lifetime = ServiceLifetime.Scoped)
Type type, ServiceLifetime lifetime = ServiceLifetime.Scoped)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
if (!typeof(IOpenIddictScopeStoreResolver).IsAssignableFrom(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0232), nameof(type));
@ -497,8 +552,13 @@ public class OpenIddictCoreBuilder
/// </summary>
/// <param name="type">The type of the custom manager.</param>
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
public OpenIddictCoreBuilder ReplaceTokenManager(Type type!!)
public OpenIddictCoreBuilder ReplaceTokenManager(Type type)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(OpenIddictTokenManager<>)) ??
throw new ArgumentException(SR.GetResourceString(SR.ID0232), nameof(type));
@ -546,8 +606,13 @@ public class OpenIddictCoreBuilder
/// <param name="lifetime">The lifetime of the registered service.</param>
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
public OpenIddictCoreBuilder ReplaceTokenStoreResolver(
Type type!!, ServiceLifetime lifetime = ServiceLifetime.Scoped)
Type type, ServiceLifetime lifetime = ServiceLifetime.Scoped)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
if (!typeof(IOpenIddictTokenStoreResolver).IsAssignableFrom(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0232), nameof(type));
@ -590,8 +655,13 @@ public class OpenIddictCoreBuilder
/// </summary>
/// <param name="type">The application entity type.</param>
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
public OpenIddictCoreBuilder SetDefaultApplicationEntity(Type type!!)
public OpenIddictCoreBuilder SetDefaultApplicationEntity(Type type)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
if (type.IsValueType)
{
throw new ArgumentException(SR.GetResourceString(SR.ID0232), nameof(type));
@ -612,8 +682,13 @@ public class OpenIddictCoreBuilder
/// </summary>
/// <param name="type">The authorization entity type.</param>
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
public OpenIddictCoreBuilder SetDefaultAuthorizationEntity(Type type!!)
public OpenIddictCoreBuilder SetDefaultAuthorizationEntity(Type type)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
if (type.IsValueType)
{
throw new ArgumentException(SR.GetResourceString(SR.ID0232), nameof(type));
@ -634,8 +709,13 @@ public class OpenIddictCoreBuilder
/// </summary>
/// <param name="type">The scope entity type.</param>
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
public OpenIddictCoreBuilder SetDefaultScopeEntity(Type type!!)
public OpenIddictCoreBuilder SetDefaultScopeEntity(Type type)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
if (type.IsValueType)
{
throw new ArgumentException(SR.GetResourceString(SR.ID0232), nameof(type));
@ -656,8 +736,13 @@ public class OpenIddictCoreBuilder
/// </summary>
/// <param name="type">The token entity type.</param>
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
public OpenIddictCoreBuilder SetDefaultTokenEntity(Type type!!)
public OpenIddictCoreBuilder SetDefaultTokenEntity(Type type)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
if (type.IsValueType)
{
throw new ArgumentException(SR.GetResourceString(SR.ID0232), nameof(type));

19
src/OpenIddict.Core/OpenIddictCoreExtensions.cs

@ -22,8 +22,13 @@ public static class OpenIddictCoreExtensions
/// <param name="builder">The services builder used by OpenIddict to register new services.</param>
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
public static OpenIddictCoreBuilder AddCore(this OpenIddictBuilder builder!!)
public static OpenIddictCoreBuilder AddCore(this OpenIddictBuilder builder)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Services.AddLogging();
builder.Services.AddMemoryCache();
builder.Services.AddOptions();
@ -93,8 +98,18 @@ public static class OpenIddictCoreExtensions
/// <param name="configuration">The configuration delegate used to configure the core services.</param>
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictBuilder"/>.</returns>
public static OpenIddictBuilder AddCore(this OpenIddictBuilder builder!!, Action<OpenIddictCoreBuilder> configuration!!)
public static OpenIddictBuilder AddCore(this OpenIddictBuilder builder, Action<OpenIddictCoreBuilder> configuration)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
configuration(builder.AddCore());
return builder;

4
src/OpenIddict.Core/Resolvers/OpenIddictApplicationStoreResolver.cs

@ -9,8 +9,8 @@ public class OpenIddictApplicationStoreResolver : IOpenIddictApplicationStoreRes
{
private readonly IServiceProvider _provider;
public OpenIddictApplicationStoreResolver(IServiceProvider provider!!)
=> _provider = provider;
public OpenIddictApplicationStoreResolver(IServiceProvider provider)
=> _provider = provider ?? throw new ArgumentNullException(nameof(provider));
/// <summary>
/// Returns an application store compatible with the specified application type or throws an

4
src/OpenIddict.Core/Resolvers/OpenIddictAuthorizationStoreResolver.cs

@ -9,8 +9,8 @@ public class OpenIddictAuthorizationStoreResolver : IOpenIddictAuthorizationStor
{
private readonly IServiceProvider _provider;
public OpenIddictAuthorizationStoreResolver(IServiceProvider provider!!)
=> _provider = provider;
public OpenIddictAuthorizationStoreResolver(IServiceProvider provider)
=> _provider = provider ?? throw new ArgumentNullException(nameof(provider));
/// <summary>
/// Returns an authorization store compatible with the specified authorization type or throws an

4
src/OpenIddict.Core/Resolvers/OpenIddictScopeStoreResolver.cs

@ -9,8 +9,8 @@ public class OpenIddictScopeStoreResolver : IOpenIddictScopeStoreResolver
{
private readonly IServiceProvider _provider;
public OpenIddictScopeStoreResolver(IServiceProvider provider!!)
=> _provider = provider;
public OpenIddictScopeStoreResolver(IServiceProvider provider)
=> _provider = provider ?? throw new ArgumentNullException(nameof(provider));
/// <summary>
/// Returns a scope store compatible with the specified scope type or throws an

4
src/OpenIddict.Core/Resolvers/OpenIddictTokenStoreResolver.cs

@ -9,8 +9,8 @@ public class OpenIddictTokenStoreResolver : IOpenIddictTokenStoreResolver
{
private readonly IServiceProvider _provider;
public OpenIddictTokenStoreResolver(IServiceProvider provider!!)
=> _provider = provider;
public OpenIddictTokenStoreResolver(IServiceProvider provider)
=> _provider = provider ?? throw new ArgumentNullException(nameof(provider));
/// <summary>
/// Returns a token store compatible with the specified token type or throws an

18
src/OpenIddict.EntityFramework/OpenIddictEntityFrameworkBuilder.cs

@ -21,8 +21,8 @@ public class OpenIddictEntityFrameworkBuilder
/// Initializes a new instance of <see cref="OpenIddictEntityFrameworkBuilder"/>.
/// </summary>
/// <param name="services">The services collection.</param>
public OpenIddictEntityFrameworkBuilder(IServiceCollection services!!)
=> Services = services;
public OpenIddictEntityFrameworkBuilder(IServiceCollection services)
=> Services = services ?? throw new ArgumentNullException(nameof(services));
/// <summary>
/// Gets the services collection.
@ -36,8 +36,13 @@ public class OpenIddictEntityFrameworkBuilder
/// <param name="configuration">The delegate used to configure the OpenIddict options.</param>
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictEntityFrameworkBuilder"/>.</returns>
public OpenIddictEntityFrameworkBuilder Configure(Action<OpenIddictEntityFrameworkOptions> configuration!!)
public OpenIddictEntityFrameworkBuilder Configure(Action<OpenIddictEntityFrameworkOptions> configuration)
{
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
Services.Configure(configuration);
return this;
@ -89,8 +94,13 @@ public class OpenIddictEntityFrameworkBuilder
/// </summary>
/// <param name="type">The type of the <see cref="DbContext"/> used by OpenIddict.</param>
/// <returns>The <see cref="OpenIddictEntityFrameworkBuilder"/>.</returns>
public OpenIddictEntityFrameworkBuilder UseDbContext(Type type!!)
public OpenIddictEntityFrameworkBuilder UseDbContext(Type type)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
if (!typeof(DbContext).IsAssignableFrom(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0232), nameof(type));

19
src/OpenIddict.EntityFramework/OpenIddictEntityFrameworkExtensions.cs

@ -22,8 +22,13 @@ public static class OpenIddictEntityFrameworkExtensions
/// <param name="builder">The services builder used by OpenIddict to register new services.</param>
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictEntityFrameworkBuilder"/>.</returns>
public static OpenIddictEntityFrameworkBuilder UseEntityFramework(this OpenIddictCoreBuilder builder!!)
public static OpenIddictEntityFrameworkBuilder UseEntityFramework(this OpenIddictCoreBuilder builder)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
// Since Entity Framework 6.x may be used with databases performing case-insensitive
// or culture-sensitive comparisons, ensure the additional filtering logic is enforced
// in case case-sensitive stores were registered before this extension was called.
@ -61,8 +66,18 @@ public static class OpenIddictEntityFrameworkExtensions
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
public static OpenIddictCoreBuilder UseEntityFramework(
this OpenIddictCoreBuilder builder!!, Action<OpenIddictEntityFrameworkBuilder> configuration!!)
this OpenIddictCoreBuilder builder, Action<OpenIddictEntityFrameworkBuilder> configuration)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
configuration(builder.UseEntityFramework());
return builder;

14
src/OpenIddict.EntityFramework/OpenIddictEntityFrameworkHelpers.cs

@ -38,13 +38,18 @@ public static class OpenIddictEntityFrameworkHelpers
/// </remarks>
/// <param name="builder">The builder used to configure the Entity Framework context.</param>
/// <returns>The Entity Framework context builder.</returns>
public static DbModelBuilder UseOpenIddict<TApplication, TAuthorization, TScope, TToken, TKey>(this DbModelBuilder builder!!)
public static DbModelBuilder UseOpenIddict<TApplication, TAuthorization, TScope, TToken, TKey>(this DbModelBuilder builder)
where TApplication : OpenIddictEntityFrameworkApplication<TKey, TAuthorization, TToken>
where TAuthorization : OpenIddictEntityFrameworkAuthorization<TKey, TApplication, TToken>
where TScope : OpenIddictEntityFrameworkScope<TKey>
where TToken : OpenIddictEntityFrameworkToken<TKey, TApplication, TAuthorization>
where TKey : notnull, IEquatable<TKey>
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Configurations
.Add(new OpenIddictEntityFrameworkApplicationConfiguration<TApplication, TAuthorization, TToken, TKey>())
.Add(new OpenIddictEntityFrameworkAuthorizationConfiguration<TAuthorization, TApplication, TToken, TKey>())
@ -61,8 +66,13 @@ public static class OpenIddictEntityFrameworkHelpers
/// <param name="source">The query source.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The non-streamed async enumeration containing the results.</returns>
internal static IAsyncEnumerable<T> AsAsyncEnumerable<T>(this IQueryable<T> source!!, CancellationToken cancellationToken)
internal static IAsyncEnumerable<T> AsAsyncEnumerable<T>(this IQueryable<T> source, CancellationToken cancellationToken)
{
if (source is null)
{
throw new ArgumentNullException(nameof(source));
}
return ExecuteAsync(source, cancellationToken);
static async IAsyncEnumerable<T> ExecuteAsync(IQueryable<T> source, [EnumeratorCancellation] CancellationToken cancellationToken)

12
src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkApplicationStoreResolver.cs

@ -22,13 +22,13 @@ public class OpenIddictEntityFrameworkApplicationStoreResolver : IOpenIddictAppl
private readonly IServiceProvider _provider;
public OpenIddictEntityFrameworkApplicationStoreResolver(
TypeResolutionCache cache!!,
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options!!,
IServiceProvider provider!!)
TypeResolutionCache cache,
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options,
IServiceProvider provider)
{
_cache = cache;
_options = options;
_provider = provider;
_cache = cache ?? throw new ArgumentNullException(nameof(cache));
_options = options ?? throw new ArgumentNullException(nameof(options));
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
}
/// <summary>

12
src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkAuthorizationStoreResolver.cs

@ -22,13 +22,13 @@ public class OpenIddictEntityFrameworkAuthorizationStoreResolver : IOpenIddictAu
private readonly IServiceProvider _provider;
public OpenIddictEntityFrameworkAuthorizationStoreResolver(
TypeResolutionCache cache!!,
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options!!,
IServiceProvider provider!!)
TypeResolutionCache cache,
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options,
IServiceProvider provider)
{
_cache = cache;
_options = options;
_provider = provider;
_cache = cache ?? throw new ArgumentNullException(nameof(cache));
_options = options ?? throw new ArgumentNullException(nameof(options));
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
}
/// <summary>

12
src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkScopeStoreResolver.cs

@ -22,13 +22,13 @@ public class OpenIddictEntityFrameworkScopeStoreResolver : IOpenIddictScopeStore
private readonly IServiceProvider _provider;
public OpenIddictEntityFrameworkScopeStoreResolver(
TypeResolutionCache cache!!,
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options!!,
IServiceProvider provider!!)
TypeResolutionCache cache,
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options,
IServiceProvider provider)
{
_cache = cache;
_options = options;
_provider = provider;
_cache = cache ?? throw new ArgumentNullException(nameof(cache));
_options = options ?? throw new ArgumentNullException(nameof(options));
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
}
/// <summary>

12
src/OpenIddict.EntityFramework/Resolvers/OpenIddictEntityFrameworkTokenStoreResolver.cs

@ -22,13 +22,13 @@ public class OpenIddictEntityFrameworkTokenStoreResolver : IOpenIddictTokenStore
private readonly IServiceProvider _provider;
public OpenIddictEntityFrameworkTokenStoreResolver(
TypeResolutionCache cache!!,
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options!!,
IServiceProvider provider!!)
TypeResolutionCache cache,
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options,
IServiceProvider provider)
{
_cache = cache;
_options = options;
_provider = provider;
_cache = cache ?? throw new ArgumentNullException(nameof(cache));
_options = options ?? throw new ArgumentNullException(nameof(options));
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
}
/// <summary>

249
src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkApplicationStore.cs

@ -32,7 +32,7 @@ public class OpenIddictEntityFrameworkApplicationStore<TContext> :
public OpenIddictEntityFrameworkApplicationStore(
IMemoryCache cache,
TContext context,
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options!!)
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options)
: base(cache, context, options)
{
}
@ -54,13 +54,13 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
where TKey : notnull, IEquatable<TKey>
{
public OpenIddictEntityFrameworkApplicationStore(
IMemoryCache cache!!,
TContext context!!,
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options!!)
IMemoryCache cache,
TContext context,
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options)
{
Cache = cache;
Context = context;
Options = options;
Cache = cache ?? throw new ArgumentNullException(nameof(cache));
Context = context ?? throw new ArgumentNullException(nameof(context));
Options = options ?? throw new ArgumentNullException(nameof(options));
}
/// <summary>
@ -98,20 +98,37 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
=> await Applications.LongCountAsync(cancellationToken);
/// <inheritdoc/>
public virtual async ValueTask<long> CountAsync<TResult>(Func<IQueryable<TApplication>, IQueryable<TResult>> query!!, CancellationToken cancellationToken)
=> await query(Applications).LongCountAsync(cancellationToken);
public virtual async ValueTask<long> CountAsync<TResult>(Func<IQueryable<TApplication>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return await query(Applications).LongCountAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual async ValueTask CreateAsync(TApplication application!!, CancellationToken cancellationToken)
public virtual async ValueTask CreateAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
Applications.Add(application);
await Context.SaveChangesAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual async ValueTask DeleteAsync(TApplication application!!, CancellationToken cancellationToken)
public virtual async ValueTask DeleteAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
DbContextTransaction? CreateTransaction()
{
try
@ -286,33 +303,80 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
/// <inheritdoc/>
public virtual async ValueTask<TResult?> GetAsync<TState, TResult>(
Func<IQueryable<TApplication>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TApplication>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken)
=> await query(Applications, state).FirstOrDefaultAsync(cancellationToken);
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return await query(Applications, state).FirstOrDefaultAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetClientIdAsync(TApplication application!!, CancellationToken cancellationToken)
=> new(application.ClientId);
public virtual ValueTask<string?> GetClientIdAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
return new(application.ClientId);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetClientSecretAsync(TApplication application!!, CancellationToken cancellationToken)
=> new(application.ClientSecret);
public virtual ValueTask<string?> GetClientSecretAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
return new(application.ClientSecret);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetClientTypeAsync(TApplication application!!, CancellationToken cancellationToken)
=> new(application.Type);
public virtual ValueTask<string?> GetClientTypeAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
return new(application.Type);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetConsentTypeAsync(TApplication application!!, CancellationToken cancellationToken)
=> new(application.ConsentType);
public virtual ValueTask<string?> GetConsentTypeAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
return new(application.ConsentType);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetDisplayNameAsync(TApplication application!!, CancellationToken cancellationToken)
=> new(application.DisplayName);
public virtual ValueTask<string?> GetDisplayNameAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
return new(application.DisplayName);
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableDictionary<CultureInfo, string>> GetDisplayNamesAsync(TApplication application!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableDictionary<CultureInfo, string>> GetDisplayNamesAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (string.IsNullOrEmpty(application.DisplayNames))
{
return new(ImmutableDictionary.Create<CultureInfo, string>());
@ -347,12 +411,24 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetIdAsync(TApplication application!!, CancellationToken cancellationToken)
=> new(ConvertIdentifierToString(application.Id));
public virtual ValueTask<string?> GetIdAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
return new(ConvertIdentifierToString(application.Id));
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableArray<string>> GetPermissionsAsync(TApplication application!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableArray<string>> GetPermissionsAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (string.IsNullOrEmpty(application.Permissions))
{
return new(ImmutableArray.Create<string>());
@ -387,8 +463,13 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableArray<string>> GetPostLogoutRedirectUrisAsync(TApplication application!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableArray<string>> GetPostLogoutRedirectUrisAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (string.IsNullOrEmpty(application.PostLogoutRedirectUris))
{
return new(ImmutableArray.Create<string>());
@ -423,8 +504,13 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(TApplication application!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (string.IsNullOrEmpty(application.Properties))
{
return new(ImmutableDictionary.Create<string, JsonElement>());
@ -453,8 +539,13 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableArray<string>> GetRedirectUrisAsync(TApplication application!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableArray<string>> GetRedirectUrisAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (string.IsNullOrEmpty(application.RedirectUris))
{
return new(ImmutableArray.Create<string>());
@ -489,8 +580,13 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableArray<string>> GetRequirementsAsync(TApplication application!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableArray<string>> GetRequirementsAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (string.IsNullOrEmpty(application.Requirements))
{
return new(ImmutableArray.Create<string>());
@ -560,56 +656,91 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
/// <inheritdoc/>
public virtual IAsyncEnumerable<TResult> ListAsync<TState, TResult>(
Func<IQueryable<TApplication>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TApplication>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return query(Applications, state).AsAsyncEnumerable(cancellationToken);
}
/// <inheritdoc/>
public virtual ValueTask SetClientIdAsync(TApplication application!!, string? identifier, CancellationToken cancellationToken)
public virtual ValueTask SetClientIdAsync(TApplication application, string? identifier, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
application.ClientId = identifier;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetClientSecretAsync(TApplication application!!, string? secret, CancellationToken cancellationToken)
public virtual ValueTask SetClientSecretAsync(TApplication application, string? secret, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
application.ClientSecret = secret;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetClientTypeAsync(TApplication application!!, string? type, CancellationToken cancellationToken)
public virtual ValueTask SetClientTypeAsync(TApplication application, string? type, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
application.Type = type;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetConsentTypeAsync(TApplication application!!, string? type, CancellationToken cancellationToken)
public virtual ValueTask SetConsentTypeAsync(TApplication application, string? type, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
application.ConsentType = type;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetDisplayNameAsync(TApplication application!!, string? name, CancellationToken cancellationToken)
public virtual ValueTask SetDisplayNameAsync(TApplication application, string? name, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
application.DisplayName = name;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetDisplayNamesAsync(TApplication application!!,
public virtual ValueTask SetDisplayNamesAsync(TApplication application,
ImmutableDictionary<CultureInfo, string> names, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (names is not { Count: > 0 })
{
application.DisplayNames = null;
@ -641,8 +772,13 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
}
/// <inheritdoc/>
public virtual ValueTask SetPermissionsAsync(TApplication application!!, ImmutableArray<string> permissions, CancellationToken cancellationToken)
public virtual ValueTask SetPermissionsAsync(TApplication application, ImmutableArray<string> permissions, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (permissions.IsDefaultOrEmpty)
{
application.Permissions = null;
@ -673,9 +809,14 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
}
/// <inheritdoc/>
public virtual ValueTask SetPostLogoutRedirectUrisAsync(TApplication application!!,
public virtual ValueTask SetPostLogoutRedirectUrisAsync(TApplication application,
ImmutableArray<string> addresses, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (addresses.IsDefaultOrEmpty)
{
application.PostLogoutRedirectUris = null;
@ -706,9 +847,14 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
}
/// <inheritdoc/>
public virtual ValueTask SetPropertiesAsync(TApplication application!!,
public virtual ValueTask SetPropertiesAsync(TApplication application,
ImmutableDictionary<string, JsonElement> properties, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (properties is not { Count: > 0 })
{
application.Properties = null;
@ -740,9 +886,14 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
}
/// <inheritdoc/>
public virtual ValueTask SetRedirectUrisAsync(TApplication application!!,
public virtual ValueTask SetRedirectUrisAsync(TApplication application,
ImmutableArray<string> addresses, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (addresses.IsDefaultOrEmpty)
{
application.RedirectUris = null;
@ -773,8 +924,13 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
}
/// <inheritdoc/>
public virtual ValueTask SetRequirementsAsync(TApplication application!!, ImmutableArray<string> requirements, CancellationToken cancellationToken)
public virtual ValueTask SetRequirementsAsync(TApplication application, ImmutableArray<string> requirements, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (requirements.IsDefaultOrEmpty)
{
application.Requirements = null;
@ -805,8 +961,13 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
}
/// <inheritdoc/>
public virtual async ValueTask UpdateAsync(TApplication application!!, CancellationToken cancellationToken)
public virtual async ValueTask UpdateAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
Applications.Attach(application);
// Generate a new concurrency token and attach it

198
src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkAuthorizationStore.cs

@ -31,7 +31,7 @@ public class OpenIddictEntityFrameworkAuthorizationStore<TContext> :
public OpenIddictEntityFrameworkAuthorizationStore(
IMemoryCache cache,
TContext context,
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options!!)
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options)
: base(cache, context, options)
{
}
@ -53,13 +53,13 @@ public class OpenIddictEntityFrameworkAuthorizationStore<TAuthorization, TApplic
where TKey : notnull, IEquatable<TKey>
{
public OpenIddictEntityFrameworkAuthorizationStore(
IMemoryCache cache!!,
TContext context!!,
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options!!)
IMemoryCache cache,
TContext context,
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options)
{
Cache = cache;
Context = context;
Options = options;
Cache = cache ?? throw new ArgumentNullException(nameof(cache));
Context = context ?? throw new ArgumentNullException(nameof(context));
Options = options ?? throw new ArgumentNullException(nameof(options));
}
/// <summary>
@ -97,20 +97,37 @@ public class OpenIddictEntityFrameworkAuthorizationStore<TAuthorization, TApplic
=> await Authorizations.LongCountAsync(cancellationToken);
/// <inheritdoc/>
public virtual async ValueTask<long> CountAsync<TResult>(Func<IQueryable<TAuthorization>, IQueryable<TResult>> query!!, CancellationToken cancellationToken)
=> await query(Authorizations).LongCountAsync(cancellationToken);
public virtual async ValueTask<long> CountAsync<TResult>(Func<IQueryable<TAuthorization>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return await query(Authorizations).LongCountAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual async ValueTask CreateAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
public virtual async ValueTask CreateAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
Authorizations.Add(authorization);
await Context.SaveChangesAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual async ValueTask DeleteAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
public virtual async ValueTask DeleteAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
DbContextTransaction? CreateTransaction()
{
try
@ -344,8 +361,13 @@ public class OpenIddictEntityFrameworkAuthorizationStore<TAuthorization, TApplic
}
/// <inheritdoc/>
public virtual async ValueTask<string?> GetApplicationIdAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
public virtual async ValueTask<string?> GetApplicationIdAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
// If the application is not attached to the authorization, try to load it manually.
if (authorization.Application is null)
{
@ -368,22 +390,53 @@ public class OpenIddictEntityFrameworkAuthorizationStore<TAuthorization, TApplic
/// <inheritdoc/>
public virtual async ValueTask<TResult?> GetAsync<TState, TResult>(
Func<IQueryable<TAuthorization>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TAuthorization>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken)
=> await query(
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return await query(
Authorizations.Include(authorization => authorization.Application), state).FirstOrDefaultAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual ValueTask<DateTimeOffset?> GetCreationDateAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
=> new(authorization.CreationDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null);
public virtual ValueTask<DateTimeOffset?> GetCreationDateAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (authorization.CreationDate is null)
{
return new(result: null);
}
return new(DateTime.SpecifyKind(authorization.CreationDate.Value, DateTimeKind.Utc));
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetIdAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
=> new(ConvertIdentifierToString(authorization.Id));
public virtual ValueTask<string?> GetIdAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
return new(ConvertIdentifierToString(authorization.Id));
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (string.IsNullOrEmpty(authorization.Properties))
{
return new(ImmutableDictionary.Create<string, JsonElement>());
@ -412,8 +465,13 @@ public class OpenIddictEntityFrameworkAuthorizationStore<TAuthorization, TApplic
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableArray<string>> GetScopesAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableArray<string>> GetScopesAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (string.IsNullOrEmpty(authorization.Scopes))
{
return new(ImmutableArray.Create<string>());
@ -448,16 +506,37 @@ public class OpenIddictEntityFrameworkAuthorizationStore<TAuthorization, TApplic
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetStatusAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
=> new(authorization.Status);
public virtual ValueTask<string?> GetStatusAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
return new(authorization.Status);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetSubjectAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
=> new(authorization.Subject);
public virtual ValueTask<string?> GetSubjectAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
return new(authorization.Subject);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetTypeAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
=> new(authorization.Type);
public virtual ValueTask<string?> GetTypeAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
return new(authorization.Type);
}
/// <inheritdoc/>
public virtual ValueTask<TAuthorization> InstantiateAsync(CancellationToken cancellationToken)
@ -496,9 +575,16 @@ public class OpenIddictEntityFrameworkAuthorizationStore<TAuthorization, TApplic
/// <inheritdoc/>
public virtual IAsyncEnumerable<TResult> ListAsync<TState, TResult>(
Func<IQueryable<TAuthorization>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TAuthorization>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken)
=> query(Authorizations.Include(authorization => authorization.Application), state).AsAsyncEnumerable(cancellationToken);
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return query(Authorizations.Include(authorization => authorization.Application), state).AsAsyncEnumerable(cancellationToken);
}
/// <inheritdoc/>
public virtual async ValueTask PruneAsync(DateTimeOffset threshold, CancellationToken cancellationToken)
@ -582,9 +668,14 @@ public class OpenIddictEntityFrameworkAuthorizationStore<TAuthorization, TApplic
}
/// <inheritdoc/>
public virtual async ValueTask SetApplicationIdAsync(TAuthorization authorization!!,
public virtual async ValueTask SetApplicationIdAsync(TAuthorization authorization,
string? identifier, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (!string.IsNullOrEmpty(identifier))
{
authorization.Application = await Applications.FindAsync(
@ -611,18 +702,28 @@ public class OpenIddictEntityFrameworkAuthorizationStore<TAuthorization, TApplic
}
/// <inheritdoc/>
public virtual ValueTask SetCreationDateAsync(TAuthorization authorization!!,
public virtual ValueTask SetCreationDateAsync(TAuthorization authorization,
DateTimeOffset? date, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
authorization.CreationDate = date?.UtcDateTime;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetPropertiesAsync(TAuthorization authorization!!,
public virtual ValueTask SetPropertiesAsync(TAuthorization authorization,
ImmutableDictionary<string, JsonElement> properties, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (properties is not { Count: > 0 })
{
authorization.Properties = null;
@ -654,9 +755,14 @@ public class OpenIddictEntityFrameworkAuthorizationStore<TAuthorization, TApplic
}
/// <inheritdoc/>
public virtual ValueTask SetScopesAsync(TAuthorization authorization!!,
public virtual ValueTask SetScopesAsync(TAuthorization authorization,
ImmutableArray<string> scopes, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (scopes.IsDefaultOrEmpty)
{
authorization.Scopes = null;
@ -687,32 +793,52 @@ public class OpenIddictEntityFrameworkAuthorizationStore<TAuthorization, TApplic
}
/// <inheritdoc/>
public virtual ValueTask SetStatusAsync(TAuthorization authorization!!, string? status, CancellationToken cancellationToken)
public virtual ValueTask SetStatusAsync(TAuthorization authorization, string? status, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
authorization.Status = status;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetSubjectAsync(TAuthorization authorization!!, string? subject, CancellationToken cancellationToken)
public virtual ValueTask SetSubjectAsync(TAuthorization authorization, string? subject, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
authorization.Subject = subject;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetTypeAsync(TAuthorization authorization!!, string? type, CancellationToken cancellationToken)
public virtual ValueTask SetTypeAsync(TAuthorization authorization, string? type, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
authorization.Type = type;
return default;
}
/// <inheritdoc/>
public virtual async ValueTask UpdateAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
public virtual async ValueTask UpdateAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
Authorizations.Attach(authorization);
// Generate a new concurrency token and attach it

187
src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkScopeStore.cs

@ -29,7 +29,7 @@ public class OpenIddictEntityFrameworkScopeStore<TContext> :
public OpenIddictEntityFrameworkScopeStore(
IMemoryCache cache,
TContext context,
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options!!)
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options)
: base(cache, context, options)
{
}
@ -47,13 +47,13 @@ public class OpenIddictEntityFrameworkScopeStore<TScope, TContext, TKey> : IOpen
where TKey : notnull, IEquatable<TKey>
{
public OpenIddictEntityFrameworkScopeStore(
IMemoryCache cache!!,
TContext context!!,
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options!!)
IMemoryCache cache,
TContext context,
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options)
{
Cache = cache;
Context = context;
Options = options;
Cache = cache ?? throw new ArgumentNullException(nameof(cache));
Context = context ?? throw new ArgumentNullException(nameof(context));
Options = options ?? throw new ArgumentNullException(nameof(options));
}
/// <summary>
@ -81,20 +81,37 @@ public class OpenIddictEntityFrameworkScopeStore<TScope, TContext, TKey> : IOpen
=> await Scopes.LongCountAsync(cancellationToken);
/// <inheritdoc/>
public virtual async ValueTask<long> CountAsync<TResult>(Func<IQueryable<TScope>, IQueryable<TResult>> query!!, CancellationToken cancellationToken)
=> await query(Scopes).LongCountAsync(cancellationToken);
public virtual async ValueTask<long> CountAsync<TResult>(Func<IQueryable<TScope>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return await query(Scopes).LongCountAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual async ValueTask CreateAsync(TScope scope!!, CancellationToken cancellationToken)
public virtual async ValueTask CreateAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
Scopes.Add(scope);
await Context.SaveChangesAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual async ValueTask DeleteAsync(TScope scope!!, CancellationToken cancellationToken)
public virtual async ValueTask DeleteAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
Scopes.Remove(scope);
try
@ -143,7 +160,7 @@ public class OpenIddictEntityFrameworkScopeStore<TScope, TContext, TKey> : IOpen
public virtual IAsyncEnumerable<TScope> FindByNamesAsync(
ImmutableArray<string> names, CancellationToken cancellationToken)
{
if (names.Any(string.IsNullOrEmpty))
if (names.Any(name => string.IsNullOrEmpty(name)))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0203), nameof(names));
}
@ -191,17 +208,36 @@ public class OpenIddictEntityFrameworkScopeStore<TScope, TContext, TKey> : IOpen
/// <inheritdoc/>
public virtual async ValueTask<TResult?> GetAsync<TState, TResult>(
Func<IQueryable<TScope>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TScope>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken)
=> await query(Scopes, state).FirstOrDefaultAsync(cancellationToken);
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return await query(Scopes, state).FirstOrDefaultAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetDescriptionAsync(TScope scope!!, CancellationToken cancellationToken)
=> new(scope.Description);
public virtual ValueTask<string?> GetDescriptionAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
return new(scope.Description);
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableDictionary<CultureInfo, string>> GetDescriptionsAsync(TScope scope!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableDictionary<CultureInfo, string>> GetDescriptionsAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
if (string.IsNullOrEmpty(scope.Descriptions))
{
return new(ImmutableDictionary.Create<CultureInfo, string>());
@ -236,14 +272,24 @@ public class OpenIddictEntityFrameworkScopeStore<TScope, TContext, TKey> : IOpen
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetDisplayNameAsync(TScope scope!!, CancellationToken cancellationToken)
public virtual ValueTask<string?> GetDisplayNameAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
return new(scope.DisplayName);
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableDictionary<CultureInfo, string>> GetDisplayNamesAsync(TScope scope!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableDictionary<CultureInfo, string>> GetDisplayNamesAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
if (string.IsNullOrEmpty(scope.DisplayNames))
{
return new(ImmutableDictionary.Create<CultureInfo, string>());
@ -278,16 +324,35 @@ public class OpenIddictEntityFrameworkScopeStore<TScope, TContext, TKey> : IOpen
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetIdAsync(TScope scope!!, CancellationToken cancellationToken)
=> new(ConvertIdentifierToString(scope.Id));
public virtual ValueTask<string?> GetIdAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
return new(ConvertIdentifierToString(scope.Id));
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetNameAsync(TScope scope!!, CancellationToken cancellationToken)
=> new(scope.Name);
public virtual ValueTask<string?> GetNameAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
return new(scope.Name);
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(TScope scope!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
if (string.IsNullOrEmpty(scope.Properties))
{
return new(ImmutableDictionary.Create<string, JsonElement>());
@ -316,8 +381,13 @@ public class OpenIddictEntityFrameworkScopeStore<TScope, TContext, TKey> : IOpen
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableArray<string>> GetResourcesAsync(TScope scope!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableArray<string>> GetResourcesAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
if (string.IsNullOrEmpty(scope.Resources))
{
return new(ImmutableArray.Create<string>());
@ -386,22 +456,39 @@ public class OpenIddictEntityFrameworkScopeStore<TScope, TContext, TKey> : IOpen
/// <inheritdoc/>
public virtual IAsyncEnumerable<TResult> ListAsync<TState, TResult>(
Func<IQueryable<TScope>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TScope>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken)
=> query(Scopes, state).AsAsyncEnumerable(cancellationToken);
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return query(Scopes, state).AsAsyncEnumerable(cancellationToken);
}
/// <inheritdoc/>
public virtual ValueTask SetDescriptionAsync(TScope scope!!, string? description, CancellationToken cancellationToken)
public virtual ValueTask SetDescriptionAsync(TScope scope, string? description, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
scope.Description = description;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetDescriptionsAsync(TScope scope!!,
public virtual ValueTask SetDescriptionsAsync(TScope scope,
ImmutableDictionary<CultureInfo, string> descriptions, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
if (descriptions is not { Count: > 0 })
{
scope.Descriptions = null;
@ -433,17 +520,27 @@ public class OpenIddictEntityFrameworkScopeStore<TScope, TContext, TKey> : IOpen
}
/// <inheritdoc/>
public virtual ValueTask SetDisplayNameAsync(TScope scope!!, string? name, CancellationToken cancellationToken)
public virtual ValueTask SetDisplayNameAsync(TScope scope, string? name, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
scope.DisplayName = name;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetDisplayNamesAsync(TScope scope!!,
public virtual ValueTask SetDisplayNamesAsync(TScope scope,
ImmutableDictionary<CultureInfo, string> names, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
if (names is not { Count: > 0 })
{
scope.DisplayNames = null;
@ -475,17 +572,27 @@ public class OpenIddictEntityFrameworkScopeStore<TScope, TContext, TKey> : IOpen
}
/// <inheritdoc/>
public virtual ValueTask SetNameAsync(TScope scope!!, string? name, CancellationToken cancellationToken)
public virtual ValueTask SetNameAsync(TScope scope, string? name, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
scope.Name = name;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetPropertiesAsync(TScope scope!!,
public virtual ValueTask SetPropertiesAsync(TScope scope,
ImmutableDictionary<string, JsonElement> properties, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
if (properties is not { Count: > 0 })
{
scope.Properties = null;
@ -517,8 +624,13 @@ public class OpenIddictEntityFrameworkScopeStore<TScope, TContext, TKey> : IOpen
}
/// <inheritdoc/>
public virtual ValueTask SetResourcesAsync(TScope scope!!, ImmutableArray<string> resources, CancellationToken cancellationToken)
public virtual ValueTask SetResourcesAsync(TScope scope, ImmutableArray<string> resources, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
if (resources.IsDefaultOrEmpty)
{
scope.Resources = null;
@ -549,8 +661,13 @@ public class OpenIddictEntityFrameworkScopeStore<TScope, TContext, TKey> : IOpen
}
/// <inheritdoc/>
public virtual async ValueTask UpdateAsync(TScope scope!!, CancellationToken cancellationToken)
public virtual async ValueTask UpdateAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
Scopes.Attach(scope);
// Generate a new concurrency token and attach it

280
src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkTokenStore.cs

@ -30,7 +30,7 @@ public class OpenIddictEntityFrameworkTokenStore<TContext> :
public OpenIddictEntityFrameworkTokenStore(
IMemoryCache cache,
TContext context,
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options!!)
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options)
: base(cache, context, options)
{
}
@ -52,13 +52,13 @@ public class OpenIddictEntityFrameworkTokenStore<TToken, TApplication, TAuthoriz
where TKey : notnull, IEquatable<TKey>
{
public OpenIddictEntityFrameworkTokenStore(
IMemoryCache cache!!,
TContext context!!,
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options!!)
IMemoryCache cache,
TContext context,
IOptionsMonitor<OpenIddictEntityFrameworkOptions> options)
{
Cache = cache;
Context = context;
Options = options;
Cache = cache ?? throw new ArgumentNullException(nameof(cache));
Context = context ?? throw new ArgumentNullException(nameof(context));
Options = options ?? throw new ArgumentNullException(nameof(options));
}
/// <summary>
@ -96,20 +96,37 @@ public class OpenIddictEntityFrameworkTokenStore<TToken, TApplication, TAuthoriz
=> await Tokens.LongCountAsync(cancellationToken);
/// <inheritdoc/>
public virtual async ValueTask<long> CountAsync<TResult>(Func<IQueryable<TToken>, IQueryable<TResult>> query!!, CancellationToken cancellationToken)
=> await query(Tokens).LongCountAsync(cancellationToken);
public virtual async ValueTask<long> CountAsync<TResult>(Func<IQueryable<TToken>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return await query(Tokens).LongCountAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual async ValueTask CreateAsync(TToken token!!, CancellationToken cancellationToken)
public virtual async ValueTask CreateAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
Tokens.Add(token);
await Context.SaveChangesAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual async ValueTask DeleteAsync(TToken token!!, CancellationToken cancellationToken)
public virtual async ValueTask DeleteAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
Tokens.Remove(token);
try
@ -284,8 +301,13 @@ public class OpenIddictEntityFrameworkTokenStore<TToken, TApplication, TAuthoriz
}
/// <inheritdoc/>
public virtual async ValueTask<string?> GetApplicationIdAsync(TToken token!!, CancellationToken cancellationToken)
public virtual async ValueTask<string?> GetApplicationIdAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
// If the application is not attached to the token, try to load it manually.
if (token.Application is null)
{
@ -308,15 +330,27 @@ public class OpenIddictEntityFrameworkTokenStore<TToken, TApplication, TAuthoriz
/// <inheritdoc/>
public virtual async ValueTask<TResult?> GetAsync<TState, TResult>(
Func<IQueryable<TToken>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TToken>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken)
=> await query(
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return await query(
Tokens.Include(token => token.Application)
.Include(token => token.Authorization), state).FirstOrDefaultAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual async ValueTask<string?> GetAuthorizationIdAsync(TToken token!!, CancellationToken cancellationToken)
public virtual async ValueTask<string?> GetAuthorizationIdAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
// If the authorization is not attached to the token, try to load it manually.
if (token.Authorization is null)
{
@ -338,24 +372,67 @@ public class OpenIddictEntityFrameworkTokenStore<TToken, TApplication, TAuthoriz
}
/// <inheritdoc/>
public virtual ValueTask<DateTimeOffset?> GetCreationDateAsync(TToken token!!, CancellationToken cancellationToken)
=> new(token.CreationDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null);
public virtual ValueTask<DateTimeOffset?> GetCreationDateAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
if (token.CreationDate is null)
{
return new(result: null);
}
return new(DateTime.SpecifyKind(token.CreationDate.Value, DateTimeKind.Utc));
}
/// <inheritdoc/>
public virtual ValueTask<DateTimeOffset?> GetExpirationDateAsync(TToken token!!, CancellationToken cancellationToken)
=> new(token.ExpirationDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null);
public virtual ValueTask<DateTimeOffset?> GetExpirationDateAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
if (token.ExpirationDate is null)
{
return new(result: null);
}
return new(DateTime.SpecifyKind(token.ExpirationDate.Value, DateTimeKind.Utc));
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetIdAsync(TToken token!!, CancellationToken cancellationToken)
=> new(ConvertIdentifierToString(token.Id));
public virtual ValueTask<string?> GetIdAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return new(ConvertIdentifierToString(token.Id));
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetPayloadAsync(TToken token!!, CancellationToken cancellationToken)
=> new(token.Payload);
public virtual ValueTask<string?> GetPayloadAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return new(token.Payload);
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(TToken token!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
if (string.IsNullOrEmpty(token.Properties))
{
return new(ImmutableDictionary.Create<string, JsonElement>());
@ -384,24 +461,64 @@ public class OpenIddictEntityFrameworkTokenStore<TToken, TApplication, TAuthoriz
}
/// <inheritdoc/>
public virtual ValueTask<DateTimeOffset?> GetRedemptionDateAsync(TToken token!!, CancellationToken cancellationToken)
=> new(token.RedemptionDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null);
public virtual ValueTask<DateTimeOffset?> GetRedemptionDateAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
if (token.RedemptionDate is null)
{
return new(result: null);
}
return new(DateTime.SpecifyKind(token.RedemptionDate.Value, DateTimeKind.Utc));
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetReferenceIdAsync(TToken token!!, CancellationToken cancellationToken)
=> new(token.ReferenceId);
public virtual ValueTask<string?> GetReferenceIdAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return new(token.ReferenceId);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetStatusAsync(TToken token!!, CancellationToken cancellationToken)
=> new(token.Status);
public virtual ValueTask<string?> GetStatusAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return new(token.Status);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetSubjectAsync(TToken token!!, CancellationToken cancellationToken)
=> new(token.Subject);
public virtual ValueTask<string?> GetSubjectAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return new(token.Subject);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetTypeAsync(TToken token!!, CancellationToken cancellationToken)
=> new(token.Type);
public virtual ValueTask<string?> GetTypeAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return new(token.Type);
}
/// <inheritdoc/>
public virtual ValueTask<TToken> InstantiateAsync(CancellationToken cancellationToken)
@ -441,11 +558,18 @@ public class OpenIddictEntityFrameworkTokenStore<TToken, TApplication, TAuthoriz
/// <inheritdoc/>
public virtual IAsyncEnumerable<TResult> ListAsync<TState, TResult>(
Func<IQueryable<TToken>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TToken>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken)
=> query(
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return query(
Tokens.Include(token => token.Application)
.Include(token => token.Authorization), state).AsAsyncEnumerable(cancellationToken);
}
/// <inheritdoc/>
public virtual async ValueTask PruneAsync(DateTimeOffset threshold, CancellationToken cancellationToken)
@ -526,8 +650,13 @@ public class OpenIddictEntityFrameworkTokenStore<TToken, TApplication, TAuthoriz
}
/// <inheritdoc/>
public virtual async ValueTask SetApplicationIdAsync(TToken token!!, string? identifier, CancellationToken cancellationToken)
public virtual async ValueTask SetApplicationIdAsync(TToken token, string? identifier, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
if (!string.IsNullOrEmpty(identifier))
{
token.Application = await Applications.FindAsync(
@ -554,8 +683,13 @@ public class OpenIddictEntityFrameworkTokenStore<TToken, TApplication, TAuthoriz
}
/// <inheritdoc/>
public virtual async ValueTask SetAuthorizationIdAsync(TToken token!!, string? identifier, CancellationToken cancellationToken)
public virtual async ValueTask SetAuthorizationIdAsync(TToken token, string? identifier, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
if (!string.IsNullOrEmpty(identifier))
{
token.Authorization = await Authorizations.FindAsync(
@ -582,33 +716,53 @@ public class OpenIddictEntityFrameworkTokenStore<TToken, TApplication, TAuthoriz
}
/// <inheritdoc/>
public virtual ValueTask SetCreationDateAsync(TToken token!!, DateTimeOffset? date, CancellationToken cancellationToken)
public virtual ValueTask SetCreationDateAsync(TToken token, DateTimeOffset? date, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
token.CreationDate = date?.UtcDateTime;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetExpirationDateAsync(TToken token!!, DateTimeOffset? date, CancellationToken cancellationToken)
public virtual ValueTask SetExpirationDateAsync(TToken token, DateTimeOffset? date, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
token.ExpirationDate = date?.UtcDateTime;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetPayloadAsync(TToken token!!, string? payload, CancellationToken cancellationToken)
public virtual ValueTask SetPayloadAsync(TToken token, string? payload, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
token.Payload = payload;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetPropertiesAsync(TToken token!!,
public virtual ValueTask SetPropertiesAsync(TToken token,
ImmutableDictionary<string, JsonElement> properties, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
if (properties is not { Count: > 0 })
{
token.Properties = null;
@ -640,48 +794,78 @@ public class OpenIddictEntityFrameworkTokenStore<TToken, TApplication, TAuthoriz
}
/// <inheritdoc/>
public virtual ValueTask SetRedemptionDateAsync(TToken token!!, DateTimeOffset? date, CancellationToken cancellationToken)
public virtual ValueTask SetRedemptionDateAsync(TToken token, DateTimeOffset? date, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
token.RedemptionDate = date?.UtcDateTime;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetReferenceIdAsync(TToken token!!, string? identifier, CancellationToken cancellationToken)
public virtual ValueTask SetReferenceIdAsync(TToken token, string? identifier, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
token.ReferenceId = identifier;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetStatusAsync(TToken token!!, string? status, CancellationToken cancellationToken)
public virtual ValueTask SetStatusAsync(TToken token, string? status, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
token.Status = status;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetSubjectAsync(TToken token!!, string? subject, CancellationToken cancellationToken)
public virtual ValueTask SetSubjectAsync(TToken token, string? subject, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
token.Subject = subject;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetTypeAsync(TToken token!!, string? type, CancellationToken cancellationToken)
public virtual ValueTask SetTypeAsync(TToken token, string? type, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
token.Type = type;
return default;
}
/// <inheritdoc/>
public virtual async ValueTask UpdateAsync(TToken token!!, CancellationToken cancellationToken)
public virtual async ValueTask UpdateAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
Tokens.Attach(token);
// Generate a new concurrency token and attach it

7
src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictEntityFrameworkCoreApplicationConfiguration.cs

@ -24,8 +24,13 @@ public class OpenIddictEntityFrameworkCoreApplicationConfiguration<TApplication,
where TToken : OpenIddictEntityFrameworkCoreToken<TKey, TApplication, TAuthorization>
where TKey : notnull, IEquatable<TKey>
{
public void Configure(EntityTypeBuilder<TApplication> builder!!)
public void Configure(EntityTypeBuilder<TApplication> builder)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
// Warning: optional foreign keys MUST NOT be added as CLR properties because
// Entity Framework would throw an exception due to the TKey generic parameter
// being non-nullable when using value types like short, int, long or Guid.

7
src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictEntityFrameworkCoreAuthorizationConfiguration.cs

@ -24,8 +24,13 @@ public class OpenIddictEntityFrameworkCoreAuthorizationConfiguration<TAuthorizat
where TToken : OpenIddictEntityFrameworkCoreToken<TKey, TApplication, TAuthorization>
where TKey : notnull, IEquatable<TKey>
{
public void Configure(EntityTypeBuilder<TAuthorization> builder!!)
public void Configure(EntityTypeBuilder<TAuthorization> builder)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
// Warning: optional foreign keys MUST NOT be added as CLR properties because
// Entity Framework would throw an exception due to the TKey generic parameter
// being non-nullable when using value types like short, int, long or Guid.

7
src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictEntityFrameworkCoreScopeConfiguration.cs

@ -20,8 +20,13 @@ public class OpenIddictEntityFrameworkCoreScopeConfiguration<TScope, TKey> : IEn
where TScope : OpenIddictEntityFrameworkCoreScope<TKey>
where TKey : notnull, IEquatable<TKey>
{
public void Configure(EntityTypeBuilder<TScope> builder!!)
public void Configure(EntityTypeBuilder<TScope> builder)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
// Warning: optional foreign keys MUST NOT be added as CLR properties because
// Entity Framework would throw an exception due to the TKey generic parameter
// being non-nullable when using value types like short, int, long or Guid.

7
src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictEntityFrameworkCoreTokenConfiguration.cs

@ -24,8 +24,13 @@ public class OpenIddictEntityFrameworkCoreTokenConfiguration<TToken, TApplicatio
where TAuthorization : OpenIddictEntityFrameworkCoreAuthorization<TKey, TApplication, TToken>
where TKey : notnull, IEquatable<TKey>
{
public void Configure(EntityTypeBuilder<TToken> builder!!)
public void Configure(EntityTypeBuilder<TToken> builder)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
// Warning: optional foreign keys MUST NOT be added as CLR properties because
// Entity Framework would throw an exception due to the TKey generic parameter
// being non-nullable when using value types like short, int, long or Guid.

18
src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreBuilder.cs

@ -20,8 +20,8 @@ public class OpenIddictEntityFrameworkCoreBuilder
/// Initializes a new instance of <see cref="OpenIddictEntityFrameworkCoreBuilder"/>.
/// </summary>
/// <param name="services">The services collection.</param>
public OpenIddictEntityFrameworkCoreBuilder(IServiceCollection services!!)
=> Services = services;
public OpenIddictEntityFrameworkCoreBuilder(IServiceCollection services)
=> Services = services ?? throw new ArgumentNullException(nameof(services));
/// <summary>
/// Gets the services collection.
@ -35,8 +35,13 @@ public class OpenIddictEntityFrameworkCoreBuilder
/// <param name="configuration">The delegate used to configure the OpenIddict options.</param>
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictEntityFrameworkCoreBuilder"/>.</returns>
public OpenIddictEntityFrameworkCoreBuilder Configure(Action<OpenIddictEntityFrameworkCoreOptions> configuration!!)
public OpenIddictEntityFrameworkCoreBuilder Configure(Action<OpenIddictEntityFrameworkCoreOptions> configuration)
{
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
Services.Configure(configuration);
return this;
@ -91,8 +96,13 @@ public class OpenIddictEntityFrameworkCoreBuilder
/// </summary>
/// <param name="type">The type of the <see cref="DbContext"/> used by OpenIddict.</param>
/// <returns>The <see cref="OpenIddictEntityFrameworkCoreBuilder"/>.</returns>
public OpenIddictEntityFrameworkCoreBuilder UseDbContext(Type type!!)
public OpenIddictEntityFrameworkCoreBuilder UseDbContext(Type type)
{
if (type is null)
{
throw new ArgumentNullException(nameof(type));
}
if (!typeof(DbContext).IsAssignableFrom(type))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0232), nameof(type));

12
src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreCustomizer.cs

@ -25,8 +25,18 @@ public class OpenIddictEntityFrameworkCoreCustomizer<TApplication, TAuthorizatio
}
/// <inheritdoc/>
public override void Customize(ModelBuilder modelBuilder!!, DbContext context!!)
public override void Customize(ModelBuilder modelBuilder, DbContext context)
{
if (modelBuilder is null)
{
throw new ArgumentNullException(nameof(modelBuilder));
}
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
// Register the OpenIddict entity sets.
modelBuilder.UseOpenIddict<TApplication, TAuthorization, TScope, TToken, TKey>();

19
src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreExtensions.cs

@ -22,8 +22,13 @@ public static class OpenIddictEntityFrameworkCoreExtensions
/// <param name="builder">The services builder used by OpenIddict to register new services.</param>
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictEntityFrameworkCoreBuilder"/>.</returns>
public static OpenIddictEntityFrameworkCoreBuilder UseEntityFrameworkCore(this OpenIddictCoreBuilder builder!!)
public static OpenIddictEntityFrameworkCoreBuilder UseEntityFrameworkCore(this OpenIddictCoreBuilder builder)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
// Since Entity Framework Core may be used with databases performing case-insensitive
// or culture-sensitive comparisons, ensure the additional filtering logic is enforced
// in case case-sensitive stores were registered before this extension was called.
@ -61,8 +66,18 @@ public static class OpenIddictEntityFrameworkCoreExtensions
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
public static OpenIddictCoreBuilder UseEntityFrameworkCore(
this OpenIddictCoreBuilder builder!!, Action<OpenIddictEntityFrameworkCoreBuilder> configuration!!)
this OpenIddictCoreBuilder builder, Action<OpenIddictEntityFrameworkCoreBuilder> configuration)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
configuration(builder.UseEntityFrameworkCore());
return builder;

29
src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreHelpers.cs

@ -56,14 +56,21 @@ public static class OpenIddictEntityFrameworkCoreHelpers
/// <param name="builder">The builder used to configure the Entity Framework context.</param>
/// <returns>The Entity Framework context builder.</returns>
public static DbContextOptionsBuilder UseOpenIddict<TApplication, TAuthorization, TScope, TToken, TKey>(
this DbContextOptionsBuilder builder!!)
this DbContextOptionsBuilder builder)
where TApplication : OpenIddictEntityFrameworkCoreApplication<TKey, TAuthorization, TToken>
where TAuthorization : OpenIddictEntityFrameworkCoreAuthorization<TKey, TApplication, TToken>
where TScope : OpenIddictEntityFrameworkCoreScope<TKey>
where TToken : OpenIddictEntityFrameworkCoreToken<TKey, TApplication, TAuthorization>
where TKey : notnull, IEquatable<TKey>
=> builder.ReplaceService<IModelCustomizer, OpenIddictEntityFrameworkCoreCustomizer<
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
return builder.ReplaceService<IModelCustomizer, OpenIddictEntityFrameworkCoreCustomizer<
TApplication, TAuthorization, TScope, TToken, TKey>>();
}
/// <summary>
/// Registers the OpenIddict entity sets in the Entity Framework Core context
@ -103,17 +110,24 @@ public static class OpenIddictEntityFrameworkCoreHelpers
/// </remarks>
/// <param name="builder">The builder used to configure the Entity Framework context.</param>
/// <returns>The Entity Framework context builder.</returns>
public static ModelBuilder UseOpenIddict<TApplication, TAuthorization, TScope, TToken, TKey>(this ModelBuilder builder!!)
public static ModelBuilder UseOpenIddict<TApplication, TAuthorization, TScope, TToken, TKey>(this ModelBuilder builder)
where TApplication : OpenIddictEntityFrameworkCoreApplication<TKey, TAuthorization, TToken>
where TAuthorization : OpenIddictEntityFrameworkCoreAuthorization<TKey, TApplication, TToken>
where TScope : OpenIddictEntityFrameworkCoreScope<TKey>
where TToken : OpenIddictEntityFrameworkCoreToken<TKey, TApplication, TAuthorization>
where TKey : notnull, IEquatable<TKey>
=> builder
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
return builder
.ApplyConfiguration(new OpenIddictEntityFrameworkCoreApplicationConfiguration<TApplication, TAuthorization, TToken, TKey>())
.ApplyConfiguration(new OpenIddictEntityFrameworkCoreAuthorizationConfiguration<TAuthorization, TApplication, TToken, TKey>())
.ApplyConfiguration(new OpenIddictEntityFrameworkCoreScopeConfiguration<TScope, TKey>())
.ApplyConfiguration(new OpenIddictEntityFrameworkCoreTokenConfiguration<TToken, TApplication, TAuthorization, TKey>());
}
#if SUPPORTS_BCL_ASYNC_ENUMERABLE
/// <summary>
@ -132,8 +146,13 @@ public static class OpenIddictEntityFrameworkCoreHelpers
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The non-streamed async enumeration containing the results.</returns>
#endif
internal static IAsyncEnumerable<T> AsAsyncEnumerable<T>(this IQueryable<T> source!!, CancellationToken cancellationToken)
internal static IAsyncEnumerable<T> AsAsyncEnumerable<T>(this IQueryable<T> source, CancellationToken cancellationToken)
{
if (source is null)
{
throw new ArgumentNullException(nameof(source));
}
return ExecuteAsync(source, cancellationToken);
static async IAsyncEnumerable<T> ExecuteAsync(IQueryable<T> source, [EnumeratorCancellation] CancellationToken cancellationToken)

12
src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreApplicationStoreResolver.cs

@ -22,13 +22,13 @@ public class OpenIddictEntityFrameworkCoreApplicationStoreResolver : IOpenIddict
private readonly IServiceProvider _provider;
public OpenIddictEntityFrameworkCoreApplicationStoreResolver(
TypeResolutionCache cache!!,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options!!,
IServiceProvider provider!!)
TypeResolutionCache cache,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options,
IServiceProvider provider)
{
_cache = cache;
_options = options;
_provider = provider;
_cache = cache ?? throw new ArgumentNullException(nameof(cache));
_options = options ?? throw new ArgumentNullException(nameof(options));
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
}
/// <summary>

12
src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreAuthorizationStoreResolver.cs

@ -22,13 +22,13 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStoreResolver : IOpenIddi
private readonly IServiceProvider _provider;
public OpenIddictEntityFrameworkCoreAuthorizationStoreResolver(
TypeResolutionCache cache!!,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options!!,
IServiceProvider provider!!)
TypeResolutionCache cache,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options,
IServiceProvider provider)
{
_cache = cache;
_options = options;
_provider = provider;
_cache = cache ?? throw new ArgumentNullException(nameof(cache));
_options = options ?? throw new ArgumentNullException(nameof(options));
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
}
/// <summary>

12
src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreScopeStoreResolver.cs

@ -22,13 +22,13 @@ public class OpenIddictEntityFrameworkCoreScopeStoreResolver : IOpenIddictScopeS
private readonly IServiceProvider _provider;
public OpenIddictEntityFrameworkCoreScopeStoreResolver(
TypeResolutionCache cache!!,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options!!,
IServiceProvider provider!!)
TypeResolutionCache cache,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options,
IServiceProvider provider)
{
_cache = cache;
_options = options;
_provider = provider;
_cache = cache ?? throw new ArgumentNullException(nameof(cache));
_options = options ?? throw new ArgumentNullException(nameof(options));
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
}
/// <summary>

12
src/OpenIddict.EntityFrameworkCore/Resolvers/OpenIddictEntityFrameworkCoreTokenStoreResolver.cs

@ -22,13 +22,13 @@ public class OpenIddictEntityFrameworkCoreTokenStoreResolver : IOpenIddictTokenS
private readonly IServiceProvider _provider;
public OpenIddictEntityFrameworkCoreTokenStoreResolver(
TypeResolutionCache cache!!,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options!!,
IServiceProvider provider!!)
TypeResolutionCache cache,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options,
IServiceProvider provider)
{
_cache = cache;
_options = options;
_provider = provider;
_cache = cache ?? throw new ArgumentNullException(nameof(cache));
_options = options ?? throw new ArgumentNullException(nameof(options));
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
}
/// <summary>

255
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreApplicationStore.cs

@ -31,7 +31,7 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TContext> :
public OpenIddictEntityFrameworkCoreApplicationStore(
IMemoryCache cache,
TContext context,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options!!)
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options)
: base(cache, context, options)
{
}
@ -52,7 +52,7 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TContext, TKey> :
public OpenIddictEntityFrameworkCoreApplicationStore(
IMemoryCache cache,
TContext context,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options!!)
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options)
: base(cache, context, options)
{
}
@ -74,13 +74,13 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
where TKey : notnull, IEquatable<TKey>
{
public OpenIddictEntityFrameworkCoreApplicationStore(
IMemoryCache cache!!,
TContext context!!,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options!!)
IMemoryCache cache,
TContext context,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options)
{
Cache = cache;
Context = context;
Options = options;
Cache = cache ?? throw new ArgumentNullException(nameof(cache));
Context = context ?? throw new ArgumentNullException(nameof(context));
Options = options ?? throw new ArgumentNullException(nameof(options));
}
/// <summary>
@ -118,20 +118,37 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
=> await Applications.AsQueryable().LongCountAsync(cancellationToken);
/// <inheritdoc/>
public virtual async ValueTask<long> CountAsync<TResult>(Func<IQueryable<TApplication>, IQueryable<TResult>> query!!, CancellationToken cancellationToken)
=> await query(Applications).LongCountAsync(cancellationToken);
public virtual async ValueTask<long> CountAsync<TResult>(Func<IQueryable<TApplication>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return await query(Applications).LongCountAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual async ValueTask CreateAsync(TApplication application!!, CancellationToken cancellationToken)
public virtual async ValueTask CreateAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
Context.Add(application);
await Context.SaveChangesAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual async ValueTask DeleteAsync(TApplication application!!, CancellationToken cancellationToken)
public virtual async ValueTask DeleteAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
async ValueTask<IDbContextTransaction?> CreateTransactionAsync()
{
// Note: transactions that specify an explicit isolation level are only supported by
@ -328,33 +345,80 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
/// <inheritdoc/>
public virtual async ValueTask<TResult?> GetAsync<TState, TResult>(
Func<IQueryable<TApplication>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TApplication>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken)
=> await query(Applications.AsTracking(), state).FirstOrDefaultAsync(cancellationToken);
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return await query(Applications.AsTracking(), state).FirstOrDefaultAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetClientIdAsync(TApplication application!!, CancellationToken cancellationToken)
=> new(application.ClientId);
public virtual ValueTask<string?> GetClientIdAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
return new(application.ClientId);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetClientSecretAsync(TApplication application!!, CancellationToken cancellationToken)
=> new(application.ClientSecret);
public virtual ValueTask<string?> GetClientSecretAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
return new(application.ClientSecret);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetClientTypeAsync(TApplication application!!, CancellationToken cancellationToken)
=> new(application.Type);
public virtual ValueTask<string?> GetClientTypeAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
return new(application.Type);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetConsentTypeAsync(TApplication application!!, CancellationToken cancellationToken)
=> new(application.ConsentType);
public virtual ValueTask<string?> GetConsentTypeAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
return new(application.ConsentType);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetDisplayNameAsync(TApplication application!!, CancellationToken cancellationToken)
=> new(application.DisplayName);
public virtual ValueTask<string?> GetDisplayNameAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
return new(application.DisplayName);
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableDictionary<CultureInfo, string>> GetDisplayNamesAsync(TApplication application!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableDictionary<CultureInfo, string>> GetDisplayNamesAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (string.IsNullOrEmpty(application.DisplayNames))
{
return new(ImmutableDictionary.Create<CultureInfo, string>());
@ -389,12 +453,24 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetIdAsync(TApplication application!!, CancellationToken cancellationToken)
=> new(ConvertIdentifierToString(application.Id));
public virtual ValueTask<string?> GetIdAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
return new(ConvertIdentifierToString(application.Id));
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableArray<string>> GetPermissionsAsync(TApplication application!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableArray<string>> GetPermissionsAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (string.IsNullOrEmpty(application.Permissions))
{
return new(ImmutableArray.Create<string>());
@ -429,8 +505,13 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableArray<string>> GetPostLogoutRedirectUrisAsync(TApplication application!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableArray<string>> GetPostLogoutRedirectUrisAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (string.IsNullOrEmpty(application.PostLogoutRedirectUris))
{
return new(ImmutableArray.Create<string>());
@ -465,8 +546,13 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(TApplication application!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (string.IsNullOrEmpty(application.Properties))
{
return new(ImmutableDictionary.Create<string, JsonElement>());
@ -495,8 +581,13 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableArray<string>> GetRedirectUrisAsync(TApplication application!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableArray<string>> GetRedirectUrisAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (string.IsNullOrEmpty(application.RedirectUris))
{
return new(ImmutableArray.Create<string>());
@ -531,8 +622,13 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableArray<string>> GetRequirementsAsync(TApplication application!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableArray<string>> GetRequirementsAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (string.IsNullOrEmpty(application.Requirements))
{
return new(ImmutableArray.Create<string>());
@ -601,54 +697,91 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
/// <inheritdoc/>
public virtual IAsyncEnumerable<TResult> ListAsync<TState, TResult>(
Func<IQueryable<TApplication>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TApplication>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken)
=> query(Applications.AsTracking(), state).AsAsyncEnumerable(cancellationToken);
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return query(Applications.AsTracking(), state).AsAsyncEnumerable(cancellationToken);
}
/// <inheritdoc/>
public virtual ValueTask SetClientIdAsync(TApplication application!!, string? identifier, CancellationToken cancellationToken)
public virtual ValueTask SetClientIdAsync(TApplication application, string? identifier, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
application.ClientId = identifier;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetClientSecretAsync(TApplication application!!, string? secret, CancellationToken cancellationToken)
public virtual ValueTask SetClientSecretAsync(TApplication application, string? secret, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
application.ClientSecret = secret;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetClientTypeAsync(TApplication application!!, string? type, CancellationToken cancellationToken)
public virtual ValueTask SetClientTypeAsync(TApplication application, string? type, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
application.Type = type;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetConsentTypeAsync(TApplication application!!, string? type, CancellationToken cancellationToken)
public virtual ValueTask SetConsentTypeAsync(TApplication application, string? type, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
application.ConsentType = type;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetDisplayNameAsync(TApplication application!!, string? name, CancellationToken cancellationToken)
public virtual ValueTask SetDisplayNameAsync(TApplication application, string? name, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
application.DisplayName = name;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetDisplayNamesAsync(TApplication application!!,
public virtual ValueTask SetDisplayNamesAsync(TApplication application,
ImmutableDictionary<CultureInfo, string> names, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (names is not { Count: > 0 })
{
application.DisplayNames = null;
@ -680,8 +813,13 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
}
/// <inheritdoc/>
public virtual ValueTask SetPermissionsAsync(TApplication application!!, ImmutableArray<string> permissions, CancellationToken cancellationToken)
public virtual ValueTask SetPermissionsAsync(TApplication application, ImmutableArray<string> permissions, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (permissions.IsDefaultOrEmpty)
{
application.Permissions = null;
@ -712,9 +850,14 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
}
/// <inheritdoc/>
public virtual ValueTask SetPostLogoutRedirectUrisAsync(TApplication application!!,
public virtual ValueTask SetPostLogoutRedirectUrisAsync(TApplication application,
ImmutableArray<string> addresses, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (addresses.IsDefaultOrEmpty)
{
application.PostLogoutRedirectUris = null;
@ -745,9 +888,14 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
}
/// <inheritdoc/>
public virtual ValueTask SetPropertiesAsync(TApplication application!!,
public virtual ValueTask SetPropertiesAsync(TApplication application,
ImmutableDictionary<string, JsonElement> properties, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (properties is not { Count: > 0 })
{
application.Properties = null;
@ -779,9 +927,14 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
}
/// <inheritdoc/>
public virtual ValueTask SetRedirectUrisAsync(TApplication application!!,
public virtual ValueTask SetRedirectUrisAsync(TApplication application,
ImmutableArray<string> addresses, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (addresses.IsDefaultOrEmpty)
{
application.RedirectUris = null;
@ -812,8 +965,13 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
}
/// <inheritdoc/>
public virtual ValueTask SetRequirementsAsync(TApplication application!!, ImmutableArray<string> requirements, CancellationToken cancellationToken)
public virtual ValueTask SetRequirementsAsync(TApplication application, ImmutableArray<string> requirements, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
if (requirements.IsDefaultOrEmpty)
{
application.Requirements = null;
@ -844,8 +1002,13 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<TApplication, TAuthor
}
/// <inheritdoc/>
public virtual async ValueTask UpdateAsync(TApplication application!!, CancellationToken cancellationToken)
public virtual async ValueTask UpdateAsync(TApplication application, CancellationToken cancellationToken)
{
if (application is null)
{
throw new ArgumentNullException(nameof(application));
}
Context.Attach(application);
// Generate a new concurrency token and attach it

196
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreAuthorizationStore.cs

@ -30,7 +30,7 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<TContext> :
public OpenIddictEntityFrameworkCoreAuthorizationStore(
IMemoryCache cache,
TContext context,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options!!)
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options)
: base(cache, context, options)
{
}
@ -51,7 +51,7 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<TContext, TKey> :
public OpenIddictEntityFrameworkCoreAuthorizationStore(
IMemoryCache cache,
TContext context,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options!!)
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options)
: base(cache, context, options)
{
}
@ -73,13 +73,13 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<TAuthorization, TAp
where TKey : notnull, IEquatable<TKey>
{
public OpenIddictEntityFrameworkCoreAuthorizationStore(
IMemoryCache cache!!,
TContext context!!,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options!!)
IMemoryCache cache,
TContext context,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options)
{
Cache = cache;
Context = context;
Options = options;
Cache = cache ?? throw new ArgumentNullException(nameof(cache));
Context = context ?? throw new ArgumentNullException(nameof(context));
Options = options ?? throw new ArgumentNullException(nameof(options));
}
/// <summary>
@ -117,20 +117,37 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<TAuthorization, TAp
=> await Authorizations.AsQueryable().LongCountAsync(cancellationToken);
/// <inheritdoc/>
public virtual async ValueTask<long> CountAsync<TResult>(Func<IQueryable<TAuthorization>, IQueryable<TResult>> query!!, CancellationToken cancellationToken)
=> await query(Authorizations).LongCountAsync(cancellationToken);
public virtual async ValueTask<long> CountAsync<TResult>(Func<IQueryable<TAuthorization>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return await query(Authorizations).LongCountAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual async ValueTask CreateAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
public virtual async ValueTask CreateAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
Context.Add(authorization);
await Context.SaveChangesAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual async ValueTask DeleteAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
public virtual async ValueTask DeleteAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
async ValueTask<IDbContextTransaction?> CreateTransactionAsync()
{
// Note: transactions that specify an explicit isolation level are only supported by
@ -409,8 +426,13 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<TAuthorization, TAp
}
/// <inheritdoc/>
public virtual async ValueTask<string?> GetApplicationIdAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
public virtual async ValueTask<string?> GetApplicationIdAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
// If the application is not attached to the authorization, try to load it manually.
if (authorization.Application is null)
{
@ -433,23 +455,54 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<TAuthorization, TAp
/// <inheritdoc/>
public virtual async ValueTask<TResult?> GetAsync<TState, TResult>(
Func<IQueryable<TAuthorization>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TAuthorization>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken)
=> await query(
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return await query(
Authorizations.Include(authorization => authorization.Application)
.AsTracking(), state).FirstOrDefaultAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual ValueTask<DateTimeOffset?> GetCreationDateAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
=> new(authorization.CreationDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null);
public virtual ValueTask<DateTimeOffset?> GetCreationDateAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (authorization.CreationDate is null)
{
return new(result: null);
}
return new(DateTime.SpecifyKind(authorization.CreationDate.Value, DateTimeKind.Utc));
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetIdAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
=> new(ConvertIdentifierToString(authorization.Id));
public virtual ValueTask<string?> GetIdAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
return new(ConvertIdentifierToString(authorization.Id));
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (string.IsNullOrEmpty(authorization.Properties))
{
return new(ImmutableDictionary.Create<string, JsonElement>());
@ -478,8 +531,13 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<TAuthorization, TAp
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableArray<string>> GetScopesAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableArray<string>> GetScopesAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (string.IsNullOrEmpty(authorization.Scopes))
{
return new(ImmutableArray.Create<string>());
@ -514,16 +572,37 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<TAuthorization, TAp
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetStatusAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
=> new(authorization.Status);
public virtual ValueTask<string?> GetStatusAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
return new(authorization.Status);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetSubjectAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
=> new(authorization.Subject);
public virtual ValueTask<string?> GetSubjectAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
return new(authorization.Subject);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetTypeAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
=> new(authorization.Type);
public virtual ValueTask<string?> GetTypeAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
return new(authorization.Type);
}
/// <inheritdoc/>
public virtual ValueTask<TAuthorization> InstantiateAsync(CancellationToken cancellationToken)
@ -562,9 +641,14 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<TAuthorization, TAp
/// <inheritdoc/>
public virtual IAsyncEnumerable<TResult> ListAsync<TState, TResult>(
Func<IQueryable<TAuthorization>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TAuthorization>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return query(
Authorizations.Include(authorization => authorization.Application)
.AsTracking(), state).AsAsyncEnumerable(cancellationToken);
@ -662,9 +746,14 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<TAuthorization, TAp
}
/// <inheritdoc/>
public virtual async ValueTask SetApplicationIdAsync(TAuthorization authorization!!,
public virtual async ValueTask SetApplicationIdAsync(TAuthorization authorization,
string? identifier, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (!string.IsNullOrEmpty(identifier))
{
var key = ConvertIdentifierFromString(identifier);
@ -696,18 +785,28 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<TAuthorization, TAp
}
/// <inheritdoc/>
public virtual ValueTask SetCreationDateAsync(TAuthorization authorization!!,
public virtual ValueTask SetCreationDateAsync(TAuthorization authorization,
DateTimeOffset? date, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
authorization.CreationDate = date?.UtcDateTime;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetPropertiesAsync(TAuthorization authorization!!,
public virtual ValueTask SetPropertiesAsync(TAuthorization authorization,
ImmutableDictionary<string, JsonElement> properties, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (properties is not { Count: > 0 })
{
authorization.Properties = null;
@ -739,9 +838,14 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<TAuthorization, TAp
}
/// <inheritdoc/>
public virtual ValueTask SetScopesAsync(TAuthorization authorization!!,
public virtual ValueTask SetScopesAsync(TAuthorization authorization,
ImmutableArray<string> scopes, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (scopes.IsDefaultOrEmpty)
{
authorization.Scopes = null;
@ -772,35 +876,55 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<TAuthorization, TAp
}
/// <inheritdoc/>
public virtual ValueTask SetStatusAsync(TAuthorization authorization!!,
public virtual ValueTask SetStatusAsync(TAuthorization authorization,
string? status, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
authorization.Status = status;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetSubjectAsync(TAuthorization authorization!!,
public virtual ValueTask SetSubjectAsync(TAuthorization authorization,
string? subject, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
authorization.Subject = subject;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetTypeAsync(TAuthorization authorization!!,
public virtual ValueTask SetTypeAsync(TAuthorization authorization,
string? type, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
authorization.Type = type;
return default;
}
/// <inheritdoc/>
public virtual async ValueTask UpdateAsync(TAuthorization authorization!!, CancellationToken cancellationToken)
public virtual async ValueTask UpdateAsync(TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization is null)
{
throw new ArgumentNullException(nameof(authorization));
}
Context.Attach(authorization);
// Generate a new concurrency token and attach it

193
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreScopeStore.cs

@ -27,7 +27,7 @@ public class OpenIddictEntityFrameworkCoreScopeStore<TContext> : OpenIddictEntit
public OpenIddictEntityFrameworkCoreScopeStore(
IMemoryCache cache,
TContext context,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options!!)
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options)
: base(cache, context, options)
{
}
@ -45,7 +45,7 @@ public class OpenIddictEntityFrameworkCoreScopeStore<TContext, TKey> : OpenIddic
public OpenIddictEntityFrameworkCoreScopeStore(
IMemoryCache cache,
TContext context,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options!!)
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options)
: base(cache, context, options)
{
}
@ -63,13 +63,13 @@ public class OpenIddictEntityFrameworkCoreScopeStore<TScope, TContext, TKey> : I
where TKey : notnull, IEquatable<TKey>
{
public OpenIddictEntityFrameworkCoreScopeStore(
IMemoryCache cache!!,
TContext context!!,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options!!)
IMemoryCache cache,
TContext context,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options)
{
Cache = cache;
Context = context;
Options = options;
Cache = cache ?? throw new ArgumentNullException(nameof(cache));
Context = context ?? throw new ArgumentNullException(nameof(context));
Options = options ?? throw new ArgumentNullException(nameof(options));
}
/// <summary>
@ -97,20 +97,37 @@ public class OpenIddictEntityFrameworkCoreScopeStore<TScope, TContext, TKey> : I
=> await Scopes.AsQueryable().LongCountAsync(cancellationToken);
/// <inheritdoc/>
public virtual async ValueTask<long> CountAsync<TResult>(Func<IQueryable<TScope>, IQueryable<TResult>> query!!, CancellationToken cancellationToken)
=> await query(Scopes).LongCountAsync(cancellationToken);
public virtual async ValueTask<long> CountAsync<TResult>(Func<IQueryable<TScope>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return await query(Scopes).LongCountAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual async ValueTask CreateAsync(TScope scope!!, CancellationToken cancellationToken)
public virtual async ValueTask CreateAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
Scopes.Add(scope);
await Context.SaveChangesAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual async ValueTask DeleteAsync(TScope scope!!, CancellationToken cancellationToken)
public virtual async ValueTask DeleteAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
Context.Remove(scope);
try
@ -159,7 +176,7 @@ public class OpenIddictEntityFrameworkCoreScopeStore<TScope, TContext, TKey> : I
public virtual IAsyncEnumerable<TScope> FindByNamesAsync(
ImmutableArray<string> names, CancellationToken cancellationToken)
{
if (names.Any(string.IsNullOrEmpty))
if (names.Any(name => string.IsNullOrEmpty(name)))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0203), nameof(names));
}
@ -207,17 +224,36 @@ public class OpenIddictEntityFrameworkCoreScopeStore<TScope, TContext, TKey> : I
/// <inheritdoc/>
public virtual async ValueTask<TResult?> GetAsync<TState, TResult>(
Func<IQueryable<TScope>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TScope>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken)
=> await query(Scopes.AsTracking(), state).FirstOrDefaultAsync(cancellationToken);
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return await query(Scopes.AsTracking(), state).FirstOrDefaultAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetDescriptionAsync(TScope scope!!, CancellationToken cancellationToken)
=> new(scope.Description);
public virtual ValueTask<string?> GetDescriptionAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
return new(scope.Description);
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableDictionary<CultureInfo, string>> GetDescriptionsAsync(TScope scope!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableDictionary<CultureInfo, string>> GetDescriptionsAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
if (string.IsNullOrEmpty(scope.Descriptions))
{
return new(ImmutableDictionary.Create<CultureInfo, string>());
@ -252,12 +288,24 @@ public class OpenIddictEntityFrameworkCoreScopeStore<TScope, TContext, TKey> : I
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetDisplayNameAsync(TScope scope!!, CancellationToken cancellationToken)
=> new(scope.DisplayName);
public virtual ValueTask<string?> GetDisplayNameAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
return new(scope.DisplayName);
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableDictionary<CultureInfo, string>> GetDisplayNamesAsync(TScope scope!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableDictionary<CultureInfo, string>> GetDisplayNamesAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
if (string.IsNullOrEmpty(scope.DisplayNames))
{
return new(ImmutableDictionary.Create<CultureInfo, string>());
@ -292,16 +340,35 @@ public class OpenIddictEntityFrameworkCoreScopeStore<TScope, TContext, TKey> : I
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetIdAsync(TScope scope!!, CancellationToken cancellationToken)
=> new(ConvertIdentifierToString(scope.Id));
public virtual ValueTask<string?> GetIdAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
return new(ConvertIdentifierToString(scope.Id));
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetNameAsync(TScope scope!!, CancellationToken cancellationToken)
=> new(scope.Name);
public virtual ValueTask<string?> GetNameAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
return new(scope.Name);
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(TScope scope!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
if (string.IsNullOrEmpty(scope.Properties))
{
return new(ImmutableDictionary.Create<string, JsonElement>());
@ -330,8 +397,13 @@ public class OpenIddictEntityFrameworkCoreScopeStore<TScope, TContext, TKey> : I
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableArray<string>> GetResourcesAsync(TScope scope!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableArray<string>> GetResourcesAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
if (string.IsNullOrEmpty(scope.Resources))
{
return new(ImmutableArray.Create<string>());
@ -400,22 +472,39 @@ public class OpenIddictEntityFrameworkCoreScopeStore<TScope, TContext, TKey> : I
/// <inheritdoc/>
public virtual IAsyncEnumerable<TResult> ListAsync<TState, TResult>(
Func<IQueryable<TScope>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TScope>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken)
=> query(Scopes.AsTracking(), state).AsAsyncEnumerable(cancellationToken);
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return query(Scopes.AsTracking(), state).AsAsyncEnumerable(cancellationToken);
}
/// <inheritdoc/>
public virtual ValueTask SetDescriptionAsync(TScope scope!!, string? description, CancellationToken cancellationToken)
public virtual ValueTask SetDescriptionAsync(TScope scope, string? description, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
scope.Description = description;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetDescriptionsAsync(TScope scope!!,
public virtual ValueTask SetDescriptionsAsync(TScope scope,
ImmutableDictionary<CultureInfo, string> descriptions, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
if (descriptions is not { Count: > 0 })
{
scope.Descriptions = null;
@ -447,17 +536,27 @@ public class OpenIddictEntityFrameworkCoreScopeStore<TScope, TContext, TKey> : I
}
/// <inheritdoc/>
public virtual ValueTask SetDisplayNameAsync(TScope scope!!, string? name, CancellationToken cancellationToken)
public virtual ValueTask SetDisplayNameAsync(TScope scope, string? name, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
scope.DisplayName = name;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetDisplayNamesAsync(TScope scope!!,
public virtual ValueTask SetDisplayNamesAsync(TScope scope,
ImmutableDictionary<CultureInfo, string> names, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
if (names is not { Count: > 0 })
{
scope.DisplayNames = null;
@ -489,17 +588,27 @@ public class OpenIddictEntityFrameworkCoreScopeStore<TScope, TContext, TKey> : I
}
/// <inheritdoc/>
public virtual ValueTask SetNameAsync(TScope scope!!, string? name, CancellationToken cancellationToken)
public virtual ValueTask SetNameAsync(TScope scope, string? name, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
scope.Name = name;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetPropertiesAsync(TScope scope!!,
public virtual ValueTask SetPropertiesAsync(TScope scope,
ImmutableDictionary<string, JsonElement> properties, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
if (properties is not { Count: > 0 })
{
scope.Properties = null;
@ -531,8 +640,13 @@ public class OpenIddictEntityFrameworkCoreScopeStore<TScope, TContext, TKey> : I
}
/// <inheritdoc/>
public virtual ValueTask SetResourcesAsync(TScope scope!!, ImmutableArray<string> resources, CancellationToken cancellationToken)
public virtual ValueTask SetResourcesAsync(TScope scope, ImmutableArray<string> resources, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
if (resources.IsDefaultOrEmpty)
{
scope.Resources = null;
@ -563,8 +677,13 @@ public class OpenIddictEntityFrameworkCoreScopeStore<TScope, TContext, TKey> : I
}
/// <inheritdoc/>
public virtual async ValueTask UpdateAsync(TScope scope!!, CancellationToken cancellationToken)
public virtual async ValueTask UpdateAsync(TScope scope, CancellationToken cancellationToken)
{
if (scope is null)
{
throw new ArgumentNullException(nameof(scope));
}
Context.Attach(scope);
// Generate a new concurrency token and attach it

282
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreTokenStore.cs

@ -29,7 +29,7 @@ public class OpenIddictEntityFrameworkCoreTokenStore<TContext> :
public OpenIddictEntityFrameworkCoreTokenStore(
IMemoryCache cache,
TContext context,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options!!)
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options)
: base(cache, context, options)
{
}
@ -50,7 +50,7 @@ public class OpenIddictEntityFrameworkCoreTokenStore<TContext, TKey> :
public OpenIddictEntityFrameworkCoreTokenStore(
IMemoryCache cache,
TContext context,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options!!)
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options)
: base(cache, context, options)
{
}
@ -72,13 +72,13 @@ public class OpenIddictEntityFrameworkCoreTokenStore<TToken, TApplication, TAuth
where TKey : notnull, IEquatable<TKey>
{
public OpenIddictEntityFrameworkCoreTokenStore(
IMemoryCache cache!!,
TContext context!!,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options!!)
IMemoryCache cache,
TContext context,
IOptionsMonitor<OpenIddictEntityFrameworkCoreOptions> options)
{
Cache = cache;
Context = context;
Options = options;
Cache = cache ?? throw new ArgumentNullException(nameof(cache));
Context = context ?? throw new ArgumentNullException(nameof(context));
Options = options ?? throw new ArgumentNullException(nameof(options));
}
/// <summary>
@ -116,20 +116,37 @@ public class OpenIddictEntityFrameworkCoreTokenStore<TToken, TApplication, TAuth
=> await Tokens.AsQueryable().LongCountAsync(cancellationToken);
/// <inheritdoc/>
public virtual async ValueTask<long> CountAsync<TResult>(Func<IQueryable<TToken>, IQueryable<TResult>> query!!, CancellationToken cancellationToken)
=> await query(Tokens).LongCountAsync(cancellationToken);
public virtual async ValueTask<long> CountAsync<TResult>(Func<IQueryable<TToken>, IQueryable<TResult>> query, CancellationToken cancellationToken)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return await query(Tokens).LongCountAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual async ValueTask CreateAsync(TToken token!!, CancellationToken cancellationToken)
public virtual async ValueTask CreateAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
Context.Add(token);
await Context.SaveChangesAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual async ValueTask DeleteAsync(TToken token!!, CancellationToken cancellationToken)
public virtual async ValueTask DeleteAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
Context.Remove(token);
try
@ -333,8 +350,13 @@ public class OpenIddictEntityFrameworkCoreTokenStore<TToken, TApplication, TAuth
}
/// <inheritdoc/>
public virtual async ValueTask<string?> GetApplicationIdAsync(TToken token!!, CancellationToken cancellationToken)
public virtual async ValueTask<string?> GetApplicationIdAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
// If the application is not attached to the token, try to load it manually.
if (token.Application is null)
{
@ -357,15 +379,27 @@ public class OpenIddictEntityFrameworkCoreTokenStore<TToken, TApplication, TAuth
/// <inheritdoc/>
public virtual async ValueTask<TResult?> GetAsync<TState, TResult>(
Func<IQueryable<TToken>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TToken>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken)
=> await query(Tokens.Include(token => token.Application)
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return await query(Tokens.Include(token => token.Application)
.Include(token => token.Authorization)
.AsTracking(), state).FirstOrDefaultAsync(cancellationToken);
}
/// <inheritdoc/>
public virtual async ValueTask<string?> GetAuthorizationIdAsync(TToken token!!, CancellationToken cancellationToken)
public virtual async ValueTask<string?> GetAuthorizationIdAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
// If the authorization is not attached to the token, try to load it manually.
if (token.Authorization is null)
{
@ -387,24 +421,67 @@ public class OpenIddictEntityFrameworkCoreTokenStore<TToken, TApplication, TAuth
}
/// <inheritdoc/>
public virtual ValueTask<DateTimeOffset?> GetCreationDateAsync(TToken token!!, CancellationToken cancellationToken)
=> new(token.CreationDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null);
public virtual ValueTask<DateTimeOffset?> GetCreationDateAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
if (token.CreationDate is null)
{
return new(result: null);
}
return new(DateTime.SpecifyKind(token.CreationDate.Value, DateTimeKind.Utc));
}
/// <inheritdoc/>
public virtual ValueTask<DateTimeOffset?> GetExpirationDateAsync(TToken token!!, CancellationToken cancellationToken)
=> new(token.ExpirationDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null);
public virtual ValueTask<DateTimeOffset?> GetExpirationDateAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
if (token.ExpirationDate is null)
{
return new(result: null);
}
return new(DateTime.SpecifyKind(token.ExpirationDate.Value, DateTimeKind.Utc));
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetIdAsync(TToken token!!, CancellationToken cancellationToken)
=> new(ConvertIdentifierToString(token.Id));
public virtual ValueTask<string?> GetIdAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return new(ConvertIdentifierToString(token.Id));
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetPayloadAsync(TToken token!!, CancellationToken cancellationToken)
=> new(token.Payload);
public virtual ValueTask<string?> GetPayloadAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return new(token.Payload);
}
/// <inheritdoc/>
public virtual ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(TToken token!!, CancellationToken cancellationToken)
public virtual ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
if (string.IsNullOrEmpty(token.Properties))
{
return new(ImmutableDictionary.Create<string, JsonElement>());
@ -433,24 +510,64 @@ public class OpenIddictEntityFrameworkCoreTokenStore<TToken, TApplication, TAuth
}
/// <inheritdoc/>
public virtual ValueTask<DateTimeOffset?> GetRedemptionDateAsync(TToken token!!, CancellationToken cancellationToken)
=> new(token.RedemptionDate is DateTime date ? DateTime.SpecifyKind(date, DateTimeKind.Utc) : null);
public virtual ValueTask<DateTimeOffset?> GetRedemptionDateAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
if (token.RedemptionDate is null)
{
return new(result: null);
}
return new(DateTime.SpecifyKind(token.RedemptionDate.Value, DateTimeKind.Utc));
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetReferenceIdAsync(TToken token!!, CancellationToken cancellationToken)
=> new(token.ReferenceId);
public virtual ValueTask<string?> GetReferenceIdAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return new(token.ReferenceId);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetStatusAsync(TToken token!!, CancellationToken cancellationToken)
=> new(token.Status);
public virtual ValueTask<string?> GetStatusAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return new(token.Status);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetSubjectAsync(TToken token!!, CancellationToken cancellationToken)
=> new(token.Subject);
public virtual ValueTask<string?> GetSubjectAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return new(token.Subject);
}
/// <inheritdoc/>
public virtual ValueTask<string?> GetTypeAsync(TToken token!!, CancellationToken cancellationToken)
=> new(token.Type);
public virtual ValueTask<string?> GetTypeAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
return new(token.Type);
}
/// <inheritdoc/>
public virtual ValueTask<TToken> InstantiateAsync(CancellationToken cancellationToken)
@ -490,12 +607,19 @@ public class OpenIddictEntityFrameworkCoreTokenStore<TToken, TApplication, TAuth
/// <inheritdoc/>
public virtual IAsyncEnumerable<TResult> ListAsync<TState, TResult>(
Func<IQueryable<TToken>, TState, IQueryable<TResult>> query!!,
Func<IQueryable<TToken>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken)
=> query(
{
if (query is null)
{
throw new ArgumentNullException(nameof(query));
}
return query(
Tokens.Include(token => token.Application)
.Include(token => token.Authorization)
.AsTracking(), state).AsAsyncEnumerable(cancellationToken);
}
/// <inheritdoc/>
public virtual async ValueTask PruneAsync(DateTimeOffset threshold, CancellationToken cancellationToken)
@ -586,8 +710,13 @@ public class OpenIddictEntityFrameworkCoreTokenStore<TToken, TApplication, TAuth
}
/// <inheritdoc/>
public virtual async ValueTask SetApplicationIdAsync(TToken token!!, string? identifier, CancellationToken cancellationToken)
public virtual async ValueTask SetApplicationIdAsync(TToken token, string? identifier, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
if (!string.IsNullOrEmpty(identifier))
{
var key = ConvertIdentifierFromString(identifier);
@ -619,8 +748,13 @@ public class OpenIddictEntityFrameworkCoreTokenStore<TToken, TApplication, TAuth
}
/// <inheritdoc/>
public virtual async ValueTask SetAuthorizationIdAsync(TToken token!!, string? identifier, CancellationToken cancellationToken)
public virtual async ValueTask SetAuthorizationIdAsync(TToken token, string? identifier, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
if (!string.IsNullOrEmpty(identifier))
{
var key = ConvertIdentifierFromString(identifier);
@ -652,33 +786,53 @@ public class OpenIddictEntityFrameworkCoreTokenStore<TToken, TApplication, TAuth
}
/// <inheritdoc/>
public virtual ValueTask SetCreationDateAsync(TToken token!!, DateTimeOffset? date, CancellationToken cancellationToken)
public virtual ValueTask SetCreationDateAsync(TToken token, DateTimeOffset? date, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
token.CreationDate = date?.UtcDateTime;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetExpirationDateAsync(TToken token!!, DateTimeOffset? date, CancellationToken cancellationToken)
public virtual ValueTask SetExpirationDateAsync(TToken token, DateTimeOffset? date, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
token.ExpirationDate = date?.UtcDateTime;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetPayloadAsync(TToken token!!, string? payload, CancellationToken cancellationToken)
public virtual ValueTask SetPayloadAsync(TToken token, string? payload, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
token.Payload = payload;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetPropertiesAsync(TToken token!!,
public virtual ValueTask SetPropertiesAsync(TToken token,
ImmutableDictionary<string, JsonElement> properties, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
if (properties is not { Count: > 0 })
{
token.Properties = null;
@ -710,48 +864,78 @@ public class OpenIddictEntityFrameworkCoreTokenStore<TToken, TApplication, TAuth
}
/// <inheritdoc/>
public virtual ValueTask SetRedemptionDateAsync(TToken token!!, DateTimeOffset? date, CancellationToken cancellationToken)
public virtual ValueTask SetRedemptionDateAsync(TToken token, DateTimeOffset? date, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
token.RedemptionDate = date?.UtcDateTime;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetReferenceIdAsync(TToken token!!, string? identifier, CancellationToken cancellationToken)
public virtual ValueTask SetReferenceIdAsync(TToken token, string? identifier, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
token.ReferenceId = identifier;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetStatusAsync(TToken token!!, string? status, CancellationToken cancellationToken)
public virtual ValueTask SetStatusAsync(TToken token, string? status, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
token.Status = status;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetSubjectAsync(TToken token!!, string? subject, CancellationToken cancellationToken)
public virtual ValueTask SetSubjectAsync(TToken token, string? subject, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
token.Subject = subject;
return default;
}
/// <inheritdoc/>
public virtual ValueTask SetTypeAsync(TToken token!!, string? type, CancellationToken cancellationToken)
public virtual ValueTask SetTypeAsync(TToken token, string? type, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
token.Type = type;
return default;
}
/// <inheritdoc/>
public virtual async ValueTask UpdateAsync(TToken token!!, CancellationToken cancellationToken)
public virtual async ValueTask UpdateAsync(TToken token, CancellationToken cancellationToken)
{
if (token is null)
{
throw new ArgumentNullException(nameof(token));
}
Context.Attach(token);
// Generate a new concurrency token and attach it

18
src/OpenIddict.MongoDb/OpenIddictMongoDbBuilder.cs

@ -20,8 +20,8 @@ public class OpenIddictMongoDbBuilder
/// Initializes a new instance of <see cref="OpenIddictMongoDbBuilder"/>.
/// </summary>
/// <param name="services">The services collection.</param>
public OpenIddictMongoDbBuilder(IServiceCollection services!!)
=> Services = services;
public OpenIddictMongoDbBuilder(IServiceCollection services)
=> Services = services ?? throw new ArgumentNullException(nameof(services));
/// <summary>
/// Gets the services collection.
@ -35,8 +35,13 @@ public class OpenIddictMongoDbBuilder
/// <param name="configuration">The delegate used to configure the OpenIddict options.</param>
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictMongoDbBuilder"/>.</returns>
public OpenIddictMongoDbBuilder Configure(Action<OpenIddictMongoDbOptions> configuration!!)
public OpenIddictMongoDbBuilder Configure(Action<OpenIddictMongoDbOptions> configuration)
{
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
Services.Configure(configuration);
return this;
@ -156,8 +161,13 @@ public class OpenIddictMongoDbBuilder
/// </summary>
/// <param name="database">The <see cref="IMongoDatabase"/>.</param>
/// <returns>The <see cref="OpenIddictMongoDbBuilder"/>.</returns>
public OpenIddictMongoDbBuilder UseDatabase(IMongoDatabase database!!)
public OpenIddictMongoDbBuilder UseDatabase(IMongoDatabase database)
{
if (database is null)
{
throw new ArgumentNullException(nameof(database));
}
return Configure(options => options.Database = database);
}

8
src/OpenIddict.MongoDb/OpenIddictMongoDbContext.cs

@ -16,11 +16,11 @@ public class OpenIddictMongoDbContext : IOpenIddictMongoDbContext
private readonly IServiceProvider _provider;
public OpenIddictMongoDbContext(
IOptionsMonitor<OpenIddictMongoDbOptions> options!!,
IServiceProvider provider!!)
IOptionsMonitor<OpenIddictMongoDbOptions> options,
IServiceProvider provider)
{
_options = options;
_provider = provider;
_options = options ?? throw new ArgumentNullException(nameof(options));
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
}
/// <inheritdoc/>

19
src/OpenIddict.MongoDb/OpenIddictMongoDbExtensions.cs

@ -22,8 +22,13 @@ public static class OpenIddictMongoDbExtensions
/// <param name="builder">The services builder used by OpenIddict to register new services.</param>
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictMongoDbBuilder"/>.</returns>
public static OpenIddictMongoDbBuilder UseMongoDb(this OpenIddictCoreBuilder builder!!)
public static OpenIddictMongoDbBuilder UseMongoDb(this OpenIddictCoreBuilder builder)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
// Note: Mongo uses simple binary comparison checks by default so the additional
// query filtering applied by the default OpenIddict managers can be safely disabled.
builder.DisableAdditionalFiltering();
@ -59,8 +64,18 @@ public static class OpenIddictMongoDbExtensions
/// <remarks>This extension can be safely called multiple times.</remarks>
/// <returns>The <see cref="OpenIddictCoreBuilder"/>.</returns>
public static OpenIddictCoreBuilder UseMongoDb(
this OpenIddictCoreBuilder builder!!, Action<OpenIddictMongoDbBuilder> configuration!!)
this OpenIddictCoreBuilder builder, Action<OpenIddictMongoDbBuilder> configuration)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
if (configuration is null)
{
throw new ArgumentNullException(nameof(configuration));
}
configuration(builder.UseMongoDb());
return builder;

18
src/OpenIddict.MongoDb/OpenIddictMongoDbHelpers.cs

@ -20,8 +20,13 @@ internal static class OpenIddictMongoDbHelpers
/// <param name="source">The query source.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The streamed async enumeration containing the results.</returns>
internal static IAsyncEnumerable<T> ToAsyncEnumerable<T>(this IAsyncCursorSource<T> source!!, CancellationToken cancellationToken)
internal static IAsyncEnumerable<T> ToAsyncEnumerable<T>(this IAsyncCursorSource<T> source, CancellationToken cancellationToken)
{
if (source is null)
{
throw new ArgumentNullException(nameof(source));
}
return ExecuteAsync(source, cancellationToken);
static async IAsyncEnumerable<T> ExecuteAsync(IAsyncCursorSource<T> source, [EnumeratorCancellation] CancellationToken cancellationToken)
@ -45,6 +50,13 @@ internal static class OpenIddictMongoDbHelpers
/// <param name="source">The query source.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The streamed async enumeration containing the results.</returns>
internal static IAsyncEnumerable<T> ToAsyncEnumerable<T>(this IQueryable<T> source!!, CancellationToken cancellationToken)
=> ((IAsyncCursorSource<T>) source).ToAsyncEnumerable(cancellationToken);
internal static IAsyncEnumerable<T> ToAsyncEnumerable<T>(this IQueryable<T> source, CancellationToken cancellationToken)
{
if (source is null)
{
throw new ArgumentNullException(nameof(source));
}
return ((IAsyncCursorSource<T>) source).ToAsyncEnumerable(cancellationToken);
}
}

4
src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbApplicationStoreResolver.cs

@ -18,8 +18,8 @@ public class OpenIddictMongoDbApplicationStoreResolver : IOpenIddictApplicationS
private readonly ConcurrentDictionary<Type, Type> _cache = new ConcurrentDictionary<Type, Type>();
private readonly IServiceProvider _provider;
public OpenIddictMongoDbApplicationStoreResolver(IServiceProvider provider!!)
=> _provider = provider;
public OpenIddictMongoDbApplicationStoreResolver(IServiceProvider provider)
=> _provider = provider ?? throw new ArgumentNullException(nameof(provider));
/// <summary>
/// Returns an application store compatible with the specified application type or throws an

4
src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbAuthorizationStoreResolver.cs

@ -18,8 +18,8 @@ public class OpenIddictMongoDbAuthorizationStoreResolver : IOpenIddictAuthorizat
private readonly ConcurrentDictionary<Type, Type> _cache = new ConcurrentDictionary<Type, Type>();
private readonly IServiceProvider _provider;
public OpenIddictMongoDbAuthorizationStoreResolver(IServiceProvider provider!!)
=> _provider = provider;
public OpenIddictMongoDbAuthorizationStoreResolver(IServiceProvider provider)
=> _provider = provider ?? throw new ArgumentNullException(nameof(provider));
/// <summary>
/// Returns an authorization store compatible with the specified authorization type or throws an

4
src/OpenIddict.MongoDb/Resolvers/OpenIddictMongoDbScopeStoreResolver.cs

@ -18,8 +18,8 @@ public class OpenIddictMongoDbScopeStoreResolver : IOpenIddictScopeStoreResolver
private readonly ConcurrentDictionary<Type, Type> _cache = new ConcurrentDictionary<Type, Type>();
private readonly IServiceProvider _provider;
public OpenIddictMongoDbScopeStoreResolver(IServiceProvider provider!!)
=> _provider = provider;
public OpenIddictMongoDbScopeStoreResolver(IServiceProvider provider)
=> _provider = provider ?? throw new ArgumentNullException(nameof(provider));
/// <summary>
/// Returns a scope store compatible with the specified scope type or throws an

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save