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", "*"); } }