简体   繁体   中英

Get claims from JWT token in ASP.NET Core 2.0 API

I'm using mixed authentication in my ASP.NET Core 2.0 Web and API app. Meaning both cookies and now adding JWT token .

The web part of the app uses cookies and in the API part, I want to use JWT token.

My question is how do I get the claims from JWT token ? In my web controllers, I can simply use HttpContext.User; to get the claims stored in a cookie. How do I handle it in my API methods where I want to use JWT token ?

Here's my AuthenticationBuilder:

public static void MyAuthenticationConfig(IServiceCollection services, IConfiguration configuration)
{
   services.AddAuthentication(options =>
   {
      options.DefaultAuthenticateScheme = "myApp_cookie";
      options.DefaultChallengeScheme = "myApp_cookie";
    })
    .AddCookie("myApp_cookie", options =>
    {
      options.AccessDeniedPath = "/Unauthorized";
      options.LoginPath = "/Login";
    })
    .AddCookie("social_auth_cookie")
    .AddOAuth("LinkedIn", options =>
    {
      options.SignInScheme = "social_auth_cookie";

      options.ClientId = "my_client_id";
      options.ClientSecret = "my_secret";

      options.CallbackPath = "/linkedin-callback";

      options.AuthorizationEndpoint = "https://www.linkedin.com/oauth/v2/authorization";
      options.TokenEndpoint = "https://www.linkedin.com/oauth/v2/accessToken";
      options.UserInformationEndpoint = "https://api.linkedin.com/v1/people/~:(id,first-name,last-name,email-address,picture-url,picture-urls::(original))";

      options.Scope.Add("r_basicprofile");
      options.Scope.Add("r_emailaddress");

      options.Events = new OAuthEvents
      {
         OnCreatingTicket = OnCreatingTicketLinkedInCallBack,
         OnTicketReceived = OnTicketReceivedCallback
       };
    })
    .AddFacebook(options =>
    {
        options.SignInScheme = "social_auth_cookie";
        options.AppId = "my_app_is";
        options.AppSecret = "my_secret";
        options.Events = new OAuthEvents
        {
           OnCreatingTicket = OnCreatingTicketFacebookCallback,
           OnTicketReceived = OnTicketReceivedCallback
         };
     })
     .AddGoogle(options =>
     {
         options.SignInScheme = "social_auth_cookie";
         options.ClientId = "my_id.apps.googleusercontent.com";
         options.ClientSecret = "my_secret";
         options.CallbackPath = "/google-callback";
         options.Events = new OAuthEvents
         {
             OnCreatingTicket = OnCreatingTicketGoogleCallback,
             OnTicketReceived = OnTicketReceivedCallback
         };
      })
      .AddJwtBearer("JwtBearer", jwtBearerOptions =>
      {
         jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters
         {
             ValidateIssuerSigningKey = true,
             IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("my_secret")),

             ValidateIssuer = true,
             ValidIssuer = "my-api",

             ValidateAudience = true,
             ValidAudience = "my-client",

             ValidateLifetime = true,

             ClockSkew = TimeSpan.FromMinutes(5)
        };
    });
}

Normally the claims of JWT are automatically added to the ClaimsIdentity.

Source:
https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/af5e5c2b0100e8348c63e2d2bb45612e2080841e/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs#L1110 ).

So you should be able to just use 'User' property of the base 'Controller' class.

public async Task<IActionResult> Get()
{
    // TODO Move 'Claims' extraction code to an extension method
    var address = User.Claims.Where('GET THE NEEDED CLAIM');
    ...
}

I never had any problems getting the claims from a JWT token. But I only used IdentityServer4.AccessTokenValidation so far. But internally it uses the Microsoft JWT Handler afaik.

Couldn't comment because my post would be to long, so making a seperate post instead.

If you follow the guide/link ErazerBrecht posted, the claims are indeed stored in the ClaimsPrincipal User. I created an extension method to retrieve the claim.

Note that I use an Enum for registering my claims. I use a dictionary to pass my claims to the method that generates my token, so my claim key should always be unique.

The extension method:

public static string GetClaim(this ClaimsPrincipal claimsPrincipal, JwtClaim jwtClaim)
{
  var claim = claimsPrincipal.Claims.Where(c => c.Type == jwtClaim.ToString()).FirstOrDefault();

  if (claim == null)
  {
      throw new JwtClaimNotFoundException(jwtClaim);
  }

  return claim.Value;
}

Call it like:

var userId = User.GetClaim(JwtClaim.UserId);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM