package io.dropwizard.auth.principal;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import io.dropwizard.auth.AbstractAuthResourceConfig;
import io.dropwizard.auth.Authenticator;
import io.dropwizard.auth.PolymorphicAuthDynamicFeature;
import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider;
import io.dropwizard.auth.basic.BasicCredentialAuthFilter;
import io.dropwizard.auth.basic.BasicCredentials;
import io.dropwizard.logging.BootstrapLogging;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
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.junit.Test;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.DynamicFeature;
import javax.ws.rs.core.HttpHeaders;
import java.security.Principal;
import java.util.Optional;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;
/**
* Testing that polymorphic principal entity injection works.
*/
public class PolymorphicPrincipalEntityTest extends JerseyTest {
private static final String JSON_USERNAME = "good-guy";
private static final String NULL_USERNAME = "bad-guy";
private static final String JSON_USERNAME_ENCODED_TOKEN = "Z29vZC1ndXk6c2VjcmV0";
private static final String NULL_USERNAME_ENCODED_TOKEN = "YmFkLWd1eTpzZWNyZXQ=";
static {
BootstrapLogging.bootstrap();
}
@Override
protected DeploymentContext configureDeployment() {
forceSet(TestProperties.CONTAINER_PORT, "0");
return ServletDeploymentContext
.builder(new PolymorphicPrincipalInjectedResourceConfig())
.initParam(
ServletProperties.JAXRS_APPLICATION_CLASS,
PolymorphicPrincipalInjectedResourceConfig.class.getName())
.build();
}
public static class PolymorphicPrincipalInjectedResourceConfig extends AbstractAuthResourceConfig {
public PolymorphicPrincipalInjectedResourceConfig() {
register(PolymorphicPrincipalEntityResource.class);
packages("io.dropwizard.jersey.jackson");
}
@Override protected Class<? extends Principal> getPrincipalClass() {
throw new AssertionError("getPrincipalClass must not be invoked");
}
@Override protected ContainerRequestFilter getAuthFilter() {
return requestContext -> {
throw new AssertionError("getAuthFilter result must not be invoked");
};
}
@Override protected AbstractBinder getAuthBinder() {
return new PolymorphicAuthValueFactoryProvider.Binder<>(
ImmutableSet.of(JsonPrincipal.class, NullPrincipal.class));
}
@Override protected DynamicFeature getAuthDynamicFeature(ContainerRequestFilter authFilter) {
final Authenticator<BasicCredentials, JsonPrincipal> jsonAuthenticator = credentials -> {
if (credentials.getUsername().equals(JSON_USERNAME)) {
return Optional.of(new JsonPrincipal(credentials.getUsername()));
} else {
return Optional.empty();
}
};
final Authenticator<BasicCredentials, NullPrincipal> nullAuthenticator = credentials -> {
if (credentials.getUsername().equals(NULL_USERNAME)) {
return Optional.of(new NullPrincipal());
} else {
return Optional.empty();
}
};
final BasicCredentialAuthFilter jsonAuthFilter = new BasicCredentialAuthFilter.Builder<JsonPrincipal>()
.setAuthenticator(jsonAuthenticator)
.buildAuthFilter();
final BasicCredentialAuthFilter nullAuthFilter = new BasicCredentialAuthFilter.Builder<NullPrincipal>()
.setAuthenticator(nullAuthenticator)
.buildAuthFilter();
return new PolymorphicAuthDynamicFeature<Principal>(ImmutableMap.of(
JsonPrincipal.class, jsonAuthFilter,
NullPrincipal.class, nullAuthFilter
));
}
}
@Test
public void jsonPrincipalEntityResourceAuth200() {
assertThat(target("/auth-test/json-principal-entity").request()
.header(HttpHeaders.AUTHORIZATION, "Basic " + JSON_USERNAME_ENCODED_TOKEN)
.get(String.class))
.isEqualTo(JSON_USERNAME);
}
@Test
public void jsonPrincipalEntityResourceNoAuth401() {
try {
target("/auth-test/json-principal-entity").request().get(String.class);
failBecauseExceptionWasNotThrown(WebApplicationException.class);
} catch (WebApplicationException e) {
assertThat(e.getResponse().getStatus()).isEqualTo(401);
}
}
@Test
public void nullPrincipalEntityResourceAuth200() {
assertThat(target("/auth-test/null-principal-entity").request()
.header(HttpHeaders.AUTHORIZATION, "Basic " + NULL_USERNAME_ENCODED_TOKEN)
.get(String.class))
.isEqualTo("null");
}
@Test
public void nullPrincipalEntityResourceNoAuth401() {
try {
target("/auth-test/null-principal-entity").request().get(String.class);
failBecauseExceptionWasNotThrown(WebApplicationException.class);
} catch (WebApplicationException e) {
assertThat(e.getResponse().getStatus()).isEqualTo(401);
}
}
@Test
public void resourceWithValidOptionalAuthentication200() {
assertThat(target("/auth-test/optional").request()
.header(HttpHeaders.AUTHORIZATION, "Basic " + NULL_USERNAME_ENCODED_TOKEN)
.get(String.class))
.isEqualTo("principal was present");
}
@Test
public void resourceWithInvalidOptionalAuthentication200() {
assertThat(target("/auth-test/optional").request()
.header(HttpHeaders.AUTHORIZATION, "Basic cats")
.get(String.class))
.isEqualTo("principal was not present");
}
@Test
public void resourceWithoutOptionalAuthentication200() {
assertThat(target("/auth-test/optional").request()
.get(String.class))
.isEqualTo("principal was not present");
}
@Test
public void resourceWithDifferentOptionalAuthentication200() {
assertThat(target("/auth-test/optional").request()
.header(HttpHeaders.AUTHORIZATION, "Basic " + JSON_USERNAME_ENCODED_TOKEN)
.get(String.class))
.isEqualTo("principal was not present");
}
}