package net.curisit.securis.utils; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Date; import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; import net.curisit.integrity.commons.Utils; import net.curisit.securis.services.ApiResource; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jboss.resteasy.util.Base64; @ApplicationScoped public class TokenHelper { private static final Logger LOG = LogManager.getLogger(TokenHelper.class); /** * Period before token expires, set in hours. */ private static int VALID_TOKEN_PERIOD = 24; public static final String TOKEN_HEADER_PĂ€RAM = "X-SECURIS-TOKEN"; @Inject public TokenHelper() { } private static byte[] seed = "S3Cur15S33dForT0k3nG3n3r@tion".getBytes(); /** * Generate a token encoded in Base64 for user passed as parameter and * taking the current moment as token timestamp * * @param user * @return */ public String generateToken(String user) { return generateToken(user, new Date()); } public String generateToken(String user, Date date) { try { String secret = generateSecret(user, date); StringBuffer sb = new StringBuffer(); sb.append(secret); sb.append(' '); sb.append(user); sb.append(' '); sb.append(Utils.toIsoFormat(date)); return Base64.encodeBytes(sb.toString().getBytes("utf-8")); } catch (NoSuchAlgorithmException e) { LOG.error("Error generating SHA-256 hash", e); } catch (UnsupportedEncodingException e) { LOG.error("Error generating SHA-256 hash", e); } return null; } private String generateSecret(String user, Date date) throws UnsupportedEncodingException, NoSuchAlgorithmException { MessageDigest mDigest = MessageDigest.getInstance("SHA-256"); mDigest.update(seed, 0, seed.length); byte[] userbytes = user.getBytes("utf-8"); mDigest.update(userbytes, 0, userbytes.length); byte[] isodate = Utils.toIsoFormat(date).getBytes(); mDigest.update(isodate, 0, isodate.length); BigInteger i = new BigInteger(1, mDigest.digest()); String secret = String.format("%1$064x", i); return secret; } /** * Check if passed token is still valid, It use to check if token is expired * the attribute VALID_TOKEN_PERIOD (in hours) * * @param token * @return */ public boolean isTokenValid(String token) { try { String tokenDecoded = new String(Base64.decode(token)); String[] parts = StringUtils.split(tokenDecoded, ' '); if (parts == null || parts.length < 3) { return false; } String secret = parts[0]; String user = parts[1]; Date date = Utils.toDateFromIso(parts[2]); if (date.getTime() > 0 || !user.equals(ApiResource.API_CLIENT_USERNAME)) { if (new Date().after(new Date(date.getTime() + VALID_TOKEN_PERIOD * 60 * 60 * 1000))) { return false; } } // else: It's a securis-client API call String newSecret = generateSecret(user, date); return newSecret.equals(secret); } catch (IOException e) { LOG.error("Error decoding Base64 token", e); } catch (NoSuchAlgorithmException e) { LOG.error("Error generation secret to compare with", e); } return false; } public String extractUserFromToken(String token) { try { if (token == null) { return null; } String tokenDecoded = new String(Base64.decode(token)); String[] parts = StringUtils.split(tokenDecoded, ' '); if (parts == null || parts.length < 3) { return null; } String user = parts[1]; return user; } catch (IOException e) { LOG.error("Error decoding Base64 token", e); } return null; } public Date extractDateCreationFromToken(String token) { try { String tokenDecoded = new String(Base64.decode(token)); String[] parts = StringUtils.split(tokenDecoded, ' '); if (parts == null || parts.length < 3) { return null; } Date date = Utils.toDateFromIso(parts[2]); return date; } catch (IOException e) { LOG.error("Error decoding Base64 token", e); } return null; } public static void main(String[] args) throws IOException { // client token: // OTk3ODRiMzY5NzQ5MWI5NmYyZGQyODRiYjY2ZTU2YzdmMTZjYzM3YTY3N2ExM2M3ODI2MjU5ZTMzOTIyYjUzNSBfY2xpZW50IDE5NzAtMDEtMDFUMDA6NTk6NTkuOTk5KzAxMDA= // OTk3ODRiMzY5NzQ5MWI5NmYyZGQyODRiYjY2ZTU2YzdmMTZjYzM3YTY3N2ExM2M3ODI2MjU5ZTMzOTIyYjUzNSBfY2xpZW50IDE5NzAtMDEtMDFUMDA6NTk6NTkuOTk5KzAxMDA= String t = new TokenHelper().generateToken("_client", new Date(-1)); System.out.println("client token: " + t); System.out.println("client token: " + new String(Base64.decode(t))); System.out.println("is valid client token: " + new TokenHelper().isTokenValid(t)); } }