Created
May 12, 2020 10:54
-
-
Save dmi3coder/3f4dec7e1f3aa754d9f69d8ef2fb6f33 to your computer and use it in GitHub Desktop.
TokenUtils class for Quarkus token security
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package tech.donau.quarkify.security; | |
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; | |
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; | |
/** | |
* Utilities for generating a JWT for testing | |
*/ | |
public class TokenUtils { | |
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.pem"); | |
return generateTokenString(pk, "/privateKey.pem", 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<String, Object> 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); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment