/* * Copyright 2013-2017 Simba Open Source * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.simbasecurity.core.chain; import org.simbasecurity.api.service.thrift.ActionDescriptor; import org.simbasecurity.api.service.thrift.ActionType; import org.simbasecurity.api.service.thrift.RequestData; import org.simbasecurity.api.service.thrift.SSOToken; import org.simbasecurity.core.chain.eid.SAMLUser; import org.simbasecurity.core.config.SimbaConfigurationParameter; import org.simbasecurity.core.config.ConfigurationService; import org.simbasecurity.core.domain.LoginMapping; import org.simbasecurity.core.domain.Session; import org.simbasecurity.core.exception.SimbaMessageKey; import org.simbasecurity.core.service.LoginMappingService; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.UUID; import static org.apache.commons.lang.StringUtils.isBlank; import static org.simbasecurity.common.constants.AuthenticationConstants.*; import static org.simbasecurity.common.request.RequestConstants.SIMBA_SSO_TOKEN; import static org.simbasecurity.common.request.RequestUtil.addParametersToUrlAndFilterInternalParameters; import static org.simbasecurity.core.config.SimbaConfigurationParameter.*; import static org.simbasecurity.core.exception.SimbaMessageKey.ACCESS_DENIED; import static org.simbasecurity.core.exception.SimbaMessageKey.LOGIN_TIME_EXPIRED; public class ChainContextImpl implements ChainContext { private static final String HTTP_SIMBA_CHANGE_PWD = "/http/simba-change-pwd"; private static final String SIMBA_CREDENTIAL_CONTROLLER_PATH_SUFFIX = "http/simba-login"; static final String USER_AGENT_HEADER = "user-agent"; private static final long serialVersionUID = -4955438470368723192L; protected RequestData requestData; private ActionDescriptor actionDescriptor = new ActionDescriptor(); private Session currentSession; private final ConfigurationService configurationService; private final LoginMappingService loginMappingService; private long commandCounter = 0; private UUID uuiIdForAChain; private LoginMapping loginMapping; private SAMLUser samlUser; /** * Create a new ChainContext from the given {@link HttpServletRequest}. The * required info is stripped from the {@link HttpServletRequest} and stored * for easy access. * @param requestWrapper * @param session * @param configurationService */ public ChainContextImpl(RequestData requestWrapper, Session session, ConfigurationService configurationService, LoginMappingService loginMappingService) { this.requestData = requestWrapper; this.currentSession = session; this.configurationService = configurationService; this.loginMappingService = loginMappingService; } public Session getCurrentSession() { return currentSession; } public void setNewSession(Session session) { currentSession = session; } public String getRequestHeader(String name) { return requestData.getRequestHeaders().get(name); } public String getRequestParameter(String name) { return requestData.getRequestParameters().get(name); } public Map<String, String> getRequestParameters() { return requestData.getRequestParameters(); } public String getRequestMethod() { return requestData.getRequestMethod(); } public String getRequestURL() { return requestData.getRequestURL(); } public SSOToken getRequestSSOToken() { return requestData.getSsoToken(); } public void setSSOTokenForActions(SSOToken ssoToken) { getActionDescriptor().setSsoToken(ssoToken); } @Override public void setMappingTokenForActions(String mappingToken) { getActionDescriptor().setMappingToken(mappingToken); } public void setRedirectURL(String redirectURL) { getActionDescriptor().setRedirectURL(redirectURL); } public void addParameterToTarget(String key, String value) { getActionDescriptor().getParameterMap().put(key, value); } public void addParametersToTarget(Map<String,String> parameters) { Set<Entry<String, String>> entrySet = parameters.entrySet(); for (Entry<String, String> parameter : entrySet) { getActionDescriptor().getParameterMap().put(parameter.getKey(), parameter.getValue()); } } public void activateAction(ActionType actionType) { getActionDescriptor().getActionTypes().add(actionType); } public boolean isLogoutRequest() { return requestData.isLogoutRequest(); } public String getClientIpAddress() { return requestData.getClientIPAddress(); } public String getHostServerName() { return requestData.getHostServerName(); } public boolean isLoginRequest() { return requestData.isLoginRequest(); } public boolean isChangePasswordRequest() { return requestData.isChangePasswordRequest(); } public boolean isShowChangePasswordRequest() { return requestData.isShowChangePasswordRequest(); } public ActionDescriptor getActionDescriptor() { return actionDescriptor; } public String getSimbaWebURL() { return requestData.getSimbaWebURL(); } public void setUserPrincipal(String userName) { actionDescriptor.setPrincipal(userName); } public boolean isSsoTokenMappingKeyProvided() { return requestData.isSsoTokenMappingKeyProvided(); } public void redirectWithParameters(String redirectURL, Map<String, String> parameters) { activateAction(ActionType.ADD_PARAMETER_TO_TARGET); activateAction(ActionType.REDIRECT); addParametersToTarget(parameters); setRedirectURL(redirectURL); } public void redirectToChangePasswordWithFilter() { Map<String, String> requestParameters = new HashMap<>(); requestParameters.put(USERNAME, getUserName()); addLoginTokenToRequestParameters(requestParameters, createLoginMapping()); String url = getSimbaWebURL() + configurationService.getValue(CHANGE_PASSWORD_URL); redirectWithParameters(url, requestParameters); } public void setSAMLUser(SAMLUser samlUser) { this.samlUser = samlUser; } public SAMLUser getSAMLUser() { return this.samlUser; } public boolean isLoginUsingEID() { return getSAMLUser() != null; } private void addLoginTokenToRequestParameters(Map<String, String> requestParameters, LoginMapping loginMapping) { if (loginMapping != null) { requestParameters.put(LOGIN_TOKEN, loginMapping.getToken()); } } @Override public LoginMapping createLoginMapping() { LoginMapping newMapping = null; if (getLoginToken() != null) { LoginMapping mapping = getLoginMapping() != null ? getLoginMapping() : loginMappingService.getMapping(getLoginToken()); if (mapping != null) { newMapping = loginMappingService.createMapping(mapping.getTargetURL()); loginMappingService.removeMapping(getLoginToken()); } } else if(!isLoginUsingJSP()){ String targetURL = addParametersToUrlAndFilterInternalParameters(getRequestURL(), getRequestParameters()); newMapping = loginMappingService.createMapping(targetURL); } if (newMapping != null) { setLoginMapping(newMapping); } return getLoginMapping(); } public void redirectToChangePasswordDirect(){ Map<String, String> requestParameters = new HashMap<>(); requestParameters.put(USERNAME, getUserName()); requestParameters.put(SIMBA_SSO_TOKEN, getRequestSSOToken().toString()); LoginMapping loginToken = createLoginMapping(); requestParameters.put(LOGIN_TOKEN, loginToken.getToken()); String url = getSimbaWebURL() + configurationService.getValue(CHANGE_PASSWORD_URL); redirectWithParameters(url, requestParameters); } public void redirectToPasswordChanged(){ String passwordChangedURL = configurationService.getValue(SimbaConfigurationParameter.PASSWORD_CHANGED_URL); redirectWithParameters(getSimbaWebURL() + passwordChangedURL, new HashMap<>()); } public void redirectWhenLoginTokenExpired(){ Map<String, String> requestParameters = new HashMap<>(); requestParameters.put(ERROR_MESSAGE, LOGIN_TIME_EXPIRED.name()); redirectWithParameters(getSimbaWebURL() + configurationService.getValue(SimbaConfigurationParameter.EXPIRED_URL) , requestParameters); } public void redirectToLogin(){ Map<String, String> parameters = new HashMap<>(); LoginMapping loginToken = createLoginMapping(); parameters.put(LOGIN_TOKEN, loginToken.getToken()); String url = getSimbaWebURL() + configurationService.getValue(LOGIN_URL); redirectWithParameters(url, parameters); } public void redirectToLogout(){ Map<String, String> parameters = new HashMap<>(); String url = getSimbaWebURL() + configurationService.getValue(LOGOUT_URL); redirectWithParameters(url, parameters); } public void redirectToAccessDenied(){ Map<String, String> requestParameters = new HashMap<>(); requestParameters.put(ERROR_MESSAGE, ACCESS_DENIED.name()); String url = getSimbaWebURL() + configurationService.getValue(ACCESS_DENIED_URL); redirectWithParameters(url, requestParameters); } @Override public void redirectWithCredentialError(SimbaMessageKey errorKey) { Map<String, String> requestParameters = new HashMap<>(); requestParameters.put(USERNAME, getUserName()); requestParameters.put(ERROR_MESSAGE, errorKey.name()); addLoginTokenToRequestParameters(requestParameters, createLoginMapping()); redirectWithParameters(getSimbaWebURL() + getCredentialPath(), requestParameters); } public boolean isLoginUsingJSP() { return getRequestURL().endsWith(SIMBA_CREDENTIAL_CONTROLLER_PATH_SUFFIX) || getRequestURL().endsWith(HTTP_SIMBA_CHANGE_PWD); } private String getCredentialPath() { if(isChangePasswordRequest()) { return configurationService.getValue(CHANGE_PASSWORD_URL); } else if(isLoginRequest()) { return configurationService.getValue(LOGIN_URL); } else { throw new IllegalStateException("Redirect with credential should be called from login or change password request"); } } public String getUserName() { String userName = null; if (getSAMLUser() != null) { userName = getSAMLUser().getInsz(); } if (isBlank(userName)) { userName = getRequestParameter(USERNAME); } if (isBlank(userName) && currentSession != null) { userName = currentSession.getUser().getUserName(); } return userName; } @Override public String getChainContextId() { if(uuiIdForAChain == null){ uuiIdForAChain = UUID.randomUUID(); } return uuiIdForAChain.toString() + "-" + commandCounter; } @Override public void increaseCommandCounter() { commandCounter++; } @Override public void resetCommandCounter() { commandCounter = 0; } @Override public String getUserAgent() { return requestData.getRequestHeaders().get(USER_AGENT_HEADER); } @Override public String getLoginToken() { return requestData.getLoginToken(); } @Override public LoginMapping getLoginMapping() { return loginMapping; } @Override public void setLoginMapping(LoginMapping loginMapping) { this.loginMapping = loginMapping; } @Override public String getSimbaEidSuccessUrl() { return requestData.getSimbaEidSuccessUrl(); } }