package com.wesabe.grendel.auth; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.ext.Provider; import org.eclipse.jetty.http.security.B64Code; import org.eclipse.jetty.util.StringUtil; import com.codahale.shore.injection.AbstractInjectionProvider; import com.sun.jersey.api.core.HttpContext; /** * A Jersey injection provider for {@link Credentials} instances. * <p> * Decodes Basic authentication credentials. If none are present, or the * credentials are malformed, throws a {@link WebApplicationException} with an * appropriate authentication challenge. * <p> * To add a Basic authentication requirement to a method, simply annotate a * {@link Credentials} parameter with {@link Context}: * <pre> * public Response show(@Context Credentials creds) { * ... * } * </pre> * * @author coda */ @Provider public class BasicAuthProvider extends AbstractInjectionProvider<Credentials> { private static final String HEADER_PREFIX = "Basic "; private static final char CREDENTIAL_DELIMITER = ':'; public BasicAuthProvider() { super(Credentials.class); } @Override public Credentials getValue(HttpContext context) { String header = context.getRequest().getHeaderValue(HttpHeaders.AUTHORIZATION); try { try { if ((header != null) && header.startsWith(HEADER_PREFIX)) { final String encoded = header.substring(header.indexOf(' ') + 1); final String credentials = B64Code.decode(encoded, StringUtil.__ISO_8859_1); final int i = credentials.indexOf(CREDENTIAL_DELIMITER); final String username = credentials.substring(0, i); final String password = credentials.substring(i + 1); if ((username != null) && (password != null)) { return new Credentials(username, password); } } } catch (IllegalArgumentException e) { // fall through to sending an auth challenge } catch (StringIndexOutOfBoundsException e) { // fall through to sending an auth challenge } throw new WebApplicationException(Credentials.CHALLENGE); } catch (WebApplicationException e) { throw e; } catch (Exception e) { throw new RuntimeException(e); } } }