CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-dropwizard--dropwizard-project

Java framework for developing ops-friendly, high-performance, RESTful web applications

Pending
Overview
Eval results
Files

authentication.mddocs/

Authentication

Pluggable authentication system supporting basic auth, OAuth, and custom authentication schemes with fine-grained authorization control.

Capabilities

Authenticator Interface

Core interface for converting credentials into authenticated principals.

package io.dropwizard.auth;

public interface Authenticator<C, P> {
    /**
     * Authenticates the given credentials and returns an optional principal.
     * @param credentials the credentials to authenticate
     * @return the authenticated principal if successful, empty otherwise
     * @throws AuthenticationException if authentication fails
     */
    Optional<P> authenticate(C credentials) throws AuthenticationException;
}

Usage Example:

public class SimpleAuthenticator implements Authenticator<BasicCredentials, User> {
    private final UserService userService;
    
    public SimpleAuthenticator(UserService userService) {
        this.userService = userService;
    }
    
    @Override
    public Optional<User> authenticate(BasicCredentials credentials) throws AuthenticationException {
        if ("secret".equals(credentials.getPassword())) {
            return userService.findByUsername(credentials.getUsername());
        }
        return Optional.empty();
    }
}

Authorizer Interface

Interface for implementing authorization logic to control access to resources based on roles or permissions.

package io.dropwizard.auth;

public interface Authorizer<P> {
    /**
     * Determines if the principal is authorized for the given role.
     * @param principal the authenticated principal
     * @param role the role to check authorization for
     * @return true if authorized, false otherwise
     */
    boolean authorize(P principal, String role);
}

Usage Example:

public class SimpleAuthorizer implements Authorizer<User> {
    @Override
    public boolean authorize(User user, String role) {
        return user.getRoles().contains(role);
    }
}

Authentication Filters

Pre-built authentication filters for common authentication schemes.

package io.dropwizard.auth;

public class BasicCredentialAuthFilter<P> extends AuthFilter<BasicCredentials, P> {
    public static class Builder<P> extends AuthFilterBuilder<BasicCredentials, P, BasicCredentialAuthFilter<P>> {
        public Builder<P> setAuthenticator(Authenticator<BasicCredentials, P> authenticator);
        public Builder<P> setAuthorizer(Authorizer<P> authorizer);
        public Builder<P> setRealm(String realm);
        public BasicCredentialAuthFilter<P> buildAuthFilter();
    }
}

public class OAuthCredentialAuthFilter<P> extends AuthFilter<String, P> {
    public static class Builder<P> extends AuthFilterBuilder<String, P, OAuthCredentialAuthFilter<P>> {
        public Builder<P> setAuthenticator(Authenticator<String, P> authenticator);
        public Builder<P> setAuthorizer(Authorizer<P> authorizer);
        public Builder<P> setPrefix(String prefix);
        public OAuthCredentialAuthFilter<P> buildAuthFilter();
    }
}

Usage Example:

@Override
public void run(MyConfiguration configuration, Environment environment) {
    // Basic Authentication
    environment.jersey().register(new AuthDynamicFeature(
        new BasicCredentialAuthFilter.Builder<User>()
            .setAuthenticator(new SimpleAuthenticator(userService))
            .setAuthorizer(new SimpleAuthorizer())
            .setRealm("SUPER SECRET STUFF")
            .buildAuthFilter()
    ));
    
    // OAuth Authentication
    environment.jersey().register(new AuthDynamicFeature(
        new OAuthCredentialAuthFilter.Builder<User>()
            .setAuthenticator(new OAuthAuthenticator(tokenService))
            .setAuthorizer(new SimpleAuthorizer())
            .setPrefix("Bearer")
            .buildAuthFilter()
    ));
    
    // Enable authorization annotations
    environment.jersey().register(RolesAllowedDynamicFeature.class);
}

Auth Dynamic Feature

Jersey dynamic feature for registering authentication filters with the application.

package io.dropwizard.auth;

public class AuthDynamicFeature implements DynamicFeature {
    /**
     * Creates an auth dynamic feature with the given auth filter.
     */
    public AuthDynamicFeature(AuthFilter<?, ?> authFilter);
    
    @Override
    public void configure(ResourceInfo resourceInfo, FeatureContext context);
}

@Provider
public class RolesAllowedDynamicFeature implements DynamicFeature {
    /**
     * Enables @RolesAllowed, @PermitAll, and @DenyAll annotations.
     */
    @Override
    public void configure(ResourceInfo resourceInfo, FeatureContext context);
}

Authentication Annotations

JAX-RS security annotations for protecting resources and methods.

// Security annotations
@RolesAllowed({"ADMIN", "USER"})
@PermitAll
@DenyAll

// Authentication context
@Auth Principal principal

Usage Example:

@Path("/admin")
@RolesAllowed("ADMIN")
public class AdminResource {
    
    @GET
    @Path("/users")
    public List<User> getAllUsers(@Auth User currentUser) {
        // Only accessible by users with ADMIN role
        return userService.findAll();
    }
    
    @POST
    @Path("/users")
    @RolesAllowed({"ADMIN", "MODERATOR"})
    public User createUser(@Auth User currentUser, @Valid User newUser) {
        // Accessible by ADMIN or MODERATOR roles
        return userService.create(newUser);
    }
}

