Skip to main content

Migration Guides

v10.0.1 → v10.0.2​

Breaking Change: None for call sites​

The single DependencyInjectionExtensions class is split into one class per target type: ServiceCollectionExtensions (the Add method) and ApplicationBuilderExtensions (the Use method). Both methods are now declared as C# 14 extension members (extension blocks). Method names, signatures, and the RA.Utilities.Authentication.JwtBearer.Extensions namespace are unchanged.

Why this change?​

The split mirrors the classic ASP.NET Core naming convention used across the RA.Utilities packages — ServiceCollectionExtensions for service registration, ApplicationBuilderExtensions for pipeline setup — so each class has a single, obvious responsibility.

What changed​

Aspectv10.0.1v10.0.2
AddJwtBearerAuthentication() declared inDependencyInjectionExtensionsServiceCollectionExtensions
UseAuth() declared inDependencyInjectionExtensionsApplicationBuilderExtensions
Method names / signatures—unchanged
Implementation styleclassic extension methodsC# 14 extension blocks

Migration Steps​

1. No code changes required for consuming projects​

These are extension methods — they are resolved by the compiler based on the target type (IServiceCollection, IApplicationBuilder), not the static class name. The using directive is unchanged:

// ✅ This code is unchanged in v10.0.2
using RA.Utilities.Authentication.JwtBearer.Extensions;

builder.Services.AddJwtBearerAuthentication(builder.Configuration); // Resolved on IServiceCollection

var app = builder.Build();

app.UseAuth(); // Resolved on IApplicationBuilder

2. Update direct class name references (if any)​

// ❌ v10.0.1
typeof(DependencyInjectionExtensions)

// ✅ v10.0.2
typeof(ServiceCollectionExtensions) // AddJwtBearerAuthentication()
typeof(ApplicationBuilderExtensions) // UseAuth()

v10.0.0 → v10.0.1​

Breaking Change: None​

This is a non-breaking release. All public APIs (AddJwtBearerAuthentication, UseAuth) are unchanged. The configureOptions callback signature and behavior are fully backward-compatible.

What changed​

Consolidated configuration pipeline. In v10.0.0, JwtBearerOptions were configured in two separate places — the AddJwtBearer lambda (which bound standard config and invoked the user callback) and the ConfigureJwtBearerOptions class (which applied ClockSkewInSeconds and IssuerSigningKeyString conversions). Because ConfigureJwtBearerOptions ran second, any ClockSkew or IssuerSigningKey values set in the user's configureOptions callback were silently overwritten.

In v10.0.1, all configuration happens in a single ConfigureJwtBearerOptions class that applies settings in a fixed, documented order:

StepActionOverrideable?
1Bind standard JwtBearerOptions from Authentication:Schemes:BearerYes, by step 3
2Apply special conversions (ClockSkewInSeconds → TimeSpan, IssuerSigningKeyString → SymmetricSecurityKey)Yes, by step 3
3Invoke user's configureOptions callbackFinal — always wins

Fail-fast key validation. The issuer signing key is now validated at construction time (app startup). If the key is shorter than 32 bytes, the app throws InvalidOperationException immediately rather than failing at runtime with a cryptic token validation error.

Added null guard. ConfigureJwtBearerOptions now throws ArgumentNullException if IConfiguration is null, matching the guard already present in the DI extension method.

Migration Steps​

No code changes are required. Your existing Program.cs continues to compile and work identically:

// ✅ This code works in both v10.0.0 and v10.0.1
using RA.Utilities.Authentication.JwtBearer.Extensions;

builder.Services.AddJwtBearerAuthentication(builder.Configuration, options =>
{
options.Events = new JwtBearerEvents { /* ... */ };
});

app.UseAuth();

If you were previously working around the silent-overwrite bug by avoiding the configureOptions callback for ClockSkew or IssuerSigningKey, you can now safely use it:

// ✅ In v10.0.1, this override now works correctly
builder.Services.AddJwtBearerAuthentication(builder.Configuration, options =>
{
// This now takes effect — the config value is no longer overwritten
options.TokenValidationParameters.ClockSkew = TimeSpan.Zero;
});

Verify the upgrade​

After upgrading, confirm the key validation still passes by checking your signing key length:

// If your IssuerSigningKeyString is >= 32 bytes, startup proceeds normally.
// If it's shorter, you'll now see a clear error at startup:
// InvalidOperationException: The configured issuer signing key must be at least 32 bytes long.

Full Changelog​

See the package release notes for a complete version history.