'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.
Solution 1:[1]
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>
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);
}
}
Solution 2:[2]
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.
Solution 3:[3]
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()
Solution 4:[4]
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/
Solution 5:[5]
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();
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Kunal Vohra |
| Solution 3 | Alexey |
| Solution 4 | Vineeth Bhaskaran |
| Solution 5 | MJM |