@Path("/public")
@PermitAll
public class PublicResource {
    
    @GET
    @Path("/health")
    public String health() {
        // Publicly accessible
        return "OK";
    }
}

Custom Authentication Schemes

Creating custom authentication filters for specialized authentication requirements.

package io.dropwizard.auth;

public abstract class AuthFilter<C, P> implements ContainerRequestFilter {
    /**
     * Extracts credentials from the request.
     */
    public abstract C getCredentials(ContainerRequestContext requestContext);
    
    /**
     * Called when authentication fails.
     */
    public abstract void onAuthenticationFailure(String challenge, 
                                                ContainerRequestContext requestContext);
    
    /**
     * Called when authorization fails.
     */
    public abstract void onAuthorizationFailure(String challenge,
                                               ContainerRequestContext requestContext);
}

public abstract class AuthFilterBuilder<C, P, T extends AuthFilter<C, P>> {
    public abstract T buildAuthFilter();
    
    protected AuthFilterBuilder<C, P, T> setAuthenticator(Authenticator<C, P> authenticator);
    protected AuthFilterBuilder<C, P, T> setAuthorizer(Authorizer<P> authorizer);
}

Usage Example:

public class ApiKeyAuthFilter extends AuthFilter<String, User> {
    
    @Override
    public String getCredentials(ContainerRequestContext requestContext) {
        return requestContext.getHeaderString("X-API-Key");
    }
    
    @Override
    public void onAuthenticationFailure(String challenge, 
                                       ContainerRequestContext requestContext) {
        requestContext.abortWith(
            Response.status(Response.Status.UNAUTHORIZED)
                   .header(HttpHeaders.WWW_AUTHENTICATE, challenge)
                   .entity("Invalid API key")
                   .build()
        );
    }
    
    @Override
    public void onAuthorizationFailure(String challenge,
                                      ContainerRequestContext requestContext) {
        requestContext.abortWith(
            Response.status(Response.Status.FORBIDDEN)
                   .entity("Insufficient permissions")
                   .build()
        );
    }
    
    public static class Builder extends AuthFilterBuilder<String, User, ApiKeyAuthFilter> {
        @Override
        protected ApiKeyAuthFilter newInstance() {
            return new ApiKeyAuthFilter();
        }
    }
}

Caching Authenticators

Wrapper authenticators that cache authentication results to improve performance.

package io.dropwizard.auth;

public class CachingAuthenticator<C, P> implements Authenticator<C, P> {
    /**
     * Creates a caching authenticator with the given cache spec.
     */
    public static <C, P> CachingAuthenticator<C, P> wrap(
        Authenticator<C, P> underlying, 
        CacheBuilderSpec cacheSpec);
    
    /**
     * Creates a caching authenticator with a cache builder.
     */
    public static <C, P> CachingAuthenticator<C, P> wrap(
        Authenticator<C, P> underlying,
        CacheBuilder<Object, Object> cacheBuilder);
}

Usage Example:

@Override
public void run(MyConfiguration configuration, Environment environment) {
    // Cache authentication results for 10 minutes
    Authenticator<BasicCredentials, User> authenticator = 
        CachingAuthenticator.wrap(
            new DatabaseAuthenticator(userService),
            CacheBuilderSpec.parse("maximumSize=1000, expireAfterWrite=10m")
        );
    
    environment.jersey().register(new AuthDynamicFeature(
        new BasicCredentialAuthFilter.Builder<User>()
            .setAuthenticator(authenticator)
            .setAuthorizer(new SimpleAuthorizer())
            .setRealm("My Service")
            .buildAuthFilter()
    ));
}

Authentication Patterns

JWT Token Authentication

Example implementation for JSON Web Token authentication.

public class JWTAuthenticator implements Authenticator<String, User> {
    private final JWTVerifier verifier;
    private final UserService userService;
    
    public JWTAuthenticator(JWTVerifier verifier, UserService userService) {
        this.verifier = verifier;
        this.userService = userService;
    }
    
    @Override
    public Optional<User> authenticate(String token) throws AuthenticationException {
        try {
            DecodedJWT jwt = verifier.verify(token);
            String username = jwt.getSubject();
            return userService.findByUsername(username);
        } catch (JWTVerificationException e) {
            return Optional.empty();
        }
    }
}

Multi-Factor Authentication

Combining multiple authentication factors for enhanced security.

public class MFAAuthenticator implements Authenticator<BasicCredentials, User> {
    private final Authenticator<BasicCredentials, User> primaryAuth;
    private final TOTPService totpService;
    
    @Override
    public Optional<User> authenticate(BasicCredentials credentials) throws AuthenticationException {
        // First factor: username/password
        Optional<User> user = primaryAuth.authenticate(credentials);
        if (!user.isPresent()) {
            return Optional.empty();
        }
        
        // Second factor: TOTP code (assumed to be in password field after |)
        String[] parts = credentials.getPassword().split("\\|");
        if (parts.length != 2) {
            return Optional.empty();
        }
        
        String totpCode = parts[1];
        if (!totpService.verify(user.get().getTotpSecret(), totpCode)) {
            return Optional.empty();
        }
        
        return user;
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-io-dropwizard--dropwizard-project

docs

authentication.md

configuration.md

core-application.md

database.md

index.md

metrics.md

rest-api.md

testing.md

validation.md

tile.json