package jwt4j; import com.google.gson.JsonObject; import jwt4j.exceptions.AlgorithmException; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.Base64; import java.util.Map; import java.util.StringJoiner; public class JWTEncoder { private final Algorithm algorithm; private final byte[] secret; private final String base64JsonHeader; private final RegisteredClaimsValidator registeredClaimsValidator; public JWTEncoder(final Algorithm algorithm, final byte[] secret, final RegisteredClaimsValidator registeredClaimsValidator) { this.algorithm = algorithm; this.secret = secret; this.base64JsonHeader = encodeHeader(); this.registeredClaimsValidator = registeredClaimsValidator; } private String encodeHeader() { final JsonObject headerJsonObject = new JsonObject(); headerJsonObject.addProperty(JWTConstants.TYPE, JWTConstants.JWT); headerJsonObject.addProperty(JWTConstants.ALGORITHM, algorithm.name()); return toBase64Json(headerJsonObject); } public String encode(final Map<String, String> claims) { registeredClaimsValidator.validate(claims); final String base64JsonPayload = encodePayload(claims); final StringJoiner stringJoiner = new StringJoiner(JWTConstants.DELIMITER) .add(base64JsonHeader) .add(base64JsonPayload); if (algorithm != Algorithm.none) { stringJoiner.add(sign(stringJoiner.toString())); } else { stringJoiner.add(""); } return stringJoiner.toString(); } private String encodePayload(final Map<String, String> claims) { final JsonObject payloadJsonObject = new JsonObject(); claims.forEach((claim, value) -> { payloadJsonObject.addProperty(claim, value); }); return toBase64Json(payloadJsonObject); } private String sign(final String message) { try { final Mac mac = Mac.getInstance(algorithm.name); mac.init(new SecretKeySpec(secret, algorithm.name)); final String signature = new String(Base64.getEncoder().encodeToString(mac.doFinal(message.getBytes()))); return signature; } catch (NoSuchAlgorithmException | InvalidKeyException | IllegalArgumentException e) { throw new AlgorithmException(e); } } private String toBase64Json(final JsonObject jsonObject) { final String base64ObjectJson = Base64.getEncoder() .encodeToString(jsonObject.toString().getBytes(StandardCharsets.UTF_8)); return base64ObjectJson; } }