diff --git a/sandbox/OpenIddict.Sandbox.AspNet.Client/Startup.cs b/sandbox/OpenIddict.Sandbox.AspNet.Client/Startup.cs index b724e927..55860da2 100644 --- a/sandbox/OpenIddict.Sandbox.AspNet.Client/Startup.cs +++ b/sandbox/OpenIddict.Sandbox.AspNet.Client/Startup.cs @@ -92,9 +92,11 @@ namespace OpenIddict.Sandbox.AspNet.Client .EnableRedirectionEndpointPassthrough() .EnablePostLogoutRedirectionEndpointPassthrough(); - // Register the System.Net.Http integration and configure the HTTP options. + // Register the System.Net.Http integration and use the identity of the current + // assembly as a more specific user agent, which can be useful when dealing with + // providers that use the user agent as a way to throttle requests (e.g Reddit). options.UseSystemNetHttp() - .SetProductInformation("DemoApp", "1.0.0"); + .SetProductInformation(typeof(Startup).Assembly); // Add a client registration matching the client application definition in the server project. options.AddRegistration(new OpenIddictClientRegistration diff --git a/sandbox/OpenIddict.Sandbox.AspNet.Server/Startup.cs b/sandbox/OpenIddict.Sandbox.AspNet.Server/Startup.cs index fcd0019b..7a67cccd 100644 --- a/sandbox/OpenIddict.Sandbox.AspNet.Server/Startup.cs +++ b/sandbox/OpenIddict.Sandbox.AspNet.Server/Startup.cs @@ -140,9 +140,11 @@ namespace OpenIddict.Sandbox.AspNet.Server options.UseOwin() .EnableRedirectionEndpointPassthrough(); - // Register the System.Net.Http integration and configure the HTTP options. + // Register the System.Net.Http integration and use the identity of the current + // assembly as a more specific user agent, which can be useful when dealing with + // providers that use the user agent as a way to throttle requests (e.g Reddit). options.UseSystemNetHttp() - .SetProductInformation("DemoApp", "1.0.0"); + .SetProductInformation(typeof(Startup).Assembly); // Register the Web providers integrations. options.UseWebProviders() diff --git a/sandbox/OpenIddict.Sandbox.AspNetCore.Client/Startup.cs b/sandbox/OpenIddict.Sandbox.AspNetCore.Client/Startup.cs index a8a59d91..698d0dda 100644 --- a/sandbox/OpenIddict.Sandbox.AspNetCore.Client/Startup.cs +++ b/sandbox/OpenIddict.Sandbox.AspNetCore.Client/Startup.cs @@ -102,9 +102,11 @@ public class Startup .EnableRedirectionEndpointPassthrough() .EnablePostLogoutRedirectionEndpointPassthrough(); - // Register the System.Net.Http integration and configure the HTTP options. + // Register the System.Net.Http integration and use the identity of the current + // assembly as a more specific user agent, which can be useful when dealing with + // providers that use the user agent as a way to throttle requests (e.g Reddit). options.UseSystemNetHttp() - .SetProductInformation("DemoApp", "1.0.0"); + .SetProductInformation(typeof(Startup).Assembly); // Add a client registration matching the client application definition in the server project. options.AddRegistration(new OpenIddictClientRegistration diff --git a/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Startup.cs b/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Startup.cs index 895c7ea2..ba088566 100644 --- a/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Startup.cs +++ b/sandbox/OpenIddict.Sandbox.AspNetCore.Server/Startup.cs @@ -1,4 +1,3 @@ -using System.Net.Http.Headers; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using OpenIddict.Sandbox.AspNetCore.Server.Models; @@ -87,9 +86,11 @@ public class Startup .EnableStatusCodePagesIntegration() .EnableRedirectionEndpointPassthrough(); - // Register the System.Net.Http integration and configure the HTTP options. + // Register the System.Net.Http integration and use the identity of the current + // assembly as a more specific user agent, which can be useful when dealing with + // providers that use the user agent as a way to throttle requests (e.g Reddit). options.UseSystemNetHttp() - .SetProductInformation("DemoApp", "1.0.0"); + .SetProductInformation(typeof(Startup).Assembly); // Register the Web providers integrations. options.UseWebProviders() diff --git a/src/OpenIddict.Abstractions/OpenIddictResources.resx b/src/OpenIddict.Abstractions/OpenIddictResources.resx index c844411d..378d81c7 100644 --- a/src/OpenIddict.Abstractions/OpenIddictResources.resx +++ b/src/OpenIddict.Abstractions/OpenIddictResources.resx @@ -1331,6 +1331,9 @@ Alternatively, you can disable the token storage feature by calling 'services.Ad The request forgery protection claim cannot be resolved from the sign-out context. + + The product name cannot be null or empty. + The security token is missing. diff --git a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpBuilder.cs b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpBuilder.cs index d584ac34..0be71e0f 100644 --- a/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpBuilder.cs +++ b/src/OpenIddict.Client.SystemNetHttp/OpenIddictClientSystemNetHttpBuilder.cs @@ -6,6 +6,7 @@ using System.ComponentModel; using System.Net.Http.Headers; +using System.Reflection; using OpenIddict.Client.SystemNetHttp; using Polly; @@ -52,8 +53,15 @@ public class OpenIddictClientSystemNetHttpBuilder /// /// The HTTP Polly error policy. /// The . - public OpenIddictClientSystemNetHttpBuilder SetHttpErrorPolicy(IAsyncPolicy? policy) - => Configure(options => options.HttpErrorPolicy = policy); + public OpenIddictClientSystemNetHttpBuilder SetHttpErrorPolicy(IAsyncPolicy policy) + { + if (policy is null) + { + throw new ArgumentNullException(nameof(policy)); + } + + return Configure(options => options.HttpErrorPolicy = policy); + } /// /// Sets the product information used in the user agent header that is attached @@ -61,8 +69,15 @@ public class OpenIddictClientSystemNetHttpBuilder /// /// The product information. /// The . - public OpenIddictClientSystemNetHttpBuilder SetProductInformation(ProductInfoHeaderValue? information) - => Configure(options => options.ProductInformation = information); + public OpenIddictClientSystemNetHttpBuilder SetProductInformation(ProductInfoHeaderValue information) + { + if (information is null) + { + throw new ArgumentNullException(nameof(information)); + } + + return Configure(options => options.ProductInformation = information); + } /// /// Sets the product information used in the user agent header that is attached @@ -71,8 +86,34 @@ public class OpenIddictClientSystemNetHttpBuilder /// The product name. /// The product version. /// The . - public OpenIddictClientSystemNetHttpBuilder SetProductInformation(string? name, string? version) - => SetProductInformation(!string.IsNullOrEmpty(name) ? new ProductInfoHeaderValue(name, version) : null); + public OpenIddictClientSystemNetHttpBuilder SetProductInformation(string name, string? version) + { + if (string.IsNullOrEmpty(name)) + { + throw new ArgumentException(SR.GetResourceString(SR.ID0345), nameof(name)); + } + + return SetProductInformation(new ProductInfoHeaderValue(name, version)); + } + + /// + /// Sets the product information used in the user agent header that is attached + /// to the backchannel HTTP requests sent to the authorization server based + /// on the identity of the specified .NET assembly (name and version). + /// + /// The assembly from which the product information is created. + /// The . + public OpenIddictClientSystemNetHttpBuilder SetProductInformation(Assembly assembly) + { + if (assembly is null) + { + throw new ArgumentNullException(nameof(assembly)); + } + + return SetProductInformation(new ProductInfoHeaderValue( + productName: assembly.GetName().Name!, + productVersion: assembly.GetName().Version!.ToString())); + } /// [EditorBrowsable(EditorBrowsableState.Never)] diff --git a/src/OpenIddict.Core/Caches/OpenIddictScopeCache.cs b/src/OpenIddict.Core/Caches/OpenIddictScopeCache.cs index 4ea3614c..761643f1 100644 --- a/src/OpenIddict.Core/Caches/OpenIddictScopeCache.cs +++ b/src/OpenIddict.Core/Caches/OpenIddictScopeCache.cs @@ -160,7 +160,7 @@ public class OpenIddictScopeCache : IOpenIddictScopeCache, IDisp /// public IAsyncEnumerable FindByNamesAsync(ImmutableArray names, CancellationToken cancellationToken) { - if (names.Any(name => string.IsNullOrEmpty(name))) + if (names.Any(string.IsNullOrEmpty)) { throw new ArgumentException(SR.GetResourceString(SR.ID0203), nameof(names)); } diff --git a/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs b/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs index 0ddbb395..62b521d4 100644 --- a/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs +++ b/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs @@ -274,7 +274,7 @@ public class OpenIddictScopeManager : IOpenIddictScopeManager where TSco public virtual IAsyncEnumerable FindByNamesAsync( ImmutableArray names, CancellationToken cancellationToken = default) { - if (names.Any(name => string.IsNullOrEmpty(name))) + if (names.Any(string.IsNullOrEmpty)) { throw new ArgumentException(SR.GetResourceString(SR.ID0203), nameof(names)); } diff --git a/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkScopeStore.cs b/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkScopeStore.cs index af8b691c..2b3f839b 100644 --- a/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkScopeStore.cs +++ b/src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkScopeStore.cs @@ -161,7 +161,7 @@ public class OpenIddictEntityFrameworkScopeStore : IOpen public virtual IAsyncEnumerable FindByNamesAsync( ImmutableArray names, CancellationToken cancellationToken) { - if (names.Any(name => string.IsNullOrEmpty(name))) + if (names.Any(string.IsNullOrEmpty)) { throw new ArgumentException(SR.GetResourceString(SR.ID0203), nameof(names)); } diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreScopeStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreScopeStore.cs index 25b4b043..bf2bc809 100644 --- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreScopeStore.cs +++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreScopeStore.cs @@ -177,7 +177,7 @@ public class OpenIddictEntityFrameworkCoreScopeStore : I public virtual IAsyncEnumerable FindByNamesAsync( ImmutableArray names, CancellationToken cancellationToken) { - if (names.Any(name => string.IsNullOrEmpty(name))) + if (names.Any(string.IsNullOrEmpty)) { throw new ArgumentException(SR.GetResourceString(SR.ID0203), nameof(names)); } diff --git a/src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbScopeStore.cs b/src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbScopeStore.cs index 486aac5e..d1961d9c 100644 --- a/src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbScopeStore.cs +++ b/src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbScopeStore.cs @@ -129,7 +129,7 @@ public class OpenIddictMongoDbScopeStore : IOpenIddictScopeStore /// public virtual IAsyncEnumerable FindByNamesAsync(ImmutableArray names, CancellationToken cancellationToken) { - if (names.Any(name => string.IsNullOrEmpty(name))) + if (names.Any(string.IsNullOrEmpty)) { throw new ArgumentException(SR.GetResourceString(SR.ID0203), nameof(names)); } diff --git a/src/OpenIddict.Server/OpenIddictServerBuilder.cs b/src/OpenIddict.Server/OpenIddictServerBuilder.cs index 405a6e6b..000ce0b6 100644 --- a/src/OpenIddict.Server/OpenIddictServerBuilder.cs +++ b/src/OpenIddict.Server/OpenIddictServerBuilder.cs @@ -1676,7 +1676,7 @@ public class OpenIddictServerBuilder throw new ArgumentNullException(nameof(claims)); } - if (claims.Any(claim => string.IsNullOrEmpty(claim))) + if (claims.Any(string.IsNullOrEmpty)) { throw new ArgumentException(SR.GetResourceString(SR.ID0073), nameof(claims)); } @@ -1697,7 +1697,7 @@ public class OpenIddictServerBuilder throw new ArgumentNullException(nameof(scopes)); } - if (scopes.Any(scope => string.IsNullOrEmpty(scope))) + if (scopes.Any(string.IsNullOrEmpty)) { throw new ArgumentException(SR.GetResourceString(SR.ID0074), nameof(scopes)); } diff --git a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpBuilder.cs b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpBuilder.cs index c190758a..d149303f 100644 --- a/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpBuilder.cs +++ b/src/OpenIddict.Validation.SystemNetHttp/OpenIddictValidationSystemNetHttpBuilder.cs @@ -6,6 +6,7 @@ using System.ComponentModel; using System.Net.Http.Headers; +using System.Reflection; using OpenIddict.Validation.SystemNetHttp; using Polly; @@ -48,12 +49,19 @@ public class OpenIddictValidationSystemNetHttpBuilder } /// - /// Replaces the default HTTP error policy used by the OpenIddict validation services. + /// Replaces the default HTTP error policy used by the OpenIddict client services. /// /// The HTTP Polly error policy. /// The . - public OpenIddictValidationSystemNetHttpBuilder SetHttpErrorPolicy(IAsyncPolicy? policy) - => Configure(options => options.HttpErrorPolicy = policy); + public OpenIddictValidationSystemNetHttpBuilder SetHttpErrorPolicy(IAsyncPolicy policy) + { + if (policy is null) + { + throw new ArgumentNullException(nameof(policy)); + } + + return Configure(options => options.HttpErrorPolicy = policy); + } /// /// Sets the product information used in the user agent header that is attached @@ -61,8 +69,15 @@ public class OpenIddictValidationSystemNetHttpBuilder /// /// The product information. /// The . - public OpenIddictValidationSystemNetHttpBuilder SetProductInformation(ProductInfoHeaderValue? information) - => Configure(options => options.ProductInformation = information); + public OpenIddictValidationSystemNetHttpBuilder SetProductInformation(ProductInfoHeaderValue information) + { + if (information is null) + { + throw new ArgumentNullException(nameof(information)); + } + + return Configure(options => options.ProductInformation = information); + } /// /// Sets the product information used in the user agent header that is attached @@ -71,8 +86,34 @@ public class OpenIddictValidationSystemNetHttpBuilder /// The product name. /// The product version. /// The . - public OpenIddictValidationSystemNetHttpBuilder SetProductInformation(string? name, string? version) - => SetProductInformation(!string.IsNullOrEmpty(name) ? new ProductInfoHeaderValue(name, version) : null); + public OpenIddictValidationSystemNetHttpBuilder SetProductInformation(string name, string? version) + { + if (string.IsNullOrEmpty(name)) + { + throw new ArgumentException(SR.GetResourceString(SR.ID0345), nameof(name)); + } + + return SetProductInformation(new ProductInfoHeaderValue(name, version)); + } + + /// + /// Sets the product information used in the user agent header that is attached + /// to the backchannel HTTP requests sent to the authorization server based + /// on the identity of the specified .NET assembly (name and version). + /// + /// The assembly from which the product information is created. + /// The . + public OpenIddictValidationSystemNetHttpBuilder SetProductInformation(Assembly assembly) + { + if (assembly is null) + { + throw new ArgumentNullException(nameof(assembly)); + } + + return SetProductInformation(new ProductInfoHeaderValue( + productName: assembly.GetName().Name!, + productVersion: assembly.GetName().Version!.ToString())); + } /// [EditorBrowsable(EditorBrowsableState.Never)] diff --git a/src/OpenIddict.Validation/OpenIddictValidationBuilder.cs b/src/OpenIddict.Validation/OpenIddictValidationBuilder.cs index 8f66f9cd..1ccf2d73 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationBuilder.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationBuilder.cs @@ -358,7 +358,7 @@ public class OpenIddictValidationBuilder throw new ArgumentNullException(nameof(audiences)); } - if (audiences.Any(audience => string.IsNullOrEmpty(audience))) + if (audiences.Any(string.IsNullOrEmpty)) { throw new ArgumentException(SR.GetResourceString(SR.ID0123), nameof(audiences)); }