package com.bitmonlab.osiris.api.security.dropwizard;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import static com.google.common.base.Preconditions.*;
import com.bitmonlab.osiris.commons.model.security.BasicAuth;
import com.bitmonlab.osiris.commons.model.security.Constants;
import com.google.common.base.Optional;
import com.google.common.base.Throwables;
import com.sun.jersey.api.core.HttpContext;
import com.sun.jersey.server.impl.inject.AbstractHttpContextInjectable;
import com.yammer.dropwizard.auth.AuthenticationException;
import com.yammer.dropwizard.auth.Authenticator;
public class SpringSecurityInjectable extends
AbstractHttpContextInjectable<BasicAuth> {
private static final Logger LOGGER = LoggerFactory.getLogger(SpringSecurityInjectable.class);
private final boolean authenticationRequired;
private final ApplicationContext appContext;
public SpringSecurityInjectable(boolean authenticationRequired, ApplicationContext context) {
this.authenticationRequired = authenticationRequired;
this.appContext = context;
}
@Override
public BasicAuth getValue(HttpContext context) {
Optional<BasicAuth> principal = Optional.absent();
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null && authenticationRequired) {
String username = String.valueOf(auth.getPrincipal());
String password = String.valueOf(auth.getCredentials());
String api_key = String.valueOf(context.getRequest().getRequestHeader("api_key").get(0));
if (username == null || username.isEmpty())
throw new AuthException(Constants.REQUIRED_USERNAME);
if (password == null || password.isEmpty())
throw new AuthException(Constants.REQUIRED_PASSWORD);
if (api_key == null || api_key.isEmpty())
throw new AuthException(Constants.REQUIRED_APPID);
@SuppressWarnings("unchecked")
Authenticator<SpringSecurityCredentials, BasicAuth> authenticator =
(Authenticator<SpringSecurityCredentials, BasicAuth>) appContext.getBean(DropwizardAuthenticator.class.getName());
SpringSecurityCredentials credentials = new SpringSecurityCredentials(username, password, api_key);
principal = authenticate(authenticator, credentials);
} else if (auth == null && authenticationRequired)
throw new AuthException(Constants.REQUIRED_CREDENTIALS);
return principal.get();
}
private <C, P> Optional<P> authenticate(Authenticator<C, P> authenticator, C credentials) {
checkNotNull(authenticator);
checkNotNull(credentials);
Optional<P> principal;
try {
principal = authenticator.authenticate(credentials);
} catch (AuthenticationException e) {
Throwable cause = Throwables.getRootCause(e);
LOGGER.info("authentication failed", cause.getMessage());
throw new WebApplicationException(Response.status(Response.Status.UNAUTHORIZED).build());
} catch (Exception e) {
LOGGER.error("authentication error", e);
throw new WebApplicationException(Response.status(Response.Status.INTERNAL_SERVER_ERROR).build());
}
return principal;
}
}