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