3

I have set claims in JWT token in the token provider. now I want to get claim value through authentication when API is hit.

I have checked in Principal, details, credential, authorities but I am not getting claims in any of them.

Claims claims = Jwts.claims().setSubject(authentication.getName());
    claims.put(AUTHORITIES_KEY, authorities);
    claims.put("userId", userRepo.findUserIdByUsername(authentication.getName()));

   return Jwts.builder()
            .setSubject(authentication.getName())
            .setClaims(claims)
            //.claim(AUTHORITIES_KEY, authorities)
            .signWith(SignatureAlgorithm.HS512, SIGNING_KEY)
            .setIssuedAt(new Date(System.currentTimeMillis()))
            .setExpiration(new Date(System.currentTimeMillis() + ACCESS_TOKEN_VALIDITY_SECONDS*1000))
            .compact();

I want to get "userId" claim from the authentication or any other way to get claims value from token.

sameer nainawat
  • 41
  • 1
  • 2
  • 9

6 Answers6

4

This is how I read Claim from Token

private Claims getAllClaimsFromToken(String token) {
        Claims claims;
        try {
            claims = Jwts.parser()
                    .setSigningKey(SECRET)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            LOGGER.error("Could not get all claims Token from passed token");
            claims = null;
        }
        return claims;
    }

I am using this for JWT

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.0</version>
</dependency>

More detail here

Edit 1:

Adding Filter to get token from Request and Validate

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.filter.OncePerRequestFilter;

public class TokenAuthenticationFilter extends OncePerRequestFilter {

    protected final Log logger = LogFactory.getLog(getClass());

    private TokenHelper tokenHelper;

    private UserDetailsService userDetailsService;

    public TokenAuthenticationFilter(TokenHelper tokenHelper, UserDetailsService userDetailsService) {
        this.tokenHelper = tokenHelper;
        this.userDetailsService = userDetailsService;
    }


    @Override
    public void doFilterInternal(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain chain
    ) throws IOException, ServletException {

        String username;
        String authToken = tokenHelper.getToken(request);

        logger.info("AuthToken: "+authToken);

        if (authToken != null) {
            // get username from token
            username = tokenHelper.getUsernameFromToken(authToken);
            logger.info("UserName: "+username);
            if (username != null) {
                // get user
                UserDetails userDetails = userDetailsService.loadUserByUsername(username);
                if (tokenHelper.validateToken(authToken, userDetails)) {
                    // create authentication
                    TokenBasedAuthentication authentication = new TokenBasedAuthentication(userDetails);
                    authentication.setToken(authToken);
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            }else{
                logger.error("Something is wrong with Token.");
            }
        }
        chain.doFilter(request, response);
    }



}
MyTwoCents
  • 7,284
  • 3
  • 24
  • 52
  • 1
    how i will get token when API is hit...? – sameer nainawat Jan 24 '19 at 06:04
  • If you see the link I have added. There is TokenAuthenticationFilter class where I get Token when API is hit. You can do something similar – MyTwoCents Jan 24 '19 at 06:13
  • 1
    I have seen your code, but I didn't get the answer to my question that when we hit API then at the controller side we only get Principal, details, credential, authorities and in your code, we are generating token so I didn't find it related to my question. – sameer nainawat Jan 24 '19 at 11:42
1

It should help.

You should be able to retrieve a claims like this within your controller

var identity = HttpContext.User.Identity as ClaimsIdentity;
if (identity != null)
{
    IEnumerable<Claim> claims = identity.Claims; 
    // or
    identity.FindFirst("ClaimName").Value;

}

If you wanted, you could write extension methods for the IPrincipal interface and retrieve claims using the code above, then retrieve them using (for example)

HttpContext.User.Identity.MethodName();

For completeness of the answer. To Decode the JWT token let's write a method to validate the token and extract the information.

public static ClaimsPrincipal ValidateToken(string jwtToken)
    {
        IdentityModelEventSource.ShowPII = true;

        SecurityToken validatedToken;
        TokenValidationParameters validationParameters = new TokenValidationParameters();

        validationParameters.ValidateLifetime = true;

        validationParameters.ValidAudience = _audience.ToLower();
        validationParameters.ValidIssuer = _issuer.ToLower();
        validationParameters.IssuerSigningKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(Encoding.UTF8.GetBytes(_appSettings.Secret));

        ClaimsPrincipal principal = new JwtSecurityTokenHandler().ValidateToken(jwtToken, validationParameters, out validatedToken);


        return principal;
    }

Now we can validate and extract the Claims by using:

ValidateToken(tokenString)?.FindFirst("ClaimName")?.Value

You should note that the ValidateToken method will return null value if the validation fails.

Kunal Vohra
  • 2,703
  • 2
  • 15
  • 33
  • is there any reference available for the answer you provided. I m not able to get HttpContext.User.Identity – sameer nainawat Jan 24 '19 at 06:08
  • @sameernainawat That doesn't even seem to be Java but Kotlin code. – howlger Jan 24 '19 at 10:04
  • @sameernainawat The `as` in `HttpContext.User.Identity as ClaimsIdentity` is not a valid keyword in Java. If you are using something other than plain Java, please say so in your question. – howlger Jan 24 '19 at 12:09
1

Using Spring Security 5 you can use @AuthenticationPrincipal org.springframework.security.oauth2.jwt.Jwt token as parameter in your controller method. And then call token.getClaims()

Alexey
  • 186
  • 1
  • 6
0

It would be recommended to refer the blog given below. It explained how the JWT token works in spring boot

https://auth0.com/blog/implementing-jwt-authentication-on-spring-boot/

Vineeth Bhaskaran
  • 2,161
  • 1
  • 29
  • 36
0

List out all the claims using JWT

private void listClaimUsingJWT(String accessToken) {
        try {
            SignedJWT signedJWT = SignedJWT.parse(accessToken);
            JWTClaimsSet claimsSet= signedJWT.getJWTClaimsSet();
            Map<String,Object> myClain =claimsSet.getClaims();

            String[] keySet = myClain.keySet().toArray(new String[0]);
            Log.d("JWT_Claims", "loadAllOptionalClaim JWT keySetSize "+keySet.length);

            for (String s : keySet) {
                Log.d("JWT_Claims", "loadAllOptionalClaim JWT key ==> " + s + " ====> " + myClain.get(s));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
MJM
  • 5,119
  • 5
  • 27
  • 53
0

If it is in quarkus, we can get it by injecting JSONWebToken:

    /**
     * Injection point for the ID Token issued by the OpenID Connect Provider
     */
    @Inject
    @IdToken
    JsonWebToken idToken;

In Java, Keys for claim in keycloak provided by JSONWebToken can be accessed via getClaimNames() method. Following is an example:

        Set<String> allClaims = this.idToken.getClaimNames();
        for (String claimName: allClaims) {
            System.out.println("Claim name: " + claimName);
        }

Ref: https://quarkus.io/guides/security-openid-connect-web-authentication

mohu
  • 79
  • 1
  • 4