Skip to content

Commit

Permalink
Remove Authenticator generic parameter from AuthFilterBuilder
Browse files Browse the repository at this point in the history
Generic parameter that controls a type of a passed authenticator
to the `AuthFilterBuilder` is not actually needed. Type-safety is already
forced by the generic parameters C(credentials) and P(principal).
The user has to provide a class that implements interface
`Authenticator<C,P>`, and we don't care about concrete type of
this implementation, because it doesn't affect the auth filter.

This commit also moves the common logic of building auth filters to
the `AuthFilterBuilder` and adds some comments for the public API.
  • Loading branch information
arteam committed Jul 11, 2015
1 parent d215714 commit cd0635a
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 62 deletions.
4 changes: 2 additions & 2 deletions docs/source/manual/auth.rst
Expand Up @@ -100,7 +100,7 @@ takes instances of ``BasicCredentials``:
public void run(ExampleConfiguration configuration,
Environment environment) {
environment.jersey().register(new AuthDynamicFeature(
new BasicCredentialAuthFilter.Builder<User, ExampleAuthenticator>()
new BasicCredentialAuthFilter.Builder<User>()
.setAuthenticator(new ExampleAuthenticator())
.setAuthorizer(new ExampleAuthorizer())
.setRealm("SUPER SECRET STUFF")
Expand All @@ -125,7 +125,7 @@ takes instances of ``String``:
public void run(ExampleConfiguration configuration,
Environment environment) {
environment.jersey().register(new AuthDynamicFeature(
new OAuthCredentialAuthFilter.Builder<User, ExampleOAuthAuthenticator>()
new OAuthCredentialAuthFilter.Builder<User>()
.setAuthenticator(new ExampleOAuthAuthenticator())
.setAuthorizer(new ExampleAuthorizer())
.setPrefix("Bearer")
Expand Down
88 changes: 63 additions & 25 deletions dropwizard-auth/src/main/java/io/dropwizard/auth/AuthFilter.java
@@ -1,60 +1,98 @@
package io.dropwizard.auth;

import com.google.common.base.Preconditions;

import javax.annotation.Priority;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestFilter;
import java.security.Principal;

@Priority(Priorities.AUTHENTICATION)
public abstract class AuthFilter<C, P extends Principal> implements ContainerRequestFilter {

protected String prefix;
protected String realm;
protected Authenticator<C, P> authenticator;
protected Authorizer<P> authorizer;
protected UnauthorizedHandler unauthorizedHandler = new DefaultUnauthorizedHandler();

protected void setPrefix(String prefix) {
this.prefix = prefix;
}

protected void setRealm(String realm) {
this.realm = realm;
}

protected void setAuthenticator(Authenticator<C, P> authenticator) {
this.authenticator = authenticator;
}

protected void setAuthorizer(Authorizer<P> authorizer) {
this.authorizer = authorizer;
}
/**
* Abstract builder for auth filters.
*
* @param <C> the type of credentials that the filter accepts
* @param <P> the type of the principal that the filter accepts
*/
public abstract static class AuthFilterBuilder<C, P extends Principal, T extends AuthFilter<C, P>> {

public abstract static class AuthFilterBuilder<C, P extends Principal, T extends AuthFilter<C, P>, A extends Authenticator<C, P>> {
protected String realm = "realm";
protected String prefix = "Basic";
protected Authenticator<C, P> authenticator;
protected Authorizer<P> authorizer;
private String realm = "realm";
private String prefix = "Basic";
private Authenticator<C, P> authenticator;
private Authorizer<P> authorizer;

public AuthFilterBuilder<C, P, T, A> setRealm(String realm) {
/**
* Sets the given realm
*
* @param realm a realm
* @return the current builder
*/
public AuthFilterBuilder<C, P, T> setRealm(String realm) {
this.realm = realm;
return this;
}

public AuthFilterBuilder<C, P, T, A> setPrefix(String prefix) {
/**
* Sets the given prefix
*
* @param prefix a prefix
* @return the current builder
*/
public AuthFilterBuilder<C, P, T> setPrefix(String prefix) {
this.prefix = prefix;
return this;
}

public AuthFilterBuilder<C, P, T, A> setAuthorizer(Authorizer<P> authorizer) {
/**
* Sets the given authorizer
*
* @param authorizer an {@link Authorizer}
* @return the current builder
*/
public AuthFilterBuilder<C, P, T> setAuthorizer(Authorizer<P> authorizer) {
this.authorizer = authorizer;
return this;
}

public AuthFilterBuilder<C, P, T, A> setAuthenticator(A authenticator) {
/**
* Sets the given authenticator
*
* @param authenticator an {@link Authenticator}
* @return the current builder
*/
public AuthFilterBuilder<C, P, T> setAuthenticator(Authenticator<C, P> authenticator) {
this.authenticator = authenticator;
return this;
}

public abstract T buildAuthFilter();
/**
* Builds an instance of the filter with provided an authenticator,
* an authorizer, a prefix, and a realm.
*
* @return a new instance of a filter
*/
public T buildAuthFilter() {
Preconditions.checkArgument(realm != null, "Realm is not set");
Preconditions.checkArgument(prefix != null, "Prefix is not set");
Preconditions.checkArgument(authenticator != null, "Authenticator is not set");
Preconditions.checkArgument(authorizer != null, "Authorizer is not set");

T authFilter = newInstance();
authFilter.authorizer = authorizer;
authFilter.authenticator = authenticator;
authFilter.prefix = prefix;
authFilter.realm = realm;
return authFilter;
}

protected abstract T newInstance();
}
}
Expand Up @@ -5,6 +5,7 @@
import io.dropwizard.auth.AuthenticationException;
import io.dropwizard.auth.AuthFilter;
import io.dropwizard.auth.Authenticator;
import io.dropwizard.auth.Authorizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Priority;
Expand Down Expand Up @@ -84,21 +85,18 @@ public String getAuthenticationScheme() {
}


public static class Builder<APrincipal extends Principal, AAuthenticator extends Authenticator<BasicCredentials, APrincipal>>
extends AuthFilterBuilder<BasicCredentials, APrincipal, BasicCredentialAuthFilter<APrincipal>, AAuthenticator> {
/**
* Builder for {@link BasicCredentialAuthFilter}.
* <p>An {@link Authenticator} and an {@link Authorizer} must be provided during the building process.</p>
*
* @param <P> the principal
*/
public static class Builder<P extends Principal> extends
AuthFilterBuilder<BasicCredentials, P, BasicCredentialAuthFilter<P>> {

@Override
public BasicCredentialAuthFilter<APrincipal> buildAuthFilter() {
if (realm == null || authenticator == null || prefix == null || authorizer == null) {
throw new RuntimeException("Required auth filter parameters not set");
}

BasicCredentialAuthFilter<APrincipal> basicCredentialAuthFilter = new BasicCredentialAuthFilter<>();
basicCredentialAuthFilter.setRealm(realm);
basicCredentialAuthFilter.setAuthenticator(authenticator);
basicCredentialAuthFilter.setPrefix(prefix);
basicCredentialAuthFilter.setAuthorizer(authorizer);
return basicCredentialAuthFilter;
protected BasicCredentialAuthFilter<P> newInstance() {
return new BasicCredentialAuthFilter<>();
}
}
}
Expand Up @@ -4,6 +4,7 @@
import io.dropwizard.auth.AuthenticationException;
import io.dropwizard.auth.AuthFilter;
import io.dropwizard.auth.Authenticator;
import io.dropwizard.auth.Authorizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -69,20 +70,18 @@ public String getAuthenticationScheme() {
throw new WebApplicationException(unauthorizedHandler.buildResponse(prefix, realm));
}

public static class Builder<APrincipal extends Principal, AAuthenticator extends Authenticator<String, APrincipal>>
extends AuthFilterBuilder<String, APrincipal, OAuthCredentialAuthFilter<APrincipal>, AAuthenticator> {
@Override
public OAuthCredentialAuthFilter<APrincipal> buildAuthFilter() {
if (realm == null || authenticator == null || prefix == null || authorizer == null) {
throw new RuntimeException("Required auth filter parameters not set");
}
/**
* Builder for {@link OAuthCredentialAuthFilter}.
* <p>An {@link Authenticator} and an {@link Authorizer} must be provided during the building process.</p>
*
* @param <P> the type of the principal
*/
public static class Builder<P extends Principal>
extends AuthFilterBuilder<String, P, OAuthCredentialAuthFilter<P>> {

OAuthCredentialAuthFilter<APrincipal> oauthCredentialAuthFilter = new OAuthCredentialAuthFilter<>();
oauthCredentialAuthFilter.setRealm(realm);
oauthCredentialAuthFilter.setAuthenticator(authenticator);
oauthCredentialAuthFilter.setPrefix(prefix);
oauthCredentialAuthFilter.setAuthorizer(authorizer);
return oauthCredentialAuthFilter;
@Override
protected OAuthCredentialAuthFilter<P> newInstance() {
return new OAuthCredentialAuthFilter<>();
}
}
}
Expand Up @@ -3,7 +3,6 @@
import com.codahale.metrics.MetricRegistry;
import io.dropwizard.auth.AuthDynamicFeature;
import io.dropwizard.auth.AuthResource;
import io.dropwizard.auth.Authenticator;
import io.dropwizard.auth.util.AuthUtil;
import io.dropwizard.jersey.DropwizardResourceConfig;
import io.dropwizard.logging.BootstrapLogging;
Expand Down Expand Up @@ -155,8 +154,7 @@ public BasicAuthTestResourceConfig() {
private ContainerRequestFilter getAuthFilter() {
final String validUser = "good-guy";

BasicCredentialAuthFilter.Builder<Principal, Authenticator<BasicCredentials, Principal>> builder
= new BasicCredentialAuthFilter.Builder<>();
BasicCredentialAuthFilter.Builder<Principal> builder = new BasicCredentialAuthFilter.Builder<>();
builder.setAuthorizer(AuthUtil.getTestAuthorizer(validUser, VALID_ROLE));
builder.setAuthenticator(AuthUtil.<BasicCredentials, Principal>getTestAuthenticatorBasicCredential(validUser));
return builder.buildAuthFilter();
Expand Down
Expand Up @@ -147,8 +147,7 @@ public BasicAuthTestResourceConfig() {
private ContainerRequestFilter getAuthFilter() {
final String validUser = "good-guy";

BasicCredentialAuthFilter.Builder<Principal, Authenticator<BasicCredentials, Principal>> builder
= new BasicCredentialAuthFilter.Builder<>();
BasicCredentialAuthFilter.Builder<Principal> builder = new BasicCredentialAuthFilter.Builder<>();
builder.setAuthorizer(AuthUtil.getTestAuthorizer(validUser, VALID_ROLE));
builder.setAuthenticator(AuthUtil.getTestAuthenticatorBasicCredential(validUser));
builder.setPrefix("Custom");
Expand Down
Expand Up @@ -19,7 +19,7 @@
import org.junit.Test;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.SecurityContext;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;

Expand Down
Expand Up @@ -82,7 +82,7 @@ public void run(HelloWorldConfiguration configuration, Environment environment)

environment.healthChecks().register("template", new TemplateHealthCheck(template));
environment.jersey().register(DateRequiredFeature.class);
environment.jersey().register(new AuthDynamicFeature(new BasicCredentialAuthFilter.Builder<User, ExampleAuthenticator>()
environment.jersey().register(new AuthDynamicFeature(new BasicCredentialAuthFilter.Builder<User>()
.setAuthenticator(new ExampleAuthenticator())
.setAuthorizer(new ExampleAuthorizer())
.setRealm("SUPER SECRET STUFF")
Expand Down
@@ -1,7 +1,6 @@
package com.example.helloworld.resources;

import com.example.helloworld.core.User;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import io.dropwizard.auth.*;
import io.dropwizard.auth.basic.BasicCredentialAuthFilter;
Expand Down Expand Up @@ -46,7 +45,7 @@ public boolean authorize(User user, String role) {
}
};

BASIC_AUTH_HANDLER = new BasicCredentialAuthFilter.Builder<User, Authenticator<BasicCredentials, User>>()
BASIC_AUTH_HANDLER = new BasicCredentialAuthFilter.Builder<User>()
.setAuthenticator(AUTHENTICATOR)
.setAuthorizer(AUTHORIZER)
.setPrefix("Basic")
Expand Down

0 comments on commit cd0635a

Please sign in to comment.