All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.cosenonjaviste.security.jwt.utils.JwtTokenBuilder Maven / Gradle / Ivy

package it.cosenonjaviste.security.jwt.utils;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import com.auth0.jwt.Algorithm;
import com.auth0.jwt.JWTSigner;
import com.auth0.jwt.JWTSigner.Options;

/**
 * Builder class for simplifying JWT token creation.
 * 
 * userId and roles values are mandatory.
 * 
 * @author acomo
 *
 */
public class JwtTokenBuilder {
	
	private static final String NOT_BEFORE = "nbf";

	private static final String JWT_ID = "jti";

	private static final String EXPIRE = "exp";

	private static final String ISSUED_AT = "iat";

	private JWTSigner signer;
	
	private Map claims = new HashMap<>();

	private Options options = new Options();
	
	private JwtTokenBuilder() {
		
	}
	
	/**
	 * Creates a new {@link JwtTokenBuilder} instance
	 * 
	 * @param secret secret phrase
	 * 
	 * @return a new {@link JwtTokenBuilder} instance
	 */
	public static JwtTokenBuilder create(String secret) {
		JwtTokenBuilder builder = new JwtTokenBuilder();
		builder.signer = new JWTSigner(secret); 
		builder.options.setIssuedAt(true);
		
		return builder;
	}
	
	/**
	 * Creates a {@link JwtTokenBuilder} instance from token and secret.
	 * 
* Token will be validated before parsing. *
* Token must contains "iat" param in order to restore builder status *
*
* 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 * @param secret * @return */ public static JwtTokenBuilder from(String token, String secret) { JwtTokenVerifier verifier = JwtTokenVerifier.create(secret); verifier.verify(token); return from(verifier, secret); } /** * 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 verifier * @param secret * @return * * @throws IllegalStateException if token is not verified by provided verifier */ public static JwtTokenBuilder from(JwtTokenVerifier verifier, String secret) { JwtTokenBuilder builder = create(secret); Map verifiedClaims = verifier.getClaims(); restoreInternalStatus(builder, verifiedClaims); return builder; } /** * Creates a {@link JwtTokenBuilder} instance from token and secret. *
* Token will be validated before parsing. *
* 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 *
*
* 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 verifier * @param token * @param secret * @return * * @throws IllegalStateException if token is not verified by provided verifier */ public static JwtTokenBuilder from(JwtTokenVerifier verifier, String token, String secret) { verifier.verify(token); return from(verifier, secret); } private static void restoreInternalStatus(JwtTokenBuilder builder, Map verifiedClaims) { if (verifiedClaims.containsKey(ISSUED_AT)) { int issuedAt = (int) verifiedClaims.remove(ISSUED_AT); if (verifiedClaims.containsKey(EXPIRE)) { int expire = (int) verifiedClaims.remove(EXPIRE) - issuedAt; builder.options.setExpirySeconds(expire); } if (verifiedClaims.containsKey(NOT_BEFORE)) { int notBefore = (int) verifiedClaims.remove(NOT_BEFORE) + issuedAt; builder.options.setNotValidBeforeLeeway(notBefore); } if (verifiedClaims.containsKey(JWT_ID)) { verifiedClaims.remove(JWT_ID); builder.options.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) { return claimEntry(JwtConstants.USER_ID, name); } /** * Add roles claim to JWT body * * @param roles * * @return {@link JwtTokenBuilder} */ public JwtTokenBuilder roles(Collection roles) { return claimEntry(JwtConstants.ROLES, roles); } /** * Add a custom claim to JWT body * * @param key * @param value * * @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 * * @return {@link JwtTokenBuilder} */ public JwtTokenBuilder expirySecs(int seconds) { options.setExpirySeconds(seconds); return this; } /** * Specify algorithm to sign JWT with. Default is HS256. * * @param algorithm * * @return {@link JwtTokenBuilder} */ public JwtTokenBuilder algorithm(Algorithm algorithm) { options.setAlgorithm(algorithm); return this; } /** * Should JWT claim iat be added? * Value will be set to current timestamp * * @param issuedAt * * @return {@link JwtTokenBuilder} */ public JwtTokenBuilder issuedEntry(boolean issuedAt) { options.setIssuedAt(issuedAt); return this; } /** * Should JWT claim jti be added? * Value will be set to a pseudo random unique value (UUID) * * @param jwtId * * @return {@link JwtTokenBuilder} */ public JwtTokenBuilder generateJwtId(boolean jwtId) { options.setJwtId(jwtId); return this; } /** * Add JWT claim nbf to current timestamp - notValidBeforeLeeway * * @param notValidBeforeLeeway * * @return {@link JwtTokenBuilder} */ public JwtTokenBuilder notValidBeforeLeeway(int notValidBeforeLeeway) { options.setNotValidBeforeLeeway(notValidBeforeLeeway); return this; } /** * Create a new JWT token * * @return JWT token * * @throws IllegalStateException if userId and roles are not provided */ public String build() { if (claims.containsKey(JwtConstants.USER_ID) && claims.containsKey(JwtConstants.ROLES)) { return signer.sign(claims, options); } else { throw new IllegalStateException("userId and roles claims must be added!"); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy