package org.ovirt.engine.core.sso.servlets;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.ovirt.engine.api.extensions.ExtMap;
import org.ovirt.engine.api.extensions.aaa.Authz;
import org.ovirt.engine.core.sso.search.DirectorySearch;
import org.ovirt.engine.core.sso.utils.OAuthException;
import org.ovirt.engine.core.sso.utils.SsoConstants;
import org.ovirt.engine.core.sso.utils.SsoContext;
import org.ovirt.engine.core.sso.utils.SsoSession;
import org.ovirt.engine.core.sso.utils.SsoUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OAuthTokenInfoServlet extends HttpServlet {
private static final long serialVersionUID = 5190618483759215735L;
private static Logger log = LoggerFactory.getLogger(OAuthTokenInfoServlet.class);
private Map<String, DirectorySearch> directoryQueries = new HashMap<>();
private Map<String, DirectorySearch> directoryPublicQueries = new HashMap<>();
private SsoContext ssoContext;
@Override
public void init(ServletConfig config) throws ServletException {
ssoContext = SsoUtils.getSsoContext(config.getServletContext());
for (DirectorySearch query : DirectorySearch.values()) {
if (query.isPublicQuery()) {
directoryPublicQueries.put(query.getName(), query);
} else {
directoryQueries.put(query.getName(), query);
}
}
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
log.debug("Entered OAuthTokenInfo QueryString: {}, Parameters : {}",
request.getQueryString(),
SsoUtils.getRequestParameters(request));
boolean isValidateRequest = false;
boolean isSearchAuthzRequest;
boolean isPublicSearchAuthzRequest;
try {
String scope = SsoUtils.getRequestParameter(request, SsoConstants.HTTP_PARAM_SCOPE, "");
isValidateRequest = SsoUtils.scopeAsList(scope).contains(SsoConstants.VALIDATE_SCOPE);
isSearchAuthzRequest = SsoUtils.scopeAsList(scope).contains(SsoConstants.AUTHZ_SEARCH_SCOPE);
isPublicSearchAuthzRequest = SsoUtils.scopeAsList(scope).contains(SsoConstants.PUBLIC_AUTHZ_SEARCH_SCOPE);
SsoUtils.validateClientAcceptHeader(request);
if (isValidateRequest) {
String token = SsoUtils.getRequestParameter(request, SsoConstants.HTTP_PARAM_TOKEN);
SsoUtils.getSsoSession(request, null, token, true);
log.debug("Sending json response");
SsoUtils.sendJsonData(response, Collections.emptyMap());
} else {
String[] clientIdAndSecret = SsoUtils.getClientIdClientSecret(request);
SsoUtils.validateClientRequest(request, clientIdAndSecret[0], clientIdAndSecret[1], null, null);
if (isSearchAuthzRequest || isPublicSearchAuthzRequest) {
validateQueryType(request);
}
if (!isPublicSearchAuthzRequest) {
String token = SsoUtils.getRequestParameter(request, SsoConstants.HTTP_PARAM_TOKEN);
SsoUtils.validateRequestScope(request, token, scope);
SsoUtils.getSsoSession(request, clientIdAndSecret[0], token, true)
.getAssociatedClientIds()
.add(clientIdAndSecret[0]);
}
log.debug("Sending json response");
SsoUtils.sendJsonData(response, isSearchAuthzRequest || isPublicSearchAuthzRequest ?
buildSearchResponse(request, isPublicSearchAuthzRequest) :
buildResponse(request, clientIdAndSecret[0], scope));
}
} catch(OAuthException ex) {
SsoUtils.sendJsonDataWithMessage(response, ex, isValidateRequest);
} catch(Exception ex) {
SsoUtils.sendJsonDataWithMessage(response, SsoConstants.ERR_CODE_SERVER_ERROR, ex);
}
}
private void validateQueryType(HttpServletRequest request) throws Exception {
String queryType = SsoUtils.getRequestParameter(request, SsoConstants.HTTP_PARAM_SEARCH_QUERY_TYPE);
if (!directoryQueries.containsKey(queryType) && !directoryPublicQueries.containsKey(queryType)) {
throw new OAuthException(SsoConstants.ERR_CODE_INVALID_REQUEST,
String.format(
ssoContext.getLocalizationUtils().localize(
SsoConstants.APP_ERROR_UNSUPPORTED_PARAMETER_IN_REQUEST,
(Locale) request.getAttribute(SsoConstants.LOCALE)),
queryType,
SsoConstants.HTTP_PARAM_SEARCH_QUERY_TYPE));
}
}
private Map<String, Object> buildSearchResponse(HttpServletRequest request,
boolean isPublicSearchAuthzRequest) throws Exception {
log.debug("Entered SearchDirectoryServlet Query String: {}, Parameters : {}",
request.getQueryString(),
SsoUtils.getRequestParameters(request));
Map<String, Object> data = new HashMap<>();
data.put("result",
isPublicSearchAuthzRequest ?
directoryPublicQueries.get(
SsoUtils.getRequestParameter(request,
SsoConstants.HTTP_PARAM_SEARCH_QUERY_TYPE)).executeQuery(ssoContext, request) :
directoryQueries.get(
SsoUtils.getRequestParameter(request,
SsoConstants.HTTP_PARAM_SEARCH_QUERY_TYPE)).executeQuery(ssoContext, request));
return data;
}
private Map<String, Object> buildResponse(HttpServletRequest request, String clientId, String scope) throws Exception {
String token = SsoUtils.getRequestParameter(request, SsoConstants.HTTP_PARAM_TOKEN);
SsoSession ssoSession = SsoUtils.getSsoSession(request, clientId, token, true);
String password = null;
if (SsoUtils.scopeAsList(scope).contains(SsoConstants.PASSWORD_ACCESS_SCOPE)) {
password = ssoSession.getPassword();
}
return buildResponse(ssoSession, password);
}
private Map<String, Object> buildResponse(SsoSession ssoSession, String password) {
Map<String, Object> payload = new HashMap<>();
payload.put(SsoConstants.JSON_ACTIVE, ssoSession.isActive());
payload.put(SsoConstants.JSON_TOKEN_TYPE, "bearer");
payload.put(SsoConstants.JSON_CLIENT_ID, ssoSession.getClientId());
payload.put(SsoConstants.JSON_USER_ID, String.format("%s@%s", ssoSession.getUserId(),
ssoSession.getProfile()));
payload.put(SsoConstants.JSON_SCOPE, StringUtils.isEmpty(ssoSession.getScope()) ? "" : ssoSession.getScope());
payload.put(SsoConstants.JSON_EXPIRES_IN, ssoSession.getValidTo().toString());
Map<String, Object> ovirt = new HashMap<>();
ovirt.put("version", SsoConstants.OVIRT_SSO_VERSION);
ovirt.put("principal_id", ssoSession.getPrincipalRecord().<String>get(Authz.PrincipalRecord.ID));
ovirt.put("email", ssoSession.getPrincipalRecord().<String>get(Authz.PrincipalRecord.EMAIL));
ovirt.put("namespace", ssoSession.getPrincipalRecord().<String>get(Authz.PrincipalRecord.NAMESPACE));
ovirt.put("first_name", ssoSession.getPrincipalRecord().<String>get(Authz.PrincipalRecord.FIRST_NAME));
ovirt.put("last_name", ssoSession.getPrincipalRecord().<String>get(Authz.PrincipalRecord.LAST_NAME));
ovirt.put("group_ids", ssoSession.getPrincipalRecord().<Collection>get(Authz.PrincipalRecord.GROUPS,
Collections.<ExtMap>emptyList()));
if (password != null) {
ovirt.put("password", password);
}
ovirt.put("capability_credentials_change",
ssoContext.getSsoProfilesSupportingPasswdChange().contains(ssoSession.getProfile()));
payload.put("ovirt", ovirt);
return payload;
}
}