fingers10
fingers10

Reputation: 7947

why should we provide issuer, audience and key in both AddJwtBearer in ConfigureServices and while creating new JwtSecurityToken in asp.net core

I'm new to JWT Authentication. I'm practicing it using this demo solution in my repo. I understood how the code flows and able to make it work. But I have a question which keeps bothering me. Why should we provide key, issuer and audience at both places?

ConfigureServices - Startup:

services
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,

                ValidIssuer = "http://localhost:44348",
                ValidAudience = "http://localhost:44348",
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("superSecretKey@345"))
            };
        });

Token Creation Code in AuthController:

private JwtSecurityToken GenerateToken(IEnumerable<Claim> claims)
{
    var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("superSecretKey@345"));
    var signinCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256);

    var tokeOptions = new JwtSecurityToken(
        issuer: "http://localhost:44348",
        audience: "http://localhost:44348",
        claims: claims,
        expires: DateTime.Now.AddMinutes(1),
        signingCredentials: signinCredentials
    );
    return tokeOptions;
}

If we notice we can see the key, issuer and audience at both places. As far as I see we are doing because of configuration or setup? I think we should provide these configuration only at ConfigureServices. Please correct me if I'm wrong and assist me with reasons for why we are doing it at two places.

Upvotes: 1

Views: 1618

Answers (1)

itminus
itminus

Reputation: 25350

Why should we provide key, issuer and audience at both places?

You don't have to. Just inject the named JwtBearerOptions when you need. For example, change your AuthController to accept a IOptionsSnapshot<JwtBearerOptions:

public class AuthController : ControllerBase
{
    private static readonly Dictionary<string, string> _userTokens = new Dictionary<string, string> { { "abdul", null } };
    private readonly JwtBearerOptions jwtOpts;

    public AuthController(IOptionsSnapshot<JwtBearerOptions> jwtOpts)
    {
        this.jwtOpts = jwtOpts.Get(JwtBearerDefaults.AuthenticationScheme) ?? throw new Exception("JwtBearerOptions is null!");
    }

    private JwtSecurityToken GenerateToken(IEnumerable<Claim> claims)
    {
        var key = this.jwtOpts.TokenValidationParameters.IssuerSigningKey;
        var signCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        var tokeOptions = new JwtSecurityToken(
            issuer: jwtOpts.TokenValidationParameters.ValidIssuer,
            audience: jwtOpts.TokenValidationParameters.ValidAudience,
            claims: claims,
            expires: DateTime.Now.AddMinutes(1),
            signingCredentials: signCredentials
        );
        return tokeOptions;
    }

   ...

Upvotes: 2

Related Questions