package io.dropwizard.auth; import io.dropwizard.jersey.DropwizardResourceConfig; import io.dropwizard.logging.BootstrapLogging; import org.glassfish.jersey.servlet.ServletProperties; import org.glassfish.jersey.test.DeploymentContext; import org.glassfish.jersey.test.JerseyTest; import org.glassfish.jersey.test.ServletDeploymentContext; import org.glassfish.jersey.test.TestProperties; import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory; import org.glassfish.jersey.test.spi.TestContainerException; import org.glassfish.jersey.test.spi.TestContainerFactory; import org.junit.Test; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.HttpHeaders; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown; public abstract class AuthBaseTest<T extends DropwizardResourceConfig> extends JerseyTest { protected static final String ADMIN_ROLE = "ADMIN"; protected static final String ADMIN_USER = "good-guy"; protected static final String ORDINARY_USER = "ordinary-guy"; protected static final String BADGUY_USER = "bad-guy"; protected static final String CUSTOM_PREFIX = "Custom"; protected static final String BEARER_PREFIX = "Bearer"; protected static final String BASIC_PREFIX = "Basic"; protected static final String ORDINARY_USER_ENCODED_TOKEN = "b3JkaW5hcnktZ3V5OnNlY3JldA=="; protected static final String GOOD_USER_ENCODED_TOKEN = "Z29vZC1ndXk6c2VjcmV0"; protected static final String BAD_USER_ENCODED_TOKEN = "YmFkLWd1eTpzZWNyZXQ="; static { BootstrapLogging.bootstrap(); } @Override protected TestContainerFactory getTestContainerFactory() throws TestContainerException { return new GrizzlyWebTestContainerFactory(); } protected abstract DropwizardResourceConfig getDropwizardResourceConfig(); protected abstract Class<T> getDropwizardResourceConfigClass(); protected abstract String getPrefix(); protected abstract String getOrdinaryGuyValidToken(); protected abstract String getGoodGuyValidToken(); protected abstract String getBadGuyToken(); @Override protected DeploymentContext configureDeployment() { forceSet(TestProperties.CONTAINER_PORT, "0"); return ServletDeploymentContext.builder(getDropwizardResourceConfig()) .initParam(ServletProperties.JAXRS_APPLICATION_CLASS, getDropwizardResourceConfigClass().getName()) .build(); } @Test public void respondsToMissingCredentialsWith401() throws Exception { try { target("/test/admin").request().get(String.class); failBecauseExceptionWasNotThrown(WebApplicationException.class); } catch (WebApplicationException e) { assertThat(e.getResponse().getStatus()).isEqualTo(401); assertThat(e.getResponse().getHeaders().get(HttpHeaders.WWW_AUTHENTICATE)) .containsOnly(getPrefix() + " realm=\"realm\""); } } @Test public void resourceWithoutAuth200() { assertThat(target("/test/noauth").request() .get(String.class)) .isEqualTo("hello"); } @Test public void resourceWithAuthenticationWithoutAuthorizationWithCorrectCredentials200() { assertThat(target("/test/profile").request() .header(HttpHeaders.AUTHORIZATION, getPrefix() + " " + getOrdinaryGuyValidToken()) .get(String.class)) .isEqualTo("'" + ORDINARY_USER + "' has user privileges"); } @Test public void resourceWithAuthenticationWithoutAuthorizationNoCredentials401() { try { target("/test/profile").request().get(String.class); failBecauseExceptionWasNotThrown(WebApplicationException.class); } catch (WebApplicationException e) { assertThat(e.getResponse().getStatus()).isEqualTo(401); assertThat(e.getResponse().getHeaders().get(HttpHeaders.WWW_AUTHENTICATE)) .containsOnly(getPrefix() + " realm=\"realm\""); } } @Test public void resourceWithValidOptionalAuthentication200() { assertThat(target("/test/optional").request() .header(HttpHeaders.AUTHORIZATION, getPrefix() + " " + getOrdinaryGuyValidToken()) .get(String.class)) .isEqualTo("principal was present"); } @Test public void resourceWithInvalidOptionalAuthentication200() { assertThat(target("/test/optional").request() .header(HttpHeaders.AUTHORIZATION, getPrefix() + " " + getBadGuyToken()) .get(String.class)) .isEqualTo("principal was not present"); } @Test public void resourceWithoutOptionalAuthentication200() { assertThat(target("/test/optional").request() .get(String.class)) .isEqualTo("principal was not present"); } @Test public void resourceWithAuthorizationPrincipalIsNotAuthorized403() { try { target("/test/admin").request() .header(HttpHeaders.AUTHORIZATION, getPrefix() + " " + getOrdinaryGuyValidToken()) .get(String.class); failBecauseExceptionWasNotThrown(WebApplicationException.class); } catch (WebApplicationException e) { assertThat(e.getResponse().getStatus()).isEqualTo(403); } } @Test public void resourceWithDenyAllAndNoAuth401() { try { target("/test/denied").request().get(String.class); failBecauseExceptionWasNotThrown(WebApplicationException.class); } catch (WebApplicationException e) { assertThat(e.getResponse().getStatus()).isEqualTo(401); } } @Test public void resourceWithDenyAllAndAuth403() { try { target("/test/denied").request() .header(HttpHeaders.AUTHORIZATION, getPrefix() + " " + getGoodGuyValidToken()) .get(String.class); failBecauseExceptionWasNotThrown(WebApplicationException.class); } catch (WebApplicationException e) { assertThat(e.getResponse().getStatus()).isEqualTo(403); } } @Test public void transformsCredentialsToPrincipals() throws Exception { assertThat(target("/test/admin").request() .header(HttpHeaders.AUTHORIZATION, getPrefix() + " " + getGoodGuyValidToken()) .get(String.class)) .isEqualTo("'" + ADMIN_USER + "' has admin privileges"); } @Test public void transformsCredentialsToPrincipalsWhenAuthAnnotationExistsWithoutMethodAnnotation() throws Exception { assertThat(target("/test/implicit-permitall").request() .header(HttpHeaders.AUTHORIZATION, getPrefix() + " " + getGoodGuyValidToken()) .get(String.class)) .isEqualTo("'" + ADMIN_USER + "' has user privileges"); } @Test public void respondsToNonBasicCredentialsWith401() throws Exception { try { target("/test/admin").request() .header(HttpHeaders.AUTHORIZATION, "Derp irrelevant") .get(String.class); failBecauseExceptionWasNotThrown(WebApplicationException.class); } catch (WebApplicationException e) { assertThat(e.getResponse().getStatus()).isEqualTo(401); assertThat(e.getResponse().getHeaders().get(HttpHeaders.WWW_AUTHENTICATE)) .containsOnly(getPrefix() + " realm=\"realm\""); } } @Test public void respondsToExceptionsWith500() throws Exception { try { target("/test/admin").request() .header(HttpHeaders.AUTHORIZATION, getPrefix() + " " + getBadGuyToken()) .get(String.class); failBecauseExceptionWasNotThrown(WebApplicationException.class); } catch (WebApplicationException e) { assertThat(e.getResponse().getStatus()).isEqualTo(500); } } }