/******************************************************************************* * Copyright 2017 Graz University of Technology * EAAF-Core Components has been developed in a cooperation between EGIZ, * A-SIT+, A-SIT, and Graz University of Technology. * * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by * the European Commission - subsequent versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * * Unless required by applicable law or agreed to in writing, software * distributed under the Licence is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and * limitations under the Licence. * * This product combines work with different licenses. See the "NOTICE" text * file for details on the various modules and licenses. * The "NOTICE" text file is part of the distribution. Any derivative works * that you distribute must include a readable copy of the "NOTICE" text file. *******************************************************************************/ /******************************************************************************* *******************************************************************************/ /******************************************************************************* *******************************************************************************/ package at.gv.egiz.eaaf.core.impl.idp.controller.protocols; import java.io.Serializable; import java.net.MalformedURLException; import java.net.URL; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import javax.naming.ConfigurationException; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.data.EAAFConstants; import at.gv.egiz.eaaf.core.api.idp.IConfiguration; import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; import at.gv.egiz.eaaf.core.exceptions.EAAFAuthenticationException; import at.gv.egiz.eaaf.core.exceptions.EAAFException; import at.gv.egiz.eaaf.core.exceptions.EAAFStorageException; import at.gv.egiz.eaaf.core.impl.utils.HTTPUtils; import at.gv.egiz.eaaf.core.impl.utils.Random; import at.gv.egiz.eaaf.core.impl.utils.TransactionIDUtils; public abstract class RequestImpl implements IRequest, Serializable{ private static final Logger log = LoggerFactory.getLogger(RequestImpl.class); public static final String DATAID_REQUESTER_IP_ADDRESS = "reqestImpl_requesterIPAddr"; private static final long serialVersionUID = 1L; private String module = null; private String action = null; private String pendingRequestId; private String processInstanceId; private String internalSSOSessionId; private String uniqueTransactionIdentifer; private String uniqueSessionIdentifer; private String requestedServiceProviderIdentifer; private String idpAuthURL = null; private ISPConfiguration spConfiguration = null; private boolean passiv = false; private boolean force = false; private boolean isAbortedByUser = false; //every request needs authentication by default private boolean needAuthentication = true; //every request is not authenticated by default private boolean isAuthenticated = false; //every request needs no SSO by default private boolean needSSO = false; private boolean needUserConsent = false; private Map genericDataStorage = new HashMap(); /** * @throws ConfigurationException * */ public final void initialize(HttpServletRequest req, IConfiguration authConfig) throws EAAFException { //set pendingRequestId pendingRequestId = Random.nextLongRandom(); //set unique transaction identifier for logging uniqueTransactionIdentifer = Random.nextLongRandom(); TransactionIDUtils.setTransactionId(uniqueTransactionIdentifer); //initialize session object genericDataStorage.put(EAAFConstants.AUTH_DATA_CREATED, new Date()); //genericDataStorage.put(EAAFConstants.VALUE_SESSIONID, Random.nextLongRandom()); //check if End-Point is valid String authURLString = HTTPUtils.extractAuthURLFromRequest(req); URL authReqURL; try { authReqURL = new URL(authURLString); } catch (MalformedURLException e) { log.error("IDP AuthenticationServiceURL Prefix is not a valid URL." + authURLString, e); throw new EAAFAuthenticationException("errorId", new Object[]{authURLString}, e); } this.idpAuthURL = authConfig.validateIDPURL(authReqURL); if (this.idpAuthURL == null) { log.warn("Extract AuthenticationServiceURL: " + authReqURL + " is NOT found in configuration."); throw new EAAFAuthenticationException("errorId", new Object[]{authURLString}); } //set unique session identifier String uniqueID = (String) req.getAttribute(EAAFConstants.UNIQUESESSIONIDENTIFIER); if (StringUtils.isNotEmpty(uniqueID)) this.uniqueSessionIdentifer = uniqueID; else { log.debug("Create new sessionIdentifier for this pendingRequest ... "); this.uniqueSessionIdentifer = Random.nextLongRandom(); } //set requester's IP address try { setGenericDataToSession(DATAID_REQUESTER_IP_ADDRESS, req.getRemoteAddr()); } catch (EAAFStorageException e) { log.info("Can NOT store remote IP address into 'pendingRequest'." , e); } } public final void setSPEntityId(String spIdentifier) { this.requestedServiceProviderIdentifer = spIdentifier; } @Override public final String getSPEntityId() { return this.requestedServiceProviderIdentifer; } @Override public final boolean isPassiv() { return passiv; } @Override public final boolean forceAuth() { return force; } public final void setPassiv(boolean passiv) { this.passiv = passiv; } public final void setForce(boolean force) { this.force = force; } @Override public final String requestedAction() { return action; } public final void setAction(String action) { this.action = action; } @Override public final String requestedModule() { return module; } public final void setModule(String module) { this.module = module; } public final void setPendingRequestId(String pendingReqId) { this.pendingRequestId = pendingReqId; } @Override public final String getPendingRequestId() { return pendingRequestId; } @Override public final String getInternalSSOSessionIdentifier() { return this.internalSSOSessionId; } @Override public final void setInternalSSOSessionIdentifier(String internalSSOSessionId) { this.internalSSOSessionId = internalSSOSessionId; } @Override public final Map genericFullDataStorage() { return this.genericDataStorage; } @Override public final ISPConfiguration getServiceProviderConfiguration() { return this.spConfiguration; } @Override public T getServiceProviderConfiguration(final Class decorator) { if (this.spConfiguration != null) { if (decorator.isAssignableFrom(this.spConfiguration.getClass())) { return (T) this.spConfiguration; } else log.error("Can not decorate SP configuration by '" + decorator.getName() + "'."); throw new RuntimeException("Can not decorate SP configuration by '" + decorator.getName() + "'."); } return null; } public void setOnlineApplicationConfiguration(ISPConfiguration spConfig) { this.spConfiguration = spConfig; } @Override public final String getUniqueTransactionIdentifier() { return this.uniqueTransactionIdentifer; } @Override public final String getUniqueSessionIdentifier() { return this.uniqueSessionIdentifer; } @Override public final String getProcessInstanceId() { return this.processInstanceId; } public final void setUniqueTransactionIdentifier(String id) { this.uniqueTransactionIdentifer = id; } public final void setUniqueSessionIdentifier(String id) { this.uniqueSessionIdentifer = id; } public void setProcessInstanceId(String id) { this.processInstanceId = id; } @Override public final String getAuthURL() { return this.idpAuthURL; } @Override public final String getAuthURLWithOutSlash() { if (this.idpAuthURL.endsWith("/")) return this.idpAuthURL.substring(0, this.idpAuthURL.length()-1); else return this.idpAuthURL; } @Override public final boolean isNeedAuthentication() { return needAuthentication; } public final void setNeedAuthentication(boolean needAuthentication) { this.needAuthentication = needAuthentication; } @Override public final boolean isAuthenticated() { return isAuthenticated; } public final void setAuthenticated(boolean isAuthenticated) { this.isAuthenticated = isAuthenticated; } @Override public final boolean needSingleSignOnFunctionality() { return needSSO; } public final void setNeedSingleSignOnFunctionality(boolean needSSO) { this.needSSO = needSSO; } @Override public final boolean isNeedUserConsent() { return this.needUserConsent; } public final void setNeedUserConsent(boolean needConsent) { this.needUserConsent = needConsent; } @Override public final boolean isAbortedByUser() { return this.isAbortedByUser; } public final void setAbortedByUser(boolean isAborted) { this.isAbortedByUser = isAborted; } @Override public final Object getGenericData(String key) { if (StringUtils.isNotEmpty(key)) { return genericDataStorage.get(key); } log.info("Can not load generic request-data with key='null'"); return null; } @Override public final T getGenericData(String key, final Class clazz) { if (StringUtils.isNotEmpty(key)) { Object data = genericDataStorage.get(key); if (data == null) return null; try { @SuppressWarnings("unchecked") T test = (T) data; return test; } catch (Exception e) { log.warn("Generic request-data object can not be casted to requested type", e); return null; } } log.info("Can not load generic request-data with key='null'"); return null; } @Override public final void setGenericDataToSession(String key, Object object) throws EAAFStorageException { if (StringUtils.isEmpty(key)) { log.info("Generic request-data can not be stored with a 'null' key"); throw new EAAFStorageException("Generic request-data can not be stored with a 'null' key", null); } if (object != null) { if (!Serializable.class.isInstance(object)) { log.warn("Generic request-data can only store objects which implements the 'Seralizable' interface"); throw new EAAFStorageException("Generic request-data can only store objects which implements the 'Seralizable' interface", null); } } if (genericDataStorage.containsKey(key)) log.trace("Overwrite generic request-data with key:" + key); else log.trace("Add generic request-data with key:" + key + " to session."); genericDataStorage.put(key, object); } @Override public final void setGenericDataToSession(Map map) throws EAAFStorageException { if (map == null) { log.info("Generic request-data can not be stored with a 'null' map"); throw new EAAFStorageException("Generic request-data can not be stored with a 'null' map", null); } //validate and store values for (Entry el : map.entrySet()) setGenericDataToSession(el.getKey(), el.getValue()); } }