sameer nainawat
sameer nainawat

Reputation: 41

how to get claims value from JWT token authentication

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.

Upvotes: 3

Views: 89067

Answers (7)

shreyash
shreyash

Reputation: 1

In newer versions of Jwts you will find the parser() as deprecated, in that case just use the parserBuilder().build() method in place of parser().

Hope this helps someone who is coping with this issue.

Upvotes: 0

elyte5star
elyte5star

Reputation: 311

// for retrieving any information from token we will need the signing key
private Claims getAllClaimsFromToken(String token) {
    return Jwts.parser().verifyWith(<SigningKey>).build().parseSignedClaims(token).getPayload();
}

Upvotes: 4

mohu
mohu

Reputation: 89

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

Upvotes: 0

MJM
MJM

Reputation: 5291

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();
        }
    }

Upvotes: 0

Alexey
Alexey

Reputation: 186

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()

Upvotes: 1

MyTwoCents
MyTwoCents

Reputation: 7624

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);
    }



}

Upvotes: 5

Kunal Vohra
Kunal Vohra

Reputation: 2836

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.

Upvotes: 0

Related Questions