What is the best way to share a configuration object between the ASP.NET Core 3.1 Startup class and Controllers?
I have seen some examples using DI, and this seems like a good idea, but I need to use the dependency within public void ConfigureServices(IServiceCollection services)
.
Furthermore the object depends on a Microsoft.Extensions.Configuration.IConfiguration
instance.
The object will be used within
Startup.cs
, within theConfigureServices
itself as well as inControllers
.
Would DI work? Or is the solution a Singleton with parameters?
Here is the specific code that needs to be shared:
// openssl rand -hex 16 => 256 bits when read
var jwt_key = Configuration.GetSection("JwtOption:IssuerSigningKey").Value;
var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwt_key));
var tokenValidationParameters = new TokenValidationParameters
{
// The signing key must match!
ValidateIssuerSigningKey = true,
IssuerSigningKey = signingKey,
// Validate the JWT Issuer (iss) claim
ValidateIssuer = true,
ValidIssuer = "some host name",
// Validate the JWT Audience (aud) claim
ValidateAudience = true,
ValidAudience = "web_intranet",
// Validate the token expiry
ValidateLifetime = true,
// If you want to allow a certain amount of clock drift, set that here:
ClockSkew = TimeSpan.Zero
};
This object is used as follows within the public void ConfigureServices(IServiceCollection services)
method
services
.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.TicketDataFormat = new CustomJwtDataFormat(
SecurityAlgorithms.HmacSha256,
tokenValidationParameters);
});
Try to avoid passing IConfiguration around. The shared code can be done in Startup and the model populated and added to the container
You can register the instance directly with the container in Startup.ConfigureServices
void ConfigureServices(IServiceCollection services) {
var jwt_key = Configuration.GetSection("JwtOption:IssuerSigningKey").Value;
var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwt_key));
var tokenValidationParameters = new TokenValidationParameters {
//...code omitted for brevity
}
services.AddSingleton(tokenValidationParameters);
//...can still use tokenValidationParameters
services
.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.TicketDataFormat = new CustomJwtDataFormat(
SecurityAlgorithms.HmacSha256,
tokenValidationParameters);
});
}
and inject it explicitly where needed
//ctr
public MyController(TokenValidationParameters tokenParameters) {
//...
}
Or you can use options pattern
Reference Options pattern in ASP.NET Core
void ConfigureServices(IServiceCollection services) {
//...code omitted for brevity
var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwt_key));
services.Configure<TokenValidationParameters>(options => {
// The signing key must match!
options.ValidateIssuerSigningKey = true;
options.IssuerSigningKey = signingKey;
// Validate the JWT Issuer (iss) claim
options.ValidateIssuer = true;
options.ValidIssuer = "some host name";
// Validate the JWT Audience (aud) claim
options.ValidateAudience = true;
options.ValidAudience = "web_intranet";
// Validate the token expiry
options.ValidateLifetime = true;
// If you want to allow a certain amount of clock drift, set that here:
options.ClockSkew = TimeSpan.Zero;
});
//...
//Use DI services to configure cookie options
var scheme = CookieAuthenticationDefaults.AuthenticationScheme;
services.AddOptions<CookieAuthenticationOptions>(scheme)
.Configure<IOptions<TokenValidationParameters>>((options, token) => {
options.TicketDataFormat = new CustomJwtDataFormat(
SecurityAlgorithms.HmacSha256,
token.Value); //<--
});
services
.AddAuthentication(scheme)
.AddCookie();
}
Reference Use DI services to configure options
and Inject IOptions<TokenValidationParameters>
where needed
//ctr
public MyController(IOptions<TokenValidationParameters> options) {
TokenValidationParameters tokenParameters = options.Value;
//...
}