package io.robe.auth.token; import io.dropwizard.Configuration; import io.dropwizard.ConfiguredBundle; import io.dropwizard.setup.Bootstrap; import io.dropwizard.setup.Environment; import io.robe.auth.Credentials; import io.robe.auth.SecurityHeadersFilter; import io.robe.auth.token.configuration.HasTokenBasedAuthConfiguration; import io.robe.auth.token.configuration.TokenBasedAuthConfiguration; import io.robe.auth.token.jersey.TokenBasedAuthResponseFilter; import io.robe.auth.token.jersey.TokenFactoryProvider; import io.robe.auth.token.jersey.TokenFeature; import org.jasypt.encryption.pbe.PooledPBEStringEncryptor; import org.jasypt.exceptions.EncryptionOperationNotPossibleException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.crypto.Cipher; import java.lang.reflect.Field; import java.security.NoSuchAlgorithmException; public class TokenAuthBundle<T extends Configuration & HasTokenBasedAuthConfiguration> implements ConfiguredBundle<T> { private static final Logger LOGGER = LoggerFactory.getLogger(TokenAuthBundle.class); private static final String JCE_SECURITY_CRYPTOGRAPHY_LINK = "http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html"; private TokenBasedAuthConfiguration configuration; /** * Initializes the environment. * * @param configuration the configuration object * @param environment the service's {@link io.dropwizard.setup.Environment} * @throws Exception if something goes wrong */ @Override public void run(T configuration, Environment environment) throws Exception { this.configuration = configuration.getAuth(); environment.jersey().register(new TokenFactoryProvider.Binder<Credentials>(Credentials.class)); environment.jersey().register(new TokenBasedAuthResponseFilter(configuration.getAuth())); environment.jersey().register(TokenFeature.class); BasicToken.configure(configuration.getAuth()); if(configuration.getAuth().getAlgorithm() != null) { checkCryptography(this.configuration); } environment.jersey().register(new SecurityHeadersFilter(configuration.getAuth())); } /** * Initializes the service bootstrap. * * @param bootstrap the service bootstrap */ @Override public void initialize(Bootstrap<?> bootstrap) { } /** * Determines if cryptography restrictions apply. * Restrictions apply if the value of {@link Cipher#getMaxAllowedKeyLength(String)} returns a value smaller than {@link Integer#MAX_VALUE} if there are any restrictions according to the JavaDoc of the method. * This method is used with the transform <code>"AES/CBC/PKCS5Padding"</code> as this is an often used algorithm that is <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#impl">an implementation requirement for Java SE</a>. * * @return <code>true</code> if restrictions apply, <code>false</code> otherwise */ public static void checkCryptography(TokenBasedAuthConfiguration configuration) { try { Field field = Class.forName("javax.crypto.JceSecurity").getDeclaredField("isRestricted"); field.setAccessible(true); field.set(null, java.lang.Boolean.FALSE); } catch (ClassNotFoundException e) { StringBuilder builder = new StringBuilder("javax.crypto.JceSecurity class not found !\n" ); builder.append(getUpgradJceErrorMessage()); throw new RuntimeException(builder.toString(), e); } catch (final IllegalAccessException | NoSuchFieldException e) { try { if(BasicToken.getEncryptor().isInitialized()) { BasicToken.getEncryptor().encrypt("Sample Data"); } } catch (EncryptionOperationNotPossibleException ex) { StringBuilder builder = new StringBuilder(); builder .append(configuration.getAlgorithm()) .append(" not exist on Java Cryptography Extension (JCE)") .append(getUpgradJceErrorMessage()); LOGGER.error(builder.toString()); throw new RuntimeException(builder.toString(), ex); } } } public static String getUpgradJceErrorMessage() { StringBuilder builder = new StringBuilder(); builder.append("\nYou have to download JCE Security Libraries from ") .append(JCE_SECURITY_CRYPTOGRAPHY_LINK) .append(" address.") .append("\nCopy the Library under of jre/lib/security"); return builder.toString(); } public TokenBasedAuthConfiguration getConfiguration() { return configuration; } public void setConfiguration(TokenBasedAuthConfiguration configuration) { this.configuration = configuration; } }