0

I followed this tutorial to configure JWT authorization in my Web API app. The token generation and handout works fine, but when I send a request back to the server with the token, it doesn't populate the identity, so it fails if authorization is required.

I've tested both with a reactjs frontend and Postman. Both end up returning nothing (without Authorize decorator - User.Identity.isAuthorized is false), or 404 with the decorator. I have confirmed that the token is being sent properly.

I'm also using Identity, if that matters.

ConfigureServices method

    public void ConfigureServices(IServiceCollection services)
    {
        ...

        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = Configuration["Jwt:Issuer"],
                ValidAudience = Configuration["Jwt:Audience"],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
            };
        });
   }

Configure method

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseAuthentication();

        app.UseCors("SiteCorsPolicy");

        app.UseMvc();

        ...
    }

Function to build the token

    private string BuildToken(AuthViewModel user)
    {
        var claims = new[]
        {
            new Claim(JwtRegisteredClaimNames.Sub, user.Username),
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
        };

        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        var token = new JwtSecurityToken
        (
            _config["Jwt:Issuer"],
            _config["Jwt:Audience"],
            //claims,
            expires: DateTime.Now.AddMinutes(30),
            signingCredentials: creds
        );

        return new JwtSecurityTokenHandler().WriteToken(token);
    }

Excerpt from appsettings.json

"Jwt": {
    "Key": "<secret stuff>",
    "Issuer": "http://localhost:53530/",
    "Audience": "http://localhost:8080/"
 }

Test function I'm trying to call but is failing

    [HttpGet("currentuser"), Authorize]
    public async Task<ApplicationUser> GetCurrentUser()
    {
        var username = User.Identity.Name;

        return await _context.ApplicationUsers.SingleOrDefaultAsync(u => u.UserName == username);
    }
atfergs
  • 1,675
  • 1
  • 11
  • 17

2 Answers2

2

I figured it out. I had to add a new Authorization Policy.

services.AddAuthorization(auth =>
{
    auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
        .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
        .RequireAuthenticatedUser().Build());
});

Then I decorated the controller with

[Authorize("Bearer"]

I've been messing with this for a couple days, trying different tutorials, so I know this was working at one point without the policy. Dunno why I needed it this time or why it wasn't part of the tutorial.

If someone figures out what I screwed up in the first place, I'm all ears.

Ajit Panigrahi
  • 723
  • 11
  • 25
atfergs
  • 1,675
  • 1
  • 11
  • 17
1

I ran into the same issue (.net core 2.1) and was really happy to make it work using your answer @atfergs.

After fiddling with the whole setup I found out that no new Authorization Policy is required.

It is sufficient to decorate the controller with

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

considering the following setup

        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(options =>
        {...}

Now

    User?.Identity?.IsAuthenticated

is true :)

Cheers!

Noro Korny
  • 918
  • 1
  • 9
  • 8