package org.pac4j.dropwizard; import java.util.ArrayList; import java.util.Collection; import org.eclipse.jetty.server.session.SessionHandler; import org.pac4j.core.config.Config; import org.pac4j.dropwizard.Pac4jFactory.JaxRsSecurityFilterConfiguration; import org.pac4j.dropwizard.Pac4jFactory.ServletCallbackFilterConfiguration; import org.pac4j.dropwizard.Pac4jFactory.ServletLogoutFilterConfiguration; import org.pac4j.dropwizard.Pac4jFactory.ServletSecurityFilterConfiguration; import org.pac4j.jax.rs.features.JaxRsConfigProvider; import org.pac4j.jax.rs.features.Pac4JSecurityFeature; import org.pac4j.jax.rs.features.Pac4JSecurityFilterFeature; import org.pac4j.jax.rs.filters.SecurityFilter; import org.pac4j.jax.rs.jersey.features.Pac4JValueFactoryProvider; import org.pac4j.jax.rs.servlet.features.ServletJaxRsContextFactoryProvider; import io.dropwizard.Application; import io.dropwizard.Configuration; import io.dropwizard.ConfiguredBundle; import io.dropwizard.jetty.MutableServletContextHandler; import io.dropwizard.setup.Bootstrap; import io.dropwizard.setup.Environment; /** * A {@link ConfiguredBundle} which sets up {@link Pac4JSecurityFeature}, * {@link Pac4JValueFactoryProvider} as well as installs {@link SecurityFilter}s * into a Dropwizard application's Jersey filter chain. * * @author Evan Meagher * @author Victor Noel - Linagora * @since 1.0.0 */ public abstract class Pac4jBundle<T extends Configuration> implements ConfiguredBundle<T>, Pac4jConfiguration<T> { private Config config; @Override public final void initialize(Bootstrap<?> bootstrap) { for (Pac4jFeatureSupport fs : supportedFeatures()) { fs.setup(bootstrap); } } /** * In case of override, do not forget to call * {@code super.supportedFeatures()} to get the default features, or to * redefine them instead! * * @see DefaultFeatureSupport * @return the features to support for configuration parsing */ protected Collection<Pac4jFeatureSupport> supportedFeatures() { ArrayList<Pac4jFeatureSupport> res = new ArrayList<>(); res.add(new DefaultFeatureSupport()); return res; } @Override public final void run(T configuration, Environment environment) throws Exception { final Pac4jFactory pac4j = getPac4jFactory(configuration); if (pac4j != null) { config = pac4j.build(); environment.jersey().register(new JaxRsConfigProvider(config)); for (JaxRsSecurityFilterConfiguration fConf : pac4j .getGlobalFilters()) { environment.jersey() .register(new Pac4JSecurityFilterFeature( fConf.getSkipResponse(), fConf.getAuthorizers(), fConf.getClients(), fConf.getMatchers(), fConf.getMultiProfile())); } for (ServletSecurityFilterConfiguration fConf : pac4j.getServlet() .getSecurity()) { J2EHelper.registerSecurityFilter(environment, config, fConf); } for (ServletCallbackFilterConfiguration fConf : pac4j.getServlet() .getCallback()) { J2EHelper.registerCallbackFilter(environment, config, fConf); } for (ServletLogoutFilterConfiguration fConf : pac4j.getServlet() .getLogout()) { J2EHelper.registerLogoutFilter(environment, config, fConf); } environment.jersey() .register(new ServletJaxRsContextFactoryProvider()); environment.jersey().register(new Pac4JSecurityFeature()); environment.jersey() .register(new Pac4JValueFactoryProvider.Binder()); if (pac4j.getSessionEnabled()) { setupJettySession(environment); } } } /** * Override if needed, but prefer to exploit * {@link Pac4jFactory#setSessionEnabled(boolean)} first. * * @param environment * the dropwizard {@link Environment} * @since 1.1.0 */ protected void setupJettySession(Environment environment) { MutableServletContextHandler contextHandler = environment .getApplicationContext(); if (contextHandler.getSessionHandler() == null) { contextHandler.setSessionHandler(new SessionHandler()); } } /** * To be used only after this bundle has been run (i.e., in the * {@link Application#run(Configuration, Environment)} method. * * @return the {@link Config} built during * {@link #run(Configuration, Environment)} execution. */ public Config getConfig() { return config; } }