4
votes

I have a .Net Core 2 Web API project that is using JwtBearer Authentication. However, while this works in regards to Authenticating my user and respecting the [Authorize] attribute on my controller, the User Identity and Claims are never populated. Is there something more I have to do to create ensure that a ClaimsIdentity is created for my authenticated user?

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
   ...
   services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
      .AddJwtBearer(options => 
      {
          options.Authority = "https://myTenant.auth0.com";
          options.Audience = "https://localhost:5001/api/v1";
          options.RequireHttpsMetadata = false;

          options.TokenValidationParameters = new TokenValidationParameters
          {
             ValidateIssuer = true,
             ValidateAudience = true,
             ValidateLifetime = true,
             ValidateIssuerSigningKey = true,
             ValidIssuer = "myTenant.auth0.com",
             ValidAudience = "https://localhost:5001/api/v1"
          };
     });
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, SystemModelBuilder modelBuilder)
{
   ...
   app.UseHttpsRedirection();
   app.UseAuthentication();
}

My token looks like this on jwt.ms:

{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
.{
  "profileData": {
     "given_name": "Rodd",
     "family_name": "Harris"
  },
  "iss": "https://myTenant.auth0.com/",
  "sub": "auth0|37b5f5c54fdac",
  "aud": [
     "https://localhost:5050/api/v1/",
     "https://myTenant.auth0.com/userinfo"
  ],
  "iat": 1532628090,
  "exp": 1532629290,
  "azp": "2RdsNtKpUgh_wgB3NI6gxd-OAl",
  "scope": "openid profile email app.client.read"
}.[Signature]

In my controller, I have something like this:

[ApiController]
[Route("api/v1/[controller]")]
[Authorize]
public class TestController : ControllerBase
{
    [HttpGet("clients")]
    public async Task<IActionResult> ClientsList()
    {
       //Debugger gets here -- user is authenticated           
       var user = HttpContext.User.Identity.Name; //Always null
       var count = HttpContext.User.Claims.Count(); //Always 0
       var allowed = HttpContext.User.IsAuthenticated;  //Always true
       var type = HttpContext.User.AuthenticationType; //AuthenticationTypes.Federated
       ...
    }

What keeps the user's name and claims from being created?

Update

So I just realized I AM actually getting the claims mapped into HttpContext.User.Identity.Claims. Also realized that my token doesn't have a name value to automagically map to the Identity. So, I guess my real question is, how do I override the custom mapping and do my own mapping of the token into an Identity?

2

2 Answers

1
votes

Thanks to the information here and here, I was able to figure out what was going on.

First, .Net apparently tries to automap from the token claims by looking for the claim identified by the key: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name. Of course, I didn't have this in my token -- so no default name mapping.

In fact, I realized I didn't have ANY name being passed in my token -- so I had to set up a Rule on Auth0 to include something to use as a name. (I did have a name in app_metadata, but I needed to flatten that out into separate values).

Once that was done, I simply needed to tell .Net to use a different key to find the name claim in the list of token claims. I did this in Startup.cs like so:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
   .AddJwtBearer(options => 
   {
      options.TokenValidationParameters = new TokenValidationParameters
      {
          ...
          //There is no magic to this string -- it is whatever claim key is being
          //issued by the Auth Provider
          NameClaimType = "https://myshcemadefinedkey/preferred_username" 
      }
    }

With that in place, .Net began populating the User.Identity.Name value with the value associated with the token claim that had the corresponding key value.

0
votes

Maybe correct your Configure to get this :

app.UseIdentity();
app.UseJwtBearerAuthentication(new JwtBearerOptions()
{
    AutomaticAuthenticate = true,
    AutomaticChallenge = true,


            TokenValidationParameters = new TokenValidationParameters()
            {
                ValidIssuer = _config["Tokens:Issuer"],
                ValidAudience = _config["Tokens:Audience"],
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Tokens:Key"])),
                ValidateLifetime = true
            }
        });

And be carefull to put this before your UseMvc();