![JAR search and dependency download from the Maven repository](/logo.png)
it.cosenonjaviste.security.jwt.utils.JwtTokenBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tomcat-jwt-security Show documentation
Show all versions of tomcat-jwt-security Show documentation
JWT Tomcat Valve and utility classes for handling JWT tokens
The newest version!
package it.cosenonjaviste.security.jwt.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import it.cosenonjaviste.security.jwt.model.JwtAdapter;
import it.cosenonjaviste.security.jwt.utils.verifiers.JwtTokenVerifier;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import static com.auth0.jwt.impl.PublicClaims.*;
/**
* Builder class for simplifying JWT token creation.
*
* userId and roles values are mandatory.
*
* @author acomo
*
*/
public class JwtTokenBuilder {
private JWTCreator.Builder jwtBuilder = JWT.create();
private ClaimsAdapter claims = new ClaimsAdapter(jwtBuilder);
private OptionsAdapter optionsAdapter = new OptionsAdapter(jwtBuilder);
private Algorithm algorithm;
private String customUserIdClaim;
private String customRolesClaim;
private JwtTokenBuilder() {
}
/**
* Creates a new {@link JwtTokenBuilder} instance
*
* @param algorithm to use for encoding
* @param customUserIdClaim custom user id claim
* @param customRolesClaim custom roles claim
*
* @return a new {@link JwtTokenBuilder} instance
*/
public static JwtTokenBuilder create(Algorithm algorithm, String customUserIdClaim, String customRolesClaim) {
JwtTokenBuilder builder = new JwtTokenBuilder();
builder.algorithm = algorithm;
builder.optionsAdapter.setIssuedAt(true);
builder.customUserIdClaim = customUserIdClaim != null ? customUserIdClaim : JwtConstants.USER_ID;
builder.customRolesClaim = customRolesClaim != null ? customRolesClaim : JwtConstants.ROLES;
return builder;
}
/**
* Creates a new {@link JwtTokenBuilder} instance
*
* @param algorithm to use for encoding
*
* @return a new {@link JwtTokenBuilder} instance
*/
public static JwtTokenBuilder create(Algorithm algorithm) {
return create(algorithm, JwtConstants.USER_ID, JwtConstants.ROLES);
}
/**
* Creates a {@link JwtTokenBuilder} instance from token and secret.
*
* Token must contains "iat" param in order to restore builder status
*
* Use this method if you want to edit current token: if "jti" param is present, will be overwritten
*
* Token must be verified before calling this method
*
*
* Rebuilding this token has side effect:
*
* - if "jti" param is present, will be overwritten
* - if "exp" param is present, expire time will be recalculated starting from current timestamp
* - if "nbf" param is present, its value will be recalculated starting from current timestamp
*
*
* @param jwt a {@link JwtAdapter} instance
*
* @return a new {@link JwtTokenBuilder} instance
*
* @throws IllegalStateException if token is not verified by provided verifier
*/
public static JwtTokenBuilder from(JwtAdapter jwt) {
JwtTokenBuilder builder = create(jwt.getAlgorithm(), jwt.getUserIdClaim(), jwt.getRolesClaim());
DecodedJWT decodedJWT = jwt.getDecodedJWT();
restoreInternalStatus(builder, decodedJWT);
return builder;
}
/**
* Creates a {@link JwtTokenBuilder} instance from token and secret.
*
* Token must contains "iat" param in order to restore builder status
*
* Use this method if you want to edit current token: if "jti" param is present, will be overwritten
*
* Token must be verified before calling this method
*
*
* Rebuilding this token has side effect:
*
* - if "jti" param is present, will be overwritten
* - if "exp" param is present, expire time will be recalculated starting from current timestamp
* - if "nbf" param is present, its value will be recalculated starting from current timestamp
*
*
* @param token a jwt as String
* @param secret secret text
* @param customUserIdClaim custom user id claim
* @param customRolesClaim custom roles claim
*
* @return a new {@link JwtTokenBuilder} instance
*
* @throws IllegalStateException if token is not verified by provided verifier
*/
public static JwtTokenBuilder from(String token, String secret, String customUserIdClaim, String customRolesClaim) {
JwtAdapter jwtAdapter = JwtTokenVerifier.create(secret, customUserIdClaim, customRolesClaim)
.verify(token);
return from(jwtAdapter);
}
/**
* See {@link #from(String, String, String, String)}
*
* @param token a jwt as String
* @param secret secret text
*
* @return a new {@link JwtTokenBuilder} instance
*/
public static JwtTokenBuilder from(String token, String secret) {
return from(token, secret, JwtConstants.USER_ID, JwtConstants.ROLES);
}
private static void restoreInternalStatus(JwtTokenBuilder builder, DecodedJWT decodedJWT) {
Map verifiedClaims = new HashMap<>(decodedJWT.getClaims());
if (verifiedClaims.containsKey(ISSUED_AT)) {
int issuedAt = verifiedClaims.remove(ISSUED_AT).asInt();
if (verifiedClaims.containsKey(EXPIRES_AT)) {
int expire = verifiedClaims.remove(EXPIRES_AT).asInt() - issuedAt;
builder.optionsAdapter.setExpirySeconds(expire);
}
if (verifiedClaims.containsKey(NOT_BEFORE)) {
int notBefore = issuedAt - verifiedClaims.remove(NOT_BEFORE).asInt();
builder.optionsAdapter.setNotValidBeforeLeeway(notBefore);
}
if (verifiedClaims.containsKey(JWT_ID)) {
verifiedClaims.remove(JWT_ID);
builder.optionsAdapter.setJwtId(true);
}
builder.claims.putAll(verifiedClaims);
} else {
throw new IllegalStateException("Missing 'iat' value. Unable to restore builder status");
}
}
/**
* Add userId claim to JWT body
*
* @param name realm username
*
* @return {@link JwtTokenBuilder}
*/
public JwtTokenBuilder userId(String name) {
claims.put(customUserIdClaim, name);
return this;
}
/**
* Add roles claim to JWT body
*
* @param roles roles to add
*
* @return {@link JwtTokenBuilder}
*/
public JwtTokenBuilder roles(Collection roles) {
claims.put(customRolesClaim, roles.toArray(new String[]{}));
return this;
}
/**
* Add a custom claim to JWT body
*
* @param key key of new claim
* @param value value of new claim
*
* @return {@link JwtTokenBuilder}
*/
public JwtTokenBuilder claimEntry(String key, Object value) {
claims.put(key, value);
return this;
}
/**
* Add JWT claim exp to current timestamp + seconds.
*
* @param seconds expires within seconds
*
* @return {@link JwtTokenBuilder}
*/
public JwtTokenBuilder expirySecs(int seconds) {
optionsAdapter.setExpirySeconds(seconds);
return this;
}
/**
* Specify algorithm to sign JWT with. Default is HS256.
*
* @param algorithm signing algorithm
*
* @return {@link JwtTokenBuilder}
*/
public JwtTokenBuilder algorithm(Algorithm algorithm) {
this.algorithm = algorithm;
return this;
}
/**
* Should JWT claim iat be added?
* Value will be set to current timestamp
*
* @param issuedAt true to add
*
* @return {@link JwtTokenBuilder}
*/
public JwtTokenBuilder issuedEntry(boolean issuedAt) {
optionsAdapter.setIssuedAt(issuedAt);
return this;
}
/**
* Should JWT claim jti be added?
* Value will be set to a pseudo random unique value (UUID)
*
* @param jwtId true to add
*
* @return {@link JwtTokenBuilder}
*/
public JwtTokenBuilder generateJwtId(boolean jwtId) {
optionsAdapter.setJwtId(jwtId);
return this;
}
/**
* Add JWT claim nbf to current timestamp - notValidBeforeLeeway
*
* @param notValidBeforeLeeway in seconds
*
* @return {@link JwtTokenBuilder}
*/
public JwtTokenBuilder notValidBeforeLeeway(int notValidBeforeLeeway) {
optionsAdapter.setNotValidBeforeLeeway(notValidBeforeLeeway);
return this;
}
/**
* Create a new JWT token
*
* @return JWT token
*
* @throws IllegalStateException if userId and roles (or their custom variants) are not provided
*/
public String build() {
Preconditions.checkState(claims.containsKey(customUserIdClaim) && claims.containsKey(customRolesClaim), customUserIdClaim + " and " + customRolesClaim + " claims must be added!");
return jwtBuilder.sign(algorithm);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy