package org.ovirt.engine.core.aaa.filters;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import javax.naming.InitialContext;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.ovirt.engine.core.aaa.SsoOAuthServiceUtils;
import org.ovirt.engine.core.aaa.SsoUtils;
import org.ovirt.engine.core.common.constants.SessionConstants;
import org.ovirt.engine.core.common.queries.GetEngineSessionIdForSsoTokenQueryParameters;
import org.ovirt.engine.core.common.queries.VdcQueryReturnValue;
import org.ovirt.engine.core.common.queries.VdcQueryType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SsoRestApiAuthFilter implements Filter {
private final Logger log = LoggerFactory.getLogger(getClass());
private static final String scope = "ovirt-app-api";
private static final String BASIC = "Basic";
private static final String BEARER = "Bearer";
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// empty
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.debug("Entered SsoRestApiAuthFilter");
HttpServletRequest req = (HttpServletRequest) request;
if (!FiltersHelper.isAuthenticated(req) || !FiltersHelper.isSessionValid((HttpServletRequest) request)) {
log.debug("SsoRestApiAuthFilter authenticating with sso");
authenticateWithSso(req, (HttpServletResponse) response);
}
chain.doFilter(request, response);
}
protected void authenticateWithSso(HttpServletRequest req, HttpServletResponse res) throws ServletException {
String headerValue = req.getHeader(FiltersHelper.Constants.HEADER_AUTHORIZATION);
if (headerValue != null && (headerValue.startsWith(BASIC) || headerValue.startsWith(BEARER))) {
try {
String token;
boolean userSessionExists = false;
if (headerValue.startsWith(BASIC)) {
log.debug("SsoRestApiAuthFilter authenticating using BASIC header");
Map<String, Object> response = SsoOAuthServiceUtils.authenticate(req, scope);
FiltersHelper.isStatusOk(response);
token = (String) response.get("access_token");
log.debug("SsoRestApiAuthFilter successfully authenticated using BASIC header");
} else if (headerValue.startsWith(BEARER)) {
log.debug("SsoRestApiAuthFilter authenticating using BEARER header");
token = headerValue.substring("Bearer".length()).trim();
InitialContext ctx = new InitialContext();
try {
VdcQueryReturnValue queryRetVal = FiltersHelper.getBackend(ctx).runPublicQuery(
VdcQueryType.GetEngineSessionIdForSsoToken,
new GetEngineSessionIdForSsoTokenQueryParameters(token));
if (queryRetVal.getSucceeded() && StringUtils.isNotEmpty(queryRetVal.getReturnValue())) {
log.debug("SsoRestApiAuthFilter successfully authenticated using BEARER header");
req.setAttribute(
SessionConstants.HTTP_SESSION_ENGINE_SESSION_ID_KEY,
queryRetVal.getReturnValue());
req.setAttribute(
FiltersHelper.Constants.REQUEST_LOGIN_FILTER_AUTHENTICATION_DONE,
true);
userSessionExists = true;
}
} finally {
ctx.close();
}
} else {
throw new RuntimeException(String.format("Unsupported authentication header: %s", headerValue));
}
if (!userSessionExists) {
Map<String, Object> payload = FiltersHelper.getPayloadForToken(token);
String scope = (String) payload.get("scope");
if (StringUtils.isEmpty(scope) ||
!Arrays.asList(scope.trim().split("\\s *")).contains("ovirt-app-api")) {
throw new RuntimeException("The required scope ovirt-app-api is not granted.");
}
SsoUtils.createUserSession(req, payload, false);
}
} catch (Exception e) {
log.error("Cannot authenticate using authentication Headers: {}", e.getMessage());
log.debug("Cannot authenticate using authentication Headers", e);
}
}
}
@Override
public void destroy() {
// empty
}
}