package org.ovirt.engine.core.sso.servlets; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Stack; 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.core.sso.utils.InteractiveAuth; 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.ovirt.engine.core.uutils.net.URLBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class OAuthAuthorizeServlet extends HttpServlet { private static final long serialVersionUID = -4822437649213489822L; private static Logger log = LoggerFactory.getLogger(OAuthAuthorizeServlet.class); private SsoContext ssoContext; @Override public void init(ServletConfig config) throws ServletException { ssoContext = SsoUtils.getSsoContext(config.getServletContext()); } @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { log.debug("Entered AuthorizeServlet QueryString: {}, Parameters : {}", request.getQueryString(), SsoUtils.getRequestParameters(request)); String clientId = SsoUtils.getRequestParameter(request, SsoConstants.HTTP_PARAM_CLIENT_ID); String responseType = SsoUtils.getRequestParameter(request, SsoConstants.JSON_RESPONSE_TYPE); String scope = SsoUtils.getScopeRequestParameter(request, ""); String state = SsoUtils.getRequestParameter(request, SsoConstants.HTTP_PARAM_STATE, ""); String appUrl = SsoUtils.getRequestParameter(request, SsoConstants.HTTP_PARAM_APP_URL, ""); String engineUrl = SsoUtils.getRequestParameter(request, SsoConstants.HTTP_PARAM_ENGINE_URL, ""); String redirectUri = request.getParameter(SsoConstants.HTTP_PARAM_REDIRECT_URI); SsoUtils.validateClientRequest(request, clientId, null, scope, redirectUri); if (!responseType.equals("code")) { 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)), responseType, SsoConstants.JSON_RESPONSE_TYPE)); } login(request, response, clientId, scope, state, appUrl, engineUrl, redirectUri); } catch (Exception ex) { SsoUtils.redirectToErrorPage(request, response, ex); } } private void login( HttpServletRequest request, HttpServletResponse response, String clientId, String scope, String state, String appUrl, String engineUrl, String redirectUri) throws Exception { log.debug("Entered login queryString: {}", request.getQueryString()); String redirectUrl; // Create the session request.getSession(true); SsoSession ssoSession = SsoUtils.getSsoSession(request); ssoSession.setAppUrl(appUrl); ssoSession.setClientId(clientId); ssoSession.setRedirectUri(redirectUri); ssoSession.setScope(scope); ssoSession.setState(state); ssoSession.getHttpSession().setMaxInactiveInterval(-1); if (StringUtils.isNotEmpty(engineUrl)) { ssoSession.setEngineUrl(engineUrl); } else { ssoSession.setEngineUrl(SsoUtils.getSsoContext(request).getEngineUrl()); } if (SsoUtils.isUserAuthenticated(request)) { log.debug("User is authenticated redirecting to interactive-redirect-to-module"); redirectUrl = request.getContextPath() + SsoConstants.INTERACTIVE_REDIRECT_TO_MODULE_URI; } else if (SsoUtils.scopeAsList(scope).contains("ovirt-ext=auth:identity")) { redirectUrl = new URLBuilder(SsoUtils.getRedirectUrl(request)) .addParameter("error_code", SsoConstants.ERR_OVIRT_CODE_NOT_AUTHENTICATED) .addParameter("error", SsoConstants.ERR_CODE_NOT_AUTHENTICATED_MSG).build(); } else { ssoSession.setAuthStack(getAuthSeq(scope)); if (ssoSession.getAuthStack().isEmpty()) { throw new OAuthException(SsoConstants.ERR_CODE_ACCESS_DENIED, ssoContext.getLocalizationUtils().localize( SsoConstants.APP_ERROR_NO_VALID_AUTHENTICATION_MECHANISM_FOUND, (Locale) request.getAttribute(SsoConstants.LOCALE))); } redirectUrl = request.getContextPath() + SsoConstants.INTERACTIVE_LOGIN_NEXT_AUTH_URI; } log.debug("Redirecting to url: {}", redirectUrl); response.sendRedirect(redirectUrl); } private Stack<InteractiveAuth> getAuthSeq(String scopes) { String appAuthSeq = ssoContext.getSsoLocalConfig().getProperty("SSO_AUTH_LOGIN_SEQUENCE"); String authSeq = null; for (String scope : SsoUtils.scopeAsList(scopes)) { if (scope.startsWith("ovirt-ext=auth:sequence-priority=")) { String[] tokens = scope.trim().split("=", 3); authSeq = tokens[2]; } } List<InteractiveAuth> authSeqList = getAuthListForSeq(authSeq); if (StringUtils.isNotEmpty(authSeq) && authSeq.startsWith("~")) { // get unique auth seq for (char c : appAuthSeq.toCharArray()) { if (!authSeqList.contains(InteractiveAuth.valueOf("" + c))) { authSeqList.add(InteractiveAuth.valueOf("" + c)); } } // intersect auth seq with sso auth seq settings authSeqList.retainAll(getAuthListForSeq(appAuthSeq)); } Collections.reverse(authSeqList); Stack<InteractiveAuth> authSeqStack = new Stack<>(); authSeqStack.addAll(authSeqList); return authSeqStack; } private static List<InteractiveAuth> getAuthListForSeq(String authSeq) { List<InteractiveAuth> authSeqList = new ArrayList<>(); if (StringUtils.isNotEmpty(authSeq)) { for (char c : authSeq.toCharArray()) { if (c == '~') { continue; } authSeqList.add(InteractiveAuth.valueOf("" + c)); } } return authSeqList; } }