I had to recently add Basic Authentication to Dropwizard, the rather nifty RESTful web framework.

Basic Authentication

Basic auth is a Base64 encoded header provided in a request. Typically it appears like this:

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Which decodes nicely to a username:password pair.

Dropwizard - Authentication vs Authorization

Be aware that when Dropwizard documentation talks about Basic Authentication, it might not be what you're looking for (https://dropwizard.github.io/dropwizard/manual/auth.html).

There is a difference between "Authentication" and "Authorization". Authentication checks a user is valid, authorization protects a resource.

So when you want a simple way to protect your resource, don't get too concerned with the @Auth annotations and the built in dropwizard BasicAuthenticator. This is designed to return a valid user token for resue

How to do it

  1. Add users to yaml file
  2. Add the configuration object
  3. Create a security filter
  4. Add security filter to your main dropwizard class

Add users to YAML file

`auth:

  • type: webapp
    username: username
    password: password`

Add the configuration Object

MainAppRenewalConfiguration.yaml

/**
  * The auth configuration
  */
@Valid
@NotNull
private List<AuthUser> auth = new LinkedList<>();

Helper class with the Actual Config

public class AuthUser {

private String type;
private String username;
private String password;

@JsonProperty
public String getType() {
    return type;
}

@JsonProperty
public void setType(String type) {
    this.type = type;
}

@JsonProperty
public String getUsername() {
    return username;
}

@JsonProperty
public void setUsername(String username) {
    this.username = username;
}

@JsonProperty
public String getPassword() {
    return password;
}

@JsonProperty
public void setPassword(String password) {
    this.password = password;
}}

Create security filter

`public class WebClientFilter extends OncePerRequestFilter {

public static List<AuthUser> authUsers;

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

    BasicAuthUser user = null;

    try {
        user = decode(request.getHeader("Authorization"));

    for(AuthUser authUser : authUsers) {
        if(authUser.getUsername().equals(user.getUsername()) && authUser.getPassword().equals(user.getPassword()) && authUser.getType().equals("webapp")) {
            filterChain.doFilter(request, response);
        }
    }}

    catch (Exception e) {
        logger.error("Unable to parse Auth header");
        response.setStatus(401);
        response.setCharacterEncoding("UTF-8");
        response.setContentType(MediaType.APPLICATION_JSON.toString());
        response.getWriter().print("Unauthorized");
    }

    logger.error("Not Authorized");
    response.setStatus(401);
    response.setCharacterEncoding("UTF-8");
    response.setContentType(MediaType.APPLICATION_JSON.toString());
}


public BasicAuthUser decode(String auth) {

    //Replacing "Basic THE_BASE_64" to "THE_BASE_64" directly
    auth = auth.replaceFirst("[B|b]asic ", "");

    //Decode the Base64 into byte[]
    byte[] decodedBytes = DatatypeConverter.parseBase64Binary(auth);

    //If the decode fails in any case
    if(decodedBytes == null || decodedBytes.length == 0){
        return null;
    }

    //Now we can convert the byte[] into a splitted array :
    //  - the first one is login,
    //  - the second one password
    String[] authParams = new String(decodedBytes).split(":", 2);

    return new BasicAuthUser(authParams[0], authParams[1]);
}

// Inner class representing basic auth params
private class BasicAuthUser {

    private String username;
    private String password;

    BasicAuthUser(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}}

Add fiter to main dropwizard class

FilterRegistration.Dynamic filterRegistration = environment.servlets().addFilter("basicAuthFilter", WebClientFilter.class);
	filterRegistration.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, "/*");

    // Set users
    WebClientFilter.authUsers = configuration.getAuth();

Conclusion

So there you go. Basic Access Authentication in Dropwizard. The Filter used is a Spring Authentication component so you will need to add the maven dependency. Easy to use? Not as easy as it should be. Also the documentation and examples don't really point you in the right direction for a simple solution. Hopefully this helps!