package controllers; import auth.*; import auth.mapper.AuthMapper; import compositions.CorsComposition; import compositions.ErrorHandlingComposition; import compositions.NoCacheComposition; import compositions.ResponseTimeLoggingComposition; import exceptions.PoseidonException; import org.slf4j.LoggerFactory; import play.Logger; import play.data.DynamicForm; import play.data.Form; import play.libs.Json; import play.mvc.Http; import play.mvc.Result; @NoCacheComposition.NoCache @CorsComposition.Cors public class TokenController extends PoseidonController { private static org.slf4j.Logger logger = LoggerFactory.getLogger(TokenController.class); @ResponseTimeLoggingComposition.ResponseTimeLogging @ErrorHandlingComposition.ErrorHandling public Result authenticate(String callback) { AuthMapper mapper = new AuthMapper(); DynamicForm requestData = Form.form().bindFromRequest(); Credentials credentials = new Credentials(requestData.data()); logger.debug("Started authenticate to generate new token for grant_type={}", credentials.grantType); Authentication authentication = createAuthentication(credentials); auth.models.Token token = new AuthenticationManager().authenticate(authentication); if (token == null) { String msg = "Could not generate token"; logger.debug(msg + " grant_type={}",credentials.grantType); throw new PoseidonException(Http.Status.UNAUTHORIZED, msg); } else { setPragmaAndCacheControlHeaders(); //Logger.debug("Ok generation of token={} for client_id={} and grant_type={}", token.access_token, credentials.client_id, credentials.grantType); return ok(callback, Json.toJson(mapper.map2Token(token))); } } private void setPragmaAndCacheControlHeaders() { response().setHeader("Pragma", "no-cache"); response().setHeader("Cache-Control", "no-store"); } @ResponseTimeLoggingComposition.ResponseTimeLogging @ErrorHandlingComposition.ErrorHandling public Result validate(String callback) { AuthMapper mapper = new AuthMapper(); String authHeader = request().getHeader("Authorization"); Logger.debug("Start validate token: {}", authHeader); String[] authorizationParts = parseAuthorizationHeader(authHeader); if (authorizationParts.length != 2) { throw new PoseidonException(Http.Status.UNAUTHORIZED, "PartsLength to short"); } String tokenType = authorizationParts[0]; String tokenValue = authorizationParts[1]; auth.models.Token token = auth.models.Token.findByTokenValue(tokenValue); if (validToken(tokenType, token)) { setPragmaAndCacheControlHeaders(); logger.debug("Ok validation of token: {}", authHeader); return ok(callback, Json.toJson(mapper.map2ValidateTokenResponse(token))); } else { String msg = "Unauthorized validation of token"; Logger.debug("{}: {}", msg, authHeader); throw new PoseidonException(Http.Status.UNAUTHORIZED, msg); } } private boolean validToken(String tokenType, auth.models.Token token) { return "bearer".equalsIgnoreCase(tokenType) && token != null && token.isActive(); } private String[] parseAuthorizationHeader(String authHeader) { return (authHeader == null) ? new String[0] : authHeader.split(" +"); } private Authentication createAuthentication(Credentials credentials) { if (credentials.grantType == null) { throw new PoseidonException(Http.Status.BAD_REQUEST, "Valid 'grant_type' missing."); } switch (credentials.grantType) { case LDAP: logger.debug("LDAP authentication"); return new LDAPAuthentication(credentials.username, credentials.password); case PASSWORD: logger.debug("Password authentication"); return new OAuth2PasswordAuthentication(credentials.username, credentials.password); case REFRESH_TOKEN: logger.debug("Refresh authentication"); validateRefreshTokenParameters(credentials); return new OAuth2RefreshTokenAuthentication(credentials.refreshToken); default: throw new PoseidonException(Http.Status.BAD_REQUEST, "Valid 'grant_type' missing."); } } private void validateRefreshTokenParameters(Credentials credentials) { if (credentials.username != null || credentials.password != null) { throw new PoseidonException( Http.Status.BAD_REQUEST, "Parameters username and password are not allowed with refresh-token grant type."); } } }