0

I'm trying to add auth to my .NET Core 3.1 application, however each attempt to use the returned JWT results in 401 Unauthorized. I've gone through a few steps to debug:

  1. I've confirmed that the JWT that my authenticate endpoint returns is valid, using this online validator.
  2. I've re-ordered my UseRouting(), UseAuthentication(), UseAuthorization(), and UseEndpoints() to every possible order.
  3. I've disabled both audience and issuer validation entirely for the time being.

Can someone identify where I've gone wrong, or at the very least, provide some method of properly debugging so I can track the issue down? Thanks. Code below.

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddAuthentication(options => { 
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(options =>
        {
            var key = Encoding.UTF8.GetBytes("thisismycustomSecretkeyforauthentication");
            options.SaveToken = true;
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = false,
                ValidateAudience = false,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = "issuer",
                ValidAudience = "audience",
                IssuerSigningKey = new SymmetricSecurityKey(key)
            };
        });

    services
        .AddControllers();
        .AddMvc(options => { options.EnableEndpointRouting = false; });
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app
        .UseStaticFiles()
        .UseHsts()
        .UseHttpsRedirection()
        .UseMvc(routes => routes.MapRoute(name: "default", template: "{controller=App}/{action=Index}/{id?}"))
        .UseRouting()
        .UseAuthentication()
        .UseAuthorization()
        .UseEndpoints(endpoints => { endpoints.MapControllers(); });

    if (env.IsDevelopment())
        app.UseSpa(spa => spa.UseProxyToSpaDevelopmentServer("https://localhost:22010"));
}

AuthController.cs

[ApiController]
[Authorize]
[Route("[controller]")]
public class AuthController : Controller
{
    [AllowAnonymous]
    [HttpPost("authenticate")]
    public async Task<IActionResult> Authenticate(AuthenticationRequest request)
    {
        if (request.Username != "test" || request.Password != "admin")
            return Unauthorized();

        var tokenHandler = new JwtSecurityTokenHandler();
        var tokenKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("thisismycustomSecretkeyforauthentication"));
        var token = new JwtSecurityToken
        (
            issuer: null,
            audience: null,
            claims: new Claim[] { new Claim(ClaimTypes.Name, request.Username) },
            expires: DateTime.Now.AddDays(30),
            signingCredentials: new SigningCredentials(tokenKey, SecurityAlgorithms.HmacSha256)
        );
        var tokenResponse = tokenHandler.WriteToken(token);

        return Ok(tokenResponse);
    }

    [HttpGet]
    public IActionResult Do()
    {
        return Ok("Done!");
    }
}

1 Answer 1

1

Authentication setup looks fine, and your middleware order is per Microsoft Documentation. Based on the code provided you seem to be missing the actual Authorization options. This is similar to the issue solved in this question.

Sign up to request clarification or add additional context in comments.

3 Comments

This seems to have worked! That said, I thought this was being applied globally by my implementation of AddAuthentication. Any ideas how I can apply this to all authorization attributes?
You currently only setting up Authentication in your Startup class. You can extend this setup with services.AddAuthorization( ... to do the same for your Authorization.
Spot on, thank you so much. I've referenced this Microsoft article to configure the default globally.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.