|
|
|
|
@ -5,45 +5,78 @@ import java.security.KeyFactory; |
|
|
|
|
import java.security.PrivateKey; |
|
|
|
|
import java.security.spec.PKCS8EncodedKeySpec; |
|
|
|
|
import java.util.Base64; |
|
|
|
|
import java.util.HashSet; |
|
|
|
|
import java.util.Set; |
|
|
|
|
import java.util.Map; |
|
|
|
|
|
|
|
|
|
import javax.enterprise.context.ApplicationScoped; |
|
|
|
|
|
|
|
|
|
import api.menu.playa.enums.RolesEnum; |
|
|
|
|
import io.smallrye.jwt.build.Jwt; |
|
|
|
|
import io.smallrye.jwt.build.JwtClaimsBuilder; |
|
|
|
|
import org.eclipse.microprofile.config.ConfigProvider; |
|
|
|
|
import org.eclipse.microprofile.config.inject.ConfigProperty; |
|
|
|
|
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 { |
|
|
|
|
|
|
|
|
|
public static String generateToken(String username, Set<RolesEnum> roles, Long duration, String issuer) throws Exception { |
|
|
|
|
String privateKeyLocation = "/privatekey.pem"; |
|
|
|
|
PrivateKey privateKey = readPrivateKey(privateKeyLocation); |
|
|
|
|
//@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 { |
|
|
|
|
|
|
|
|
|
JwtClaimsBuilder claimsBuilder = Jwt.claims(); |
|
|
|
|
long currentTimeInSecs = currentTimeInSecs(); |
|
|
|
|
|
|
|
|
|
Set<String> groups = new HashSet<>(); |
|
|
|
|
for (RolesEnum role : roles) groups.add(role.toString()); |
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
claimsBuilder.issuer(issuer); |
|
|
|
|
claimsBuilder.subject(username); |
|
|
|
|
claimsBuilder.issuedAt(currentTimeInSecs); |
|
|
|
|
claimsBuilder.expiresAt(currentTimeInSecs + duration); |
|
|
|
|
claimsBuilder.groups(groups); |
|
|
|
|
|
|
|
|
|
return claimsBuilder.jws().keyId(privateKeyLocation).sign(privateKey); |
|
|
|
|
|
|
|
|
|
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 { |
|
|
|
|
try (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")); |
|
|
|
|
} |
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
@ -52,12 +85,12 @@ public class TokenUtils { |
|
|
|
|
return kf.generatePrivate(keySpec); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static byte[] toEncodedBytes(final String pemEncoded) { |
|
|
|
|
private static byte[] toEncodedBytes(final String pemEncoded) { |
|
|
|
|
final String normalizedPem = removeBeginEnd(pemEncoded); |
|
|
|
|
return Base64.getDecoder().decode(normalizedPem); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static String removeBeginEnd(String pem) { |
|
|
|
|
private static String removeBeginEnd(String pem) { |
|
|
|
|
pem = pem.replaceAll("-----BEGIN (.*)-----", ""); |
|
|
|
|
pem = pem.replaceAll("-----END (.*)----", ""); |
|
|
|
|
pem = pem.replaceAll("\r\n", ""); |
|
|
|
|
@ -65,6 +98,9 @@ public class TokenUtils { |
|
|
|
|
return pem.trim(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @return the current time in seconds since epoch |
|
|
|
|
*/ |
|
|
|
|
public static int currentTimeInSecs() { |
|
|
|
|
long currentTimeMS = System.currentTimeMillis(); |
|
|
|
|
return (int) (currentTimeMS / 1000); |
|
|
|
|
|