package org.ovirt.engine.core.sso.servlets;
import java.io.IOException;
import java.util.Arrays;
import java.util.Locale;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
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.AuthenticationException;
import org.ovirt.engine.core.sso.utils.AuthenticationUtils;
import org.ovirt.engine.core.sso.utils.Credentials;
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 InteractiveAuthServlet extends HttpServlet {
private static final long serialVersionUID = -88168919566901736L;
private static final String USERNAME = "username";
private static final String PASSWORD = "password";
private static final String PROFILE = "profile";
private static Logger log = LoggerFactory.getLogger(InteractiveAuthServlet.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 {
log.debug("Entered InteractiveAuthServlet");
try {
String redirectUrl;
SsoSession ssoSession = SsoUtils.getSsoSession(request);
// clean up the sso session id token
ssoContext.removeSsoSessionById(ssoSession);
if (StringUtils.isEmpty(ssoSession.getClientId())) {
redirectUrl = ssoContext.getEngineUrl();
} else {
Credentials userCredentials = getUserCredentials(request);
try {
if (SsoUtils.isUserAuthenticated(request)) {
log.debug("User is authenticated redirecting to {}",
SsoConstants.INTERACTIVE_REDIRECT_TO_MODULE_URI);
redirectUrl = request.getContextPath() + SsoConstants.INTERACTIVE_REDIRECT_TO_MODULE_URI;
} else {
redirectUrl = authenticateUser(request, response, userCredentials);
}
} catch (AuthenticationException ex) {
if (userCredentials != null) {
String profile = userCredentials.getProfile() == null ? "N/A" : userCredentials.getProfile();
log.error("Cannot authenticate user '{}@{}': {}",
userCredentials.getUsername(),
profile,
ex.getMessage());
log.debug("Exception", ex);
SsoUtils.getSsoSession(request).setLoginMessage(ex.getMessage());
}
log.debug("Redirecting to LoginPage");
ssoSession.setReauthenticate(false);
ssoContext.registerSsoSessionById(SsoUtils.generateIdToken(), ssoSession);
if (StringUtils.isNotEmpty(ssoContext.getSsoDefaultProfile()) &&
Arrays.stream(request.getCookies()).noneMatch(c -> c.getName().equals("profile"))) {
response.addCookie(new Cookie("profile", ssoContext.getSsoDefaultProfile()));
}
redirectUrl = request.getContextPath() + SsoConstants.INTERACTIVE_LOGIN_FORM_URI;
}
}
if (redirectUrl != null) {
response.sendRedirect(redirectUrl);
}
} catch (Exception ex) {
SsoUtils.redirectToErrorPage(request, response, ex);
}
}
private String authenticateUser(
HttpServletRequest request,
HttpServletResponse response,
Credentials userCredentials) throws ServletException, IOException, AuthenticationException {
if (userCredentials == null || !SsoUtils.areCredentialsValid(request, userCredentials, true)) {
throw new AuthenticationException(
ssoContext.getLocalizationUtils().localize(
SsoConstants.APP_ERROR_INVALID_CREDENTIALS,
(Locale) request.getAttribute(SsoConstants.LOCALE)));
}
try {
log.debug("Authenticating user using credentials");
response.addCookie(new Cookie("profile", userCredentials.getProfile()));
AuthenticationUtils.handleCredentials(
ssoContext,
request,
userCredentials);
return request.getContextPath() + SsoConstants.INTERACTIVE_REDIRECT_TO_MODULE_URI;
} catch (AuthenticationException ex) {
throw ex;
} catch (Exception ex) {
log.error("Internal Server Error: {}", ex.getMessage());
log.debug("Exception", ex);
throw new RuntimeException(ex.getMessage(), ex);
}
}
private Credentials getUserCredentials(HttpServletRequest request) throws Exception {
String username = SsoUtils.getFormParameter(request, USERNAME);
String password = SsoUtils.getFormParameter(request, PASSWORD);
String profile = SsoUtils.getFormParameter(request, PROFILE);
Credentials credentials;
// The code is invoked from the login screen as well as when the user changes password.
// If the login form parameters are not present the code has been invoked from change password flow and
// we extract the credentials from the credentials saved to sso session.
if (username == null || password == null || profile == null) {
credentials = SsoUtils.getSsoSession(request).getTempCredentials();
} else {
credentials = new Credentials(username, password, profile, ssoContext.getSsoProfiles().contains(profile));
}
return credentials;
}
}