Is there a server agnostic way to implement BASIC Authentication?
Asked Answered
W

2

6

I am attempting to add BASIC authentication to my RESTful web-service. Currently I have BASIC authentication for an Apache Tomcat 6.0 server, but I need to deploy my web-service on a WebSphere application server ver. 6.1 as well and I am having problems getting BASIC authentication running on WebSphere.

Is there a way in Java to check the authentication headers of an HTTP request and if the username/password provided (in Base64 encoding) doesn't match a known account force the user to enter in a new username/password?

I have tried implementing Spring Security, but since my project was made entirely without Spring it has been a huge pain trying to get it to work, and I am attempting to find a simple solution to my rather simple problem.

Technologies that I am currently using include: Java, Jersey/JAX-RS, Eclipse with Maven plugin.

Wilbourn answered 15/6, 2011 at 16:8 Comment(2)
publib.boulder.ibm.com/infocenter/wasinfo/v6r1/index.jsp?topic=/… ?Trotyl
@Marc I have looked through that pdf and it is extremely specific to the example server. I am using a completely different server with WebSphere already installed (I have no control over it) and these configurations do not match the server I am attempting to deploy to.Wilbourn
A
9

You should be able to setup a servlet filter which gets executed before your REST handlers, inspects the "Authorization" request header, base 64 decodes it, extracts the username and password, and verifies. Something like this:

public void doFilter(ServletRequest req,
                     ServletResponse res,
                     FilterChain chain) {
  if (request instanceof HttpServletRequest) {
    HttpServletRequest request = (HttpServletRequest) req;
    String authHeader = Base64.decode(request.getHeader("Authorization"));
    String creds[] = authHeader.split(":");
    String username = creds[0], password = creds[1];
    // Verify the credentials here...
    if (authorized) {
      chain.doFilter(req, res, chain);
    } else {
      // Respond 401 Authorization Required.
    }
  }
  doFilter(req, res, chain);
}

All servlet containers have a standard way to configure filter chains.

Aeon answered 15/6, 2011 at 16:32 Comment(0)
I
5

Complete implementation based on maerics answer.

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;

import sun.misc.BASE64Decoder;

public class AuthenticationFilter implements Filter {

    private static final String AUTHORIZATION_HEADER_NAME = "Authorization";
    private static final String WWW_AUTHENTICATE_HEADER_NAME = "WWW-Authenticate";
    private static final String WWW_AUTHENTICATE_HEADER_VALUE = "Basic realm=\"Default realm\"";
    private static final String BASIC_AUTHENTICATION_REGEX = "Basic\\s";
    private static final String EMPTY_STRING = "";
    private static final String USERNAME_PASSWORD_SEPARATOR = ":";
    private static final BASE64Decoder DECODER = new BASE64Decoder();

    public void init(FilterConfig arg0) throws ServletException {
    }

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest httpReq = (HttpServletRequest) req;
        HttpServletResponse httpRes = (HttpServletResponse) res;

        String authHeader = httpReq.getHeader(AUTHORIZATION_HEADER_NAME);

        if (authHeader == null) {
            this.requestAuthentication(httpRes);
            return;
        }

        authHeader = authHeader.replaceFirst(BASIC_AUTHENTICATION_REGEX, EMPTY_STRING);
        authHeader = new String(DECODER.decodeBuffer(authHeader));      

        if (StringUtils.countMatches(authHeader, USERNAME_PASSWORD_SEPARATOR) != 1) {
            this.requestAuthentication(httpRes);
            return;         
        }

        String[] creds = authHeader.split(USERNAME_PASSWORD_SEPARATOR);
        String username = creds[0];
        String password = creds[1];         

        //TODO: implement this method
        if (!authenticatedUser(username, password)) {
            this.requestAuthentication(httpRes);
            return;
        }

         chain.doFilter(req, res);
    }

    private void requestAuthentication(HttpServletResponse httpRes) {

        httpRes.setHeader(WWW_AUTHENTICATE_HEADER_NAME, WWW_AUTHENTICATE_HEADER_VALUE);
        httpRes.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    }

    public void destroy() {
    }
}
Isaacisaacs answered 15/6, 2013 at 1:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.