package auth.modules;
import auth.TokenService;
import auth.mapper.UserMapper;
import auth.models.Token;
import auth.models.User;
import controllers.PoseidonController;
import service.PoseidonPropertyService;
import exceptions.PoseidonException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import play.libs.F;
import play.mvc.Action;
import play.mvc.Http;
import play.mvc.Result;
public class TokenValidatorAction extends Action<TokenAuthorize> {
private static final String AUTHORIZATION = "Authorization";
Logger logger = LoggerFactory.getLogger(TokenValidatorAction.class);
private UserMapper userMapper = new UserMapper();
@Override
public F.Promise<Result> call(final Http.Context context) throws Throwable {
if(PoseidonPropertyService.getProperty("tokenvalidation").equals("disabled")){
logger.info("Validation disabled, skipping token validation");
User dummyuser = User.findByUsername("dummyuser");
if(dummyuser==null){
throw new PoseidonException(Http.Status.BAD_REQUEST,"Dummyuser not configured");
}
api.v1.User user = userMapper.mapToApi(dummyuser);
context.args.put(PoseidonController.USER,user);
return delegate.call(context);
}
// Get token from header or session
String accessToken = context.request().getHeader(AUTHORIZATION);
// validate Bearer token in header
if (invalidBearer(accessToken)) {
String msg = "Authorization header missing";
logger.info(msg);
return notAuthorized(context, msg);
}
// bearer exist, do more fine grained validation
try {
String tokenUID = accessToken.replaceFirst("Bearer ", "");
MDC.put("token", tokenUID);
logger.debug("finding token");
TokenService tokenService = new TokenService();
Token token = tokenService.findByTokenValue(tokenUID);
tokenService.validateToken(token);
tokenService.validateUser(token);
tokenService.validateUserPermission(token, configuration.requiredPermission());
api.v1.User user = userMapper.mapToApi(token.user);
context.args.put(PoseidonController.USER,user);
return delegate.call(context);
} catch (TokenException te){
logger.info("TokenException: status {},message {} ",te.getErrorCode(),te.getMessage());
if (te.getErrorCode() == Http.Status.UNAUTHORIZED) {
return notAuthorized(context, te.getMessage());
}
else if (te.getErrorCode() == Http.Status.FORBIDDEN) {
return forbidden(context,te.getMessage());
}else {
logger.error("Unhandled status handling TokenException");
return internalServerError(context,te.getMessage());
}
}finally {
MDC.remove("token");
MDC.remove("userid");
}
}
protected boolean invalidBearer(String accessToken) {
return accessToken == null || !accessToken.startsWith("Bearer");
}
private F.Promise<Result> notAuthorized(Http.Context context, String msg) {
applyCORSHeader(context);
return F.Promise.pure((Result) unauthorized(msg));
}
private F.Promise<Result> forbidden(Http.Context context, String msg) {
applyCORSHeader(context);
return F.Promise.pure((Result) forbidden(msg));
}
private F.Promise<Result> internalServerError(Http.Context context, String msg) {
applyCORSHeader(context);
return F.Promise.pure((Result) internalServerError(msg));
}
private void applyCORSHeader(Http.Context context) {
context.response().setHeader("Access-Control-Allow-Origin", "*");
}
}