package api.menu.playa.util; import java.io.InputStream; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import java.util.Map; import javax.enterprise.context.ApplicationScoped; import org.eclipse.microprofile.config.ConfigProvider; import org.eclipse.microprofile.jwt.Claims; import org.jose4j.jws.AlgorithmIdentifiers; import org.jose4j.jws.JsonWebSignature; import org.jose4j.jwt.JwtClaims; import org.jose4j.jwt.NumericDate; @ApplicationScoped public class TokenUtils { //@ConfigProperty(name = "config.private.key") private static String privateKey = ConfigProvider.getConfig().getValue("config.private.key",String.class);; private TokenUtils() { } public static String generateTokenString(JwtClaims claims) throws Exception { // Use the private key associated with the public key for a valid signature PrivateKey pk = readPrivateKey(privateKey); return generateTokenString(pk, privateKey, claims); } private static String generateTokenString(PrivateKey privateKey, String kid, JwtClaims claims) throws Exception { long currentTimeInSecs = currentTimeInSecs(); claims.setIssuedAt(NumericDate.fromSeconds(currentTimeInSecs)); claims.setClaim(Claims.auth_time.name(), NumericDate.fromSeconds(currentTimeInSecs)); for (Map.Entry entry : claims.getClaimsMap().entrySet()) { System.out.printf("\tAdded claim: %s, value: %s\n", entry.getKey(), entry.getValue()); } JsonWebSignature jws = new JsonWebSignature(); jws.setPayload(claims.toJson()); jws.setKey(privateKey); jws.setKeyIdHeaderValue(kid); jws.setHeader("typ", "JWT"); jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256); return jws.getCompactSerialization(); } /** * Read a PEM encoded private key from the classpath * * @param pemResName - key file resource name * @return PrivateKey * @throws Exception on decode failure */ public static PrivateKey readPrivateKey(final String pemResName) throws Exception { InputStream contentIS = TokenUtils.class.getResourceAsStream(pemResName); byte[] tmp = new byte[4096]; int length = contentIS.read(tmp); return decodePrivateKey(new String(tmp, 0, length, "UTF-8")); } /** * Decode a PEM encoded private key string to an RSA PrivateKey * * @param pemEncoded - PEM string for private key * @return PrivateKey * @throws Exception on decode failure */ public static PrivateKey decodePrivateKey(final String pemEncoded) throws Exception { byte[] encodedBytes = toEncodedBytes(pemEncoded); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedBytes); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePrivate(keySpec); } private static byte[] toEncodedBytes(final String pemEncoded) { final String normalizedPem = removeBeginEnd(pemEncoded); return Base64.getDecoder().decode(normalizedPem); } private static String removeBeginEnd(String pem) { pem = pem.replaceAll("-----BEGIN (.*)-----", ""); pem = pem.replaceAll("-----END (.*)----", ""); pem = pem.replaceAll("\r\n", ""); pem = pem.replaceAll("\n", ""); return pem.trim(); } /** * @return the current time in seconds since epoch */ public static int currentTimeInSecs() { long currentTimeMS = System.currentTimeMillis(); return (int) (currentTimeMS / 1000); } }