skip to Main Content

I’m having some difficulty trying to understand this, and I can’t find a more specific solution for my problem.
The problem is the following, I have an API with many endpoints, all of them use Authorize and a token is generated with Jwt.
What I’m trying to do, and I’m not sure if it’s possible, is that a controller uses an exclusive token for it. That is to say, this token if the user has access to it does not allow him to use it in the other existing endpoints.
I would also like that it is not necessary to modify the rest of the [Authorize] headers because there are a lot of endpoints.

Is it possible? Could you if it is not too much trouble point me a little better on how I should take this inconvenience?

I share with you some actual code:


            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme => JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(options =>
            {
                options.SaveToken = true;
                options.RequireHttpsMetadata = false;
                    options.TokenValidationParameters = new     Microsoft.IdentityModel.Tokens.TokenValidationParameters()
                {
                    RequireExpirationTime = false,
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    ValidAudience = "FULLAPI",
                    ValidIssuer = "FULLAPI",
                    IssuerSigningKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecurityKey))
                };
            });

Tried using policies and schemes but didn’t get to work how I wanted.

2

Answers


  1. you can define multiple authentication schemes.

    .AddJwtBearer("Scheme1", options =>
    {
        options.SaveToken = true;
        options.RequireHttpsMetadata = false;
        options.TokenValidationParameters = new TokenValidationParameters()
        {
            RequireExpirationTime = false,
            ValidateIssuer = false,
            ValidateAudience = false,
            ValidAudience = "FULLAPI",
            ValidIssuer = "FULLAPI",
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecurityKey))
        };
    })
    .AddJwtBearer("Scheme2", options =>
    {
        options.SaveToken = true;
        options.RequireHttpsMetadata = false;
        options.TokenValidationParameters = new TokenValidationParameters()
        {
            RequireExpirationTime = false,
            ValidateIssuer = false,
            ValidateAudience = false,
            ValidAudience = "FULLAPI",
            ValidIssuer = "FULLAPI",
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecurityKey2))
        };
    });
    

    and use like this.

    [Authorize(AuthenticationSchemes = "Scheme1")]
    public IActionResult Get()
    {
    
    Login or Signup to reply.
  2. This is a much cleaner way without modifying the existing [Authorize] attribute.

    First, modify the AddJwtBearer as below –

        .AddJwtBearer(options =>
                   {
                    options.Events.OnTokenValidated = context =>
                    {
                        var controller = context.HttpContext.Request.RouteValues["controller"];
                        var action = context.HttpContext.Request.RouteValues["action"];
    // validation logic goes here
                        return  Task.CompletedTask;
                    };
                    options.SaveToken = true;
                    options.RequireHttpsMetadata = false;
                    options.TokenValidationParameters = new     Microsoft.IdentityModel.Tokens.TokenValidationParameters()
                    {
                        RequireExpirationTime = false,
                        ValidateIssuer = false,
                        ValidateAudience = false,
                        ValidAudience = "FULLAPI",
                        ValidIssuer = "FULLAPI",
                        IssuerSigningKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecurityKey))
                    };
                });
    

    One of the ways would be that you group the all endpoints and map with a key having a specific group of endpoints. Then you can put that key in claims when you are creating the token.

    Now that you have access to the controller and action names and the token context, You can directly check the claims and validate if the key is valid for the currently requested endpoint and send the unauthorize response if the token does not meet the requirement.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search