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));
}