diff options
Diffstat (limited to 'id/server/idserverlib/src/main/java/at')
109 files changed, 7252 insertions, 6367 deletions
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/advancedlogging/MOAReversionLogger.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/advancedlogging/MOAReversionLogger.java index 8ee32c54e..17e39f766 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/advancedlogging/MOAReversionLogger.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/advancedlogging/MOAReversionLogger.java @@ -23,15 +23,16 @@ package at.gv.egovernment.moa.id.advancedlogging; import java.security.MessageDigest; +import java.util.Arrays; import java.util.Date; import java.util.List; -import com.google.common.primitives.Ints; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import at.gv.e_government.reference.namespace.mandates._20040701_.Mandate; import at.gv.egovernment.moa.id.auth.data.IdentityLink; -import at.gv.egovernment.moa.id.config.ConfigurationException; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; import at.gv.egovernment.moa.id.data.MISMandate; import at.gv.egovernment.moa.id.moduls.IRequest; @@ -43,11 +44,12 @@ import at.gv.egovernment.moa.util.MiscUtil; * @author tlenz * */ +@Service("MOAReversionLogger") public class MOAReversionLogger { - - private static MOAReversionLogger instance = null; - private static final List<Integer> defaultEventCodes = Ints.asList( + @Autowired protected AuthConfiguration authConfig; + + private static final List<Integer> defaultEventCodes = Arrays.asList( MOAIDEventConstants.SESSION_CREATED, MOAIDEventConstants.SESSION_DESTROYED, MOAIDEventConstants.SESSION_ERROR, @@ -69,17 +71,7 @@ public class MOAReversionLogger { MOAIDEventConstants.AUTHPROCESS_INTERFEDERATION, MOAIDEventConstants.AUTHPROCESS_STORK_REQUESTED, MOAIDEventConstants.AUTHPROCESS_SERVICEPROVIDER - ); - - public static synchronized MOAReversionLogger getInstance() { - if (instance == null) { - instance = new MOAReversionLogger(); - MOAIDEventLog.reload(); - - } - - return instance; - } + ); public void logEvent(IOAAuthParameters oaConfig, int eventCode, String message) { @@ -91,8 +83,8 @@ public class MOAReversionLogger { int eventCode) { if (selectOASpecificEventCodes(oaConfig).contains(eventCode)) MOAIDEventLog.logEvent(MOAIDEventLog.createNewEvent(new Date().getTime(), eventCode, - pendingRequest.getSessionIdentifier(), - pendingRequest.getRequestID())); + pendingRequest.getUniqueSessionIdentifier(), + pendingRequest.getUniqueTransactionIdentifier())); } @@ -101,8 +93,8 @@ public class MOAReversionLogger { if (selectOASpecificEventCodes(oaConfig).contains(eventCode)) MOAIDEventLog.logEvent(MOAIDEventLog.createNewEvent(new Date().getTime(), eventCode, message, - pendingRequest.getSessionIdentifier(), - pendingRequest.getRequestID() + pendingRequest.getUniqueSessionIdentifier(), + pendingRequest.getUniqueTransactionIdentifier() )); } @@ -140,8 +132,8 @@ public class MOAReversionLogger { */ public void logEvent(IRequest pendingRequest, int eventCode) { MOAIDEventLog.logEvent(MOAIDEventLog.createNewEvent(new Date().getTime(), eventCode, - pendingRequest.getSessionIdentifier(), - pendingRequest.getRequestID())); + pendingRequest.getUniqueSessionIdentifier(), + pendingRequest.getUniqueTransactionIdentifier())); } @@ -249,15 +241,9 @@ public class MOAReversionLogger { } public List<Integer> getDefaulttReversionsLoggingEventCodes() { - try { - List<Integer> configuredDefaultEventCodes = AuthConfigurationProviderFactory.getInstance().getDefaultRevisionsLogEventCodes(); - if (configuredDefaultEventCodes != null) - return configuredDefaultEventCodes; - - } catch (ConfigurationException e) { - Logger.error("Access to configuration FAILED.", e); - - } + List<Integer> configuredDefaultEventCodes = authConfig.getDefaultRevisionsLogEventCodes(); + if (configuredDefaultEventCodes != null) + return configuredDefaultEventCodes; return defaultEventCodes; } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/advancedlogging/StatisticLogger.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/advancedlogging/StatisticLogger.java index bfed65ae2..87b3bc9ca 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/advancedlogging/StatisticLogger.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/advancedlogging/StatisticLogger.java @@ -26,14 +26,14 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Date; -import java.util.List; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import org.apache.commons.lang3.StringEscapeUtils; - +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import at.gv.e_government.reference.namespace.mandates._20040701_.Mandate; import at.gv.e_government.reference.namespace.mandates._20040701_.Mandator; @@ -44,22 +44,21 @@ import at.gv.egovernment.moa.id.auth.exception.MISSimpleClientException; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; import at.gv.egovernment.moa.id.auth.exception.ServiceException; import at.gv.egovernment.moa.id.client.SZRGWClientException; - import at.gv.egovernment.moa.id.commons.db.StatisticLogDBUtils; import at.gv.egovernment.moa.id.commons.db.dao.statistic.StatisticLog; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; import at.gv.egovernment.moa.id.config.ConfigurationException; import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; import at.gv.egovernment.moa.id.data.IAuthData; import at.gv.egovernment.moa.id.data.MISMandate; import at.gv.egovernment.moa.id.moduls.IRequest; -import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; +import at.gv.egovernment.moa.id.storage.IAuthenticationSessionStoreage; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; +@Service("StatisticLogger") public class StatisticLogger { private static final String GENERIC_LOCALBKU = ":3496/https-security-layer-request"; @@ -68,7 +67,7 @@ public class StatisticLogger { private static final String MANTATORTYPE_JUR = "jur"; private static final String MANTATORTYPE_NAT = "nat"; - private static final int MAXERRORLENGTH = 250; + private static final int MAXERRORLENGTH = 200; private static final String ERRORTYPE_UNKNOWN = "unkown"; private static final String ERRORTYPE_BKU = "bku"; @@ -76,45 +75,19 @@ public class StatisticLogger { private static final String ERRORTYPE_MANDATE = "mandate"; private static final String ERRORTYPE_MOAID = "moa-id"; private static final String ERRORTYPE_SZRGW = "szrgw"; - - private static StatisticLogger instance; - - private boolean isAktive = false; - - public static StatisticLogger getInstance() { - if (instance == null) - instance = new StatisticLogger(); - return instance; - } - - private StatisticLogger() { - try { - AuthConfiguration config = AuthConfigurationProviderFactory.getInstance(); - - if (config != null) - isAktive = config.isAdvancedLoggingActive(); - - } catch (ConfigurationException e) { - Logger.error("StatisticLogger can not be inizialized", e); - } - } - + @Autowired AuthConfiguration authConfig; + @Autowired IAuthenticationSessionStoreage authenticatedSessionStorage; + public void logSuccessOperation(IRequest protocolRequest, IAuthData authData, boolean isSSOSession) { - if ( isAktive && protocolRequest != null && authData != null) { + if ( authConfig.isAdvancedLoggingActive() && protocolRequest != null && authData != null) { - OAAuthParameter dbOA = null; - try { - dbOA = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(protocolRequest.getOAURL()); + IOAAuthParameters dbOA = null; + dbOA = protocolRequest.getOnlineApplicationConfiguration(); - if (dbOA == null) { - Logger.warn("Advanced logging failed: OA can not be found in database."); - return; - } - - } catch (ConfigurationException e1) { - Logger.error("Access MOA-ID configuration FAILED.", e1); + if (dbOA == null) { + Logger.warn("Advanced logging failed: OA can not be found in database."); return; } @@ -224,7 +197,7 @@ public class StatisticLogger { } public void logErrorOperation(Throwable throwable) { - if ( isAktive ) { + if ( authConfig.isAdvancedLoggingActive() ) { StatisticLog dblog = new StatisticLog(); //set actual date and time @@ -252,7 +225,7 @@ public class StatisticLogger { public void logErrorOperation(Throwable throwable, IRequest errorRequest) { - if (isAktive && throwable != null && errorRequest != null) { + if (authConfig.isAdvancedLoggingActive() && throwable != null && errorRequest != null) { StatisticLog dblog = new StatisticLog(); //set actual date and time @@ -263,44 +236,45 @@ public class StatisticLogger { dblog.setProtocoltype(errorRequest.requestedModule()); dblog.setProtocolsubtype(errorRequest.requestedAction()); - try { - OAAuthParameter dbOA = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(errorRequest.getOAURL()); - if (dbOA != null) { - dblog.setOafriendlyName(dbOA.getFriendlyName()); - dblog.setOatarget(dbOA.getTarget()); - //dblog.setOaID(dbOA.getHjid()); - dblog.setBusinessservice(isBusinessService(dbOA)); - - - AuthenticationSession moasession = AuthenticationSessionStoreage.getSessionWithPendingRequestID(errorRequest.getRequestID()); + IOAAuthParameters dbOA = errorRequest.getOnlineApplicationConfiguration(); + if (dbOA != null) { + dblog.setOafriendlyName(dbOA.getFriendlyName()); + dblog.setOatarget(dbOA.getTarget()); + //dblog.setOaID(dbOA.getHjid()); + dblog.setBusinessservice(isBusinessService(dbOA)); + + try { + AuthenticationSession moasession = authenticatedSessionStorage. + getSession(errorRequest.getMOASessionIdentifier()); if (moasession != null) { if (MiscUtil.isNotEmpty(moasession.getBkuURL())) { dblog.setBkuurl(moasession.getBkuURL()); dblog.setBkutype(findBKUType(moasession.getBkuURL(), dbOA)); } - + dblog.setMandatelogin(moasession.getUseMandate()); } - - generateErrorLogFormThrowable(throwable, dblog); + } catch (MOADatabaseException e) { + Logger.debug(e.getMessage() + " --> StatistikLog will not include MOASession information."); - - try { - StatisticLogDBUtils.saveOrUpdate(dblog); + } + + generateErrorLogFormThrowable(throwable, dblog); - } catch (MOADatabaseException e) { - Logger.warn("Statistic Log can not be stored into Database", e); - } + + + try { + StatisticLogDBUtils.saveOrUpdate(dblog); + + } catch (MOADatabaseException e) { + Logger.warn("Statistic Log can not be stored into Database", e); } - } catch (ConfigurationException e) { - Logger.error("Access MOA-ID configuration FAILED.", e); - return; } } } - private boolean isBusinessService(OAAuthParameter dbOA) { + private boolean isBusinessService(IOAAuthParameters dbOA) { if (dbOA.getOaType().equals("businessService")) return true; @@ -363,7 +337,7 @@ public class StatisticLogger { } - private String findBKUType(String bkuURL, OAAuthParameter dbOA) { + private String findBKUType(String bkuURL, IOAAuthParameters dbOA) { if (dbOA != null) { if (bkuURL.equals(dbOA.getBKUURL(OAAuthParameter.HANDYBKU))) @@ -379,14 +353,13 @@ public class StatisticLogger { Logger.trace("Staticic Log search BKUType from DefaultBKUs"); try { - AuthConfiguration authconfig = AuthConfigurationProviderFactory.getInstance(); - if (bkuURL.equals(authconfig.getDefaultBKUURL(IOAAuthParameters.ONLINEBKU))) + if (bkuURL.equals(authConfig.getDefaultBKUURL(IOAAuthParameters.ONLINEBKU))) return IOAAuthParameters.ONLINEBKU; - if (bkuURL.equals(authconfig.getDefaultBKUURL(IOAAuthParameters.LOCALBKU))) + if (bkuURL.equals(authConfig.getDefaultBKUURL(IOAAuthParameters.LOCALBKU))) return IOAAuthParameters.LOCALBKU; - if (bkuURL.equals(authconfig.getDefaultBKUURL(IOAAuthParameters.HANDYBKU))) + if (bkuURL.equals(authConfig.getDefaultBKUURL(IOAAuthParameters.HANDYBKU))) return IOAAuthParameters.HANDYBKU; } catch (ConfigurationException e) { diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationSessionCleaner.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationSessionCleaner.java index 1f12675ca..a1ba00e02 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationSessionCleaner.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationSessionCleaner.java @@ -3,6 +3,14 @@ package at.gv.egovernment.moa.id.auth; +import java.util.Date; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; +import at.gv.egovernment.moa.id.storage.IAuthenticationSessionStoreage; +import at.gv.egovernment.moa.id.storage.ITransactionStorage; import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; import at.gv.egovernment.moa.logging.Logger; @@ -13,22 +21,47 @@ import at.gv.egovernment.moa.logging.Logger; * @author Paul Ivancsics * @version $Id$ */ +@Service("AuthenticationSessionCleaner") public class AuthenticationSessionCleaner implements Runnable { + @Autowired private IAuthenticationSessionStoreage authenticationSessionStorage; + @Autowired private ITransactionStorage transactionStorage; + @Autowired protected AuthConfiguration authConfig; + /** interval the <code>AuthenticationSessionCleaner</code> is run in */ private static final long SESSION_CLEANUP_INTERVAL = 5 * 60; // 5 min /** * Runs the thread. Cleans the <code>AuthenticationServer</code> session store * and authentication data store from garbage, then sleeps for given interval, and restarts. + * + * Cleans up expired session and authentication data stores. + * */ public void run() { while (true) { try { Logger.debug("AuthenticationSessionCleaner run"); - BaseAuthenticationServer.cleanup(); - } - catch (Exception e) { + Date now = new Date(); + + try { + int sessionTimeOutCreated = authConfig.getSSOCreatedTimeOut() * 1000; + int sessionTimeOutUpdated = authConfig.getSSOUpdatedTimeOut() * 1000; + int authDataTimeOut = authConfig.getTransactionTimeOut() * 1000; + + //clean AuthenticationSessionStore + authenticationSessionStorage.clean(now, sessionTimeOutCreated, sessionTimeOutUpdated); + + //clean TransactionStorage + transactionStorage.clean(now, authDataTimeOut); + + + } catch (Exception e) { + Logger.error("Session cleanUp FAILED!" , e); + + } + + } catch (Exception e) { Logger.error(MOAIDMessageProvider.getInstance().getMessage("cleaner.01", null), e); } try { @@ -42,10 +75,10 @@ public class AuthenticationSessionCleaner implements Runnable { /** * start the sessionCleaner */ - public static void start() { + public static void start(Runnable clazz) { // start the session cleanup thread Thread sessionCleaner = - new Thread(new AuthenticationSessionCleaner(), "AuthenticationSessionCleaner"); + new Thread(clazz, "AuthenticationSessionCleaner"); sessionCleaner.setName("SessionCleaner"); sessionCleaner.setDaemon(true); sessionCleaner.setPriority(Thread.MIN_PRIORITY); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/BaseAuthenticationServer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/BaseAuthenticationServer.java index 5e3b6653b..1ce6fa1e9 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/BaseAuthenticationServer.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/BaseAuthenticationServer.java @@ -1,37 +1,13 @@ package at.gv.egovernment.moa.id.auth; -import java.io.UnsupportedEncodingException; -import java.util.Date; -import java.util.List; -import java.util.UUID; - -import org.opensaml.xml.util.XMLHelper; - -import org.w3c.dom.Element; +import org.springframework.beans.factory.annotation.Autowired; import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; -import at.gv.egovernment.moa.id.client.SZRGWClient; -import at.gv.egovernment.moa.id.client.SZRGWClientException; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; -import at.gv.egovernment.moa.id.config.ConfigurationException; -import at.gv.egovernment.moa.id.config.ConnectionParameter; import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; -import at.gv.egovernment.moa.id.storage.AssertionStorage; -import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; -import at.gv.egovernment.moa.id.storage.DBExceptionStoreImpl; -import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; -import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.MiscUtil; -import at.gv.util.xsd.mis.MandateIdentifiers; -import at.gv.util.xsd.mis.Target; -import at.gv.util.xsd.srzgw.CreateIdentityLinkRequest; -import at.gv.util.xsd.srzgw.CreateIdentityLinkRequest.PEPSData; -import at.gv.util.xsd.srzgw.CreateIdentityLinkResponse; -import at.gv.util.xsd.srzgw.MISType; -import at.gv.util.xsd.srzgw.MISType.Filters; +import at.gv.egovernment.moa.id.storage.IAuthenticationSessionStoreage; /** * API for MOA ID Authentication Service.<br> {@link AuthenticationSession} is @@ -43,6 +19,9 @@ import at.gv.util.xsd.srzgw.MISType.Filters; */ public abstract class BaseAuthenticationServer extends MOAIDAuthConstants { + @Autowired private IAuthenticationSessionStoreage authenticationSessionStorage; + @Autowired protected AuthConfiguration authConfig; + /** * Retrieves a session from the session store. * @@ -50,11 +29,11 @@ public abstract class BaseAuthenticationServer extends MOAIDAuthConstants { * @return <code>AuthenticationSession</code> stored with given session ID (never {@code null}). * @throws AuthenticationException in case the session id does not reflect a valic, active session. */ - public static AuthenticationSession getSession(String id) + public AuthenticationSession getSession(String id) throws AuthenticationException { AuthenticationSession session; try { - session = AuthenticationSessionStoreage.getSession(id); + session = authenticationSessionStorage.getSession(id); if (session == null) throw new AuthenticationException("auth.02", new Object[]{id}); @@ -68,33 +47,4 @@ public abstract class BaseAuthenticationServer extends MOAIDAuthConstants { } } - /** - * Cleans up expired session and authentication data stores. - */ - public static void cleanup() { - long now = new Date().getTime(); - - try { - int sessionTimeOutCreated = AuthConfigurationProviderFactory.getInstance().getSSOCreatedTimeOut() * 1000; - int sessionTimeOutUpdated = AuthConfigurationProviderFactory.getInstance().getSSOUpdatedTimeOut() * 1000; - int authDataTimeOut = AuthConfigurationProviderFactory.getInstance().getTransactionTimeOut() * 1000; - - //clean AuthenticationSessionStore - AuthenticationSessionStoreage.clean(now, sessionTimeOutCreated, sessionTimeOutUpdated); - - //clean AssertionStore - AssertionStorage assertionstore = AssertionStorage.getInstance(); - assertionstore.clean(now, authDataTimeOut); - - //clean ExeptionStore - DBExceptionStoreImpl exstore = DBExceptionStoreImpl.getStore(); - exstore.clean(now, authDataTimeOut); - - } catch (Exception e) { - Logger.error("Session cleanUp FAILED!" , e); - - } - - } - } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java index fa30f9ffd..1a9018563 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java @@ -10,8 +10,6 @@ import java.util.List; import java.util.Map; import at.gv.egovernment.moa.id.commons.MOAIDConstants; -import at.gv.egovernment.moa.id.commons.config.persistence.MOAIDConfiguration; - import iaik.asn1.ObjectID; @@ -35,6 +33,7 @@ public class MOAIDAuthConstants extends MOAIDConstants{ public static final String PARAM_ACTION = "ACTION"; public static final String PARAM_SSO = "SSO"; public static final String INTERFEDERATION_IDP = "interIDP"; + public static final String PARAM_TARGET_PENDINGREQUESTID = "pendingid"; public static final String PARAM_SLOSTATUS = "status"; public static final String PARAM_SLORESTART = "restart"; @@ -130,6 +129,8 @@ public class MOAIDAuthConstants extends MOAIDConstants{ public static final String REQ_BKU_TYPE_HANDY = "handy"; public static final List<String> REQ_BKU_TYPES = Arrays.asList(REQ_BKU_TYPE_LOCAL, REQ_BKU_TYPE_ONLINE, REQ_BKU_TYPE_HANDY); + public static final List<String> LEGACYPARAMETERWHITELIST + = Arrays.asList(PARAM_TARGET, PARAM_BKU, PARAM_OA, PARAM_TEMPLATE, PARAM_USEMANDATE, PARAM_CCC, PARAM_SOURCEID); public final static String EXT_SAML_MANDATE_OIDTEXTUALDESCRIPTION = "OIDTextualDescription"; public final static String EXT_SAML_MANDATE_OID = "OID"; @@ -173,7 +174,15 @@ public class MOAIDAuthConstants extends MOAIDConstants{ //AuthnRequest IssueInstant validation public static final int TIME_JITTER = 5; //all 5 minutes time jitter - public static final String PROCESSCONTEXT_INTERFEDERATION_ENTITYID = "interfederationIDPEntityID"; + public static final String PROCESSCONTEXT_PERFORM_INTERFEDERATION_AUTH = "interfederationAuthentication"; public static final String PROCESSCONTEXT_REQUIRELOCALAUTHENTICATION = "requireLocalAuthentication"; + public static final String PROCESSCONTEXT_PERFORM_BKUSELECTION = "performBKUSelection"; + public static final String PROCESSCONTEXT_ISLEGACYREQUEST = "isLegacyRequest"; + + //General protocol-request data-store keys + public static final String AUTHPROCESS_DATA_TARGET = "authProces_Target"; + public static final String AUTHPROCESS_DATA_TARGETFRIENDLYNAME = "authProces_TargetFriendlyName"; + public static final String AUTHPROCESS_DATA_SECURITYLAYERTEMPLATE = "authProces_SecurityLayerTemplate"; + } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java index b3055eb34..5968736f8 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java @@ -3,23 +3,31 @@ package at.gv.egovernment.moa.id.auth; -import iaik.pki.PKIException; -import iaik.security.ecc.provider.ECCProvider; -import iaik.security.provider.IAIK; - import java.io.IOException; import java.security.GeneralSecurityException; import javax.activation.CommandMap; import javax.activation.MailcapCommandMap; -import javax.net.ssl.SSLSocketFactory; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.web.WebApplicationInitializer; +import org.springframework.web.context.ContextLoaderListener; +import org.springframework.web.context.request.RequestContextListener; +import org.springframework.web.context.support.GenericWebApplicationContext; +import org.springframework.web.context.support.ServletContextResource; +import org.springframework.web.servlet.DispatcherServlet; +import at.gv.egiz.components.spring.api.SpringLoader; import at.gv.egovernment.moa.id.config.ConfigurationException; -import at.gv.egovernment.moa.id.config.ConnectionParameter; import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.id.config.auth.MOAGarbageCollector; -import at.gv.egovernment.moa.id.util.AxisSecureSocketFactory; import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; import at.gv.egovernment.moa.id.util.SSLUtils; import at.gv.egovernment.moa.logging.Logger; @@ -29,6 +37,9 @@ import at.gv.egovernment.moa.spss.server.config.ConfigurationProvider; import at.gv.egovernment.moa.spss.server.iaik.config.IaikConfigurator; import at.gv.egovernment.moa.util.Constants; import at.gv.egovernment.moa.util.MiscUtil; +import iaik.pki.PKIException; +import iaik.security.ecc.provider.ECCProvider; +import iaik.security.provider.IAIK; /** * Web application initializer @@ -36,66 +47,136 @@ import at.gv.egovernment.moa.util.MiscUtil; * @author Paul Ivancsics * @version $Id$ */ -public class MOAIDAuthInitializer { +public class MOAIDAuthInitializer implements WebApplicationInitializer { + + private String[] rootServletContexts = null; + + private String[] servletContexts = null; + + private String[] activeProfiles = null; + + public MOAIDAuthInitializer() { + this.rootServletContexts = null; + this.servletContexts = new String[] { + "/WEB-INF/applicationContext.xml", + + }; + this.activeProfiles = null; + } + + + /* (non-Javadoc) + * @see org.springframework.web.WebApplicationInitializer#onStartup(javax.servlet.ServletContext) + */ + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + try { + Logger.info("=============== Loading Root Context! ==============="); + GenericWebApplicationContext rootContext = new GenericWebApplicationContext(); + rootContext.setServletContext(servletContext); + + Logger.info("=============== Setting active profiles! ==============="); + if (this.activeProfiles != null) { + for (String profile : this.activeProfiles) { + rootContext.getEnvironment().addActiveProfile(profile); + } + } + + Logger.info("=============== Loading Local Contexts! ==============="); + XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader( + rootContext); + if (rootServletContexts != null) { + for (String rootServletContext : rootServletContexts) { + Logger.debug("Loading: "+ rootServletContext); + xmlReader.loadBeanDefinitions(new ServletContextResource( + servletContext, rootServletContext)); + } + } + // Manage the lifecycle of the root application context + servletContext.addListener(new ContextLoaderListener(rootContext)); + + // logger.debug("Beans after logAMQP in {}", rootContext); + // dumpBeanDefinitions(rootContext); + + Logger.info("=============== Loading SPI Context! ==============="); + // logger.debug("Startup with context {}", rootContext); + if (rootContext instanceof BeanDefinitionRegistry) { + Logger.debug("Loading EGIZ components"); + SpringLoader + .loadSpringServices(rootContext); + } else { + Logger.warn("Failed to load external Spring since no BeanDefinitionRegistry"); + } + + Logger.trace("Beans after SPI in "+ rootContext); + dumpBeanDefinitions(rootContext); + + Logger.debug("Loading servlet config in "+ rootContext); + if (servletContexts != null) { + for (String servletContextString : servletContexts) { + xmlReader.loadBeanDefinitions(new ServletContextResource( + servletContext, servletContextString)); + } + } + Logger.debug("Refreshing context "+ rootContext); + rootContext.refresh(); - /** a boolean identifying if the MOAIDAuthInitializer has been startet */ - public static boolean initialized = false; + Logger.info("=============== Register Dispatcher Servlet! ==============="); + Logger.trace("Final Beans in "+ rootContext); + dumpBeanDefinitions(rootContext); + + + Logger.info("Registering dispatcher configuration"); + ServletRegistration.Dynamic dispatcher = servletContext.addServlet( + "dispatcher", new DispatcherServlet(rootContext)); + if (dispatcher != null) { + dispatcher.setLoadOnStartup(1); + dispatcher.addMapping("/"); + dispatcher.setAsyncSupported(true); + } else { + Logger.error("Failed to register dispatcher server in servlet context!"); + } + + Logger.info("=============== Register RequestContextListener! ==============="); + servletContext.addListener(new RequestContextListener()); + + Logger.info("Basic Context initalisation finished --> Start MOA-ID-Auth initialisation process ..."); + MOAIDAuthInitializer.initialize(rootContext); + Logger.info(MOAIDMessageProvider.getInstance().getMessage( + "init.00", null)); + Logger.info("MOA-ID-Auth initialization finished."); + + + } catch (Throwable e) { + Logger.fatal( + MOAIDMessageProvider.getInstance().getMessage("init.02", + null), e); + + } + + } + + + /** * Initializes the web application components which need initialization: * logging, JSSE, MOA-ID Auth configuration, Axis, session cleaner. + * @param rootContext */ - public static void initialize() throws ConfigurationException, + public static void initialize(GenericWebApplicationContext rootContext) throws ConfigurationException, PKIException, IOException, GeneralSecurityException { - if (initialized) return; - initialized = true; Logger.setHierarchy("moa.id.auth"); Logger.info("Default java file.encoding: " + System.getProperty("file.encoding")); - - Logger.info("Loading security providers."); - IAIK.addAsProvider(); - - -// Security.insertProviderAt(new IAIK(), 1); -// Security.insertProviderAt(new ECCProvider(), 1); - + //JDK bug workaround according to: // http://jce.iaik.tugraz.at/products/03_cms/faq/index.php#JarVerifier // register content data handlers for S/MIME types MailcapCommandMap mc = new MailcapCommandMap(); CommandMap.setDefaultCommandMap(mc); - // create some properties and get the default Session -// Properties props = new Properties(); -// props.put("mail.smtp.host", "localhost"); -// Session session = Session.getDefaultInstance(props, null); - - // Restricts TLS cipher suites -// System.setProperty( -// "https.cipherSuites", -// "SSL_RSA_WITH_RC4_128_SHA,SSL_RSA_WITH_RC4_128_MD5,SSL_RSA_WITH_3DES_EDE_CBC_SHA"); -// - // actual HIGH cipher suites from OpenSSL -// Mapping OpenSSL - Java -// OpenSSL Java -// http://www.openssl.org/docs/apps/ciphers.html http://docs.oracle.com/javase/6/docs/technotes/guides/security/SunProviders.html -// via !openssl ciphers -tls1 HIGH !v! -// -// ADH-AES256-SHA TLS_DH_anon_WITH_AES_256_CBC_SHA -// DHE-RSA-AES256-SHA TLS_DHE_RSA_WITH_AES_256_CBC_SHA -// DHE-DSS-AES256-SHA TLS_DHE_DSS_WITH_AES_256_CBC_SHA -// AES256-SHA TLS_RSA_WITH_AES_256_CBC_SHA -// ADH-AES128-SHA TLS_DH_anon_WITH_AES_128_CBC_SHA -// DHE-RSA-AES128-SHA TLS_DHE_RSA_WITH_AES_128_CBC_SHA -// DHE-DSS-AES128-SHA TLS_DHE_DSS_WITH_AES_128_CBC_SHA -// AES128-SHA TLS_RSA_WITH_AES_128_CBC_SHA -// ADH-DES-CBC3-SHA SSL_DH_anon_WITH_3DES_EDE_CBC_SHA -// EDH-RSA-DES-CBC3-SHA - -// EDH-DSS-DES-CBC3-SHA - -// DES-CBC3-SHA SSL_RSA_WITH_3DES_EDE_CBC_SHA - if (MiscUtil.isEmpty(System.getProperty("https.cipherSuites"))) System.setProperty( "https.cipherSuites", @@ -124,9 +205,11 @@ public class MOAIDAuthInitializer { "init.01", null), e); } + Logger.info("Loading security providers."); IAIK.addAsProvider(); ECCProvider.addAsProvider(); + // Initializes SSLSocketFactory store SSLUtils.initialize(); @@ -136,54 +219,48 @@ public class MOAIDAuthInitializer { "http://www.w3.org/2001/04/xmldsig-more#"); Constants.nSMap.put(Constants.DSIG_PREFIX, Constants.DSIG_NS_URI); - // Loads the configuration + + // Initialize configuration provider + AuthConfiguration authConf = AuthConfigurationProviderFactory.reload(rootContext); + + //test, if MOA-ID is already configured + authConf.getPublicURLPrefix(); + + + // Initialize MOA-SP + //MOA-SP is only use by API calls since MOA-ID 3.0.0 try { - AuthConfiguration authConf = AuthConfigurationProviderFactory.reload(); - - ConnectionParameter moaSPConnParam = authConf - .getMoaSpConnectionParameter(); - - // If MOA-SP API calls: loads MOA-SP configuration and configures IAIK - if (moaSPConnParam == null) { - try { - LoggingContextManager.getInstance().setLoggingContext( - new LoggingContext("startup")); - ConfigurationProvider config = ConfigurationProvider - .getInstance(); - new IaikConfigurator().configure(config); - } catch (at.gv.egovernment.moa.spss.server.config.ConfigurationException ex) { - throw new ConfigurationException("config.10", new Object[] { ex - .toString() }, ex); - } - } - - // Initializes IAIKX509TrustManager logging - /* - String log4jConfigURL = System.getProperty("log4j.configuration"); - Logger.info("Log4J Configuration: " + log4jConfigURL); - if (log4jConfigURL != null) { - IAIKX509TrustManager.initLog(new LoggerConfigImpl(log4jConfigURL)); - } - */ - - // Initializes the Axis secure socket factory for use in calling the - // MOA-SP web service - if (moaSPConnParam != null && moaSPConnParam.isHTTPSURL()) { - SSLSocketFactory ssf = SSLUtils.getSSLSocketFactory(authConf, - moaSPConnParam); - AxisSecureSocketFactory.initialize(ssf); - } - - - } catch (ConfigurationException e) { - Logger.error("MOA-ID-Auth start-up FAILED. Error during application configuration.", e); - System.exit(-1); - - } + LoggingContextManager.getInstance().setLoggingContext( + new LoggingContext("startup")); + ConfigurationProvider config = ConfigurationProvider + .getInstance(); + new IaikConfigurator().configure(config); + + } catch (at.gv.egovernment.moa.spss.server.config.ConfigurationException ex) { + throw new ConfigurationException("config.10", new Object[] { ex + .toString() }, ex); + + } + // Starts the session cleaner thread to remove unpicked authentication data - AuthenticationSessionCleaner.start(); + AuthenticationSessionCleaner sessioncleaner = rootContext.getBean("AuthenticationSessionCleaner", AuthenticationSessionCleaner.class); + AuthenticationSessionCleaner.start(sessioncleaner); + MOAGarbageCollector.start(); } + private void dumpBeanDefinitions(GenericApplicationContext context) { + Logger.trace("Registered Bean in context " + context.toString()); + + String[] registeredBeans = context.getBeanDefinitionNames(); + for (String registeredBean : registeredBeans) { + BeanDefinition beanDefinition = context + .getBeanDefinition(registeredBean); + Logger.trace(registeredBean + " -> " + beanDefinition.getBeanClassName()); + + } + + Logger.trace("Registered Bean in context --"+ context); + } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthSpringResourceProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthSpringResourceProvider.java new file mode 100644 index 000000000..a82a958db --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthSpringResourceProvider.java @@ -0,0 +1,66 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +import at.gv.egiz.components.spring.api.SpringResourceProvider; + +/** + * @author tlenz + * + */ +public class MOAIDAuthSpringResourceProvider implements SpringResourceProvider { + + /* (non-Javadoc) + * @see at.gv.egiz.components.spring.api.SpringResourceProvider#getResourcesToLoad() + */ + @Override + public Resource[] getResourcesToLoad() { + ClassPathResource moaidauthConfig = new ClassPathResource("/moaid.configuration.beans.xml", MOAIDAuthSpringResourceProvider.class); + ClassPathResource configurationDBConfig = new ClassPathResource("/configuration.beans.xml", MOAIDAuthSpringResourceProvider.class); + ClassPathResource moaIdAuthBeans = new ClassPathResource("/moaid.authentication.beans.xml", MOAIDAuthSpringResourceProvider.class); + + return new Resource[] {configurationDBConfig, moaidauthConfig, moaIdAuthBeans}; + + } + + /* (non-Javadoc) + * @see at.gv.egiz.components.spring.api.SpringResourceProvider#getPackagesToScan() + */ + @Override + public String[] getPackagesToScan() { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see at.gv.egiz.components.spring.api.SpringResourceProvider#getName() + */ + @Override + public String getName() { + return "MOA-ID-Auth SpringResourceProvider"; + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java index b79b99a65..8a9999d85 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java @@ -22,8 +22,6 @@ */ package at.gv.egovernment.moa.id.auth.builder; -import iaik.x509.X509Certificate; - import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -51,6 +49,8 @@ import org.opensaml.saml2.core.Response; import org.opensaml.ws.soap.common.SOAPException; import org.opensaml.xml.XMLObject; import org.opensaml.xml.security.SecurityException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -81,7 +81,6 @@ import at.gv.egovernment.moa.id.commons.db.dao.session.OASessionStore; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; import at.gv.egovernment.moa.id.config.ConfigurationException; import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; import at.gv.egovernment.moa.id.data.AuthenticationData; @@ -89,6 +88,7 @@ import at.gv.egovernment.moa.id.data.AuthenticationRoleFactory; import at.gv.egovernment.moa.id.data.IAuthData; import at.gv.egovernment.moa.id.data.MISMandate; import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.id.moduls.RequestImpl; import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration; import at.gv.egovernment.moa.id.protocols.pvp2x.builder.AttributQueryBuilder; @@ -96,14 +96,14 @@ import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AssertionAttributeExt import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AssertionValidationExeption; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AttributQueryException; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; +import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOAResponse; import at.gv.egovernment.moa.id.protocols.pvp2x.utils.AssertionAttributeExtractor; import at.gv.egovernment.moa.id.protocols.pvp2x.utils.MOASAMLSOAPClient; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.SAMLVerificationEngine; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.TrustEngineFactory; -import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; +import at.gv.egovernment.moa.id.storage.IAuthenticationSessionStoreage; import at.gv.egovernment.moa.id.util.IdentityLinkReSigner; import at.gv.egovernment.moa.id.util.PVPtoSTORKMapper; -import at.gv.egovernment.moa.id.util.ParamValidatorUtils; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.Base64Utils; import at.gv.egovernment.moa.util.Constants; @@ -114,35 +114,32 @@ import at.gv.util.config.EgovUtilPropertiesConfiguration; import at.gv.util.ex.EgovUtilException; import at.gv.util.wsdl.szr.SZRException; import at.gv.util.xsd.szr.PersonInfoType; +import iaik.x509.X509Certificate; /** * @author tlenz * */ +@Service("AuthenticationDataBuilder") public class AuthenticationDataBuilder extends MOAIDAuthConstants { - public static IAuthData buildAuthenticationData(IRequest protocolRequest, - AuthenticationSession session, List<Attribute> reqAttributes) throws ConfigurationException, BuildException, WrongParametersException, DynamicOABuildException { - - - String oaID = protocolRequest.getOAURL(); - if (oaID == null) { - throw new WrongParametersException("StartAuthentication", - PARAM_OA, "auth.12"); - } - - // check parameter - if (!ParamValidatorUtils.isValidOA(oaID)) - throw new WrongParametersException("StartAuthentication", - PARAM_OA, "auth.12"); - + @Autowired private IAuthenticationSessionStoreage authenticatedSessionStorage; + @Autowired protected AuthConfiguration authConfig; + @Autowired private AttributQueryBuilder attributQueryBuilder; + @Autowired private SAMLVerificationEngine samlVerificationEngine; + + public IAuthData buildAuthenticationData(IRequest protocolRequest, + AuthenticationSession session, List<Attribute> reqAttributes) throws ConfigurationException, BuildException, WrongParametersException, DynamicOABuildException { AuthenticationData authdata = null; + //only needed for SAML1 legacy support try { - Object saml1Requst = Class.forName("at.gv.egovernment.moa.id.protocols.saml1.SAML1RequestImpl").newInstance(); + //check if SAML1 authentication module is in Classpath + Class<?> saml1RequstTemplate = Class.forName("at.gv.egovernment.moa.id.protocols.saml1.SAML1RequestImpl"); IAuthData saml1authdata = (IAuthData) Class.forName("at.gv.egovernment.moa.id.protocols.saml1.SAML1AuthenticationData").newInstance(); - if (protocolRequest.getClass().isInstance(saml1Requst)) { - //request is SAML1 + if (saml1RequstTemplate != null && + saml1RequstTemplate.isInstance(protocolRequest)) { + //request is SAML1 --> invoke SAML1 protocol specific methods if (session.getExtendedSAMLAttributesOA() == null) { saml1authdata.getClass().getMethod("setExtendedSAMLAttributesOA", List.class).invoke(saml1authdata, new ArrayList<ExtendedSAMLAttribute>()); @@ -156,15 +153,14 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { authdata = new AuthenticationData(); } - - + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | java.lang.SecurityException ex) { authdata = new AuthenticationData(); } - //reuse some parameters if it is a reauthentication - OASessionStore activeOA = AuthenticationSessionStoreage.searchActiveOASSOSession(session, oaID, protocolRequest.requestedModule()); + //reuse some parameters if it is a Service-Provider reauthentication + OASessionStore activeOA = authenticatedSessionStorage.searchActiveOASSOSession(session, protocolRequest.getOAURL(), protocolRequest.requestedModule()); if (activeOA != null) { authdata.setSessionIndex(activeOA.getAssertionSessionID()); authdata.setNameID(activeOA.getUserNameID()); @@ -184,36 +180,38 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { } } } - - InterfederationSessionStore interfIDP = AuthenticationSessionStoreage.searchInterfederatedIDPFORAttributeQueryWithSessionID(session); + + //search federated IDP information in MOASession + InterfederationSessionStore interfIDP = authenticatedSessionStorage.searchInterfederatedIDPFORAttributeQueryWithSessionID(session); IOAAuthParameters oaParam = null; if (reqAttributes == null) { //get OnlineApplication from MOA-ID-Auth configuration - oaParam = AuthConfigurationProviderFactory.getInstance() - .getOnlineApplicationParameter(oaID); + oaParam = protocolRequest.getOnlineApplicationConfiguration(); - //build OA dynamically from STROK request if this OA is used as STORK<->PVP gateway + //build OA dynamically from STROK request if this OA is used as STORK<->PVP gateway if (oaParam.isSTORKPVPGateway()) oaParam = DynamicOAAuthParameterBuilder.buildFromAuthnRequest(oaParam, protocolRequest); } else { - //build OnlineApplication dynamic from requested attributes + //build OnlineApplication dynamic from requested attributes (AttributeQuerry Request) oaParam = DynamicOAAuthParameterBuilder.buildFromAttributeQuery(reqAttributes, interfIDP); } - if (interfIDP != null ) { - //IDP is a chained interfederated IDP and Authentication is requested + if (interfIDP != null ) { + //authentication by using a federated IDP if (oaParam.isInderfederationIDP() && protocolRequest instanceof PVPTargetConfiguration && !(((PVPTargetConfiguration)protocolRequest).getRequest() instanceof AttributeQuery)) { + //IDP is a chained interfederated IDP and Authentication is requested + //only set minimal response attributes authdata.setQAALevel(interfIDP.getQAALevel()); authdata.setBPK(interfIDP.getUserNameID()); } else { //get attributes from interfederated IDP - OAAuthParameter idp = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(interfIDP.getIdpurlprefix()); + OAAuthParameter idp = authConfig.getOnlineApplicationParameter(interfIDP.getIdpurlprefix()); getAuthDataFromInterfederation(authdata, session, oaParam, protocolRequest, interfIDP, idp, reqAttributes); //mark attribute request as used @@ -246,7 +244,7 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { * @throws BuildException * @throws DynamicOABuildException */ - public static IAuthData buildAuthenticationData(IRequest req, + public IAuthData buildAuthenticationData(IRequest req, AuthenticationSession session) throws WrongParametersException, ConfigurationException, BuildException, DynamicOABuildException { return buildAuthenticationData(req, session, null); } @@ -261,7 +259,7 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { * @param reqQueryAttr * @throws ConfigurationException */ - private static void getAuthDataFromInterfederation( + private void getAuthDataFromInterfederation( AuthenticationData authdata, AuthenticationSession session, IOAAuthParameters oaParam, IRequest req, InterfederationSessionStore interfIDP, OAAuthParameter idp, List<Attribute> reqQueryAttr) throws BuildException, ConfigurationException{ @@ -278,14 +276,19 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { //IDP is a service provider IDP and request interfederated IDP to collect attributes } else { //get PVP 2.1 attributes from protocol specific requested attributes - attributs = req.getRequestedAttributes(); + attributs = (List<Attribute>) req.getGenericData(RequestImpl.DATAID_REQUESTED_ATTRIBUTES); } - Response intfResp = (Response) req.getInterfederationResponse().getResponse(); - AssertionAttributeExtractor extractor = - new AssertionAttributeExtractor(intfResp); - + //get SAML2 Response from federated IDP + Response intfResp = + (Response) req.getGenericData( + RequestImpl.DATAID_INTERFEDERATIOIDP_RESPONSE, MOAResponse.class).getResponse(); + + //initialize Attribute extractor + AssertionAttributeExtractor extractor = new AssertionAttributeExtractor(intfResp); + + //check if SAML2 Assertion contains already all required attributes if (!extractor.containsAllRequiredAttributes()) { Logger.info("Received assertion does no contain a minimum set of attributes. Starting AttributeQuery process ..."); //collect attributes by using BackChannel communication @@ -297,7 +300,7 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { //build attributQuery request AttributeQuery query = - AttributQueryBuilder.buildAttributQueryRequest(interfIDP.getUserNameID(), endpoint, attributs); + attributQueryBuilder.buildAttributQueryRequest(interfIDP.getUserNameID(), endpoint, attributs); //build SOAP request List<XMLObject> xmlObjects = MOASAMLSOAPClient.send(endpoint, query); @@ -313,10 +316,10 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { //validate PVP 2.1 response try { - SAMLVerificationEngine engine = new SAMLVerificationEngine(); - engine.verifyResponse(intfResp, TrustEngineFactory.getSignatureKnownKeysTrustEngine()); + samlVerificationEngine.verifyIDPResponse(intfResp, TrustEngineFactory.getSignatureKnownKeysTrustEngine()); - SAMLVerificationEngine.validateAssertion(intfResp, false); + //TODO: find better solution + //SAMLVerificationEngine.validateAssertion(intfResp, false); } catch (Exception e) { Logger.warn("PVP 2.1 assertion validation FAILED.", e); @@ -360,7 +363,7 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { } } - private static void buildAuthDataFormInterfederationResponse( + private void buildAuthDataFormInterfederationResponse( AuthenticationData authData, AuthenticationSession session, AssertionAttributeExtractor extractor, @@ -498,7 +501,7 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { if (MiscUtil.isEmpty(authData.getIdentificationValue())) { Logger.info("No baseID found. Connect SZR to reveive baseID ..."); try { - EgovUtilPropertiesConfiguration eGovClientsConfig = AuthConfigurationProviderFactory.getInstance().geteGovUtilsConfig(); + EgovUtilPropertiesConfiguration eGovClientsConfig = authConfig.geteGovUtilsConfig(); if (eGovClientsConfig != null) { SZRClient szrclient = new SZRClient(eGovClientsConfig); @@ -532,11 +535,6 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { } - } catch (ConfigurationException e) { - Logger.warn("SZR connection FAILED. Interfederation SSO login not possible.", e); - throw new AssertionAttributeExtractorExeption("No " + PVPConstants.BPK_FRIENDLY_NAME - + " or " + PVPConstants.EID_SOURCE_PIN_NAME); - } catch (EgovUtilException e) { Logger.warn("SZR connection FAILED. Interfederation SSO login not possible.", e); throw new AssertionAttributeExtractorExeption("No " + PVPConstants.BPK_FRIENDLY_NAME @@ -841,7 +839,7 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { * @param authData * @return */ - private static boolean matchsReceivedbPKToOnlineApplication( + private boolean matchsReceivedbPKToOnlineApplication( IOAAuthParameters oaParam, AuthenticationData authData) { String oaTarget = null; @@ -868,14 +866,14 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { return false; } - private static void buildAuthDataFormMOASession(AuthenticationData authData, AuthenticationSession session, + private void buildAuthDataFormMOASession(AuthenticationData authData, AuthenticationSession session, IOAAuthParameters oaParam, IRequest protocolRequest) throws BuildException, ConfigurationException { IdentityLink identityLink = session.getIdentityLink(); VerifyXMLSignatureResponse verifyXMLSigResp = session.getXMLVerifySignatureResponse(); - authData.setIssuer(session.getAuthURL()); + authData.setIssuer(protocolRequest.getAuthURL()); //baseID or wbpk in case of BusinessService without SSO or BusinessService SSO authData.setIdentificationValue(identityLink.getIdentificationValue()); @@ -962,11 +960,11 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { } try { - authData.setSsoSession(AuthenticationSessionStoreage.isSSOSession(session.getSessionID())); + authData.setSsoSession(protocolRequest.needSingleSignOnFunctionality()); //set max. SSO session time if (authData.isSsoSession()) { - long maxSSOSessionTime = AuthConfigurationProviderFactory.getInstance().getSSOCreatedTimeOut() * 1000; + long maxSSOSessionTime = authConfig.getSSOCreatedTimeOut() * 1000; Date ssoSessionValidTo = new Date(session.getSessionCreated().getTime() + maxSSOSessionTime); authData.setSsoSessionValidTo(ssoSessionValidTo); @@ -1014,7 +1012,7 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { } - private static void buildOAspecificIdentityLink(IOAAuthParameters oaParam, AuthenticationData authData, IdentityLink idl) throws MOAIDException { + private void buildOAspecificIdentityLink(IOAAuthParameters oaParam, AuthenticationData authData, IdentityLink idl) throws MOAIDException { if (oaParam.getBusinessService()) { Element idlassertion = idl.getSamlAssertion(); //set bpk/wpbk; @@ -1031,9 +1029,8 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { IdentityLinkReSigner identitylinkresigner = IdentityLinkReSigner.getInstance(); Element resignedilAssertion; - AuthConfiguration config = AuthConfigurationProviderFactory.getInstance(); - if (config.isIdentityLinkResigning()) { - resignedilAssertion = identitylinkresigner.resignIdentityLink(businessServiceIdl.getSamlAssertion(), config.getIdentityLinkResigningKey()); + if (authConfig.isIdentityLinkResigning()) { + resignedilAssertion = identitylinkresigner.resignIdentityLink(businessServiceIdl.getSamlAssertion(), authConfig.getIdentityLinkResigningKey()); } else { resignedilAssertion = businessServiceIdl.getSamlAssertion(); } @@ -1048,7 +1045,7 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { } - private static void buildOAspecificbPK(IRequest protocolRequest, IOAAuthParameters oaParam, AuthenticationData authData, String baseID, String baseIDType) throws BuildException { + private void buildOAspecificbPK(IRequest protocolRequest, IOAAuthParameters oaParam, AuthenticationData authData, String baseID, String baseIDType) throws BuildException { if (oaParam.getBusinessService()) { //since we have foreigner, wbPK is not calculated in BKU @@ -1080,8 +1077,9 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { } if (saml1Requst != null && protocolRequest.getClass().isInstance(saml1Requst)) - target = protocolRequest.getTarget(); - else + target = protocolRequest.getGenericData( + MOAIDAuthConstants.AUTHPROCESS_DATA_TARGET, String.class); + else target = oaParam.getTarget(); String bpkBase64 = new BPKBuilder().buildBPK(baseID, target); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/CreateXMLSignatureRequestBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/CreateXMLSignatureRequestBuilder.java index bbbfacbd1..e763c5355 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/CreateXMLSignatureRequestBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/CreateXMLSignatureRequestBuilder.java @@ -50,9 +50,10 @@ import java.text.MessageFormat; import java.util.Calendar; import java.util.List; -import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; +import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; import at.gv.egovernment.moa.id.config.TargetToSectorNameMapper; -import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; +import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.util.Constants; import at.gv.egovernment.moa.util.DateTimeUtils; import at.gv.egovernment.moa.util.StringUtils; @@ -156,7 +157,7 @@ public class CreateXMLSignatureRequestBuilder implements Constants { * @param session current session * @return String representation of <code><CreateXMLSignatureRequest></code> */ - public String buildForeignID(String subject, OAAuthParameter oaParam, AuthenticationSession session) { + public String buildForeignID(String subject, IRequest pendingReq) { String request = ""; request += "<sl:CreateXMLSignatureRequest xmlns:sl=\"http://www.buergerkarte.at/namespaces/securitylayer/1.2#\">"; @@ -165,7 +166,7 @@ public class CreateXMLSignatureRequestBuilder implements Constants { request += "<sl:DataObject>"; request += "<sl:XMLContent>"; - request += buildForeignIDTextToBeSigned(subject, oaParam, session); + request += buildForeignIDTextToBeSigned(subject,pendingReq); request += "</sl:XMLContent>"; request += "</sl:DataObject>"; @@ -180,9 +181,10 @@ public class CreateXMLSignatureRequestBuilder implements Constants { return request; } - public static String buildForeignIDTextToBeSigned(String subject, OAAuthParameter oaParam, AuthenticationSession session) { - - String target = session.getTarget(); + public static String buildForeignIDTextToBeSigned(String subject, IRequest pendingReq) { + IOAAuthParameters oaParam = pendingReq.getOnlineApplicationConfiguration(); + String target = pendingReq.getGenericData( + MOAIDAuthConstants.AUTHPROCESS_DATA_TARGET, String.class); String sectorName = TargetToSectorNameMapper.getSectorNameViaTarget(target); Calendar cal = Calendar.getInstance(); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/DataURLBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/DataURLBuilder.java index 899b0fd15..9a2baf873 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/DataURLBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/DataURLBuilder.java @@ -47,7 +47,6 @@ package at.gv.egovernment.moa.id.auth.builder; import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; -import at.gv.egovernment.moa.id.auth.servlet.AuthServlet; /** * Builds a DataURL parameter meant for the security layer implementation @@ -76,28 +75,13 @@ public class DataURLBuilder { * @return String */ public String buildDataURL(String authBaseURL, String authServletName, String sessionID) { - -// String individualDataURLPrefix = null; - String dataURL; - - //is removed from config in MOA-ID 2.0 - //check if an individual prefix is configured -// individualDataURLPrefix = AuthConfigurationProvider.getInstance(). -// getGenericConfigurationParameter(AuthConfigurationProvider.INDIVIDUAL_DATA_URL_PREFIX); -// -// if (null != individualDataURLPrefix) { -// -// //check individualDataURLPrefix -// if(!individualDataURLPrefix.startsWith("http")) -// throw(new ConfigurationException("config.13", new Object[] { individualDataURLPrefix})); -// -// //when ok then use it -// dataURL = individualDataURLPrefix + authServletName; -// } else + String dataURL; + if (!authBaseURL.endsWith("/")) + authBaseURL += "/"; dataURL = authBaseURL + authServletName; - dataURL = addParameter(dataURL, MOAIDAuthConstants.PARAM_SESSIONID, sessionID); + dataURL = addParameter(dataURL, MOAIDAuthConstants.PARAM_TARGET_PENDINGREQUESTID, sessionID); return dataURL; } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/LoginFormBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/LoginFormBuilder.java index 99ba49d26..c22432d0d 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/LoginFormBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/LoginFormBuilder.java @@ -36,7 +36,6 @@ import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; import at.gv.egovernment.moa.id.config.ConfigurationException; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; -import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; import at.gv.egovernment.moa.id.config.stork.CPEPS; import at.gv.egovernment.moa.id.util.FormBuildUtils; import at.gv.egovernment.moa.logging.Logger; @@ -119,7 +118,7 @@ public class LoginFormBuilder { return template; } - public static String buildLoginForm(String modul, String action, OAAuthParameter oaParam, String contextpath, String moaSessionID) { + public static String buildLoginForm(String modul, String action, IOAAuthParameters oaParam, String contextpath, String moaSessionID) { String value = null; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/SendAssertionFormBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/SendAssertionFormBuilder.java index 02aaac8cb..7121935b0 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/SendAssertionFormBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/SendAssertionFormBuilder.java @@ -34,7 +34,8 @@ import java.net.URI; import org.apache.commons.io.IOUtils; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; -import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; +import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.id.util.FormBuildUtils; import at.gv.egovernment.moa.logging.Logger; @@ -46,8 +47,6 @@ public class SendAssertionFormBuilder { private static final String TEMPLATEBGCOLOR = "style=\"background-color: #COLOR#\""; private static String URL = "#URL#"; - private static String MODUL = "#MODUL#"; - private static String ACTION = "#ACTION#"; private static String ID = "#ID#"; private static String OANAME = "#OAName#"; private static String CONTEXTPATH = "#CONTEXTPATH#"; @@ -56,8 +55,7 @@ public class SendAssertionFormBuilder { private static String SERVLET = CONTEXTPATH+"/SSOSendAssertionServlet"; - private static String getTemplate() { - + private static String getTemplate() { String pathLocation; InputStream input = null; try { @@ -68,12 +66,9 @@ public class SendAssertionFormBuilder { File file = new File(new URI(pathLocation)); input = new FileInputStream(file); - } catch (FileNotFoundException e) { - - Logger.warn("No LoginFormTempaltes found. Use Generic Templates from package."); - - pathLocation = "resources/templates/" + HTMLTEMPLATEFULL; - + } catch (FileNotFoundException e) { + Logger.warn("No LoginFormTempaltes found. Use Generic Templates from package."); + pathLocation = "resources/templates/" + HTMLTEMPLATEFULL; input = Thread.currentThread() .getContextClassLoader() .getResourceAsStream(pathLocation); @@ -82,48 +77,43 @@ public class SendAssertionFormBuilder { return getTemplate(input); - } catch (Exception e) { + } catch (Exception e) { + return null; + + } finally { try { - input.close(); + if (input != null) + input.close(); - } catch (IOException e1) { + } catch (IOException e) { Logger.warn("SendAssertionTemplate inputstream can not be closed.", e); + } - - return null; - } - + } } private static String getTemplate(InputStream input) { + String template = null; + try { - String template = null; - - try { - - StringWriter writer = new StringWriter(); - IOUtils.copy(input, writer); - template = writer.toString(); - template = template.replace(URL, SERVLET); - - } catch (Exception e) { - Logger.error("Failed to read template", e); - - } finally { - try { - input.close(); - - } catch (IOException e) { - Logger.warn("SendAssertionTemplate inputstream can not be closed.", e); - } - } + StringWriter writer = new StringWriter(); + IOUtils.copy(input, writer); + template = writer.toString(); + template = template.replace(URL, SERVLET); + + } catch (Exception e) { + Logger.error("Failed to read template", e); + } return template; } - public static String buildForm(String modul, String action, String id, OAAuthParameter oaParam, String contextpath) { + public static String buildForm(IRequest pendingReq) { String value = null; + String contextpath = pendingReq.getAuthURL(); + IOAAuthParameters oaParam = pendingReq.getOnlineApplicationConfiguration(); + byte[] oatemplate = oaParam.getSendAssertionTemplate(); // OA specific template requires a size of 8 bits minimum if (oatemplate != null && oatemplate.length > 7) { @@ -137,16 +127,11 @@ public class SendAssertionFormBuilder { } if(value != null) { -// if(modul == null) { -// modul = SAML1Protocol.PATH; -// } -// if(action == null) { -// action = SAML1Protocol.GETARTIFACT; -// } - value = value.replace(MODUL, modul); - value = value.replace(ACTION, action); - value = value.replace(ID, id); + value = value.replace(ID, pendingReq.getRequestID()); value = value.replace(OANAME, oaParam.getFriendlyName()); + + if (contextpath.endsWith("/")) + contextpath = contextpath.substring(0, contextpath.length() - 1); value = value.replace(CONTEXTPATH, contextpath); value = FormBuildUtils.customiceLayoutBKUSelection(value, diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java index ae3ec9a9b..196415ddc 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java @@ -36,8 +36,6 @@ package at.gv.egovernment.moa.id.auth.data; -import iaik.x509.X509Certificate; - import java.io.Serializable; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; @@ -53,6 +51,7 @@ import at.gv.egovernment.moa.id.data.MISMandate; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.Constants; import at.gv.egovernment.moa.util.MiscUtil; +import iaik.x509.X509Certificate; /** * Session data to be stored between <code>AuthenticationServer</code> API calls. @@ -76,53 +75,12 @@ public class AuthenticationSession implements Serializable { private String sessionID; private Date sessionCreated = null; - - /** - * "Geschäftsbereich" the online application belongs to; maybe <code>null</code> if the - * online application is a business application - */ - private String target; - /** - * Friendly name for the target, if target is configured via MOA-ID configuration - */ - private String targetFriendlyName; - - /** - * SourceID - */ - private String sourceID; - - /** - * public online application URL requested - */ - private String oaURLRequested; - /** - * public online application URL prefix - */ - private String oaPublicURLPrefix; - /** - * URL of MOA ID authentication component - */ - private String authURL; - /** - * HTML template URL - */ - private String templateURL; - + /** * URL of the BKU */ private String bkuURL; - /** - * Indicates whether the corresponding online application is a business service or not - */ - private boolean businessService; - - /** - * Indicates whether the corresponding online application is a stork service or not - */ - private boolean storkService; // Store Mandate /** @@ -133,11 +91,6 @@ public class AuthenticationSession implements Serializable { private boolean isOW = false; /** - * STORK - */ - private String ccc; - - /** * * Mandate element */ @@ -159,12 +112,6 @@ public class AuthenticationSession implements Serializable { */ private IdentityLink identityLink; - // /** - // * timestamp logging when identity link has been received - // */ - // private Date timestampIdentityLink; - - // store Authblock /** * authentication block to be signed by the user */ @@ -177,11 +124,9 @@ public class AuthenticationSession implements Serializable { */ private String issueInstant; - // Signer certificate /** * Signer certificate of the foreign citizen or for mandate mode */ - // private X509Certificate signerCertificate; private byte[] signerCertificate; /** @@ -201,35 +146,8 @@ public class AuthenticationSession implements Serializable { * the AUTHBlock. */ private List<ExtendedSAMLAttribute> extendedSAMLAttributesAUTH; - -// /** -// * If infobox validators are needed after signing, they can be stored in this list. -// */ -// private List infoboxValidators; - - /** - * The register and number in the register parameter in case of a business service application. - */ - private String domainIdentifier; - - /** - * This string contains all identifiers of infoboxes, the online application is configured to - * accept. The infobox identifiers are comma separated. - */ - private String pushInfobox; - - // private AuthenticationData authData; - - // protocol selection - private String action; - private String modul; - - private String processInstanceId; - + private boolean authenticated; - private boolean authenticatedUsed = false; - - private boolean ssoRequested = false; private String QAALevel = null; @@ -238,39 +156,8 @@ public class AuthenticationSession implements Serializable { private boolean isForeigner; private Map<String, Object> genericSessionDataStorate = new HashedMap<String, Object>(); - - public String getModul() { - return modul; - } - - public void setModul(String modul) { - this.modul = modul; - } - - public String getAction() { - return action; - } - - public void setAction(String action) { - this.action = action; - } - - public boolean isAuthenticatedUsed() { - return authenticatedUsed; - } - - public void setAuthenticatedUsed(boolean authenticatedUsed) { - this.authenticatedUsed = authenticatedUsed; - } - - public boolean isAuthenticated() { - return authenticated; - } - - public void setAuthenticated(boolean authenticated) { - this.authenticated = authenticated; - } - + + /** * Constructor for AuthenticationSession. * @@ -283,6 +170,14 @@ public class AuthenticationSession implements Serializable { } + public boolean isAuthenticated() { + return authenticated; + } + + public void setAuthenticated(boolean authenticated) { + this.authenticated = authenticated; + } + public X509Certificate getSignerCertificate() { try { return new X509Certificate(signerCertificate); @@ -345,24 +240,6 @@ public class AuthenticationSession implements Serializable { } /** - * Returns the oaURLRequested. - * - * @return String - */ - public String getOAURLRequested() { - return oaURLRequested; - } - - /** - * Returns the oaURLRequested. - * - * @return String - */ - public String getPublicOAURLPrefix() { - return oaPublicURLPrefix; - } - - /** * Returns the BKU URL. * * @return String @@ -370,54 +247,7 @@ public class AuthenticationSession implements Serializable { public String getBkuURL() { return bkuURL; } - - /** - * Returns the target. - * - * @return String - */ - public String getTarget() { - return target; - } - - /** - * Returns the sourceID. - * - * @return String - */ - public String getSourceID() { - return sourceID; - } - - /** - * Returns the target friendly name. - * - * @return String - */ - public String getTargetFriendlyName() { - return targetFriendlyName; - } - - /** - * Sets the oaURLRequested. - * - * @param oaURLRequested - * The oaURLRequested to set - */ - public void setOAURLRequested(String oaURLRequested) { - this.oaURLRequested = oaURLRequested; - } - - /** - * Sets the oaPublicURLPrefix - * - * @param oaPublicURLPrefix - * The oaPublicURLPrefix to set - */ - public void setPublicOAURLPrefix(String oaPublicURLPrefix) { - this.oaPublicURLPrefix = oaPublicURLPrefix; - } - + /** * Sets the bkuURL * @@ -427,63 +257,7 @@ public class AuthenticationSession implements Serializable { public void setBkuURL(String bkuURL) { this.bkuURL = bkuURL; } - - /** - * Sets the target. If the target includes the target prefix, the prefix will be stripped off. - * - * @param target - * The target to set - */ - public void setTarget(String target) { - if (target != null && target.startsWith(TARGET_PREFIX_)) { - // If target starts with prefix "urn:publicid:gv.at:cdid+"; remove - // prefix - this.target = target.substring(TARGET_PREFIX_.length()); - Logger.debug("Target prefix stripped off; resulting target: " + this.target); - } else { - this.target = target; - } - } - - /** - * Sets the sourceID - * - * @param sourceID - * The sourceID to set - */ - public void setSourceID(String sourceID) { - this.sourceID = sourceID; - } - - /** - * Sets the target. If the target includes the target prefix, the prefix will be stripped off. - * - * @param target - * The target to set - */ - public void setTargetFriendlyName(String targetFriendlyName) { - this.targetFriendlyName = targetFriendlyName; - } - - /** - * Returns the authURL. - * - * @return String - */ - public String getAuthURL() { - return authURL; - } - - /** - * Sets the authURL. - * - * @param authURL - * The authURL to set - */ - public void setAuthURL(String authURL) { - this.authURL = authURL; - } - + /** * Returns the authBlock. * @@ -503,61 +277,6 @@ public class AuthenticationSession implements Serializable { this.authBlock = authBlock; } - /** - * Returns the businessService. - * - * @return <code>true</code> if the corresponding online application is a business application, - * otherwise <code>false</code> - */ - public boolean getBusinessService() { - return businessService; - } - - /** - * Sets the businessService variable. - * - * @param businessService - * the value for setting the businessService variable. - */ - public void setBusinessService(boolean businessService) { - this.businessService = businessService; - } - - - /** - * Returns the storkService. - * - * @return <code>true</code> if the corresponding online application is a stork application, - * otherwise <code>false</code> - */ - public boolean getStorkService() { - return storkService; - } - - /** - * Sets the storkService variable. - * - * @param storkService - * the value for setting the storkService variable. - */ - public void setStorkService(boolean storkService) { - this.storkService = storkService; - } - - /** - * @return template URL - */ - public String getTemplateURL() { - return templateURL; - } - - /** - * @param string - * the template URL - */ - public void setTemplateURL(String string) { - templateURL = string; - } /** * Returns the SAML Attributes to be appended to the AUTHBlock. Maybe <code>null</code>. @@ -644,54 +363,6 @@ public class AuthenticationSession implements Serializable { public void setIssueInstant(String issueInstant) { this.issueInstant = issueInstant; } - - /** - * Returns domain identifier (the register and number in the register parameter). - * <code>null</code> in the case of not a business service. - * - * @return the domainIdentifier - */ - public String getDomainIdentifier() { - return domainIdentifier; - } - - /** - * Sets the register and number in the register parameter if the application is a business - * service. If the domain identifier includes the registerAndOrdNr prefix, the prefix will be - * stripped off. - * - * @param domainIdentifier - * the domain identifier to set - */ - public void setDomainIdentifier(String domainIdentifier) { - if (domainIdentifier != null && domainIdentifier.startsWith(REGISTERANDORDNR_PREFIX_)) { - // If domainIdentifier starts with prefix - // "urn:publicid:gv.at:wbpk+"; remove this prefix - this.domainIdentifier = domainIdentifier.substring(REGISTERANDORDNR_PREFIX_.length()); - Logger.debug("Register and ordernumber prefix stripped off; resulting register string: " + this.domainIdentifier); - } else { - this.domainIdentifier = domainIdentifier; - } - } - - /** - * Gets all identifiers of infoboxes, the online application is configured to accept. The - * infobox identifiers are comma separated. - * - * @return the string containing infobox identifiers - */ - public String getPushInfobox() { - if (pushInfobox == null) return ""; - return pushInfobox; - } - - /** - * @param pushInfobox - * the infobox identifiers to set (comma separated) - */ - public void setPushInfobox(String pushInfobox) { - this.pushInfobox = pushInfobox; - } /** * @@ -747,15 +418,7 @@ public class AuthenticationSession implements Serializable { public void setMandateReferenceValue(String mandateReferenceValue) { this.mandateReferenceValue = mandateReferenceValue; } - - public String getCcc() { - return ccc; - } - - public void setCcc(String ccc) { - this.ccc = ccc; - } - + public boolean isForeigner() { return isForeigner; } @@ -779,24 +442,7 @@ public class AuthenticationSession implements Serializable { public void setMISMandate(MISMandate mandate) { this.mandate = mandate; } - - /** - * @return the ssoRequested - */ - - // TODO: SSO only allowed without mandates, actually!!!!!! - public boolean isSsoRequested() { - return ssoRequested && !useMandate; - } - - /** - * @param ssoRequested - * the ssoRequested to set - */ - public void setSsoRequested(boolean ssoRequested) { - this.ssoRequested = ssoRequested; - } - + /** * @return the isOW */ @@ -852,22 +498,6 @@ public class AuthenticationSession implements Serializable { return sessionCreated; } - /** - * Returns the identifier of the process instance associated with this moaid session. - * @return The process instance id (may be {@code null} if no process has been created yet). - */ - public String getProcessInstanceId() { - return processInstanceId; - } - - /** - * Sets the process instance identifier in order to associate a certain process instance with this moaid session. - * @param processInstanceId The process instance id. - */ - public void setProcessInstanceId(String processInstanceId) { - this.processInstanceId = processInstanceId; - } - public Map<String, Object> getGenericSessionDataStorage() { return genericSessionDataStorate; } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/exception/MOAIDException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/exception/MOAIDException.java index 165fee599..ef6aaa75c 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/exception/MOAIDException.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/exception/MOAIDException.java @@ -79,6 +79,8 @@ public class MOAIDException extends Exception { /** wrapped exception */ private Throwable wrapped; + private Object[] parameters; + /** * Create a new <code>MOAIDException</code>. * @@ -89,6 +91,7 @@ public class MOAIDException extends Exception { public MOAIDException(String messageId, Object[] parameters) { super(MOAIDMessageProvider.getInstance().getMessage(messageId, parameters)); this.messageId = messageId; + this.parameters = parameters; } /** @@ -108,6 +111,7 @@ public class MOAIDException extends Exception { super(MOAIDMessageProvider.getInstance().getMessage(messageId, parameters)); this.messageId = messageId; this.wrapped = wrapped; + this.parameters = parameters; } /** @@ -163,7 +167,16 @@ public class MOAIDException extends Exception { return wrapped; } + + /** + * @return the parameters + */ +public Object[] getParameters() { + return parameters; +} + +/** * Convert this <code>MOAIDException</code> to an <code>ErrorResponse</code> * element from the MOA namespace. * diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AbstractAuthServletTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AbstractAuthServletTask.java index 67ddd170a..8c7583855 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AbstractAuthServletTask.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AbstractAuthServletTask.java @@ -1,20 +1,14 @@ package at.gv.egovernment.moa.id.auth.modules;
-import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
-
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -24,18 +18,20 @@ import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang3.ArrayUtils;
+import org.springframework.beans.factory.annotation.Autowired;
-import at.gv.egovernment.moa.id.advancedlogging.StatisticLogger;
-import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
+import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger;
+import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
-import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
-import at.gv.egovernment.moa.id.auth.servlet.AuthServlet;
-import at.gv.egovernment.moa.id.config.ConfigurationException;
-import at.gv.egovernment.moa.id.entrypoints.DispatcherServlet;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.config.auth.AuthConfiguration;
+import at.gv.egovernment.moa.id.moduls.IRequest;
+import at.gv.egovernment.moa.id.moduls.IRequestStorage;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
import at.gv.egovernment.moa.id.process.springweb.MoaIdTask;
-import at.gv.egovernment.moa.id.storage.DBExceptionStoreImpl;
-import at.gv.egovernment.moa.id.storage.IExceptionStore;
-import at.gv.egovernment.moa.id.util.ServletUtils;
+import at.gv.egovernment.moa.id.protocols.AbstractAuthProtocolModulController;
+import at.gv.egovernment.moa.id.storage.IAuthenticationSessionStoreage;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.MiscUtil;
@@ -45,159 +41,84 @@ import at.gv.egovernment.moa.util.MiscUtil; */
public abstract class AbstractAuthServletTask extends MoaIdTask {
+ @Autowired protected IRequestStorage requestStoreage;
+ @Autowired protected IAuthenticationSessionStoreage authenticatedSessionStorage;
+ @Autowired protected MOAReversionLogger revisionsLogger;
+ @Autowired protected AuthConfiguration authConfig;
+
protected static final String ERROR_CODE_PARAM = "errorid";
- protected void handleErrorNoRedirect(String errorMessage, Throwable exceptionThrown,
- HttpServletRequest req, HttpServletResponse resp) {
-
- if (null != errorMessage) {
- Logger.error(errorMessage);
- req.setAttribute("ErrorMessage", errorMessage);
- }
-
- if (null != exceptionThrown) {
- if (null == errorMessage)
- errorMessage = exceptionThrown.getMessage();
- Logger.error(errorMessage, exceptionThrown);
- req.setAttribute("ExceptionThrown", exceptionThrown);
- }
-
- if (Logger.isDebugEnabled()) {
- req.setAttribute("LogLevel", "debug");
- }
-
-
- StatisticLogger logger = StatisticLogger.getInstance();
- logger.logErrorOperation(exceptionThrown);
+ protected IRequest pendingReq = null;
+ protected AuthenticationSession moasession = null;
+
+ public abstract void execute(ExecutionContext executionContext, HttpServletRequest request,
+ HttpServletResponse response) throws TaskExecutionException;
+
+
+ protected final IRequest internalExecute(IRequest pendingReq, ExecutionContext executionContext, HttpServletRequest request,
+ HttpServletResponse response) throws TaskExecutionException {
+ //set pending-request object
+ this.pendingReq = pendingReq;
+ //execute task specific action
+ execute(executionContext, request, response);
- // forward this to errorpage-auth.jsp where the HTML error page is
- // generated
- ServletContext context = req.getServletContext();
- RequestDispatcher dispatcher = context
- .getRequestDispatcher("/errorpage-auth.jsp");
- try {
-
- resp.setHeader(HEADER_EXPIRES, HEADER_VALUE_EXPIRES);
- resp.setHeader(HEADER_PRAGMA, HEADER_VALUE_PRAGMA);
- resp.setHeader(HEADER_CACHE_CONTROL, HEADER_VALUE_CACHE_CONTROL);
- resp.addHeader(HEADER_CACHE_CONTROL, HEADER_VALUE_CACHE_CONTROL_IE);
-
- dispatcher.forward(req, resp);
- } catch (ServletException e) {
- Logger.error(e);
- } catch (IOException e) {
- Logger.error(e);
- }
+ //return pending-request object
+ return this.pendingReq;
}
+
/**
- * Handles an error. <br>>
- * <ul>
- * <li>Logs the error</li>
- * <li>Places error message and exception thrown into the request as request
- * attributes (to be used by <code>"/errorpage-auth.jsp"</code>)</li>
- * <li>Sets HTTP status 500 (internal server error)</li>
- * </ul>
+ * Default initialization loads the MOASession object from database
*
- * @param errorMessage
- * error message
- * @param exceptionThrown
- * exception thrown
* @param req
- * servlet request
- * @param resp
- * servlet response
+ * @param executionContext
+ * @throws MOAIDException
+ * @throws MOADatabaseException
*/
- protected void handleError(String errorMessage, Throwable exceptionThrown,
- HttpServletRequest req, HttpServletResponse resp, String pendingRequestID) {
-
- if (null != errorMessage) {
- Logger.error(errorMessage);
- req.setAttribute("ErrorMessage", errorMessage);
- }
-
- if (null != exceptionThrown) {
- if (null == errorMessage)
- errorMessage = exceptionThrown.getMessage();
- Logger.error(errorMessage, exceptionThrown);
- req.setAttribute("ExceptionThrown", exceptionThrown);
- }
-
- if (Logger.isDebugEnabled()) {
- req.setAttribute("LogLevel", "debug");
- }
-
- if (!(exceptionThrown instanceof MOAIDException)) {
- Logger.error("Receive an internal error: Message=" + exceptionThrown.getMessage(), exceptionThrown);
-
+ protected void defaultTaskInitialization(HttpServletRequest req, ExecutionContext executionContext) throws MOAIDException, MOADatabaseException {
+ String moasessionid = pendingReq.getMOASessionIdentifier();
+ if (MiscUtil.isEmpty(moasessionid)) {
+ Logger.warn("MOASessionID is empty.");
+ throw new MOAIDException("auth.18", new Object[] {});
}
- IExceptionStore store = DBExceptionStoreImpl.getStore();
- String id = store.storeException(exceptionThrown);
-
- if (id != null && MiscUtil.isNotEmpty(pendingRequestID)) {
-
- String redirectURL = null;
-
- redirectURL = ServletUtils.getBaseUrl(req);
- redirectURL += "/dispatcher?" + ERROR_CODE_PARAM + "=" + id
- + "&" + DispatcherServlet.PARAM_TARGET_PENDINGREQUESTID + "=" + pendingRequestID;
-
- resp.setContentType("text/html");
- resp.setStatus(302);
-
- resp.addHeader("Location", redirectURL);
- Logger.debug("REDIRECT TO: " + redirectURL);
+ try {
+ moasession = authenticatedSessionStorage.getSession(moasessionid);
- return;
-
- } else {
+ if (moasession == null) {
+ Logger.warn("MOASessionID is empty.");
+ throw new MOAIDException("auth.18", new Object[] {});
+ }
- //Exception can not be stored in database
- handleErrorNoRedirect(errorMessage, exceptionThrown, req, resp);
- }
- }
-
- /**
- * Handles a <code>WrongParametersException</code>.
- *
- * @param req
- * servlet request
- * @param resp
- * servlet response
- */
- protected void handleWrongParameters(WrongParametersException ex,
- HttpServletRequest req, HttpServletResponse resp) {
- Logger.error(ex.toString());
- req.setAttribute("WrongParameters", ex.getMessage());
+ } catch (MOADatabaseException e) {
+ Logger.info("MOASession with SessionID=" + moasessionid + " is not found in Database");
+ throw new MOAIDException("init.04", new Object[] { moasessionid });
- // forward this to errorpage-auth.jsp where the HTML error page is
- // generated
- ServletContext context = req.getServletContext();
- RequestDispatcher dispatcher = context
- .getRequestDispatcher("/errorpage-auth.jsp");
- try {
- setNoCachingHeaders(resp);
- dispatcher.forward(req, resp);
- } catch (ServletException e) {
- Logger.error(e);
- } catch (IOException e) {
- Logger.error(e);
+ } catch (Throwable e) {
+ Logger.info("No HTTP Session found!");
+ throw new MOAIDException("auth.18", new Object[] {});
}
+
}
/**
- * Logs all servlet parameters for debugging purposes.
+ * Redirect the authentication process to protocol specific finalization endpoint.
+ *
+ * @param pendingReq Actually processed protocol specific authentication request
+ * @param httpResp
*/
- protected void logParameters(HttpServletRequest req) {
- for (Enumeration params = req.getParameterNames(); params
- .hasMoreElements();) {
- String parname = (String) params.nextElement();
- Logger.debug("Parameter " + parname + req.getParameter(parname));
- }
+ protected void performRedirectToProtocolFinialization(IRequest pendingReq, HttpServletResponse httpResp) {
+ String redirectURL = new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(),
+ AbstractAuthProtocolModulController.FINALIZEPROTOCOL_ENDPOINT, pendingReq.getRequestID());
+
+ httpResp.setContentType("text/html");
+ httpResp.setStatus(302);
+ httpResp.addHeader("Location", redirectURL);
+ Logger.debug("REDIRECT TO: " + redirectURL);
+
}
-
+
/**
* Parses the request input stream for parameters, assuming parameters are
* encoded UTF-8 (no standard exists how browsers should encode them).
@@ -256,27 +177,7 @@ public abstract class AbstractAuthServletTask extends MoaIdTask { }
}
- else {
- // request is encoded as application/x-www-urlencoded
- // [tknall]: we must not consume request body input stream once servlet-api request parameters have been accessed
-
- /*
- InputStream in = req.getInputStream();
-
- String paramName;
- String paramValueURLEncoded;
- do {
- paramName = new String(readBytesUpTo(in, '='));
- if (paramName.length() > 0) {
- paramValueURLEncoded = readBytesUpTo(in, '&');
- String paramValue = URLDecoder.decode(paramValueURLEncoded,
- "UTF-8");
- parameters.put(paramName, paramValue);
- }
- } while (paramName.length() > 0);
- in.close();
- */
-
+ else {
Iterator<Entry<String, String[]>> requestParamIt = req.getParameterMap().entrySet().iterator();
while (requestParamIt.hasNext()) {
Entry<String, String[]> entry = requestParamIt.next();
@@ -316,19 +217,6 @@ public abstract class AbstractAuthServletTask extends MoaIdTask { }
/**
- * Sets response headers that prevent caching (code taken from {@link AuthServlet}).
- *
- * @param resp
- * The HttpServletResponse.
- */
- public void setNoCachingHeaders(HttpServletResponse resp) {
- resp.setHeader(HEADER_EXPIRES, HEADER_VALUE_EXPIRES);
- resp.setHeader(HEADER_PRAGMA, HEADER_VALUE_PRAGMA);
- resp.setHeader(HEADER_CACHE_CONTROL, HEADER_VALUE_CACHE_CONTROL);
- resp.addHeader(HEADER_CACHE_CONTROL, HEADER_VALUE_CACHE_CONTROL_IE);
- }
-
- /**
* Adds a parameter to a URL.
*
* @param url
@@ -347,32 +235,4 @@ public abstract class AbstractAuthServletTask extends MoaIdTask { else
return url + "&" + param;
}
-
- /**
- * Checks if HTTP requests are allowed
- *
- * @param authURL
- * requestURL
- * @throws AuthenticationException
- * if HTTP requests are not allowed
- * @throws ConfigurationException
- */
- protected void checkIfHTTPisAllowed(String authURL)
- throws AuthenticationException, ConfigurationException {
- // check if HTTP Connection may be allowed (through
- // FRONTEND_SERVLETS_ENABLE_HTTP_CONNECTION_PROPERTY)
-
- //Removed from MOA-ID 2.0 config
-// String boolStr = AuthConfigurationProvider
-// .getInstance()
-// .getGenericConfigurationParameter(
-// AuthConfigurationProvider.FRONTEND_SERVLETS_ENABLE_HTTP_CONNECTION_PROPERTY);
- if ((!authURL.startsWith("https:"))
- //&& (false == BoolUtils.valueOf(boolStr))
- )
- throw new AuthenticationException("auth.07", new Object[] { authURL
- + "*" });
-
- }
-
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/BKUSelectionModuleImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/BKUSelectionModuleImpl.java new file mode 100644 index 000000000..c96167e71 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/BKUSelectionModuleImpl.java @@ -0,0 +1,69 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.modules; + +import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; + +/** + * @author tlenz + * + */ +public class BKUSelectionModuleImpl implements AuthModule { + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getPriority() + */ + @Override + public int getPriority() { + return 0; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#selectProcess(at.gv.egovernment.moa.id.process.api.ExecutionContext) + */ + @Override + public String selectProcess(ExecutionContext context) { + boolean performBKUSelection = false; + Object performBKUSelectionObj = context.get(MOAIDAuthConstants.PROCESSCONTEXT_PERFORM_BKUSELECTION); + if (performBKUSelectionObj != null && performBKUSelectionObj instanceof Boolean) + performBKUSelection = (boolean) performBKUSelectionObj; + + if (performBKUSelection) + return "BKUSelectionProcess"; + + else + return null; + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getProcessDefinitions() + */ + @Override + public String[] getProcessDefinitions() { + return new String[] { "classpath:at/gv/egovernment/moa/id/auth/modules/internal/BKUSelection.process.xml" }; + + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/SingleSignOnConsentsModuleImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/SingleSignOnConsentsModuleImpl.java new file mode 100644 index 000000000..d64126de6 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/SingleSignOnConsentsModuleImpl.java @@ -0,0 +1,69 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.modules; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; + +/** + * @author tlenz + * + */ +public class SingleSignOnConsentsModuleImpl implements AuthModule { + + public static final String PARAM_SSO_CONSENTS_EVALUATION = "ssoconsentsevaluation"; + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getPriority() + */ + @Override + public int getPriority() { + return 0; + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#selectProcess(at.gv.egovernment.moa.id.process.api.ExecutionContext) + */ + @Override + public String selectProcess(ExecutionContext context) { + Object evaluationObj = context.get(PARAM_SSO_CONSENTS_EVALUATION); + if (evaluationObj != null && evaluationObj instanceof Boolean) { + boolean evaluateSSOConsents = (boolean) evaluationObj; + if (evaluateSSOConsents) { + return "SSOConsentsEvluationProcess"; + + } + } + + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getProcessDefinitions() + */ + @Override + public String[] getProcessDefinitions() { + return new String[] { "classpath:at/gv/egovernment/moa/id/auth/modules/internal/SingleSignOnConsentEvaluator.process.xml" }; + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/TaskExecutionException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/TaskExecutionException.java index 3e9f4cf14..932019d2c 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/TaskExecutionException.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/TaskExecutionException.java @@ -22,7 +22,9 @@ */ package at.gv.egovernment.moa.id.auth.modules; +import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.id.process.ProcessExecutionException; +import at.gv.egovernment.moa.util.MiscUtil; /** * @author tlenz @@ -32,14 +34,18 @@ public class TaskExecutionException extends ProcessExecutionException { private static final long serialVersionUID = 1L; Throwable originalException = null; + String pendingRequestID = null; /** * @param message * @param cause */ - public TaskExecutionException(String message, Throwable cause) { + public TaskExecutionException(IRequest pendingReq, String message, Throwable cause) { super(message, cause); - originalException = cause; + this.originalException = cause; + + if (MiscUtil.isNotEmpty(pendingReq.getRequestID())) + this.pendingRequestID = pendingReq.getRequestID(); } @@ -50,7 +56,19 @@ public class TaskExecutionException extends ProcessExecutionException { */ public Throwable getOriginalException() { return originalException; + } + + /** + * Get the pending-request ID of that request, which was processed when the exception occurs + * + * @return the pendingRequestID + */ + public String getPendingRequestID() { + return pendingRequestID; + } + + diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CreateInterfedeartionRequestTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CreateInterfedeartionRequestTask.java deleted file mode 100644 index 8429baf23..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CreateInterfedeartionRequestTask.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 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: - * http://www.osor.eu/eupl/ - * - * 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.egovernment.moa.id.auth.modules.internal.tasks; - -import java.lang.reflect.InvocationTargetException; -import java.security.NoSuchAlgorithmException; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.joda.time.DateTime; -import org.opensaml.common.impl.SecureRandomIdentifierGenerator; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.core.AuthnContextClassRef; -import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration; -import org.opensaml.saml2.core.AuthnRequest; -import org.opensaml.saml2.core.Issuer; -import org.opensaml.saml2.core.NameID; -import org.opensaml.saml2.core.NameIDPolicy; -import org.opensaml.saml2.core.NameIDType; -import org.opensaml.saml2.core.RequestedAuthnContext; -import org.opensaml.saml2.metadata.EntityDescriptor; -import org.opensaml.saml2.metadata.SingleSignOnService; -import org.opensaml.saml2.metadata.provider.MetadataProviderException; -import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.opensaml.xml.security.SecurityException; - -import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; -import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger; -import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; -import at.gv.egovernment.moa.id.auth.exception.MOAIDException; -import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; -import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; -import at.gv.egovernment.moa.id.config.ConfigurationException; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; -import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; -import at.gv.egovernment.moa.id.moduls.IRequest; -import at.gv.egovernment.moa.id.moduls.RequestStorage; -import at.gv.egovernment.moa.id.process.api.ExecutionContext; -import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; -import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder; -import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding; -import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding; -import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration; -import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.PVP2Exception; -import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider; -import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; -import at.gv.egovernment.moa.id.util.PVPtoSTORKMapper; -import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.MiscUtil; - -/** - * @author tlenz - * - */ -public class CreateInterfedeartionRequestTask extends AbstractAuthServletTask { - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) - */ - @Override - public void execute(ExecutionContext executionContext, - HttpServletRequest request, HttpServletResponse response) - throws TaskExecutionException { - boolean requiredLocalAuthentication = true; - - IRequest pendingReq = RequestStorage.getPendingRequest( - (String) executionContext.get("pendingRequestID")); - - String idpEntityID = - (String) executionContext.get(MOAIDAuthConstants.PROCESSCONTEXT_INTERFEDERATION_ENTITYID); - - if (MiscUtil.isEmpty(idpEntityID)) { - Logger.info("Interfederation not possible -> not inderfederation IDP EntityID found!"); - throw new TaskExecutionException("Interfederation not possible", new MOAIDException("No inderfederation-IDP EntityID found.", null)); - - } - - //TODO: create MOASession - //TODO: set relayState to MOASession - //TODO: add support for requested attributes (from context and from metadata) - - - try { - OAAuthParameter idp = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(idpEntityID); - OAAuthParameter sp = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(pendingReq.getOAURL()); - - if (!idp.isInderfederationIDP() || !idp.isInboundSSOInterfederationAllowed()) { - Logger.info("Requested interfederation IDP " + pendingReq.getRequestedIDP() + " is not valid for interfederation."); - Logger.debug("isInderfederationIDP:" + String.valueOf(idp.isInderfederationIDP()) - + " isInboundSSOAllowed:" + String.valueOf(idp.isInboundSSOInterfederationAllowed())); - Logger.info("Switch to local authentication on this IDP ... "); - - executionContext.put(MOAIDAuthConstants.PROCESSCONTEXT_REQUIRELOCALAUTHENTICATION, true); - return; - - } - - - - - EntityDescriptor idpEntity = MOAMetadataProvider.getInstance(). - getEntityDescriptor(idpEntityID); - - if (idpEntity != null ) { - - //fetch endpoint from IDP metadata - SingleSignOnService redirectEndpoint = null; - for (SingleSignOnService sss : - idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS).getSingleSignOnServices()) { - - // use POST binding as default if it exists - //TODO: maybe use RedirectBinding as default - if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { - redirectEndpoint = sss; - - } else if ( sss.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI) && - redirectEndpoint == null ) - redirectEndpoint = sss; - } - - if (redirectEndpoint != null) { - - AuthnRequest authReq = SAML2Utils - .createSAMLObject(AuthnRequest.class); - SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator(); - authReq.setID(gen.generateIdentifier()); - - //send passive AuthnRequest - authReq.setIsPassive(idp.isPassivRequestUsedForInterfederation()); - - authReq.setAssertionConsumerServiceIndex(0); - authReq.setIssueInstant(new DateTime()); - Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); - String serviceURL = PVPConfiguration.getInstance().getIDPPublicPath(); - issuer.setValue(serviceURL); - - issuer.setFormat(NameIDType.ENTITY); - authReq.setIssuer(issuer); - NameIDPolicy policy = SAML2Utils - .createSAMLObject(NameIDPolicy.class); - policy.setAllowCreate(true); - policy.setFormat(NameID.TRANSIENT); - authReq.setNameIDPolicy(policy); - - authReq.setDestination(redirectEndpoint.getLocation()); - - RequestedAuthnContext reqAuthContext = - SAML2Utils.createSAMLObject(RequestedAuthnContext.class); - - AuthnContextClassRef authnClassRef = - SAML2Utils.createSAMLObject(AuthnContextClassRef.class); - - //check if STORK protocol module is in ClassPath - Object storkRequst = null; - Integer storkSecClass = null; - try { - storkRequst = Class.forName("at.gv.egovernment.moa.id.protocols.stork2.MOASTORKRequest").newInstance(); - if (storkRequst != null && - pendingReq.getClass().isInstance(storkRequst)) { - Object storkAuthnRequest = pendingReq.getClass().getMethod("getStorkAuthnRequest", null).invoke(pendingReq, null); - storkSecClass = (Integer) storkAuthnRequest.getClass().getMethod("getQaa", null).invoke(storkAuthnRequest, null); - - } - - } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | java.lang.SecurityException ex) { - - - } - - - if (sp != null && sp.isSTORKPVPGateway()){ - //use PVP SecClass instead of STORK QAA level - String secClass = null; - if (storkRequst != null && - pendingReq.getClass().isInstance(storkRequst)) { - - try { - secClass = PVPtoSTORKMapper.getInstance().mapToSecClass( - PVPConstants.STORK_QAA_PREFIX + String.valueOf(storkSecClass)); - - } catch (Exception e) { - Logger.warn("STORK-QAA level can not read from STORK request. Use default QAA 4", e); - - } - } - - if (MiscUtil.isNotEmpty(secClass)) - authnClassRef.setAuthnContextClassRef(secClass); - else - authnClassRef.setAuthnContextClassRef("http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-3"); - - } else { - if (storkRequst != null && - pendingReq.getClass().isInstance(storkRequst)) { - //use requested QAA level from STORK request - try { - authnClassRef.setAuthnContextClassRef( - PVPConstants.STORK_QAA_PREFIX + String.valueOf(storkSecClass)); - Logger.debug("Use STORK-QAA level " + authnClassRef.getAuthnContextClassRef() - + " from STORK request"); - - } catch (Exception e) { - Logger.warn("STORK-QAA level can not read from STORK request. Use default QAA 4", e); - - } - - } - - if (MiscUtil.isEmpty(authnClassRef.getAuthnContextClassRef())) - authnClassRef.setAuthnContextClassRef("http://www.stork.gov.eu/1.0/citizenQAALevel/4"); - - } - - reqAuthContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM); - reqAuthContext.getAuthnContextClassRefs().add(authnClassRef); - authReq.setRequestedAuthnContext(reqAuthContext); - - IEncoder binding = null; - if (redirectEndpoint.getBinding().equals( - SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { - binding = new RedirectBinding(); - - } else if (redirectEndpoint.getBinding().equals( - SAMLConstants.SAML2_POST_BINDING_URI)) { - binding = new PostBinding(); - - } - - binding.encodeRequest(request, response, authReq, - redirectEndpoint.getLocation(), pendingReq.getRequestID()); - - //build and send request without an error - requiredLocalAuthentication = false; - - MOAReversionLogger.getInstance().logEvent(pendingReq.getOnlineApplicationConfiguration(), - pendingReq, MOAIDEventConstants.AUTHPROCESS_INTERFEDERATION_IDP, idpEntity.getEntityID()); - - - } else { - Logger.warn("Requested IDP " + pendingReq.getRequestedIDP() - + " does not support POST or Redirect Binding."); - - } - - } else { - Logger.warn("Requested IDP " + pendingReq.getRequestedIDP() - + " is not found in InterFederation configuration"); - - } - - } catch (MetadataProviderException e) { - Logger.error("IDP metadata error." , e); - - } catch (NoSuchAlgorithmException e) { - Logger.error("Build IDP authentication request FAILED.", e); - - } catch (MessageEncodingException e) { - Logger.error("Build IDP authentication request FAILED.", e); - - } catch (SecurityException e) { - Logger.error("Build IDP authentication request FAILED.", e); - - } catch (PVP2Exception e) { - Logger.error("Build IDP authentication request FAILED.", e); - - } catch (ConfigurationException e1) { - Logger.error("Build IDP authentication request FAILED.", e1); - - } - - //set flag for next step - executionContext.put(MOAIDAuthConstants.PROCESSCONTEXT_REQUIRELOCALAUTHENTICATION, - requiredLocalAuthentication); - - } - -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/ReceiveInterfederationResponseTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/EvaluateBKUSelectionTask.java index f05ff07e9..bd8dd709f 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/ReceiveInterfederationResponseTask.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/EvaluateBKUSelectionTask.java @@ -22,32 +22,56 @@ */ package at.gv.egovernment.moa.id.auth.modules.internal.tasks; +import java.util.Enumeration; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang.StringEscapeUtils; +import org.springframework.stereotype.Component; + +import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; /** * @author tlenz * */ -public class ReceiveInterfederationResponseTask extends AbstractAuthServletTask { +@Component("EvaluateBKUSelectionTask") +public class EvaluateBKUSelectionTask extends AbstractAuthServletTask { /* (non-Javadoc) * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @Override - public void execute(ExecutionContext executionContext, - HttpServletRequest request, HttpServletResponse response) - throws TaskExecutionException { - - //TODO: validate SAML2 assertion - //TODO: move attributeQuery from AuthenticationDataBuilder to her - //TODO: add SAML2 interfederation Response to MOASession - //TODO: update AuthenticationDataBuilder to use Response from MOASession if exists - + public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) + throws TaskExecutionException { + try { + // set parameter execution context + Enumeration<String> reqParamNames = request.getParameterNames(); + while(reqParamNames.hasMoreElements()) { + String paramName = reqParamNames.nextElement(); + if (MiscUtil.isNotEmpty(paramName) && + !MOAIDAuthConstants.PARAM_TARGET_PENDINGREQUESTID.equalsIgnoreCase(paramName)) + executionContext.put(paramName, + StringEscapeUtils.escapeHtml(request.getParameter(paramName))); + + } + + //remove BKU-selection flag from context + executionContext.remove(MOAIDAuthConstants.PROCESSCONTEXT_PERFORM_BKUSELECTION); + + Logger.info("BKU is selected finished -> Start BKU selection evaluation ..."); + + } catch (Exception e) { + Logger.warn("EvaluateBKUSelectionTask has an internal error", e); + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/EvaluateSSOConsentsTaskImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/EvaluateSSOConsentsTaskImpl.java new file mode 100644 index 000000000..d52b76ebd --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/EvaluateSSOConsentsTaskImpl.java @@ -0,0 +1,117 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.modules.internal.tasks; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringEscapeUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.moduls.SSOManager; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.util.ParamValidatorUtils; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; + +/** + * Evaluate the Single Sign-On user consent + * + * @author tlenz + * + */ +@Component("EvaluateSSOConsentsTaskImpl") +public class EvaluateSSOConsentsTaskImpl extends AbstractAuthServletTask { + + private static final String PARAM_SSO_CONSENTS = "value"; + + @Autowired private SSOManager ssoManager; + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) + throws TaskExecutionException { + try { + //evaluate SSO consents flag + String ssoConsentsString = request.getParameter(PARAM_SSO_CONSENTS); + ssoConsentsString = StringEscapeUtils.escapeHtml(ssoConsentsString); + if (!ParamValidatorUtils.isValidUseMandate(ssoConsentsString)) + throw new WrongParametersException("EvaluateSSOConsentsTaskImpl", PARAM_SSO_CONSENTS, null); + + boolean ssoConsents = false; + if (MiscUtil.isNotEmpty(ssoConsentsString)) + ssoConsents = Boolean.parseBoolean(ssoConsentsString); + + //perform default task initialization + defaultTaskInitialization(request, executionContext); + + //check SSO session cookie and MOASession object + String ssoId = ssoManager.getSSOSessionID(request); + boolean isValidSSOSession = ssoManager.isValidSSOSession(ssoId, pendingReq); + if (!(isValidSSOSession && moasession.isAuthenticated() )) { + Logger.info("Single Sign-On consents evaluator found NO valid SSO session. Stopping authentication process ..."); + throw new AuthenticationException("auth.30", null); + + } + + //Log consents evaluator event to revisionslog + revisionsLogger.logEvent(pendingReq, MOAIDEventConstants.AUTHPROCESS_SSO_ASK_USER_FINISHED, String.valueOf(ssoConsents)); + + //user allow single sign-on authentication + if (ssoConsents) { + //authenticate pending-request + pendingReq.setAuthenticated(true); + + //store pending-request + requestStoreage.storePendingRequest(pendingReq); + + //redirect to auth. protocol finalization + performRedirectToProtocolFinialization(pendingReq, response); + + } else { + //user deny single sign-on authentication + throw new AuthenticationException("auth.21", new Object[] {}); + + } + + } catch (MOAIDException e) { + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } catch (Exception e) { + Logger.warn("FinalizeAuthenticationTask has an internal error", e); + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } + + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/FinalizeAuthenticationTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/FinalizeAuthenticationTask.java index 8add03da7..c8e379bc1 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/FinalizeAuthenticationTask.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/FinalizeAuthenticationTask.java @@ -22,29 +22,24 @@ */ package at.gv.egovernment.moa.id.auth.modules.internal.tasks; -import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.PARAM_SESSIONID; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder; -import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; +import org.springframework.stereotype.Component; + +import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; -import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; -import at.gv.egovernment.moa.id.moduls.IRequest; -import at.gv.egovernment.moa.id.moduls.ModulUtils; -import at.gv.egovernment.moa.id.moduls.RequestStorage; +import at.gv.egovernment.moa.id.moduls.RequestImpl; import at.gv.egovernment.moa.id.process.api.ExecutionContext; -import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.MiscUtil; /** * @author tlenz * */ +@Component("FinalizeAuthenticationTask") public class FinalizeAuthenticationTask extends AbstractAuthServletTask { /* (non-Javadoc) @@ -56,63 +51,32 @@ public class FinalizeAuthenticationTask extends AbstractAuthServletTask { throws TaskExecutionException { try { - IRequest pendingReq = RequestStorage.getPendingRequest( - (String) executionContext.get("pendingRequestID")); - - //get Session from context - String moasessionid = (String) executionContext.get(PARAM_SESSIONID); - AuthenticationSession session = null; - if (MiscUtil.isEmpty(moasessionid)) { - Logger.warn("MOASessionID is empty."); - throw new MOAIDException("auth.18", new Object[] {}); - } - - try { - session = AuthenticationSessionStoreage.getSession(moasessionid); - AuthenticationSessionStoreage.changeSessionID(session); - - } catch (MOADatabaseException e) { - Logger.info("MOASession with SessionID=" + moasessionid + " is not found in Database"); - throw new MOAIDException("init.04", new Object[] { moasessionid }); + defaultTaskInitialization(request, executionContext); + + //set MOASession to authenticated and store MOASession + moasession.setAuthenticated(true); + String newMOASessionID = authenticatedSessionStorage.changeSessionID(moasession); - } catch (Throwable e) { - Logger.info("No HTTP Session found!"); - throw new MOAIDException("auth.18", new Object[] {}); - - } finally { - executionContext.remove(PARAM_SESSIONID); - - } + //set pendingRequest to authenticated and set new MOASessionID + ((RequestImpl)pendingReq).setMOASessionIdentifier(newMOASessionID); + pendingReq.setAuthenticated(true); + requestStoreage.storePendingRequest(pendingReq); - - session.setAuthenticatedUsed(false); - session.setAuthenticated(true); - - - String oldsessionID = session.getSessionID(); - - //Session is implicte stored in changeSessionID!!! - String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(session); - - Logger.info("AuthProcess finished. Redirect to Protocol Dispatcher."); - - String redirectURL = new DataURLBuilder().buildDataURL(session.getAuthURL(), - ModulUtils.buildAuthURL(pendingReq.requestedModule(), pendingReq.requestedAction(), pendingReq.getRequestID()), newMOASessionID); - - response.setContentType("text/html"); - response.setStatus(302); - response.addHeader("Location", redirectURL); - Logger.debug("REDIRECT TO: " + redirectURL); - + Logger.info("AuthProcess finished. Redirect to Protocol Dispatcher."); + performRedirectToProtocolFinialization(pendingReq, response); + } catch (MOAIDException e) { - throw new TaskExecutionException(e.getMessage(), e); + throw new TaskExecutionException(pendingReq, e.getMessage(), e); } catch (Exception e) { Logger.warn("FinalizeAuthenticationTask has an internal error", e); - throw new TaskExecutionException(e.getMessage(), e); + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } finally { + executionContext.remove(MOAIDAuthConstants.PARAM_TARGET_PENDINGREQUESTID); } - + } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GenerateBKUSelectionFrameTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GenerateBKUSelectionFrameTask.java new file mode 100644 index 000000000..2cf2bfd9b --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GenerateBKUSelectionFrameTask.java @@ -0,0 +1,91 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.modules.internal.tasks; + +import java.io.PrintWriter; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.stereotype.Component; + +import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; +import at.gv.egovernment.moa.id.auth.builder.LoginFormBuilder; +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.logging.Logger; + +/** + * @author tlenz + * + */ +@Component("GenerateBKUSelectionFrameTask") +public class GenerateBKUSelectionFrameTask extends AbstractAuthServletTask { + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) + throws TaskExecutionException { + try { + revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), + pendingReq, MOAIDEventConstants.AUTHPROCESS_BKUSELECTION_INIT); + + //load Parameters from OnlineApplicationConfiguration + IOAAuthParameters oaParam = pendingReq.getOnlineApplicationConfiguration(); + + if (oaParam == null) { + throw new AuthenticationException("auth.00", new Object[] { pendingReq.getOAURL() }); + + } + + //Build authentication form + String publicURLPreFix = pendingReq.getAuthURL(); + if (publicURLPreFix.endsWith("/")) + publicURLPreFix = publicURLPreFix.substring(0, publicURLPreFix.length() - 1); + String loginForm = LoginFormBuilder.buildLoginForm(pendingReq.requestedModule(), + pendingReq.requestedAction(), oaParam, publicURLPreFix, pendingReq.getRequestID()); + + response.setContentType("text/html;charset=UTF-8"); + PrintWriter out = new PrintWriter(response.getOutputStream()); + out.print(loginForm); + out.flush(); + + + } catch (MOAIDException e) { + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } catch (Exception e) { + Logger.warn("FinalizeAuthenticationTask has an internal error", e); + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } + + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GenerateSSOConsentEvaluatorFrameTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GenerateSSOConsentEvaluatorFrameTask.java new file mode 100644 index 000000000..47afe5795 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GenerateSSOConsentEvaluatorFrameTask.java @@ -0,0 +1,90 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.modules.internal.tasks; + +import java.io.PrintWriter; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.stereotype.Component; + +import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; +import at.gv.egovernment.moa.id.auth.builder.SendAssertionFormBuilder; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.logging.Logger; + +/** + * Build a Single Sign-On consents evaluator form + * + * @author tlenz + * + */ +@Component("GenerateSSOConsentEvaluatorFrameTask") +public class GenerateSSOConsentEvaluatorFrameTask extends AbstractAuthServletTask { + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) + throws TaskExecutionException { + try { + //perform default task initialization + defaultTaskInitialization(request, executionContext); + + //set authenticated flag to false, because user consents is required + pendingReq.setAuthenticated(false); + + //build consents evaluator form + String form = SendAssertionFormBuilder.buildForm(pendingReq); + + //store pending request + requestStoreage.storePendingRequest(pendingReq); + + //Log consents evaluator event to revisionslog + revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), + pendingReq, MOAIDEventConstants.AUTHPROCESS_SSO_ASK_USER_START); + + //write form to response object + response.setContentType("text/html;charset=UTF-8"); + PrintWriter out = new PrintWriter(response.getOutputStream()); + out.print(form); + out.flush(); + + + } catch (MOAIDException e) { + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } catch (Exception e) { + Logger.warn("FinalizeAuthenticationTask has an internal error", e); + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } + + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/RestartAuthProzessManagement.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/RestartAuthProzessManagement.java new file mode 100644 index 000000000..ddda86ecc --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/RestartAuthProzessManagement.java @@ -0,0 +1,108 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.modules.internal.tasks; + +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.auth.modules.registration.ModuleRegistration; +import at.gv.egovernment.moa.id.moduls.RequestImpl; +import at.gv.egovernment.moa.id.process.ExecutionContextImpl; +import at.gv.egovernment.moa.id.process.ProcessEngine; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.logging.Logger; + +/** + * @author tlenz + * + */ +@Component("RestartAuthProzessManagement") +public class RestartAuthProzessManagement extends AbstractAuthServletTask { + + @Autowired ProcessEngine processEngine; + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) + throws TaskExecutionException { + try { + //create a new execution context and copy all elements to new context + ExecutionContext newec = new ExecutionContextImpl(); + Set<String> entries = executionContext.keySet(); + for (String key : entries) { + newec.put(key, executionContext.get(key)); + + } + + Logger.debug("Select new auth.-process and restart restart process-engine ... "); + + // select and create new process instance + String processDefinitionId = ModuleRegistration.getInstance().selectProcess(newec); + if (processDefinitionId == null) { + Logger.warn("No suitable authentication process found for SessionID " + pendingReq.getRequestID()); + throw new MOAIDException("process.02", new Object[] { pendingReq.getRequestID() }); + } + + String processInstanceId = processEngine.createProcessInstance(processDefinitionId, newec); + + // keep process instance id in moa session + ((RequestImpl)pendingReq).setProcessInstanceId(processInstanceId); + + // make sure pending request has been persisted before running the process + try { + requestStoreage.storePendingRequest(pendingReq); + + } catch (MOAIDException e) { + Logger.error("Database Error! MOASession is not stored!"); + throw new MOAIDException("init.04", new Object[] { pendingReq.getRequestID() }); + + } + + Logger.info("Restart process-engine with auth.process:" + processDefinitionId); + + // start process + processEngine.start(pendingReq); + + + } catch (MOAIDException e) { + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } catch (Exception e) { + Logger.warn("RestartAuthProzessManagement has an internal error", e); + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } + + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/StartAuthentificationParameterParser.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/StartAuthentificationParameterParser.java index 004961116..b7e95785b 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/StartAuthentificationParameterParser.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/StartAuthentificationParameterParser.java @@ -25,9 +25,10 @@ package at.gv.egovernment.moa.id.auth.parser; import java.util.List; import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringEscapeUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; @@ -35,8 +36,8 @@ import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; import at.gv.egovernment.moa.id.config.TargetToSectorNameMapper; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; -import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; +import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.id.process.api.ExecutionContext; import at.gv.egovernment.moa.id.util.ParamValidatorUtils; @@ -45,44 +46,36 @@ import at.gv.egovernment.moa.util.FileUtils; import at.gv.egovernment.moa.util.MiscUtil; import at.gv.egovernment.moa.util.StringUtils; +@Service("StartAuthentificationParameterParser") public class StartAuthentificationParameterParser extends MOAIDAuthConstants{ - public static void parse(AuthenticationSession moasession, + @Autowired AuthConfiguration authConfig; + + public void parse(AuthenticationSession moasession, String target, String oaURL, String bkuURL, String templateURL, String useMandate, String ccc, - String module, - String action, - HttpServletRequest req) throws WrongParametersException, MOAIDException { + HttpServletRequest req, + IRequest protocolReq) throws WrongParametersException, MOAIDException { String targetFriendlyName = null; - -// String sso = req.getParameter(PARAM_SSO); - + // escape parameter strings target = StringEscapeUtils.escapeHtml(target); - //oaURL = StringEscapeUtils.escapeHtml(oaURL); bkuURL = StringEscapeUtils.escapeHtml(bkuURL); templateURL = StringEscapeUtils.escapeHtml(templateURL); useMandate = StringEscapeUtils.escapeHtml(useMandate); ccc = StringEscapeUtils.escapeHtml(ccc); - // sso = StringEscapeUtils.escapeHtml(sso); - - // check parameter - - //pvp2.x can use general identifier (equals oaURL in SAML1) -// if (!ParamValidatorUtils.isValidOA(oaURL)) -// throw new WrongParametersException("StartAuthentication", PARAM_OA, "auth.12"); + //validate parameters if (!ParamValidatorUtils.isValidUseMandate(useMandate)) throw new WrongParametersException("StartAuthentication", PARAM_USEMANDATE, "auth.12"); if (!ParamValidatorUtils.isValidCCC(ccc)) throw new WrongParametersException("StartAuthentication", PARAM_CCC, "auth.12"); -// if (!ParamValidatorUtils.isValidUseMandate(sso)) -// throw new WrongParametersException("StartAuthentication", PARAM_SSO, "auth.12"); + //check UseMandate flag String useMandateString = null; @@ -102,166 +95,98 @@ public class StartAuthentificationParameterParser extends MOAIDAuthConstants{ //load OnlineApplication configuration - OAAuthParameter oaParam; - if (moasession.getPublicOAURLPrefix() != null) { - Logger.debug("Loading OA parameters for PublicURLPrefix: " + moasession.getPublicOAURLPrefix()); - oaParam = AuthConfigurationProviderFactory.getInstance() - .getOnlineApplicationParameter( - moasession.getPublicOAURLPrefix()); - - if (oaParam == null) - throw new AuthenticationException("auth.00", - new Object[] { moasession.getPublicOAURLPrefix() }); - - } else { - oaParam = AuthConfigurationProviderFactory.getInstance() - .getOnlineApplicationParameter(oaURL); - - if (oaParam == null) + IOAAuthParameters oaParam = protocolReq.getOnlineApplicationConfiguration(); + if (oaParam == null) throw new AuthenticationException("auth.00", - new Object[] { oaURL }); + new Object[] { protocolReq.getOAURL() }); - // get target and target friendly name from config - String targetConfig = oaParam.getTarget(); - String targetFriendlyNameConfig = oaParam.getTargetFriendlyName(); + // get target and target friendly name from config + String targetConfig = oaParam.getTarget(); + String targetFriendlyNameConfig = oaParam.getTargetFriendlyName(); - if (!oaParam.getBusinessService()) { - if (StringUtils.isEmpty(targetConfig) - || (module.equals("id_saml1") && - !StringUtils.isEmpty(target)) - ) { - //INFO: ONLY SAML1 legacy mode - // if SAML1 is used and target attribute is given in request - // use requested target - // check target parameter - if (!ParamValidatorUtils.isValidTarget(target)) { - Logger.error("Selected target is invalid. Using target: " + target); - throw new WrongParametersException("StartAuthentication", PARAM_TARGET, "auth.12"); - } - if (MiscUtil.isNotEmpty(targetConfig)) - targetFriendlyName = targetFriendlyNameConfig; + if (!oaParam.getBusinessService()) { + if (StringUtils.isEmpty(targetConfig) + || (protocolReq.requestedModule().equals("at.gv.egovernment.moa.id.protocols.saml1.SAML1Protocol") && + !StringUtils.isEmpty(target)) + ) { + //INFO: ONLY SAML1 legacy mode + // if SAML1 is used and target attribute is given in request + // use requested target + // check target parameter + if (!ParamValidatorUtils.isValidTarget(target)) { + Logger.error("Selected target is invalid. Using target: " + target); + throw new WrongParametersException("StartAuthentication", PARAM_TARGET, "auth.12"); + } + if (MiscUtil.isNotEmpty(targetConfig)) + targetFriendlyName = targetFriendlyNameConfig; + + else { + String sectorName = TargetToSectorNameMapper.getSectorNameViaTarget(target); + if (MiscUtil.isNotEmpty(sectorName)) + targetFriendlyName = sectorName; else { - String sectorName = TargetToSectorNameMapper.getSectorNameViaTarget(target); - if (MiscUtil.isNotEmpty(sectorName)) - targetFriendlyName = sectorName; - - else { - //check target contains subSector - int delimiter = target.indexOf("-"); - if (delimiter > 0) { - targetFriendlyName = - TargetToSectorNameMapper.getSectorNameViaTarget(target.substring(0, delimiter)); - - } - } - } - - } else { - // use target from config - target = targetConfig; - targetFriendlyName = targetFriendlyNameConfig; + //check target contains subSector + int delimiter = target.indexOf("-"); + if (delimiter > 0) { + targetFriendlyName = + TargetToSectorNameMapper.getSectorNameViaTarget(target.substring(0, delimiter)); + + } + } } - moasession.setTarget(target); - moasession.setTargetFriendlyName(targetFriendlyName); - + } else { - Logger.debug("Business: " + moasession.getBusinessService() + " stork: " + moasession.getStorkService()); - moasession.setDomainIdentifier(oaParam.getIdentityLinkDomainIdentifier()); - + // use target from config + target = targetConfig; + targetFriendlyName = targetFriendlyNameConfig; } + if (isEmpty(target)) + throw new WrongParametersException("StartAuthentication", + PARAM_TARGET, "auth.05"); -// //check useSSO flag -// String useSSOString = null; -// boolean useSSOBoolean = false; -// if ((sso != null) && (sso.compareTo("") != 0)) { -// useSSOString = sso; -// } else { -// useSSOString = "false"; -// } - // -// if (useSSOString.compareToIgnoreCase("true") == 0) -// useSSOBoolean = true; -// else -// useSSOBoolean = false; - - //moasession.setSsoRequested(useSSOBoolean); - moasession.setSsoRequested(true && oaParam.useSSO()); //make always SSO if OA requested it!!!! + protocolReq.setGenericDataToSession(MOAIDAuthConstants.AUTHPROCESS_DATA_TARGET, target); + protocolReq.setGenericDataToSession( + MOAIDAuthConstants.AUTHPROCESS_DATA_TARGETFRIENDLYNAME, targetFriendlyName); + Logger.debug("Service-Provider is of type 'PublicService' with DomainIdentifier:" + target); + + } else { + Logger.debug("Service-Provider is of type 'PrivateService' with DomainIdentifier:" + oaParam.getIdentityLinkDomainIdentifier()); - //Validate BKU URI - List<String> allowedbkus = oaParam.getBKUURL(); - allowedbkus.addAll(AuthConfigurationProviderFactory.getInstance().getDefaultBKUURLs()); - if (!ParamValidatorUtils.isValidBKUURI(bkuURL, allowedbkus)) - throw new WrongParametersException("StartAuthentication", PARAM_BKU, "auth.12"); - - moasession.setBkuURL(bkuURL); - - if ((!oaParam.getBusinessService())) { - if (isEmpty(target)) - throw new WrongParametersException("StartAuthentication", - PARAM_TARGET, "auth.05"); - - } else { - if (useMandateBoolean) { - Logger.error("Online-Mandate Mode for business application not supported."); - throw new AuthenticationException("auth.17", null); - } - target = null; - targetFriendlyName = null; + if (useMandateBoolean) { + Logger.error("Online-Mandate Mode for business application not supported."); + throw new AuthenticationException("auth.17", null); } - moasession.setPublicOAURLPrefix(oaParam.getPublicURLPrefix()); - moasession.setBusinessService(oaParam.getBusinessService()); - - //moasession.setStorkService(oaParam.getStorkService()); } - - //check OnlineApplicationURL - if (isEmpty(oaURL)) - throw new WrongParametersException("StartAuthentication", - PARAM_OA, "auth.05"); - moasession.setOAURLRequested(oaURL); - - //check AuthURL - String authURL = req.getScheme() + "://" + req.getServerName(); - if ((req.getScheme().equalsIgnoreCase("https") && req.getServerPort()!=443) || (req.getScheme().equalsIgnoreCase("http") && req.getServerPort()!=80)) { - authURL = authURL.concat(":" + req.getServerPort()); - } - authURL = authURL.concat(req.getContextPath() + "/"); - - if (!authURL.startsWith("https:") && !AuthConfigurationProviderFactory.getInstance().isHTTPAuthAllowed()) - throw new AuthenticationException("auth.07", - new Object[] { authURL + "*" }); - - //set Auth URL from configuration - moasession.setAuthURL(AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix() + "/"); - - //check and set SourceID - if (oaParam.getSAML1Parameter() != null) { - String sourceID = oaParam.getSAML1Parameter().getSourceID(); - if (MiscUtil.isNotEmpty(sourceID)) - moasession.setSourceID(sourceID); - } - + + //Validate BKU URI + List<String> allowedbkus = oaParam.getBKUURL(); + allowedbkus.addAll(authConfig.getDefaultBKUURLs()); + if (!ParamValidatorUtils.isValidBKUURI(bkuURL, allowedbkus)) + throw new WrongParametersException("StartAuthentication", PARAM_BKU, "auth.12"); + moasession.setBkuURL(bkuURL); + + //validate securityLayer-template if (MiscUtil.isEmpty(templateURL)) { List<String> templateURLList = oaParam.getTemplateURL(); List<String> defaulTemplateURLList = - AuthConfigurationProviderFactory.getInstance().getSLRequestTemplates(); + authConfig.getSLRequestTemplates(); if ( templateURLList != null && templateURLList.size() > 0 && MiscUtil.isNotEmpty(templateURLList.get(0)) ) { templateURL = FileUtils.makeAbsoluteURL( oaParam.getTemplateURL().get(0), - AuthConfigurationProviderFactory.getInstance().getRootConfigFileDir()); + authConfig.getRootConfigFileDir()); Logger.info("No SL-Template in request, load SL-Template from OA configuration (URL: " + templateURL + ")"); } else if ( (defaulTemplateURLList.size() > 0) && MiscUtil.isNotEmpty(defaulTemplateURLList.get(0))) { templateURL = FileUtils.makeAbsoluteURL( defaulTemplateURLList.get(0), - AuthConfigurationProviderFactory.getInstance().getRootConfigFileDir()); + authConfig.getRootConfigFileDir()); Logger.info("No SL-Template in request, load SL-Template from general configuration (URL: " + templateURL + ")"); } else { @@ -274,33 +199,26 @@ public class StartAuthentificationParameterParser extends MOAIDAuthConstants{ if (!ParamValidatorUtils.isValidTemplate(req, templateURL, oaParam.getTemplateURL())) throw new WrongParametersException("StartAuthentication", PARAM_TEMPLATE, "auth.12"); - moasession.setTemplateURL(templateURL); - - moasession.setCcc(ccc); - + + protocolReq.setGenericDataToSession( + MOAIDAuthConstants.AUTHPROCESS_DATA_SECURITYLAYERTEMPLATE, + templateURL); + + + //validate SSO functionality + String domainIdentifier = authConfig.getSSOTagetIdentifier().trim(); + if (MiscUtil.isEmpty(domainIdentifier) && protocolReq.needSingleSignOnFunctionality()) { + //do not use SSO if no Target is set + Logger.warn("NO SSO-Target found in configuration. Single Sign-On is deaktivated!"); + protocolReq.setNeedSingleSignOnFunctionality(false); + + } } - public static void parse(ExecutionContext ec, HttpServletRequest req, + public void parse(ExecutionContext ec, HttpServletRequest req, AuthenticationSession moasession, IRequest request) throws WrongParametersException, MOAIDException { - - - String modul = request.requestedModule();//req.getParameter(PARAM_MODUL); - String action = request.requestedAction();//req.getParameter(PARAM_ACTION); - - modul = StringEscapeUtils.escapeHtml(modul); - action = StringEscapeUtils.escapeHtml(action); -// if(modul == null) { -// modul = SAML1Protocol.PATH; -// } -// -// if(action == null) { -// action = SAML1Protocol.GETARTIFACT; -// } - moasession.setModul(modul); - moasession.setAction(action); - + //get Parameters from request - String target = (String) ec.get(PARAM_TARGET); String oaURL = (String) ec.get(PARAM_OA); String bkuURL = (String) ec.get(PARAM_BKU); String templateURL = (String) ec.get(PARAM_TEMPLATE); @@ -316,9 +234,11 @@ public class StartAuthentificationParameterParser extends MOAIDAuthConstants{ } oaURL = request.getOAURL(); - target = request.getTarget(); + + //only needed for SAML1 + String target = request.getGenericData("saml1_target", String.class); - parse(moasession, target, oaURL, bkuURL, templateURL, useMandate, ccc, modul, action, req); + parse(moasession, target, oaURL, bkuURL, templateURL, useMandate, ccc, req, request); } @@ -329,7 +249,7 @@ public class StartAuthentificationParameterParser extends MOAIDAuthConstants{ * parameter * @return true if the parameter is null or empty */ - private static boolean isEmpty(String param) { + private boolean isEmpty(String param) { return param == null || param.length() == 0; } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AbstractController.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AbstractController.java new file mode 100644 index 000000000..8c0708fd5 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AbstractController.java @@ -0,0 +1,348 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.servlet; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.URI; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.ExceptionHandler; + +import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger; +import at.gv.egovernment.moa.id.advancedlogging.StatisticLogger; +import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; +import at.gv.egovernment.moa.id.auth.exception.InvalidProtocolRequestException; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.exception.ProtocolNotActiveException; +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.config.ConfigurationException; +import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; +import at.gv.egovernment.moa.id.moduls.IRequestStorage; +import at.gv.egovernment.moa.id.process.ProcessExecutionException; +import at.gv.egovernment.moa.id.protocols.AbstractAuthProtocolModulController; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AuthnRequestValidatorException; +import at.gv.egovernment.moa.id.storage.ITransactionStorage; +import at.gv.egovernment.moa.id.util.ErrorResponseUtils; +import at.gv.egovernment.moa.id.util.Random; +import at.gv.egovernment.moa.id.util.ServletUtils; +import at.gv.egovernment.moa.id.util.VelocityProvider; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; + +/** + * @author tlenz + * + */ +public abstract class AbstractController extends MOAIDAuthConstants { + + public static final String ERROR_CODE_PARAM = "errorid"; + + private static final String HTMLTEMPLATESDIR = "htmlTemplates/"; + private static final String HTMLTEMPLATEFULL = "error_message.html"; + + @Autowired protected StatisticLogger statisticLogger; + @Autowired protected IRequestStorage requestStorage; + @Autowired protected ITransactionStorage transactionStorage; + @Autowired protected MOAReversionLogger revisionsLogger; + @Autowired protected AuthConfiguration authConfig; + + @ExceptionHandler({MOAIDException.class}) + public void MOAIDExceptionHandler(HttpServletRequest req, HttpServletResponse resp, Exception e) throws IOException { + Logger.error(e.getMessage() , e); + internalMOAIDExceptionHandler(req, resp, e, true); + + } + + @ExceptionHandler({Exception.class}) + public void GenericExceptionHandler(HttpServletResponse resp, Exception exception) throws IOException { + Logger.error("Internel Server Error." , exception); + resp.setContentType("text/html;charset=UTF-8"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal Server Error!" + + "(Errorcode=9199" + +" | Description="+ exception.getMessage() + ")"); + return; + + } + + @ExceptionHandler({IOException.class}) + public void IOExceptionHandler(HttpServletResponse resp, IOException exception) { + Logger.error("Internel Server Error." , exception); + resp.setContentType("text/html;charset=UTF-8"); + resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + return; + + } + + protected void handleError(String errorMessage, Throwable exceptionThrown, + HttpServletRequest req, HttpServletResponse resp, String pendingRequestID) throws IOException { + + Throwable loggedException = null; + Throwable extractedException = extractOriginalExceptionFromProcessException(exceptionThrown); + + //extract pendingRequestID and originalException if it was a TaskExecutionException + if (extractedException instanceof TaskExecutionException) { + //set original exception + loggedException = ((TaskExecutionException) extractedException).getOriginalException(); + + //set pending-request ID if it is set + String reqID = ((TaskExecutionException) extractedException).getPendingRequestID(); + if (MiscUtil.isNotEmpty(reqID)) + pendingRequestID = reqID; + + } else + loggedException = exceptionThrown; + + try { + //switch to protocol-finalize method to generate a protocol-specific error message + + //put exception into transaction store for redirect + String key = Random.nextRandom(); + transactionStorage.put(key, loggedException); + + //build up redirect URL + String redirectURL = null; + redirectURL = ServletUtils.getBaseUrl(req); + redirectURL += "/"+AbstractAuthProtocolModulController.FINALIZEPROTOCOL_ENDPOINT + + "?" + ERROR_CODE_PARAM + "=" + key + + "&" + MOAIDAuthConstants.PARAM_TARGET_PENDINGREQUESTID + "=" + pendingRequestID; + + resp.setContentType("text/html"); + resp.setStatus(302); + + resp.addHeader("Location", redirectURL); + Logger.debug("REDIRECT TO: " + redirectURL); + + return; + + } catch (MOADatabaseException e) { + Logger.warn("Exception can not be stored to Database.", e); + handleErrorNoRedirect(loggedException, req, resp, true); + + } + + } + + /** + * Handles all exceptions with no pending request. + * Therefore, the error is written to the users browser + * + * @param throwable + * @param req + * @param resp + * @throws IOException + */ + protected void handleErrorNoRedirect(Throwable throwable, HttpServletRequest req, + HttpServletResponse resp, boolean writeExceptionToStatisticLog) throws IOException { + + //log Exception into statistic database + if (writeExceptionToStatisticLog) + statisticLogger.logErrorOperation(throwable); + + //write errror to console + logExceptionToTechnicalLog(throwable); + + //return error to Web browser + if (throwable instanceof MOAIDException || throwable instanceof ProcessExecutionException) + internalMOAIDExceptionHandler(req, resp, (Exception)throwable, false); + + else + GenericExceptionHandler(resp, (Exception)throwable); + } + + /** + * Write a Exception to the MOA-ID-Auth internal technical log + * + * @param loggedException Exception to log + */ + protected void logExceptionToTechnicalLog(Throwable loggedException) { + if (!(loggedException instanceof MOAIDException)) { + Logger.error("Receive an internal error: Message=" + loggedException.getMessage(), loggedException); + + } else { + if (Logger.isDebugEnabled() || Logger.isTraceEnabled()) { + Logger.error(loggedException.getMessage(), loggedException); + + } else { + Logger.error(loggedException.getMessage()); + + } + } + } + + private void writeBadRequestErrorResponse(HttpServletRequest req, HttpServletResponse resp, MOAIDException e) throws IOException { + ErrorResponseUtils utils = ErrorResponseUtils.getInstance(); + String code = utils.mapInternalErrorToExternalError( + ((InvalidProtocolRequestException)e).getMessageId()); + String descr = e.getMessage(); + resp.setContentType("text/html;charset=UTF-8"); + resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Protocol validation FAILED!" + + "(Errorcode=" + code + + " | Description=" + descr + ")"); + + } + + private void writeHTMLErrorResponse(HttpServletResponse httpResp, Exception error) throws IOException { + VelocityContext context = new VelocityContext(); + + //add errorcode and errormessage + context.put("errorMsg", error.getMessage()); + context.put("errorCode", ErrorResponseUtils.getInstance().getResponseErrorCode(error)); + + //add stacktrace if debug is enabled + if (Logger.isDebugEnabled()) { + context.put("stacktrace", getStacktraceFromException(error)); + + } + + try { + InputStream is = null; + String pathLocation = null; + try { + String rootconfigdir = authConfig.getRootConfigFileDir(); + pathLocation = rootconfigdir + HTMLTEMPLATESDIR + HTMLTEMPLATEFULL; + File file = new File(new URI(pathLocation)); + is = new FileInputStream(file); + evaluateErrorTemplate(context, httpResp, is); + + } catch (Exception e) { + Logger.warn("SLO Template is not found in configuration directory (" + + pathLocation + "). Load template from project library ... "); + + try { + pathLocation = "resources/templates/" + HTMLTEMPLATEFULL; + is = Thread.currentThread() + .getContextClassLoader() + .getResourceAsStream(pathLocation); + evaluateErrorTemplate(context, httpResp, is); + + } catch (Exception e1) { + Logger.error("Single LogOut form can not created.", e); + throw new MOAIDException("Create Single LogOut information FAILED.", null, e); + } + + } finally { + if (is != null) + is.close(); + + } + } catch (Exception e) { + Logger.error("Error-message form can not created.", e); + GenericExceptionHandler(httpResp, error); + + } + } + + private void evaluateErrorTemplate(VelocityContext context, HttpServletResponse httpResp, InputStream is) throws Exception { + VelocityEngine engine = VelocityProvider.getClassPathVelocityEngine(); + BufferedReader reader = new BufferedReader(new InputStreamReader(is )); + StringWriter writer = new StringWriter(); + engine.evaluate(context, writer, "Error Template", reader); + httpResp.setContentType("text/html;charset=UTF-8"); + httpResp.getOutputStream().write(writer.toString().getBytes("UTF-8")); + + } + + private String getStacktraceFromException(Exception ex) { + StringWriter errors = new StringWriter(); + ex.printStackTrace(new PrintWriter(errors)); + return errors.toString(); + + } + + /** + * Extracts a TaskExecutionException of a ProcessExecutionExeception Stacktrace. + * + * @param exception + * @return Return the latest TaskExecutionExecption if exists, otherwise the latest ProcessExecutionException + */ + private Throwable extractOriginalExceptionFromProcessException(Throwable exception) { + Throwable exholder = exception; + TaskExecutionException taskExc = null; + + while(exholder != null + && exholder instanceof ProcessExecutionException) { + ProcessExecutionException procExc = (ProcessExecutionException) exholder; + if (procExc.getCause() != null && + procExc.getCause() instanceof TaskExecutionException) { + taskExc = (TaskExecutionException) procExc.getCause(); + exholder = taskExc.getOriginalException(); + + } + } + + if (taskExc == null) + return exholder; + + else + return taskExc; + } + + private void internalMOAIDExceptionHandler(HttpServletRequest req, HttpServletResponse resp, Exception e, boolean writeExceptionToStatisicLog) throws IOException { + if (e instanceof ProtocolNotActiveException) { + resp.getWriter().write(e.getMessage()); + resp.setContentType("text/html;charset=UTF-8"); + resp.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage()); + + } else if (e instanceof AuthnRequestValidatorException) { + AuthnRequestValidatorException ex = (AuthnRequestValidatorException)e; + //log Error Message + if (writeExceptionToStatisicLog) + statisticLogger.logErrorOperation(ex, ex.getErrorRequest()); + + //write error message + writeBadRequestErrorResponse(req, resp, (MOAIDException) e); + + } else if (e instanceof InvalidProtocolRequestException) { + //send error response + writeBadRequestErrorResponse(req, resp, (MOAIDException) e); + + } else if (e instanceof ConfigurationException) { + //send HTML formated error message + writeHTMLErrorResponse(resp, (MOAIDException) e); + + } else if (e instanceof MOAIDException) { + //send HTML formated error message + writeHTMLErrorResponse(resp, e); + + } else if (e instanceof ProcessExecutionException) { + //send HTML formated error message + writeHTMLErrorResponse(resp, e); + + } + + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AbstractProcessEngineSignalController.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AbstractProcessEngineSignalController.java new file mode 100644 index 000000000..8b96b884e --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AbstractProcessEngineSignalController.java @@ -0,0 +1,87 @@ +package at.gv.egovernment.moa.id.auth.servlet;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import at.gv.egovernment.moa.id.advancedlogging.TransactionIDUtils;
+import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.moduls.IRequest;
+import at.gv.egovernment.moa.id.process.ProcessEngine;
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * Servlet that resumes a suspended process (in case of asynchronous tasks).
+ *
+ * @author tknall
+ *
+ */
+public abstract class AbstractProcessEngineSignalController extends AbstractController {
+
+ @Autowired ProcessEngine processEngine;
+
+ protected void signalProcessManagement(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ String pendingRequestID = StringEscapeUtils.escapeHtml(getPendingRequestId(req));
+
+ try {
+ if (pendingRequestID == null) {
+ throw new IllegalStateException("Unable to determine MOA pending-request id.");
+ }
+
+ IRequest pendingReq = requestStorage.getPendingRequest(pendingRequestID);
+ if (pendingReq == null) {
+ Logger.info("No PendingRequest with Id: " + pendingRequestID + " Maybe, a transaction timeout occure.");
+ throw new MOAIDException("auth.28", new Object[]{pendingRequestID});
+
+ }
+
+ //change pending-request ID
+ requestStorage.changePendingRequestID(pendingReq);
+
+ //add transactionID and unique sessionID to Logger
+ TransactionIDUtils.setSessionId(pendingReq.getUniqueSessionIdentifier());
+ TransactionIDUtils.setTransactionId(pendingReq.getUniqueTransactionIdentifier());
+
+ // process instance is mandatory
+ if (pendingReq.getProcessInstanceId() == null) {
+ throw new IllegalStateException("MOA session does not provide process instance id.");
+ }
+
+ // wake up next task
+ processEngine.signal(pendingReq);
+
+ } catch (Exception ex) {
+ handleError(null, ex, req, resp, pendingRequestID);
+
+ } finally {
+ //MOASessionDBUtils.closeSession();
+ TransactionIDUtils.removeTransactionId();
+ TransactionIDUtils.removeSessionId();
+
+ }
+
+
+ }
+
+ /**
+ * Retrieves the current pending-request id from the HttpServletRequest parameter
+ * {@link MOAIDAuthConstants#PARAM_TARGET_PENDINGREQUESTID}.
+ * <p/>
+ * Note that this class/method can be overwritten by modules providing their own strategy of retrieving the
+ * respective pending-request id.
+ *
+ * @param request
+ * The unterlying HttpServletRequest.
+ * @return The current pending-request id.
+ */
+ public String getPendingRequestId(HttpServletRequest request) {
+ return StringEscapeUtils.escapeHtml(request.getParameter(MOAIDAuthConstants.PARAM_TARGET_PENDINGREQUESTID));
+
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AuthServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AuthServlet.java deleted file mode 100644 index 43f4f90ff..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AuthServlet.java +++ /dev/null @@ -1,504 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 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: - * http://www.osor.eu/eupl/ - * - * 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. - ******************************************************************************/ -/* - * Copyright 2003 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 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: - * http://www.osor.eu/eupl/ - * - * 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.egovernment.moa.id.auth.servlet; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletConfig; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.fileupload.FileItem; -import org.apache.commons.fileupload.FileItemFactory; -import org.apache.commons.fileupload.FileUploadException; -import org.apache.commons.fileupload.disk.DiskFileItemFactory; -import org.apache.commons.fileupload.servlet.ServletFileUpload; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.NoSuchBeanDefinitionException; -import org.springframework.beans.factory.NoUniqueBeanDefinitionException; -import org.springframework.web.context.WebApplicationContext; -import org.springframework.web.context.support.WebApplicationContextUtils; - -import at.gv.egovernment.moa.id.advancedlogging.StatisticLogger; -import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; -import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; -import at.gv.egovernment.moa.id.auth.exception.MOAIDException; -import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; -import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; -import at.gv.egovernment.moa.id.config.ConfigurationException; -import at.gv.egovernment.moa.id.entrypoints.DispatcherServlet; -import at.gv.egovernment.moa.id.process.ProcessEngine; -import at.gv.egovernment.moa.id.process.ProcessExecutionException; -import at.gv.egovernment.moa.id.storage.DBExceptionStoreImpl; -import at.gv.egovernment.moa.id.storage.IExceptionStore; -import at.gv.egovernment.moa.id.util.ServletUtils; -import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.MiscUtil; -import at.gv.egovernment.moa.util.URLDecoder; - -/** - * Base class for MOA-ID Auth Servlets, providing standard error handling and - * constant names. - * - * @author Paul Ivancsics - * @version $Id$ - */ -public class AuthServlet extends HttpServlet { - - /** - * - */ - private static final long serialVersionUID = -6929905344382283738L; - - protected static final String ERROR_CODE_PARAM = "errorid"; - - /** - * The process engine. - */ - private ProcessEngine processEngine; - - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - Logger.debug("GET " + this.getServletName()); - - this.setNoCachingHeadersInHttpRespone(req, resp); - } - - protected void handleErrorNoRedirect(String errorMessage, Throwable exceptionThrown, - HttpServletRequest req, HttpServletResponse resp) { - - if (null != errorMessage) { - Logger.error(errorMessage); - req.setAttribute("ErrorMessage", errorMessage); - } - - if (null != exceptionThrown) { - if (null == errorMessage) - errorMessage = exceptionThrown.getMessage(); - Logger.error(errorMessage, exceptionThrown); - req.setAttribute("ExceptionThrown", exceptionThrown); - } - - if (Logger.isDebugEnabled()) { - req.setAttribute("LogLevel", "debug"); - } - - - StatisticLogger logger = StatisticLogger.getInstance(); - logger.logErrorOperation(exceptionThrown); - - - // forward this to errorpage-auth.jsp where the HTML error page is - // generated - ServletContext context = getServletContext(); - RequestDispatcher dispatcher = context - .getRequestDispatcher("/errorpage-auth.jsp"); - try { - - resp.setHeader(MOAIDAuthConstants.HEADER_EXPIRES, - MOAIDAuthConstants.HEADER_VALUE_EXPIRES); - resp.setHeader(MOAIDAuthConstants.HEADER_PRAGMA, - MOAIDAuthConstants.HEADER_VALUE_PRAGMA); - resp.setHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL, - MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL); - resp.addHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL, - MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL_IE); - - dispatcher.forward(req, resp); - } catch (ServletException e) { - Logger.error(e); - } catch (IOException e) { - Logger.error(e); - } - } - - /** - * Handles an error. <br>> - * <ul> - * <li>Logs the error</li> - * <li>Places error message and exception thrown into the request as request - * attributes (to be used by <code>"/errorpage-auth.jsp"</code>)</li> - * <li>Sets HTTP status 500 (internal server error)</li> - * </ul> - * - * @param errorMessage - * error message - * @param exceptionThrown - * exception thrown - * @param req - * servlet request - * @param resp - * servlet response - */ - protected void handleError(String errorMessage, Throwable exceptionThrown, - HttpServletRequest req, HttpServletResponse resp, String pendingRequestID) { - - Throwable loggedException = null; - - if (exceptionThrown != null - && exceptionThrown instanceof ProcessExecutionException) { - ProcessExecutionException procExc = - (ProcessExecutionException) exceptionThrown; - if (procExc.getCause() != null && - procExc.getCause() instanceof TaskExecutionException) { - TaskExecutionException taskExc = (TaskExecutionException) procExc.getCause(); - loggedException = taskExc.getOriginalException(); - if (Logger.isDebugEnabled() || Logger.isTraceEnabled()) { - Logger.error(exceptionThrown.getMessage(), exceptionThrown); - - } else - Logger.error(exceptionThrown.getMessage()); - - } - } - - if (loggedException == null) - loggedException = exceptionThrown; - - - if (!(loggedException instanceof MOAIDException)) { - Logger.error("Receive an internal error: Message=" + loggedException.getMessage(), loggedException); - - } - - IExceptionStore store = DBExceptionStoreImpl.getStore(); - String id = store.storeException(loggedException); - - if (id != null && MiscUtil.isNotEmpty(pendingRequestID)) { - - String redirectURL = null; - - redirectURL = ServletUtils.getBaseUrl(req); - redirectURL += "/dispatcher?" + ERROR_CODE_PARAM + "=" + id - + "&" + DispatcherServlet.PARAM_TARGET_PENDINGREQUESTID + "=" + pendingRequestID; - - resp.setContentType("text/html"); - resp.setStatus(302); - - resp.addHeader("Location", redirectURL); - Logger.debug("REDIRECT TO: " + redirectURL); - - return; - - } else { - - //Exception can not be stored in database - handleErrorNoRedirect(errorMessage, loggedException, req, resp); - } - } - - /** - * Handles a <code>WrongParametersException</code>. - * - * @param req - * servlet request - * @param resp - * servlet response - */ - protected void handleWrongParameters(WrongParametersException ex, - HttpServletRequest req, HttpServletResponse resp) { - Logger.error(ex.toString()); - req.setAttribute("WrongParameters", ex.getMessage()); - - // forward this to errorpage-auth.jsp where the HTML error page is - // generated - ServletContext context = getServletContext(); - RequestDispatcher dispatcher = context - .getRequestDispatcher("/errorpage-auth.jsp"); - try { - resp.setHeader(MOAIDAuthConstants.HEADER_EXPIRES, - MOAIDAuthConstants.HEADER_VALUE_EXPIRES); - resp.setHeader(MOAIDAuthConstants.HEADER_PRAGMA, - MOAIDAuthConstants.HEADER_VALUE_PRAGMA); - resp.setHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL, - MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL); - resp.addHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL, - MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL_IE); - - dispatcher.forward(req, resp); - } catch (ServletException e) { - Logger.error(e); - } catch (IOException e) { - Logger.error(e); - } - } - - /** - * Logs all servlet parameters for debugging purposes. - */ - protected void logParameters(HttpServletRequest req) { - for (Enumeration params = req.getParameterNames(); params - .hasMoreElements();) { - String parname = (String) params.nextElement(); - Logger.debug("Parameter " + parname + req.getParameter(parname)); - } - } - - /** - * Parses the request input stream for parameters, assuming parameters are - * encoded UTF-8 (no standard exists how browsers should encode them). - * - * @param req - * servlet request - * - * @return mapping parameter name -> value - * - * @throws IOException - * if parsing request parameters fails. - * - * @throws FileUploadException - * if parsing request parameters fails. - */ - protected Map<String, String> getParameters(HttpServletRequest req) throws IOException, - FileUploadException { - - Map<String, String> parameters = new HashMap<String, String>(); - - if (ServletFileUpload.isMultipartContent(req)) { - // request is encoded as mulitpart/form-data - FileItemFactory factory = new DiskFileItemFactory(); - ServletFileUpload upload = null; - upload = new ServletFileUpload(factory); - List items = null; - items = upload.parseRequest(req); - for (int i = 0; i < items.size(); i++) { - FileItem item = (FileItem) items.get(i); - if (item.isFormField()) { - // Process only form fields - no file upload items - String logString = item.getString("UTF-8"); - - // TODO use RegExp - String startS = "<pr:Identification><pr:Value>"; - String endS = "</pr:Value><pr:Type>urn:publicid:gv.at:baseid</pr:Type>"; - String logWithMaskedBaseid = logString; - int start = logString.indexOf(startS); - if (start > -1) { - int end = logString.indexOf(endS); - if (end > -1) { - logWithMaskedBaseid = logString.substring(0, start); - logWithMaskedBaseid += startS; - logWithMaskedBaseid += "xxxxxxxxxxxxxxxxxxxxxxxx"; - logWithMaskedBaseid += logString.substring(end, - logString.length()); - } - } - parameters - .put(item.getFieldName(), item.getString("UTF-8")); - Logger.debug("Processed multipart/form-data request parameter: \nName: " - + item.getFieldName() - + "\nValue: " - + logWithMaskedBaseid); - } - } - } - - else { - // request is encoded as application/x-www-urlencoded - InputStream in = req.getInputStream(); - - String paramName; - String paramValueURLEncoded; - do { - paramName = new String(readBytesUpTo(in, '=')); - if (paramName.length() > 0) { - paramValueURLEncoded = readBytesUpTo(in, '&'); - String paramValue = URLDecoder.decode(paramValueURLEncoded, - "UTF-8"); - parameters.put(paramName, paramValue); - } - } while (paramName.length() > 0); - in.close(); - } - - return parameters; - } - - /** - * Reads bytes up to a delimiter, consuming the delimiter. - * - * @param in - * input stream - * @param delimiter - * delimiter character - * @return String constructed from the read bytes - * @throws IOException - */ - protected String readBytesUpTo(InputStream in, char delimiter) - throws IOException { - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - boolean done = false; - int b; - while (!done && (b = in.read()) >= 0) { - if (b == delimiter) - done = true; - else - bout.write(b); - } - return bout.toString(); - } - - /** - * Calls the web application initializer. - * - * @see javax.servlet.Servlet#init(ServletConfig) - */ - public void init(ServletConfig servletConfig) throws ServletException { - super.init(servletConfig); - } - - -// public void contextDestroyed(ServletContextEvent arg0) { -// Security.removeProvider((new IAIK()).getName()); -// Security.removeProvider((new ECCProvider()).getName()); -// } - - /** - * Set response headers to avoid caching - * - * @param request - * HttpServletRequest - * @param response - * HttpServletResponse - */ - protected void setNoCachingHeadersInHttpRespone(HttpServletRequest request, - HttpServletResponse response) { - response.setHeader(MOAIDAuthConstants.HEADER_EXPIRES, - MOAIDAuthConstants.HEADER_VALUE_EXPIRES); - response.setHeader(MOAIDAuthConstants.HEADER_PRAGMA, - MOAIDAuthConstants.HEADER_VALUE_PRAGMA); - response.setHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL, - MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL); - response.addHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL, - MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL_IE); - - } - - /** - * Adds a parameter to a URL. - * - * @param url - * the URL - * @param paramname - * parameter name - * @param paramvalue - * parameter value - * @return the URL with parameter added - */ - protected static String addURLParameter(String url, String paramname, - String paramvalue) { - String param = paramname + "=" + paramvalue; - if (url.indexOf("?") < 0) - return url + "?" + param; - else - return url + "&" + param; - } - - /** - * Checks if HTTP requests are allowed - * - * @param authURL - * requestURL - * @throws AuthenticationException - * if HTTP requests are not allowed - * @throws ConfigurationException - */ - protected void checkIfHTTPisAllowed(String authURL) - throws AuthenticationException, ConfigurationException { - // check if HTTP Connection may be allowed (through - // FRONTEND_SERVLETS_ENABLE_HTTP_CONNECTION_PROPERTY) - - //Removed from MOA-ID 2.0 config -// String boolStr = AuthConfigurationProvider -// .getInstance() -// .getGenericConfigurationParameter( -// AuthConfigurationProvider.FRONTEND_SERVLETS_ENABLE_HTTP_CONNECTION_PROPERTY); - if ((!authURL.startsWith("https:")) - //&& (false == BoolUtils.valueOf(boolStr)) - ) - throw new AuthenticationException("auth.07", new Object[] { authURL - + "*" }); - - } - - - /** - * Returns the underlying process engine instance. - * - * @return The process engine (never {@code null}). - * @throws NoSuchBeanDefinitionException - * if no {@link ProcessEngine} bean was found. - * @throws NoUniqueBeanDefinitionException - * if more than one {@link ProcessEngine} bean was found. - * @throws BeansException - * if a problem getting the {@link ProcessEngine} bean occurred. - * @throws IllegalStateException - * if the Spring WebApplicationContext was not found, which means that the servlet is used outside a - * Spring web environment. - */ - public synchronized ProcessEngine getProcessEngine() { - if (processEngine == null) { - WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); - if (ctx == null) { - throw new IllegalStateException( - "Unable to find Spring WebApplicationContext. Servlet needs to be executed within a Spring web environment."); - } - processEngine = ctx.getBean(ProcessEngine.class); - } - return processEngine; - } - -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/requestHandler/IRequestHandler.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GeneralProcessEngineSignalController.java index 293dccf6c..6bccd5b88 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/requestHandler/IRequestHandler.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GeneralProcessEngineSignalController.java @@ -1,4 +1,4 @@ -/******************************************************************************* +/* * Copyright 2014 Federal Chancellery Austria * MOA-ID has been developed in a cooperation between BRZ, the Federal * Chancellery Austria - ICT staff unit, and Graz University of Technology. @@ -19,22 +19,33 @@ * 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.egovernment.moa.id.protocols.pvp2x.requestHandler; + */ +package at.gv.egovernment.moa.id.auth.servlet; + +import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import at.gv.egovernment.moa.id.auth.exception.MOAIDException; -import at.gv.egovernment.moa.id.data.IAuthData; -import at.gv.egovernment.moa.id.data.SLOInformationInterface; -import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration; -import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessage; -import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; -public interface IRequestHandler { - public boolean handleObject(InboundMessage obj); +/** + * @author tlenz + * + */ +@Controller +public class GeneralProcessEngineSignalController extends AbstractProcessEngineSignalController { - public SLOInformationInterface process(PVPTargetConfiguration pvpRequest, HttpServletRequest req, - HttpServletResponse resp, IAuthData authData) throws MOAIDException; + + @RequestMapping(value = {"/GenerateIframeTemplate", + "/SSOSendAssertionServlet", + "/signalProcess" + }, + method = {RequestMethod.POST, RequestMethod.GET}) + public void performGenericAuthenticationProcess(HttpServletRequest req, HttpServletResponse resp) throws IOException { + signalProcessManagement(req, resp); + + } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GenerateIFrameTemplateServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GenerateIFrameTemplateServlet.java deleted file mode 100644 index 2a63968dd..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GenerateIFrameTemplateServlet.java +++ /dev/null @@ -1,161 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 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: - * http://www.osor.eu/eupl/ - * - * 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.egovernment.moa.id.auth.servlet; - -import java.io.IOException; -import java.util.Enumeration; -import java.util.List; -import java.util.Map; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang.StringEscapeUtils; - -import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; -import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger; -import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; -import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; -import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; -import at.gv.egovernment.moa.id.auth.exception.MOAIDException; -import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; -import at.gv.egovernment.moa.id.auth.modules.registration.ModuleRegistration; -import at.gv.egovernment.moa.id.auth.parser.StartAuthentificationParameterParser; - -import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; -import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; - -import at.gv.egovernment.moa.id.moduls.IRequest; -import at.gv.egovernment.moa.id.moduls.RequestStorage; - -import at.gv.egovernment.moa.id.process.ExecutionContextImpl; -import at.gv.egovernment.moa.id.process.api.ExecutionContext; -import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; -import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.FileUtils; -import at.gv.egovernment.moa.util.MiscUtil; - -public class GenerateIFrameTemplateServlet extends AuthServlet { - - private static final long serialVersionUID = 1L; - - protected void doGet(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - Logger.debug("Receive " + GenerateIFrameTemplateServlet.class + " Request"); - - String pendingRequestID = null; - - try { - String moasessionid = req.getParameter(MOAIDAuthConstants.PARAM_SESSIONID); - moasessionid = StringEscapeUtils.escapeHtml(moasessionid); - AuthenticationSession moasession = null; - try { - pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(moasessionid); - moasession = AuthenticationSessionStoreage.getSession(moasessionid); - - } catch (MOADatabaseException e) { - Logger.info("MOASession with SessionID="+ moasessionid + " is not found in Database"); - throw new MOAIDException("init.04", new Object[] { - moasessionid}); - - } catch (Throwable e) { - Logger.info("No HTTP Session found!"); - throw new MOAIDException("auth.18", new Object[] {}); - } - - - - ExecutionContext ec = new ExecutionContextImpl(); - // set execution context - Enumeration<String> reqParamNames = req.getParameterNames(); - while(reqParamNames.hasMoreElements()) { - String paramName = reqParamNames.nextElement(); - if (MiscUtil.isNotEmpty(paramName)) - ec.put(paramName, req.getParameter(paramName)); - - } - - ec.put("pendingRequestID", pendingRequestID); - ec.put(MOAIDAuthConstants.PARAM_SESSIONID, moasessionid); - -// String bkuid = req.getParameter(MOAIDAuthConstants.PARAM_BKU); -// String useMandate = req.getParameter(MOAIDAuthConstants.PARAM_USEMANDATE); -// String ccc = req.getParameter(MOAIDAuthConstants.PARAM_CCC); -// ec.put("ccc", moasession.getCcc()); -// ec.put("useMandate", moasession.getUseMandate()); -// ec.put("bkuURL", moasession.getBkuURL()); - - // select and create process instance - String processDefinitionId = ModuleRegistration.getInstance().selectProcess(ec); - if (processDefinitionId == null) { - Logger.warn("No suitable process found for SessionID " + moasession.getSessionID()); - throw new MOAIDException("process.02", new Object[] { moasession.getSessionID() }); - } - - String processInstanceId = getProcessEngine().createProcessInstance(processDefinitionId, ec); - - // keep process instance id in moa session - moasession.setProcessInstanceId(processInstanceId); - - // make sure moa session has been persisted before running the process - try { - AuthenticationSessionStoreage.storeSession(moasession); - } catch (MOADatabaseException e) { - Logger.error("Database Error! MOASession is not stored!"); - throw new MOAIDException("init.04", new Object[] { moasession.getSessionID() }); - } - - Logger.info("BKU is selected -> Start BKU communication ..."); - - // start process - getProcessEngine().start(processInstanceId); - - } - catch (WrongParametersException ex) { - handleWrongParameters(ex, req, resp); - } - - catch (MOAIDException ex) { - handleError(null, ex, req, resp, pendingRequestID); - - } catch (Exception e) { - Logger.error("BKUSelectionServlet has an interal Error.", e); - - } - - finally { - - } - } - - - - - - - - - -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/IDPSingleLogOutServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/IDPSingleLogOutServlet.java index 0a6d30be7..307b668b7 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/IDPSingleLogOutServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/IDPSingleLogOutServlet.java @@ -31,20 +31,25 @@ import javax.servlet.http.HttpServletResponse; import org.apache.velocity.VelocityContext; import org.opensaml.saml2.core.LogoutResponse; import org.opensaml.saml2.metadata.SingleLogoutService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +import at.gv.egovernment.moa.id.data.ISLOInformationContainer; import at.gv.egovernment.moa.id.data.SLOInformationContainer; import at.gv.egovernment.moa.id.moduls.AuthenticationManager; import at.gv.egovernment.moa.id.moduls.SSOManager; import at.gv.egovernment.moa.id.protocols.pvp2x.builder.SingleLogOutBuilder; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NOSLOServiceDescriptorException; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NoMetadataInformationException; -import at.gv.egovernment.moa.id.storage.AssertionStorage; -import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; +import at.gv.egovernment.moa.id.storage.IAuthenticationSessionStoreage; +import at.gv.egovernment.moa.id.util.HTTPUtils; import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; import at.gv.egovernment.moa.id.util.Random; import at.gv.egovernment.moa.logging.Logger; @@ -55,15 +60,36 @@ import at.gv.egovernment.moa.util.URLEncoder; * @author tlenz * */ -public class IDPSingleLogOutServlet extends AuthServlet { +@Controller +public class IDPSingleLogOutServlet extends AbstractController { - private static final long serialVersionUID = -1301786072691577221L; - - protected void doGet(HttpServletRequest req, HttpServletResponse resp) + @Autowired SSOManager ssoManager; + @Autowired AuthenticationManager authManager; + @Autowired IAuthenticationSessionStoreage authenicationStorage; + @Autowired SingleLogOutBuilder sloBuilder; + + @RequestMapping(value = "/idpSingleLogout", method = {RequestMethod.GET}) + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Logger.debug("receive IDP SingleLogOut Request"); - SSOManager ssomanager = SSOManager.getInstance(); - String ssoid = ssomanager.getSSOSessionID(req); + + String authURL = HTTPUtils.extractAuthURLFromRequest(req); + try { + if (!AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix().contains(authURL)) { + Logger.warn("Requested URL " + authURL + " is not in PublicPrefix Configuration"); + resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Request not allowed"); + return; + + } + + } catch (MOAIDException e) { + Logger.error("Internal Server Error.", e); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal Server Error"); + return; + + } + + String ssoid = ssoManager.getSSOSessionID(req); Object restartProcessObj = req.getParameter(MOAIDAuthConstants.PARAM_SLORESTART); @@ -73,9 +99,9 @@ public class IDPSingleLogOutServlet extends AuthServlet { if (tokkenObj != null && tokkenObj instanceof String) { tokken = (String) tokkenObj; try { - status = AssertionStorage.getInstance().get(tokken, String.class); + status = transactionStorage.get(tokken, String.class); if (MiscUtil.isNotEmpty(status)) { - AssertionStorage.getInstance().remove(tokken); + transactionStorage.remove(tokken); } VelocityContext context = new VelocityContext(); @@ -86,13 +112,13 @@ public class IDPSingleLogOutServlet extends AuthServlet { context.put("errorMsg", MOAIDMessageProvider.getInstance().getMessage("slo.01", null)); - ssomanager.printSingleLogOutInfo(context, resp); + ssoManager.printSingleLogOutInfo(context, resp); } catch (MOAIDException e) { - handleErrorNoRedirect(e.getMessage(), e, req, resp); + handleErrorNoRedirect(e, req, resp, false); } catch (MOADatabaseException e) { - handleErrorNoRedirect(e.getMessage(), e, req, resp); + handleErrorNoRedirect(e, req, resp, false); } @@ -100,16 +126,14 @@ public class IDPSingleLogOutServlet extends AuthServlet { } else if (MiscUtil.isNotEmpty(ssoid)) { try { - if (ssomanager.isValidSSOSession(ssoid, null)) { + if (ssoManager.isValidSSOSession(ssoid, null)) { - AuthenticationManager authmanager = AuthenticationManager.getInstance(); - String moaSessionID = AuthenticationSessionStoreage.getMOASessionSSOID(ssoid); + String moaSessionID = authenicationStorage.getMOASessionSSOID(ssoid); if (MiscUtil.isNotEmpty(moaSessionID)) { - AuthenticationSession authSession = AuthenticationSessionStoreage - .getSession(moaSessionID); + AuthenticationSession authSession = authenicationStorage.getSession(moaSessionID); if(authSession != null) { - authmanager.performSingleLogOut(req, resp, authSession, null); + authManager.performSingleLogOut(req, resp, authSession, authURL); return; } @@ -129,20 +153,20 @@ public class IDPSingleLogOutServlet extends AuthServlet { if (MiscUtil.isNotEmpty(restartProcess)) { Logger.info("Restart Single LogOut process after timeout ... "); try { - SLOInformationContainer sloContainer = AssertionStorage.getInstance().get(restartProcess, SLOInformationContainer.class); + ISLOInformationContainer sloContainer = transactionStorage.get(restartProcess, SLOInformationContainer.class); if (sloContainer.hasFrontChannelOA()) sloContainer.putFailedOA("differntent OAs"); String redirectURL = null; if (sloContainer.getSloRequest() != null) { //send SLO response to SLO request issuer - SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(sloContainer.getSloRequest()); - LogoutResponse message = SingleLogOutBuilder.buildSLOResponseMessage(sloService, sloContainer.getSloRequest(), sloContainer.getSloFailedOAs()); - redirectURL = SingleLogOutBuilder.getFrontChannelSLOMessageURL(sloService, message, req, resp, sloContainer.getSloRequest().getRequest().getRelayState()); + SingleLogoutService sloService = sloBuilder.getResponseSLODescriptor(sloContainer.getSloRequest()); + LogoutResponse message = sloBuilder.buildSLOResponseMessage(sloService, sloContainer.getSloRequest(), sloContainer.getSloFailedOAs()); + redirectURL = sloBuilder.getFrontChannelSLOMessageURL(sloService, message, req, resp, sloContainer.getSloRequest().getRequest().getRelayState()); } else { //print SLO information directly - redirectURL = AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix() + "/idpSingleLogout"; + redirectURL = HTTPUtils.extractAuthURLFromRequest(req) + "/idpSingleLogout"; String artifact = Random.nextRandom(); @@ -153,13 +177,13 @@ public class IDPSingleLogOutServlet extends AuthServlet { else statusCode = MOAIDAuthConstants.SLOSTATUS_ERROR; - AssertionStorage.getInstance().put(artifact, statusCode); - redirectURL = addURLParameter(redirectURL, MOAIDAuthConstants.PARAM_SLOSTATUS, artifact); + transactionStorage.put(artifact, statusCode); + redirectURL = HTTPUtils.addURLParameter(redirectURL, MOAIDAuthConstants.PARAM_SLOSTATUS, artifact); } - //redirect to Redirect Servlet - String url = AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix() + "/RedirectServlet"; - url = addURLParameter(url, RedirectServlet.REDIRCT_PARAM_URL, URLEncoder.encode(redirectURL, "UTF-8")); + //redirect to Redirect Servlet + String url = authURL + "/RedirectServlet"; + url = HTTPUtils.addURLParameter(url, RedirectServlet.REDIRCT_PARAM_URL, URLEncoder.encode(redirectURL, "UTF-8")); url = resp.encodeRedirectURL(url); resp.setContentType("text/html"); @@ -187,10 +211,11 @@ public class IDPSingleLogOutServlet extends AuthServlet { MOAIDMessageProvider.getInstance().getMessage("slo.01", null)); try { - ssomanager.printSingleLogOutInfo(context, resp); + ssoManager.printSingleLogOutInfo(context, resp); } catch (MOAIDException e) { e.printStackTrace(); + } return; } @@ -200,10 +225,11 @@ public class IDPSingleLogOutServlet extends AuthServlet { context.put("successMsg", MOAIDMessageProvider.getInstance().getMessage("slo.02", null)); try { - ssomanager.printSingleLogOutInfo(context, resp); + ssoManager.printSingleLogOutInfo(context, resp); } catch (MOAIDException e) { e.printStackTrace(); + } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/LogOutServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/LogOutServlet.java index c1e084a59..4ed276814 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/LogOutServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/LogOutServlet.java @@ -48,112 +48,88 @@ package at.gv.egovernment.moa.id.auth.servlet; import java.io.IOException; -import javax.servlet.ServletConfig; -import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; import at.gv.egovernment.moa.id.moduls.AuthenticationManager; -import at.gv.egovernment.moa.id.moduls.RequestStorage; import at.gv.egovernment.moa.id.moduls.SSOManager; -import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; +import at.gv.egovernment.moa.id.storage.IAuthenticationSessionStoreage; +import at.gv.egovernment.moa.id.util.HTTPUtils; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; -public class LogOutServlet extends AuthServlet { - - private static final long serialVersionUID = 3908001651893673395L; +@Controller +public class LogOutServlet { private static final String REDIRECT_URL = "redirect"; - protected void doGet(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - - Logger.debug("receive LogOut Request"); - - String redirectUrl = (String) req.getParameter(REDIRECT_URL); - - SSOManager ssomanager = SSOManager.getInstance(); + @Autowired private SSOManager ssomanager; + @Autowired private AuthenticationManager authmanager; + @Autowired private IAuthenticationSessionStoreage authenticatedSessionStorage; - try { - //get SSO token from request - String ssoid = ssomanager.getSSOSessionID(req); - - if (MiscUtil.isEmpty(redirectUrl)) { - //set default redirect Target - Logger.debug("Set default RedirectURL back to MOA-ID-Auth"); - redirectUrl = AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix(); + @RequestMapping(value = "/LogOut", method = {RequestMethod.POST, RequestMethod.GET}) + public void performLogOut(HttpServletRequest req, HttpServletResponse resp) throws IOException { + Logger.debug("receive LogOut Request"); + + String redirectUrl = (String) req.getParameter(REDIRECT_URL); + + try { + //get SSO token from request + String ssoid = ssomanager.getSSOSessionID(req); - } else { - //return an error if RedirectURL is not a active Online-Applikation - OAAuthParameter oa = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(redirectUrl); - if (oa == null) { - Logger.info("RedirctURL does not match to OA configuration. Set default RedirectURL back to MOA-ID-Auth"); - redirectUrl = AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix(); + if (MiscUtil.isEmpty(redirectUrl)) { + //set default redirect Target + Logger.debug("Set default RedirectURL back to MOA-ID-Auth"); + redirectUrl = HTTPUtils.extractAuthURLFromRequest(req); + + } else { + //return an error if RedirectURL is not a active Online-Applikation + OAAuthParameter oa = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(redirectUrl); + if (oa == null) { + Logger.info("RedirctURL does not match to OA configuration. Set default RedirectURL back to MOA-ID-Auth"); + redirectUrl = HTTPUtils.extractAuthURLFromRequest(req); + + } } - } + if (ssomanager.isValidSSOSession(ssoid, null)) { - if (ssomanager.isValidSSOSession(ssoid, null)) { - - //TODO: Single LogOut Implementation - - //delete SSO session and MOA session - AuthenticationManager authmanager = AuthenticationManager.getInstance(); - String moasessionid = AuthenticationSessionStoreage.getMOASessionSSOID(ssoid); - - RequestStorage.removePendingRequest(AuthenticationSessionStoreage.getPendingRequestID(moasessionid)); + //TODO: Single LogOut Implementation + + //delete SSO session and MOA session + String moasessionid = authenticatedSessionStorage.getMOASessionSSOID(ssoid); + authmanager.performOnlyIDPLogOut(req, resp, moasessionid); + + Logger.info("User with SSO Id " + ssoid + " is logged out and get redirect to "+ redirectUrl); + } else { + Logger.info("No active SSO session found. User is maybe logout already and get redirect to "+ redirectUrl); + + } + + //Remove SSO token + ssomanager.deleteSSOSessionID(req, resp); + + } catch (Exception e) { + resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Request not allowed."); + return; + + } finally { + - authmanager.performOnlyIDPLogOut(req, resp, moasessionid); - Logger.info("User with SSO Id " + ssoid + " is logged out and get redirect to "+ redirectUrl); - } else { - Logger.info("No active SSO session found. User is maybe logout already and get redirect to "+ redirectUrl); } - - //Remove SSO token - ssomanager.deleteSSOSessionID(req, resp); - - } catch (Exception e) { - resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Request not allowed."); - return; - - } finally { - - + + //Redirect to Application + resp.setStatus(302); + resp.addHeader("Location", redirectUrl); + } - - //Redirect to Application - resp.setStatus(302); - resp.addHeader("Location", redirectUrl); - } - - - protected void doPost(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - - doGet(req, resp); - } - - - /** - * Calls the web application initializer. - * - * @see javax.servlet.Servlet#init(ServletConfig) - */ - public void init(ServletConfig servletConfig) throws ServletException { -// try { -// super.init(servletConfig); -// MOAIDAuthInitializer.initialize(); -// Logger.info(MOAIDMessageProvider.getInstance().getMessage("init.00", null)); -// } -// catch (Exception ex) { -// Logger.fatal(MOAIDMessageProvider.getInstance().getMessage("init.02", null), ex); -// throw new ServletException(ex); -// } - } - + } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/ProcessEngineSignalServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/ProcessEngineSignalServlet.java deleted file mode 100644 index f3e3ae8a4..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/ProcessEngineSignalServlet.java +++ /dev/null @@ -1,122 +0,0 @@ -package at.gv.egovernment.moa.id.auth.servlet;
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.lang.StringEscapeUtils;
-
-import at.gv.egovernment.moa.id.advancedlogging.TransactionIDUtils;
-import at.gv.egovernment.moa.id.auth.BaseAuthenticationServer;
-import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
-import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
-import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionExtensions;
-import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
-import at.gv.egovernment.moa.id.moduls.IRequest;
-import at.gv.egovernment.moa.id.moduls.RequestStorage;
-import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
-import at.gv.egovernment.moa.logging.Logger;
-
-/**
- * Servlet that resumes a suspended process (in case of asynchronous tasks).
- *
- * @author tknall
- *
- */
-public class ProcessEngineSignalServlet extends AuthServlet {
-
- private static final long serialVersionUID = 1L;
-
- /**
- * Sets response headers that prevent caching (code taken from {@link AuthServlet}).
- *
- * @param resp
- * The HttpServletResponse.
- */
- private void setNoCachingHeaders(HttpServletResponse resp) {
- resp.setHeader(MOAIDAuthConstants.HEADER_EXPIRES, MOAIDAuthConstants.HEADER_VALUE_EXPIRES);
- resp.setHeader(MOAIDAuthConstants.HEADER_PRAGMA, MOAIDAuthConstants.HEADER_VALUE_PRAGMA);
- resp.setHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL, MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL);
- resp.addHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL, MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL_IE);
- }
-
- /**
- * Processes a GET request, delegating the call to {@link #doPost(HttpServletRequest, HttpServletResponse)}.
- */
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- this.doPost(req, resp);
- }
-
- /**
- * Resumes the current process instance that has been suspended due to an asynchronous task. The process instance is
- * retrieved from the MOA session referred to by the request parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}.
- */
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- String sessionID = StringEscapeUtils.escapeHtml(getMoaSessionId(req));
-
- setNoCachingHeaders(resp);
- String pendingRequestID = null;
- try {
-
- if (sessionID == null) {
- throw new IllegalStateException("Unable to determine MOA session id.");
- }
-
- // retrieve moa session
- pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
-
- IRequest pendingReq = RequestStorage.getPendingRequest(pendingRequestID);
- if (pendingReq == null) {
- Logger.info("No PendingRequest with Id: " + pendingRequestID + " Maybe, a transaction timeout occure.");
- throw new MOAIDException("auth.28", new Object[]{pendingRequestID});
-
- }
-
- AuthenticationSessionExtensions extendedSessionInformation = AuthenticationSessionStoreage.getAuthenticationSessionExtensions(sessionID);
- AuthenticationSession session = BaseAuthenticationServer.getSession(sessionID);
-
- //add transactionID and unique sessionID to Logger
- if (extendedSessionInformation != null)
- TransactionIDUtils.setSessionId(extendedSessionInformation.getUniqueSessionId());
- TransactionIDUtils.setTransactionId(pendingRequestID);
-
- // process instance is mandatory
- if (session.getProcessInstanceId() == null) {
- throw new IllegalStateException("MOA session does not provide process instance id.");
- }
-
- // wake up next task
- getProcessEngine().signal(session.getProcessInstanceId());
-
- } catch (Exception ex) {
- handleError(null, ex, req, resp, pendingRequestID);
-
- } finally {
- //MOASessionDBUtils.closeSession();
- TransactionIDUtils.removeTransactionId();
- TransactionIDUtils.removeSessionId();
-
- }
-
- }
-
- /**
- * Retrieves the current MOA session id from the HttpServletRequest parameter
- * {@link MOAIDAuthConstants#PARAM_SESSIONID}.
- * <p/>
- * Note that this class/method can be overwritten by modules providing their own strategy of retrieving the
- * respective MOA session id.
- *
- * @param request
- * The unterlying HttpServletRequest.
- * @return The current MOA session id.
- */
- public String getMoaSessionId(HttpServletRequest request) {
- return StringEscapeUtils.escapeHtml(request.getParameter(MOAIDAuthConstants.PARAM_SESSIONID));
- }
-
-}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/RedirectServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/RedirectServlet.java index 7dd8645c6..ba8ace6c9 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/RedirectServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/RedirectServlet.java @@ -25,34 +25,36 @@ package at.gv.egovernment.moa.id.auth.servlet; import java.io.IOException; import java.io.PrintWriter; -import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; import at.gv.egovernment.moa.id.auth.builder.RedirectFormBuilder; - import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; import at.gv.egovernment.moa.id.moduls.SSOManager; import at.gv.egovernment.moa.id.util.FormBuildUtils; +import at.gv.egovernment.moa.id.util.HTTPUtils; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; import at.gv.egovernment.moa.util.URLEncoder; - -public class RedirectServlet extends AuthServlet{ - - private static final long serialVersionUID = 1L; +@Controller +public class RedirectServlet { public static final String REDIRCT_PARAM_URL = "redirecturl"; - private static final String DEFAULT_REDIRECTTARGET = "_parent"; + @Autowired SSOManager ssoManager; - protected void doGet(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { + @RequestMapping(value = "/RedirectServlet", method = RequestMethod.GET) + public void performLogOut(HttpServletRequest req, HttpServletResponse resp) throws IOException { Logger.debug("Receive " + RedirectServlet.class + " Request"); String url = req.getParameter(REDIRCT_PARAM_URL); @@ -64,8 +66,10 @@ public class RedirectServlet extends AuthServlet{ OAAuthParameter oa = null; String redirectTarget = DEFAULT_REDIRECTTARGET; try { - oa = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(url); - if (oa == null && !url.startsWith(AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix())) { + oa = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(url); + String authURL = HTTPUtils.extractAuthURLFromRequest(req); + + if (oa == null && !AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix().contains(authURL)) { resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Parameters not valid"); return; @@ -86,12 +90,12 @@ public class RedirectServlet extends AuthServlet{ if (MiscUtil.isNotEmpty(target)) { // redirectURL = addURLParameter(redirectURL, PARAM_TARGET, // URLEncoder.encode(session.getTarget(), "UTF-8")); - url = addURLParameter(url, MOAIDAuthConstants.PARAM_TARGET, + url = HTTPUtils.addURLParameter(url, MOAIDAuthConstants.PARAM_TARGET, URLEncoder.encode(target, "UTF-8")); } - url = addURLParameter(url, MOAIDAuthConstants.PARAM_SAMLARTIFACT, + url = HTTPUtils.addURLParameter(url, MOAIDAuthConstants.PARAM_SAMLARTIFACT, URLEncoder.encode(artifact, "UTF-8")); url = resp.encodeRedirectURL(url); @@ -106,8 +110,7 @@ public class RedirectServlet extends AuthServlet{ } else if (MiscUtil.isNotEmpty(interIDP)) { //store IDP identifier and redirect to generate AuthRequst service Logger.info("Receive an interfederation redirect request for IDP " + interIDP); - SSOManager sso = SSOManager.getInstance(); - sso.setInterfederationIDPCookie(req, resp, interIDP); + ssoManager.setInterfederationIDPCookie(req, resp, interIDP); Logger.debug("Redirect to " + url); url = resp.encodeRedirectURL(url); @@ -138,7 +141,7 @@ public class RedirectServlet extends AuthServlet{ } + } - } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/SAML2InterfederationSignalServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/SAML2InterfederationSignalServlet.java index 62ee1ed85..1d18ccb2c 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/SAML2InterfederationSignalServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/SAML2InterfederationSignalServlet.java @@ -28,9 +28,7 @@ package at.gv.egovernment.moa.id.auth.servlet; */ public class SAML2InterfederationSignalServlet extends - ProcessEngineSignalServlet { - - private static final long serialVersionUID = 8208970012249149156L; + AbstractProcessEngineSignalController { //TODO: getMOASessionID from SAML2 relayState diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/SSOSendAssertionServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/SSOSendAssertionServlet.java deleted file mode 100644 index 064431a6b..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/SSOSendAssertionServlet.java +++ /dev/null @@ -1,176 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 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: - * http://www.osor.eu/eupl/ - * - * 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.egovernment.moa.id.auth.servlet; - -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang.StringEscapeUtils; - -import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; -import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger; -import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder; -import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; -import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; -import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; -import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; -import at.gv.egovernment.moa.id.moduls.IRequest; -import at.gv.egovernment.moa.id.moduls.ModulUtils; -import at.gv.egovernment.moa.id.moduls.RequestStorage; -import at.gv.egovernment.moa.id.moduls.SSOManager; -import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; -import at.gv.egovernment.moa.id.util.ParamValidatorUtils; -import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.MiscUtil; - -public class SSOSendAssertionServlet extends AuthServlet{ - - private static final long serialVersionUID = 1L; - - private static final String PARAM = "value"; - private static final String MODULE = "mod"; - private static final String ACTION = "action"; - private static final String ID = "identifier"; - - protected void doPost(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - - String id = null; - Logger.debug("Receive " + SSOSendAssertionServlet.class + " Request"); - try { - - Object idObject = req.getParameter(ID); - - if (idObject != null && (idObject instanceof String)) { - id = (String) idObject; - } - - String value = req.getParameter(PARAM); - value = StringEscapeUtils.escapeHtml(value); - if (!ParamValidatorUtils.isValidUseMandate(value)) - throw new WrongParametersException("SSOSendAssertionServlet", PARAM, null); - - //get module and action - Object moduleObject = req.getParameter(MODULE); - String module = null; - if (moduleObject != null && (moduleObject instanceof String)) { - module = (String) moduleObject; - } - - - Object actionObject = req.getParameter(ACTION); - String action = null; - if (actionObject != null && (actionObject instanceof String)) { - action = (String) actionObject; - } - - if (MiscUtil.isEmpty(module) || MiscUtil.isEmpty(action) || MiscUtil.isEmpty(id)) { - Logger.warn("No Moduel or Action parameter received!"); - throw new WrongParametersException("Module or Action is empty", "", "auth.10"); - } - - - SSOManager ssomanager = SSOManager.getInstance(); - //get SSO Cookie for Request - String ssoId = ssomanager.getSSOSessionID(req); - - //check SSO session - if (ssoId != null) { - String correspondingMOASession = ssomanager.existsOldSSOSession(ssoId); - - if (correspondingMOASession != null) { - Logger.warn("Request sends an old SSO Session ID("+ssoId+")! " + - "Invalidate the corresponding MOASession with ID="+ correspondingMOASession); - - - AuthenticationSessionStoreage.destroySession(correspondingMOASession); - - ssomanager.deleteSSOSessionID(req, resp); - } - } - - boolean isValidSSOSession = ssomanager.isValidSSOSession(ssoId, null); - - String moaSessionID = null; - - if (isValidSSOSession) { - - - //check UseMandate flag - String valueString = null;; - if ((value != null) && (value.compareTo("") != 0)) { - valueString = value; - } else { - valueString = "false"; - } - - if (valueString.compareToIgnoreCase("true") == 0) { - moaSessionID = AuthenticationSessionStoreage.getMOASessionSSOID(ssoId); - AuthenticationSession moasession = AuthenticationSessionStoreage.getSession(moaSessionID); - AuthenticationSessionStoreage.setAuthenticated(moaSessionID, true); - - //log event - //String pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(moaSessionID); - IRequest pendingReq = RequestStorage.getPendingRequest(id); - MOAReversionLogger.getInstance().logEvent(pendingReq, MOAIDEventConstants.AUTHPROCESS_SSO_ASK_USER_FINISHED); - - String redirectURL = new DataURLBuilder().buildDataURL(moasession.getAuthURL(), - ModulUtils.buildAuthURL(module, action, id), ""); - - resp.setContentType("text/html"); - resp.setStatus(302); - - - resp.addHeader("Location", redirectURL); - Logger.debug("REDIRECT TO: " + redirectURL); - - } - - else { - throw new AuthenticationException("auth.21", new Object[] {}); - } - - } else { - handleError("SSO Session is not valid", null, req, resp, id); - } - - - } catch (MOADatabaseException e) { - handleError("SSO Session is not found", e, req, resp, id); - - } catch (WrongParametersException e) { - handleError("Parameter is not valid", e, req, resp, id); - - } catch (AuthenticationException e) { - handleError(e.getMessage(), e, req, resp, id); - - } catch (Exception e) { - Logger.error("SSOSendAssertion has an interal Error.", e); - } - - } - -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/interceptor/UniqueSessionIdentifierInterceptor.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/interceptor/UniqueSessionIdentifierInterceptor.java new file mode 100644 index 000000000..bedc67513 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/interceptor/UniqueSessionIdentifierInterceptor.java @@ -0,0 +1,86 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.servlet.interceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +import at.gv.egovernment.moa.id.advancedlogging.TransactionIDUtils; +import at.gv.egovernment.moa.id.commons.MOAIDConstants; +import at.gv.egovernment.moa.id.moduls.SSOManager; +import at.gv.egovernment.moa.id.util.Random; +import at.gv.egovernment.moa.util.MiscUtil; + +/** + * @author tlenz + * + */ +public class UniqueSessionIdentifierInterceptor implements HandlerInterceptor { + + @Autowired private SSOManager ssomanager; + + /* (non-Javadoc) + * @see org.springframework.web.servlet.HandlerInterceptor#preHandle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object) + */ + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + + //get SSO Cookie for Request + String ssoId = ssomanager.getSSOSessionID(request); + + //search for unique session identifier + String uniqueSessionIdentifier = ssomanager.getUniqueSessionIdentifier(ssoId); + if (MiscUtil.isEmpty(uniqueSessionIdentifier)) + uniqueSessionIdentifier = Random.nextRandom(); + TransactionIDUtils.setSessionId(uniqueSessionIdentifier); + + request.setAttribute(MOAIDConstants.UNIQUESESSIONIDENTIFIER, uniqueSessionIdentifier); + + return true; + } + + /* (non-Javadoc) + * @see org.springframework.web.servlet.HandlerInterceptor#postHandle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, org.springframework.web.servlet.ModelAndView) + */ + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, + ModelAndView modelAndView) throws Exception { + + } + + /* (non-Javadoc) + * @see org.springframework.web.servlet.HandlerInterceptor#afterCompletion(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception) + */ + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) + throws Exception { + // TODO Auto-generated method stub + + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/interceptor/WebFrontEndSecurityInterceptor.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/interceptor/WebFrontEndSecurityInterceptor.java new file mode 100644 index 000000000..c5a9ad34b --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/interceptor/WebFrontEndSecurityInterceptor.java @@ -0,0 +1,104 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.servlet.interceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; +import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; +import at.gv.egovernment.moa.id.util.HTTPUtils; +import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; + +/** + * @author tlenz + * + */ +public class WebFrontEndSecurityInterceptor implements HandlerInterceptor { + + @Autowired AuthConfiguration authConfig; + + /* (non-Javadoc) + * @see org.springframework.web.servlet.HandlerInterceptor#preHandle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object) + */ + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + + //only for SAML1 GetAuthenticationData webService functionality + String requestedServlet = request.getServletPath(); + if (MiscUtil.isNotEmpty(requestedServlet) && requestedServlet.startsWith("/services/GetAuthenticationData")) { + Logger.debug("SAML1 GetAuthenticationServices allow access without SSL"); + return true; + + } + + //check AuthURL + String authURL = HTTPUtils.extractAuthURLFromRequest(request); + if (!authURL.startsWith("https:") && !authConfig.isHTTPAuthAllowed()) { + String errorMsg = MOAIDMessageProvider.getInstance().getMessage("auth.07", new Object[] { authURL + "*" }); + Logger.info(errorMsg); + response.sendError( + HttpServletResponse.SC_FORBIDDEN, + errorMsg); + + return false; + } else { + return true; + + } + } + + /* (non-Javadoc) + * @see org.springframework.web.servlet.HandlerInterceptor#postHandle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, org.springframework.web.servlet.ModelAndView) + */ + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, + ModelAndView modelAndView) throws Exception { + + //TODO: add additional headers or checks + + //set security headers + response.setHeader(MOAIDAuthConstants.HEADER_EXPIRES, MOAIDAuthConstants.HEADER_VALUE_EXPIRES); + response.setHeader(MOAIDAuthConstants.HEADER_PRAGMA, MOAIDAuthConstants.HEADER_VALUE_PRAGMA); + response.setHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL, MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL); + response.addHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL, MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL_IE); + + } + + /* (non-Javadoc) + * @see org.springframework.web.servlet.HandlerInterceptor#afterCompletion(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception) + */ + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) + throws Exception { + + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfiguration.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfiguration.java index 1d8ea4cd4..1f9259696 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfiguration.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfiguration.java @@ -90,12 +90,15 @@ public interface AuthConfiguration extends ConfigurationProvider{ public boolean isAdvancedLoggingActive(); /** - * Returns the PublicURLPrefix. NOTE: returns {@code null} if no PublicURLPrefix is set. + * Returns the PublicURLPrefix. * - * @return the PublicURLPrefix without trailing slash or {@code null} + * @return the PublicURLPrefix (one or more) of this IDP instance. All publicURLPrefix URLs are ends without / + * @throws ConfigurationException if no PublicURLPrefix is found. */ - public String getPublicURLPrefix(); + public List<String> getPublicURLPrefix() throws ConfigurationException; + public boolean isVirtualIDPsEnabled(); + public boolean isPVP2AssertionEncryptionActive(); public boolean isCertifiacteQCActive(); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProviderFactory.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProviderFactory.java index 38135b028..a00d3d313 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProviderFactory.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProviderFactory.java @@ -22,12 +22,9 @@ */ package at.gv.egovernment.moa.id.config.auth; -import java.net.URI; -import java.net.URISyntaxException; +import org.springframework.context.ApplicationContext; -import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; import at.gv.egovernment.moa.id.config.ConfigurationException; -import at.gv.egovernment.moa.id.config.ConfigurationProvider; import at.gv.egovernment.moa.logging.Logger; /** @@ -44,7 +41,8 @@ public class AuthConfigurationProviderFactory { throws ConfigurationException { if (instance == null) { - reload(); + Logger.fatal("MOA-ID-Auth Configuration is not initialized!!!!!"); + } return instance; } @@ -53,22 +51,9 @@ public class AuthConfigurationProviderFactory { * @return * @throws ConfigurationException */ - public static AuthConfiguration reload() throws ConfigurationException { - String fileName = System.getProperty(ConfigurationProvider.CONFIG_PROPERTY_NAME); - if (fileName == null) { - throw new ConfigurationException("config.01", null); - } - Logger.info("Loading MOA-ID-AUTH configuration " + fileName); - - try { - URI fileURI = new URI(fileName); - instance = new PropertyBasedAuthConfigurationProvider(fileURI); - - } catch (URISyntaxException e){ - Logger.error("MOA-ID-Auth configuration file does not starts with file:/ as prefix."); - throw new ConfigurationException("config24", new Object[]{MOAIDAuthConstants.FILE_URI_PREFIX, fileName}); - - } + public static AuthConfiguration reload(ApplicationContext springContext) throws ConfigurationException { + instance = springContext.getBean("moaidauthconfig", AuthConfiguration.class); return instance; + } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/IOAAuthParameters.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/IOAAuthParameters.java index b68f42086..58034cc7b 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/IOAAuthParameters.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/IOAAuthParameters.java @@ -66,6 +66,11 @@ public interface IOAAuthParameters { public boolean getBusinessService(); + /** + * Get target of a public service-provider + * + * @return target identifier without prefix + */ public String getTarget(); public String getTargetFriendlyName(); @@ -74,7 +79,11 @@ public interface IOAAuthParameters { public boolean isSTORKPVPGateway(); + public boolean isRemovePBKFromAuthBlock(); + /** + * Return the private-service domain-identifier with PreFix + * * @return the identityLinkDomainIdentifier */ public String getIdentityLinkDomainIdentifier(); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/PropertyBasedAuthConfigurationProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/PropertyBasedAuthConfigurationProvider.java index dce7de526..ed2f4d96b 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/PropertyBasedAuthConfigurationProvider.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/PropertyBasedAuthConfigurationProvider.java @@ -6,6 +6,8 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -16,14 +18,19 @@ import java.util.Map; import java.util.Properties; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.config.AutowireCapableBeanFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; +import at.gv.egovernment.moa.id.commons.MOAIDConstants; import at.gv.egovernment.moa.id.commons.config.MOAIDConfigurationConstants; import at.gv.egovernment.moa.id.commons.config.persistence.MOAIDConfiguration; +import at.gv.egovernment.moa.id.commons.db.dao.config.deprecated.AuthComponentGeneral; +import at.gv.egovernment.moa.id.commons.db.dao.config.deprecated.MOASP; +import at.gv.egovernment.moa.id.commons.db.dao.config.deprecated.OnlineApplication; +import at.gv.egovernment.moa.id.commons.db.dao.config.deprecated.SecurityLayer; +import at.gv.egovernment.moa.id.commons.db.dao.config.deprecated.VerifyIdentityLink; +import at.gv.egovernment.moa.id.commons.utils.KeyValueUtils; import at.gv.egovernment.moa.id.config.ConfigurationException; +import at.gv.egovernment.moa.id.config.ConfigurationProvider; import at.gv.egovernment.moa.id.config.ConfigurationProviderImpl; import at.gv.egovernment.moa.id.config.ConfigurationUtils; import at.gv.egovernment.moa.id.config.ConnectionParameter; @@ -46,19 +53,44 @@ public class PropertyBasedAuthConfigurationProvider extends ConfigurationProvide private MOAIDConfiguration configuration; private final Properties properties = new Properties(); - private ApplicationContext context = null; - public PropertyBasedAuthConfigurationProvider() { + private boolean requireJDBCBackupImplementation = false; + + public PropertyBasedAuthConfigurationProvider(String configFileName) throws ConfigurationException { + if (configFileName == null) { + configFileName = System.getProperty(ConfigurationProvider.CONFIG_PROPERTY_NAME); + + if (MiscUtil.isEmpty(configFileName)) + throw new ConfigurationException("config.01", null); + } + + Logger.info("Loading MOA-ID-AUTH configuration " + configFileName); + + try { + URI fileURI = new URI(configFileName); + //instance = new PropertyBasedAuthConfigurationProvider(fileURI); + initialize(fileURI); + + } catch (URISyntaxException e){ + Logger.error("MOA-ID-Auth configuration file does not starts with file:/ as prefix.", e); + throw new ConfigurationException("config24", new Object[]{MOAIDAuthConstants.FILE_URI_PREFIX, configFileName}); + + } } - /** - * The constructor with path to a properties file as argument. - * - * @param fileName the path to the properties file - * @throws ConfigurationException if an error occurs during loading the properties file. - */ - public PropertyBasedAuthConfigurationProvider(URI fileName) throws ConfigurationException { +// /** +// * The constructor with path to a properties file as argument. +// * +// * @param fileName the path to the properties file +// * @throws ConfigurationException if an error occurs during loading the properties file. +// */ +// public PropertyBasedAuthConfigurationProvider(URI fileName) throws ConfigurationException { +// initialize(fileName); +// +// } + + private void initialize(URI fileName) throws ConfigurationException { File propertiesFile = new File(fileName); rootConfigFileDir = propertiesFile.getParent(); try { @@ -77,13 +109,27 @@ public class PropertyBasedAuthConfigurationProvider extends ConfigurationProvide // JPAPropertiesWithJavaConfig.setLocalProperties(configProp); // System.getProperties().setProperty("location", "file:" + fileName); - context = new ClassPathXmlApplicationContext( - new String[] { "moaid.configuration.beans.xml", - "configuration.beans.xml" - }); - AutowireCapableBeanFactory acbFactory = context.getAutowireCapableBeanFactory(); - acbFactory.autowireBean(this); +// context = new ClassPathXmlApplicationContext( +// new String[] { "moaid.configuration.beans.xml", +// "configuration.beans.xml" +// }); +// AutowireCapableBeanFactory acbFactory = context.getAutowireCapableBeanFactory(); +// acbFactory.autowireBean(this); + + //Some databases do not allow the selection of a lob in SQL where expression + String dbDriver = properties.getProperty("configuration.hibernate.connection.driver_class"); + if (MiscUtil.isNotEmpty(dbDriver)) { + for (String el:MOAIDConstants.JDBC_DRIVER_NEEDS_WORKAROUND) { + if (dbDriver.startsWith(el)) { + requireJDBCBackupImplementation = true; + Logger.info("JDBC driver '" + dbDriver + + "' is blacklisted --> Switch to alternative DB access methode implementation."); + + } + } + } + } catch (FileNotFoundException e) { throw new ConfigurationException("config.03", null, e); @@ -109,8 +155,9 @@ public class PropertyBasedAuthConfigurationProvider extends ConfigurationProvide } } + } - + /** * Set the {@link Configuration} for this class. * @param configuration the configuration @@ -303,11 +350,19 @@ public class PropertyBasedAuthConfigurationProvider extends ConfigurationProvide List<String> legacy = new ArrayList<String>(); try { - if (configuration.getBooleanValue(MOAIDConfigurationConstants.GENERAL_PROTOCOLS_SAML1_LEGACY, false)) - legacy.add("id_saml1"); - + if (configuration.getBooleanValue(MOAIDConfigurationConstants.GENERAL_PROTOCOLS_SAML1_LEGACY, false)) { + try { + Class<?> saml1Protocol = Class.forName("at.gv.egovernment.moa.id.protocols.saml1.SAML1Protocol"); + legacy.add(saml1Protocol.getName()); + + } catch (ClassNotFoundException e) { + Logger.warn("SAML1 Protocol implementation is not found, but SAML1 legacy-mode is active.. "); + + } + + } if (configuration.getBooleanValue(MOAIDConfigurationConstants.GENERAL_PROTOCOLS_PVP2X_LEGACY, false)) - legacy.add(PVP2XProtocol.PATH); + legacy.add(PVP2XProtocol.NAME); } catch (at.gv.egiz.components.configuration.api.ConfigurationException e) { Logger.warn("Load legacy protocol configuration property FAILED.", e); @@ -796,20 +851,47 @@ public class PropertyBasedAuthConfigurationProvider extends ConfigurationProvide return Boolean.valueOf(prop); } - /** - * Returns the PublicURLPrefix. NOTE: returns {@code null} if no PublicURLPrefix is set. - * - * @return the PublicURLPrefix or {@code null} - */ - public String getPublicURLPrefix() { - try { - return configuration.getStringValue( - MOAIDConfigurationConstants.GENERAL_PUBLICURLPREFIX); + public List<String> getPublicURLPrefix() throws ConfigurationException{ + try { + String publicURLPrefixList = configuration.getStringValue( + MOAIDConfigurationConstants.GENERAL_PUBLICURLPREFIX); + List<String> returnValues = new ArrayList<String>(); + if (publicURLPrefixList != null) { + publicURLPrefixList = KeyValueUtils.normalizeCSVValueString(publicURLPrefixList); + List<String> publicURLPrefixArray = Arrays.asList(publicURLPrefixList.split(",")); + Logger.trace("Found " + publicURLPrefixArray.size() + " PublicURLPrefix in configuration."); + + + for (String el : publicURLPrefixArray) { + try { + new URL(el); + if (el.endsWith("/")) + returnValues.add(el.substring(0, el.length()-1)); + else + returnValues.add(el); + + } catch (MalformedURLException e) { + Logger.warn("IDP PublicURLPrefix URL " + el + " is not a valid URL", e); + } + } + } + + if (returnValues.size() > 0) + return returnValues; + + else { + Logger.warn("MOA-ID PublicURLPrefix is not found in configuration."); + throw new ConfigurationException("config.08", new Object[]{"IDP PublicURLPrefix"}); + + } + } catch (at.gv.egiz.components.configuration.api.ConfigurationException e) { Logger.warn("MOA-ID PublicURLPrefix can not be read from configuration.", e); - return null; + throw new ConfigurationException("config.08", new Object[]{"IDP PublicURLPrefix"}, e); + } + } /** @@ -988,9 +1070,11 @@ public class PropertyBasedAuthConfigurationProvider extends ConfigurationProvide Logger.trace("Get active OnlineApplication with ID " + id + " from database."); Map<String, String> oaConfig = null; try { - //OracleDB does not allow the selection of a lob in SQL where expression + + //TODO: + //Some databases do not allow the selection of a lob in SQL where expression String dbDriver = properties.getProperty("configuration.hibernate.connection.driver_class"); - if (MiscUtil.isNotEmpty(dbDriver) && dbDriver.startsWith("oracle.jdbc.")) + if (requireJDBCBackupImplementation) oaConfig = configuration.getOnlineApplicationBackupVersion(id); else @@ -1125,4 +1209,24 @@ public class PropertyBasedAuthConfigurationProvider extends ConfigurationProvide else return getMoaSpIdentityLinkTrustProfileID(); } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.config.auth.AuthConfiguration#isVirtualIDPsEnabled() + */ + @Override + public boolean isVirtualIDPsEnabled() { + try { + String value = configuration.getStringValue( + MOAIDConfigurationConstants.GENERAL_ISVIRTUALIDPSENABLED); + if (MiscUtil.isNotEmpty(value)) { + return Boolean.valueOf(value); + } + + } catch (at.gv.egiz.components.configuration.api.ConfigurationException e) { + Logger.error("Error during 'isVirutalIDPsEnabled' load operationen." , e); + + } + + return false; + } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/data/DynamicOAAuthParameters.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/data/DynamicOAAuthParameters.java index 386e04f45..171940063 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/data/DynamicOAAuthParameters.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/data/DynamicOAAuthParameters.java @@ -486,4 +486,13 @@ public class DynamicOAAuthParameters implements IOAAuthParameters, Serializable{ // TODO Auto-generated method stub return false; } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.config.auth.IOAAuthParameters#isRemovePBKFromAuthBlock() + */ + @Override + public boolean isRemovePBKFromAuthBlock() { + // TODO Auto-generated method stub + return false; + } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/ISLOInformationContainer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/ISLOInformationContainer.java new file mode 100644 index 000000000..18ffc5c6d --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/ISLOInformationContainer.java @@ -0,0 +1,67 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.data; + +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.Map.Entry; + +import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration; + +/** + * @author tlenz + * + */ +public interface ISLOInformationContainer { + + boolean hasFrontChannelOA(); + + Set<Entry<String, SLOInformationImpl>> getFrontChannelOASessionDescriptions(); + + void removeFrontChannelOA(String oaID); + + Iterator<String> getNextBackChannelOA(); + + SLOInformationImpl getBackChannelOASessionDescripten(String oaID); + + void removeBackChannelOA(String oaID); + + /** + * @return the sloRequest + */ + PVPTargetConfiguration getSloRequest(); + + /** + * @param sloRequest the sloRequest to set + */ + void setSloRequest(PVPTargetConfiguration sloRequest); + + /** + * @return the sloFailedOAs + */ + List<String> getSloFailedOAs(); + + void putFailedOA(String oaID); + +}
\ No newline at end of file diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationContainer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationContainer.java index d1e04e107..ba7f33821 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationContainer.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationContainer.java @@ -24,30 +24,20 @@ package at.gv.egovernment.moa.id.data; import java.io.Serializable; import java.util.ArrayList; -import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map.Entry; import java.util.Set; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.core.NameID; -import org.opensaml.saml2.metadata.SingleLogoutService; - -import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore; -import at.gv.egovernment.moa.id.commons.db.dao.session.OASessionStore; -import at.gv.egovernment.moa.id.protocols.pvp2x.PVP2XProtocol; import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration; -import at.gv.egovernment.moa.id.protocols.pvp2x.builder.SingleLogOutBuilder; -import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NOSLOServiceDescriptorException; /** * @author tlenz * */ -public class SLOInformationContainer implements Serializable { - +public class SLOInformationContainer implements Serializable, ISLOInformationContainer { + private static final long serialVersionUID = 7148730740582881862L; private PVPTargetConfiguration sloRequest = null; @@ -55,134 +45,111 @@ public class SLOInformationContainer implements Serializable { private LinkedHashMap<String, SLOInformationImpl> activeBackChannelOAs = null; private List<String> sloFailedOAs = null; - - public void parseActiveOAs(List<OASessionStore> dbOAs, String removeOAID) { - if (activeBackChannelOAs == null) - activeBackChannelOAs = new LinkedHashMap<String, SLOInformationImpl>(); - if (activeFrontChannalOAs == null) - activeFrontChannalOAs = new LinkedHashMap<String, SLOInformationImpl>(); - if (dbOAs != null) { - for (OASessionStore oa : dbOAs) { - if (!oa.getOaurlprefix().equals(removeOAID)) { - - //Actually only PVP 2.1 support Single LogOut - if (PVP2XProtocol.PATH.equals(oa.getProtocolType())) { - SingleLogoutService sloDesc; - try { - sloDesc = SingleLogOutBuilder.getRequestSLODescriptor(oa.getOaurlprefix()); - - if (sloDesc.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI)) - activeBackChannelOAs.put(oa.getOaurlprefix(), - new SLOInformationImpl( - oa.getAssertionSessionID(), - oa.getUserNameID(), - oa.getUserNameIDFormat(), - oa.getProtocolType(), - sloDesc)); - - else - activeFrontChannalOAs.put(oa.getOaurlprefix(), - new SLOInformationImpl( - oa.getAssertionSessionID(), - oa.getUserNameID(), - oa.getUserNameIDFormat(), - oa.getProtocolType(), - sloDesc)); - - } catch (NOSLOServiceDescriptorException e) { - putFailedOA(oa.getOaurlprefix()); - - } - - } else - putFailedOA(oa.getOaurlprefix()); - } - } - } + /** + * @return the activeFrontChannalOAs + */ + public LinkedHashMap<String, SLOInformationImpl> getActiveFrontChannalOAs() { + return activeFrontChannalOAs; } /** - * @param dbIDPs - * @param value + * @param activeFrontChannalOAs the activeFrontChannalOAs to set */ - public void parseActiveIDPs(List<InterfederationSessionStore> dbIDPs, - String removeIDP) { - if (activeBackChannelOAs == null) - activeBackChannelOAs = new LinkedHashMap<String, SLOInformationImpl>(); - if (activeFrontChannalOAs == null) - activeFrontChannalOAs = new LinkedHashMap<String, SLOInformationImpl>(); - - if (dbIDPs != null) { - for (InterfederationSessionStore el : dbIDPs) { - if (!el.getIdpurlprefix().equals(removeIDP)) { - - SingleLogoutService sloDesc; - try { - sloDesc = SingleLogOutBuilder.getRequestSLODescriptor(el.getIdpurlprefix()); - - activeFrontChannalOAs.put(el.getIdpurlprefix(), - new SLOInformationImpl( - el.getSessionIndex(), - el.getUserNameID(), - NameID.TRANSIENT, - PVP2XProtocol.PATH, - sloDesc)); - - } catch (NOSLOServiceDescriptorException e) { - putFailedOA(el.getIdpurlprefix()); - - } - } - } - } + public void setActiveFrontChannalOAs(LinkedHashMap<String, SLOInformationImpl> activeFrontChannalOAs) { + this.activeFrontChannalOAs = activeFrontChannalOAs; } - + + /** + * @return the activeBackChannelOAs + */ + public LinkedHashMap<String, SLOInformationImpl> getActiveBackChannelOAs() { + return activeBackChannelOAs; + } + + /** + * @param activeBackChannelOAs the activeBackChannelOAs to set + */ + public void setActiveBackChannelOAs(LinkedHashMap<String, SLOInformationImpl> activeBackChannelOAs) { + this.activeBackChannelOAs = activeBackChannelOAs; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.data.ISLOInformationContainer#hasFrontChannelOA() + */ + @Override public boolean hasFrontChannelOA() { return !activeFrontChannalOAs.isEmpty(); } + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.data.ISLOInformationContainer#getFrontChannelOASessionDescriptions() + */ + @Override public Set<Entry<String, SLOInformationImpl>> getFrontChannelOASessionDescriptions() { return activeFrontChannalOAs.entrySet(); } + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.data.ISLOInformationContainer#removeFrontChannelOA(java.lang.String) + */ + @Override public void removeFrontChannelOA(String oaID) { activeFrontChannalOAs.remove(oaID); } + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.data.ISLOInformationContainer#getNextBackChannelOA() + */ + @Override public Iterator<String> getNextBackChannelOA() { return activeBackChannelOAs.keySet().iterator(); } + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.data.ISLOInformationContainer#getBackChannelOASessionDescripten(java.lang.String) + */ + @Override public SLOInformationImpl getBackChannelOASessionDescripten(String oaID) { return activeBackChannelOAs.get(oaID); } + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.data.ISLOInformationContainer#removeBackChannelOA(java.lang.String) + */ + @Override public void removeBackChannelOA(String oaID) { activeBackChannelOAs.remove(oaID); } - /** - * @return the sloRequest + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.data.ISLOInformationContainer#getSloRequest() */ + @Override public PVPTargetConfiguration getSloRequest() { return sloRequest; } - /** - * @param sloRequest the sloRequest to set + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.data.ISLOInformationContainer#setSloRequest(at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration) */ + @Override public void setSloRequest(PVPTargetConfiguration sloRequest) { this.sloRequest = sloRequest; } - /** - * @return the sloFailedOAs + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.data.ISLOInformationContainer#getSloFailedOAs() */ + @Override public List<String> getSloFailedOAs() { return sloFailedOAs; } + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.data.ISLOInformationContainer#putFailedOA(java.lang.String) + */ + @Override public void putFailedOA(String oaID) { if (sloFailedOAs == null) sloFailedOAs = new ArrayList<String>(); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationImpl.java index 55b213702..55a56056d 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationImpl.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationImpl.java @@ -39,17 +39,23 @@ public class SLOInformationImpl implements SLOInformationInterface, Serializable private String nameIDFormat = null; private String binding = null; private String serviceURL = null; + private String authURL = null; - public SLOInformationImpl(String sessionID, String nameID, String nameIDFormat, String protocolType) { - new SLOInformationImpl(sessionID, nameID, nameIDFormat, protocolType, null); + public SLOInformationImpl(String authURL, String sessionID, String nameID, String nameIDFormat, String protocolType) { + new SLOInformationImpl(authURL, sessionID, nameID, nameIDFormat, protocolType, null); } - public SLOInformationImpl(String sessionID, String nameID, String nameIDFormat, String protocolType, SingleLogoutService sloService) { + public SLOInformationImpl(String authURL, String sessionID, String nameID, String nameIDFormat, String protocolType, SingleLogoutService sloService) { this.sessionIndex = sessionID; this.nameID = nameID; this.nameIDFormat = nameIDFormat; this.protocolType = protocolType; + if (authURL.endsWith("/")) + this.authURL = authURL.substring(0, authURL.length()-1); + else + this.authURL = authURL; + if (sloService != null) { this.binding = sloService.getBinding(); this.serviceURL = sloService.getLocation(); @@ -148,6 +154,13 @@ public class SLOInformationImpl implements SLOInformationInterface, Serializable public String getServiceURL() { return serviceURL; } + + /** + * @return the authURL from requested IDP without ending / + */ + public String getAuthURL() { + return authURL; + } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java deleted file mode 100644 index 771c9a35e..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java +++ /dev/null @@ -1,612 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 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: - * http://www.osor.eu/eupl/ - * - * 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.egovernment.moa.id.entrypoints; - -import java.io.IOException; -import java.util.Iterator; - -import javax.servlet.ServletConfig; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; -import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger; -import at.gv.egovernment.moa.id.advancedlogging.StatisticLogger; - -import at.gv.egovernment.moa.id.advancedlogging.TransactionIDUtils; -import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; -import at.gv.egovernment.moa.id.auth.MOAIDAuthInitializer; -import at.gv.egovernment.moa.id.auth.builder.AuthenticationDataBuilder; -import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; -import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; -import at.gv.egovernment.moa.id.auth.exception.InvalidProtocolRequestException; -import at.gv.egovernment.moa.id.auth.exception.MOAIDException; -import at.gv.egovernment.moa.id.auth.exception.ProtocolNotActiveException; -import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; -import at.gv.egovernment.moa.id.auth.servlet.AuthServlet; - -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; -import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; -import at.gv.egovernment.moa.id.data.IAuthData; -import at.gv.egovernment.moa.id.data.SLOInformationInterface; -import at.gv.egovernment.moa.id.moduls.AuthenticationManager; -import at.gv.egovernment.moa.id.moduls.IAction; -import at.gv.egovernment.moa.id.moduls.IModulInfo; -import at.gv.egovernment.moa.id.moduls.IRequest; -import at.gv.egovernment.moa.id.moduls.ModulStorage; -import at.gv.egovernment.moa.id.moduls.NoPassivAuthenticationException; -import at.gv.egovernment.moa.id.moduls.RequestStorage; -import at.gv.egovernment.moa.id.moduls.SSOManager; -import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AuthnRequestValidatorException; -import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; -import at.gv.egovernment.moa.id.storage.DBExceptionStoreImpl; -import at.gv.egovernment.moa.id.util.ErrorResponseUtils; -import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; -import at.gv.egovernment.moa.id.util.Random; -import at.gv.egovernment.moa.id.util.legacy.LegacyHelper; -import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.MiscUtil; - -public class DispatcherServlet extends AuthServlet{ - - /** - * - */ - private static final long serialVersionUID = 1L; - - public static final String PARAM_TARGET_MODULE = "mod"; - public static final String PARAM_TARGET_ACTION = "action"; - public static final String PARAM_TARGET_PENDINGREQUESTID = "pendingid"; - - @Override - public void init(ServletConfig config) throws ServletException { - try { - super.init(config); - MOAIDAuthInitializer.initialize(); - Logger.info(MOAIDMessageProvider.getInstance().getMessage( - "init.00", null)); - } catch (Exception ex) { - Logger.fatal( - MOAIDMessageProvider.getInstance().getMessage("init.02", - null), ex); - throw new ServletException(ex); - } - Logger.info("Dispatcher Servlet initialization finished."); - } - - protected void processRequest(HttpServletRequest req, - HttpServletResponse resp) throws ServletException, IOException { - boolean isValidSSOSession = false; - boolean useSSOOA = false; - String protocolRequestID = null; - - try { - Logger.debug("REQUEST: " + req.getRequestURI()); - Logger.debug("QUERY : " + req.getQueryString()); - - -// *** start of error handling *** - - String errorid = req.getParameter(ERROR_CODE_PARAM); - if (errorid != null) { - - Throwable throwable = DBExceptionStoreImpl.getStore() - .fetchException(errorid); - DBExceptionStoreImpl.getStore().removeException(errorid); - - Object idObject = req.getParameter(PARAM_TARGET_PENDINGREQUESTID); - - //Map<String, IRequest> errorRequests = RequestStorage.getPendingRequest(req.getSession()); - - String pendingRequestID = null; - if (idObject != null && (idObject instanceof String)) { - pendingRequestID = (String) idObject; - } - - if (throwable != null) { - - IRequest errorRequest = null; - if (pendingRequestID != null) { - errorRequest = RequestStorage.getPendingRequest(pendingRequestID); - - } - - if (errorRequest != null) { - RequestStorage.removePendingRequest(pendingRequestID); - MOAReversionLogger.getInstance().logEvent(errorRequest, MOAIDEventConstants.TRANSACTION_ERROR); - - try { - IModulInfo handlingModule = ModulStorage - .getModuleByPath(errorRequest - .requestedModule()); - if (handlingModule != null) { - - if (handlingModule.generateErrorMessage( - throwable, req, resp, errorRequest)) { - - //log Error Message - StatisticLogger logger = StatisticLogger.getInstance(); - logger.logErrorOperation(throwable, errorRequest); - - //remove MOASession - AuthenticationSession moaSession = AuthenticationSessionStoreage.getSessionWithPendingRequestID(pendingRequestID); - if (moaSession != null) - AuthenticationManager.getInstance().performOnlyIDPLogOut(req, resp, moaSession.getSessionID()); - - return; - - } else { - handleErrorNoRedirect(throwable.getMessage(), throwable, - req, resp); - - } - } - - } catch (Throwable e) { - Logger.error(e); - handleErrorNoRedirect(throwable.getMessage(), - throwable, req, resp); - } - - } else { - handleErrorNoRedirect(throwable.getMessage(), throwable, - req, resp); - } - - } else - handleErrorNoRedirect(MOAIDMessageProvider.getInstance().getMessage("auth.26", null), - null, req, resp); - - return; - } - -// *** end of error handling *** - - -// *** start of protocol specific stuff *** - - Object moduleObject = req.getParameter(PARAM_TARGET_MODULE); - String module = null; - if (moduleObject != null && (moduleObject instanceof String)) { - module = (String) moduleObject; - } - - if (module == null) { - module = (String) req.getAttribute(PARAM_TARGET_MODULE); - } - - Object actionObject = req.getParameter(PARAM_TARGET_ACTION); - String action = null; - if (actionObject != null && (actionObject instanceof String)) { - action = (String) actionObject; - } - - if (action == null) { - action = req.getParameter(PARAM_TARGET_ACTION); - } - - Logger.debug("dispatching to " + module + " protocol " + action); - - IModulInfo info = ModulStorage.getModuleByPath(module); - - IAction moduleAction = null; - - if (info == null) { - - Iterator<IModulInfo> modules = ModulStorage.getAllModules() - .iterator(); - while (modules.hasNext()) { - info = modules.next(); - moduleAction = info.canHandleRequest(req, resp); - if (moduleAction != null) { - action = moduleAction.getDefaultActionName(); - module = info.getPath(); - break; - } - info = null; - } - - if (moduleAction == null) { - resp.sendError(HttpServletResponse.SC_NOT_FOUND); - Logger.error("Protocol " + module - + " has no module registered"); - return; - } - } - - if (moduleAction == null) { - moduleAction = info.getAction(action); - - if (moduleAction == null) { - resp.sendError(HttpServletResponse.SC_NOT_FOUND); - Logger.error("Action " + action + " is not available!"); - return; - } - } - - //get SSO Cookie for Request - SSOManager ssomanager = SSOManager.getInstance(); - String ssoId = ssomanager.getSSOSessionID(req); - - IRequest protocolRequest = null; - String uniqueSessionIdentifier = null; - - try { - Object idObject = req.getParameter(PARAM_TARGET_PENDINGREQUESTID); - - if (idObject != null && (idObject instanceof String)) { - - protocolRequestID = (String) idObject; - protocolRequest = RequestStorage.getPendingRequest(protocolRequestID); - - //get IRequest if it exits - if (protocolRequest != null) { - Logger.debug(DispatcherServlet.class.getName()+": Found PendingRequest with ID " + protocolRequestID); - - } else { - Logger.error("No PendingRequest with ID " + protocolRequestID + " found.!"); - handleErrorNoRedirect("Während des Anmeldevorgangs ist ein Fehler aufgetreten. Bitte versuchen Sie es noch einmal.", - null, req, resp); - return; - } - } else { - try { - - //load unique session identifier with SSO-sessionID - uniqueSessionIdentifier = ssomanager.getUniqueSessionIdentifier(ssoId); - if (MiscUtil.isEmpty(uniqueSessionIdentifier)) - uniqueSessionIdentifier = Random.nextRandom(); - TransactionIDUtils.setSessionId(uniqueSessionIdentifier); - - //set transactionID to Logger - protocolRequestID = Random.nextRandom(); - TransactionIDUtils.setTransactionId(protocolRequestID); - - //log information for security and process reversion - MOAReversionLogger.getInstance().logEvent(MOAIDEventConstants.SESSION_CREATED, uniqueSessionIdentifier); - MOAReversionLogger.getInstance().logEvent(MOAIDEventConstants.TRANSACTION_CREATED, protocolRequestID); - MOAReversionLogger.getInstance().logEvent(uniqueSessionIdentifier, protocolRequestID, MOAIDEventConstants.TRANSACTION_IP, req.getRemoteAddr()); - - protocolRequest = info.preProcess(req, resp, action, uniqueSessionIdentifier, protocolRequestID); - - //request is a valid interfederation response - if (protocolRequest != null && - protocolRequest.getInterfederationResponse() != null ) { - Logger.debug("Create new interfederated MOA-Session and add to HTTPRequest"); - - //reload SP protocol implementation - info = ModulStorage.getModuleByPath(protocolRequest.requestedModule()); - moduleAction = info.getAction(protocolRequest.requestedAction()); - - //create interfederated MOASession - String sessionID = - AuthenticationSessionStoreage.createInterfederatedSession(protocolRequest, true, ssoId); - req.getParameterMap().put(MOAIDAuthConstants.PARAM_SESSIONID, new String[]{ sessionID }); - - Logger.info("PreProcessing of SSO interfederation response complete. "); - - //request is a not valid interfederation response - } else if (protocolRequest != null && - MiscUtil.isNotEmpty(protocolRequest.getRequestID())) { - - OAAuthParameter oaParams = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(protocolRequest.getOAURL()); - if (!oaParams.isPerformLocalAuthenticationOnInterfederationError()) { - // -> send end error to service provider - Logger.info("Federated authentication for entity " + protocolRequest.getOAURL() - + " FAILED. Sending error message to service provider."); - MOAIDException e = new MOAIDException("auth.27", new Object[]{}); - IModulInfo requestedModul = ModulStorage.getModuleByPath(protocolRequest.requestedModule()); - if (!requestedModul.generateErrorMessage(e, req, resp, protocolRequest)) - handleErrorNoRedirect(e.getMessage(), e, req, - resp); - - return; - - } else - //-> Restart local authentication - Logger.info("Restart authentication with stored " + protocolRequest.requestedModule() - + " AuthnRequest for OnlineApplication " + protocolRequest.getOAURL()); - - //request is a new authentication request - } else if (protocolRequest != null && - MiscUtil.isEmpty(protocolRequest.getRequestID())) { - //Start new Authentication - protocolRequest.setModule(module); - - //if preProcessing has not set a specific action from decoded request - // then set the default action - if (MiscUtil.isEmpty(protocolRequest.requestedAction())) - protocolRequest.setAction(action); - else - moduleAction = info.getAction(protocolRequest.requestedAction()); - - protocolRequest.setRequestID(protocolRequestID); - protocolRequest.setSessionIdentifier(uniqueSessionIdentifier); - RequestStorage.setPendingRequest(protocolRequest); - Logger.debug(DispatcherServlet.class.getName()+": Create PendingRequest with ID " + protocolRequestID + "."); - - - } else { - Logger.error("Failed to generate a valid protocol request!"); - resp.setContentType("text/html;charset=UTF-8"); - resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "NO valid protocol request received!"); - return; - - } - - } catch (ProtocolNotActiveException e) { - resp.getWriter().write(e.getMessage()); - resp.setContentType("text/html;charset=UTF-8"); - resp.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage()); - return; - - } catch (AuthnRequestValidatorException e) { - //log Error Message - StatisticLogger logger = StatisticLogger.getInstance(); - logger.logErrorOperation(e, e.getErrorRequest()); - return; - - }catch (InvalidProtocolRequestException e) { - ErrorResponseUtils utils = ErrorResponseUtils.getInstance(); - String code = utils.mapInternalErrorToExternalError(e.getMessageId()); - String descr = e.getMessage(); - Logger.error("Protocol validation FAILED!"); - resp.setContentType("text/html;charset=UTF-8"); - resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Protocol validation FAILED!" + - "(Errorcode=" + code + - " | Description=" + descr + ")"); - return; - } catch (MOAIDException e) { - Logger.error("Failed to generate a valid protocol request!"); - resp.setContentType("text/html;charset=UTF-8"); - resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "NO valid protocol request received!" + - "(Errorcode=6000" - +" | Description=Das Authentifizierungsprotokoll wurde nicht erkannt oder wird nicht unterst\u00FCzt" + ")"); - return; - - } - } - -// *** end of protocol specific stuff *** - - if (protocolRequest != null) - MOAReversionLogger.getInstance().logEvent(protocolRequest.getOnlineApplicationConfiguration(), - protocolRequest, MOAIDEventConstants.AUTHPROTOCOL_TYPE, protocolRequest.requestedModule()); - -// *** start handling authentication *** - - AuthenticationManager authmanager = AuthenticationManager.getInstance(); - - String moasessionID = null; - String newSSOSessionId = null; - AuthenticationSession moasession = null; - IAuthData authData = null; - - boolean needAuthentication = moduleAction.needAuthentication(protocolRequest, req, resp); - - if (needAuthentication) { - - //check if interfederation IDP is requested - ssomanager.checkInterfederationIsRequested(req, resp, protocolRequest); - - //check SSO session - if (ssoId != null) { - String correspondingMOASession = ssomanager.existsOldSSOSession(ssoId); - - if (correspondingMOASession != null) { - Logger.warn("Request sends an old SSO Session ID("+ssoId+")! " + - "Invalidate the corresponding MOASession with ID="+ correspondingMOASession); - - MOAReversionLogger.getInstance().logEvent(protocolRequest.getOnlineApplicationConfiguration(), - protocolRequest, MOAIDEventConstants.AUTHPROCESS_SSO_INVALID); - - AuthenticationSessionStoreage.destroySession(correspondingMOASession); - ssomanager.deleteSSOSessionID(req, resp); - } - } - - //load Parameters from OnlineApplicationConfiguration - OAAuthParameter oaParam = AuthConfigurationProviderFactory.getInstance() - .getOnlineApplicationParameter(protocolRequest.getOAURL()); - - if (oaParam == null) { - throw new AuthenticationException("auth.00", new Object[] { protocolRequest.getOAURL() }); - } - - - isValidSSOSession = ssomanager.isValidSSOSession(ssoId, protocolRequest); - useSSOOA = oaParam.useSSO() || oaParam.isInderfederationIDP(); - - - //if a legacy request is used SSO should not be allowed, actually - boolean isUseMandateRequested = LegacyHelper.isUseMandateRequested(req); - - if (protocolRequest.isPassiv() - && protocolRequest.forceAuth()) { - // conflict! - throw new NoPassivAuthenticationException(); - } - - boolean tryperform = authmanager.tryPerformAuthentication( - req, resp); - - if (tryperform) - MOAReversionLogger.getInstance().logEvent(protocolRequest.getOnlineApplicationConfiguration(), - protocolRequest, MOAIDEventConstants.AUTHPROCESS_FINISHED); - else - MOAReversionLogger.getInstance().logEvent(protocolRequest.getOnlineApplicationConfiguration(), - protocolRequest, MOAIDEventConstants.AUTHPROCESS_SERVICEPROVIDER, protocolRequest.getOAURL()); - - if (protocolRequest.forceAuth()) { - if (!tryperform) { - authmanager.doAuthentication(req, resp, - protocolRequest); - return; - } - } else if (protocolRequest.isPassiv()) { - if (tryperform || (isValidSSOSession && useSSOOA && !isUseMandateRequested) ) { - // Passive authentication ok! - } else { - throw new NoPassivAuthenticationException(); - } - } else { - if (tryperform || (isValidSSOSession && useSSOOA && !isUseMandateRequested) ) { - // Is authenticated .. proceed - } else { - // Start authentication! - authmanager.doAuthentication(req, resp, - protocolRequest); - return; - } - } - - if ((useSSOOA || isValidSSOSession)) //TODO: SSO with mandates requires an OVS extension - { - - if (useSSOOA && isValidSSOSession) { - - MOAReversionLogger.getInstance().logEvent(protocolRequest.getOnlineApplicationConfiguration(), - protocolRequest, MOAIDEventConstants.AUTHPROCESS_SSO); - - moasessionID = ssomanager.getMOASession(ssoId); - moasession = AuthenticationSessionStoreage.getSession(moasessionID); - - //use new OAParameter - if (oaParam.useSSOQuestion() && !AuthenticationSessionStoreage.isAuthenticated(moasessionID)) { - authmanager.sendTransmitAssertionQuestion(req, resp, protocolRequest, oaParam); - return; - } - - } else { - moasessionID = (String) req.getParameter(MOAIDAuthConstants.PARAM_SESSIONID); - moasession = AuthenticationSessionStoreage.getSession(moasessionID); - - } - //save SSO session usage in Database - if (useSSOOA) { - newSSOSessionId = ssomanager.createSSOSessionInformations(moasessionID, protocolRequest.getOAURL()); - - if (MiscUtil.isNotEmpty(newSSOSessionId)) { - ssomanager.setSSOSessionID(req, resp, newSSOSessionId); - - } else { - ssomanager.deleteSSOSessionID(req, resp); - - } - } - - } else { - moasessionID = (String) req.getParameter(MOAIDAuthConstants.PARAM_SESSIONID); - moasession = AuthenticationSessionStoreage.getSession(moasessionID); - moasessionID = AuthenticationSessionStoreage.changeSessionID(moasession); - - } - - //build authenticationdata from session information and OA configuration - authData = AuthenticationDataBuilder.buildAuthenticationData(protocolRequest, moasession); - } - -// *** end handling authentication *** - -// *** start finalizing authentication (SSO, final redirects, statistic logging etc) *** - - SLOInformationInterface assertionID = moduleAction.processRequest(protocolRequest, req, resp, authData); - - RequestStorage.removePendingRequest(protocolRequestID); - - if (needAuthentication) { - boolean isSSOSession = MiscUtil.isNotEmpty(newSSOSessionId) && useSSOOA; - - if ((useSSOOA || isSSOSession) //TODO: SSO with mandates requires an OVS extension - && !moasession.getUseMandate()) { - - try { - //Store OA specific SSO session information - AuthenticationSessionStoreage.addSSOInformation(moasessionID, - newSSOSessionId, assertionID, protocolRequest.getOAURL()); - - } catch (AuthenticationException e) { - Logger.warn("SSO Session information can not be stored -> SSO is not enabled!"); - - authmanager.performOnlyIDPLogOut(req, resp, moasessionID); - isSSOSession = false; - } - - } else { - authmanager.performOnlyIDPLogOut(req, resp, moasessionID); - } - - //Advanced statistic logging - StatisticLogger logger = StatisticLogger.getInstance(); - logger.logSuccessOperation(protocolRequest, authData, isSSOSession); - - } - -// *** end finalizing authentication *** - - } catch (Throwable e) { - Logger.warn("An authentication error occured: ", e);; - // Try handle module specific, if not possible rethrow - if (!info.generateErrorMessage(e, req, resp, protocolRequest)) - handleErrorNoRedirect(e.getMessage(), e, req, - resp); - - } - - //log transaction_destroy to reversionslog - MOAReversionLogger.getInstance().logEvent(MOAIDEventConstants.TRANSACTION_DESTROYED, protocolRequestID); - - } catch (WrongParametersException ex) { - handleWrongParameters(ex, req, resp); - - } catch (MOAIDException ex) { - handleError(null, ex, req, resp, protocolRequestID); - - } catch (Throwable e) { - handleErrorNoRedirect(e.getMessage(), e, req, - resp); - } - - finally { - - - TransactionIDUtils.removeTransactionId(); - TransactionIDUtils.removeSessionId(); - } - - Logger.debug("Clossing Dispatcher processing loop"); - } - - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - processRequest(req, resp); - } - - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - processRequest(req, resp); - } -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java index 39cb5b9c8..22561e435 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java @@ -23,9 +23,6 @@ package at.gv.egovernment.moa.id.moduls; import java.io.IOException; -import java.io.PrintWriter; -import java.lang.reflect.InvocationTargetException; -import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; @@ -37,137 +34,409 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang.StringEscapeUtils; import org.apache.velocity.VelocityContext; -import org.joda.time.DateTime; -import org.opensaml.common.impl.SecureRandomIdentifierGenerator; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.core.AuthnContextClassRef; -import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration; -import org.opensaml.saml2.core.AuthnRequest; -import org.opensaml.saml2.core.Issuer; import org.opensaml.saml2.core.LogoutRequest; import org.opensaml.saml2.core.LogoutResponse; -import org.opensaml.saml2.core.NameID; -import org.opensaml.saml2.core.NameIDPolicy; -import org.opensaml.saml2.core.NameIDType; -import org.opensaml.saml2.core.RequestedAuthnContext; import org.opensaml.saml2.core.StatusCode; -import org.opensaml.saml2.core.Subject; -import org.opensaml.saml2.metadata.EntityDescriptor; import org.opensaml.saml2.metadata.SingleLogoutService; -import org.opensaml.saml2.metadata.SingleSignOnService; -import org.opensaml.saml2.metadata.provider.MetadataProviderException; -import org.opensaml.ws.message.encoder.MessageEncodingException; import org.opensaml.ws.soap.common.SOAPException; import org.opensaml.xml.XMLObject; import org.opensaml.xml.security.SecurityException; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger; import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; -import at.gv.egovernment.moa.id.auth.builder.LoginFormBuilder; -import at.gv.egovernment.moa.id.auth.builder.SendAssertionFormBuilder; import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionExtensions; -import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; -import at.gv.egovernment.moa.id.auth.exception.BuildException; +import at.gv.egovernment.moa.id.auth.exception.InvalidProtocolRequestException; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.modules.SingleSignOnConsentsModuleImpl; +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; import at.gv.egovernment.moa.id.auth.modules.registration.ModuleRegistration; -import at.gv.egovernment.moa.id.auth.parser.StartAuthentificationParameterParser; import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore; import at.gv.egovernment.moa.id.commons.db.dao.session.OASessionStore; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; -import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; +import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; import at.gv.egovernment.moa.id.data.SLOInformationContainer; import at.gv.egovernment.moa.id.data.SLOInformationImpl; -import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; - import at.gv.egovernment.moa.id.process.ExecutionContextImpl; import at.gv.egovernment.moa.id.process.ProcessEngine; import at.gv.egovernment.moa.id.process.ProcessExecutionException; import at.gv.egovernment.moa.id.process.api.ExecutionContext; import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration; -import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder; -import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding; -import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding; import at.gv.egovernment.moa.id.protocols.pvp2x.builder.SingleLogOutBuilder; -import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; -import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider; import at.gv.egovernment.moa.id.protocols.pvp2x.utils.MOASAMLSOAPClient; -import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; -import at.gv.egovernment.moa.id.storage.AssertionStorage; -import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; +import at.gv.egovernment.moa.id.protocols.pvp2x.verification.SAMLVerificationEngine; +import at.gv.egovernment.moa.id.protocols.pvp2x.verification.TrustEngineFactory; +import at.gv.egovernment.moa.id.storage.IAuthenticationSessionStoreage; +import at.gv.egovernment.moa.id.storage.ITransactionStorage; import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; -import at.gv.egovernment.moa.id.util.PVPtoSTORKMapper; import at.gv.egovernment.moa.id.util.ParamValidatorUtils; import at.gv.egovernment.moa.id.util.Random; +import at.gv.egovernment.moa.id.util.legacy.LegacyHelper; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; +@Service("MOAID_AuthenticationManager") public class AuthenticationManager extends MOAIDAuthConstants { - private static final AuthenticationManager INSTANCE = new AuthenticationManager(); public static final String MOA_SESSION = "MoaAuthenticationSession"; public static final String MOA_AUTHENTICATED = "MoaAuthenticated"; public static final int SLOTIMEOUT = 30 * 1000; //30 sec - @Autowired - private ProcessEngine processEngine; - - private AuthenticationManager() { + @Autowired private ProcessEngine processEngine; + @Autowired private SSOManager ssoManager; + @Autowired private IRequestStorage requestStoreage; + @Autowired private ITransactionStorage transactionStorage; + @Autowired private IAuthenticationSessionStoreage authenticatedSessionStore; + @Autowired private MOAReversionLogger revisionsLogger; + @Autowired protected AuthConfiguration authConfig; + @Autowired private SingleLogOutBuilder sloBuilder; + @Autowired private SAMLVerificationEngine samlVerificationEngine; + + public void performSingleLogOut(HttpServletRequest httpReq, + HttpServletResponse httpResp, AuthenticationSession session, PVPTargetConfiguration pvpReq) throws MOAIDException { + performSingleLogOut(httpReq, httpResp, session, pvpReq, null); + } - public static AuthenticationManager getInstance() { - return INSTANCE; + public void performSingleLogOut(HttpServletRequest httpReq, + HttpServletResponse httpResp, AuthenticationSession session, String authURL) throws MOAIDException { + performSingleLogOut(httpReq, httpResp, session, null, authURL); + } + public void performOnlyIDPLogOut(HttpServletRequest request, + HttpServletResponse response, String moaSessionID) { + Logger.info("Logout"); + + if(moaSessionID == null) { + moaSessionID = (String) request.getParameter(PARAM_SESSIONID); + } + + if(moaSessionID == null) { + Logger.info("NO MOA Session to logout"); + return; + } + + AuthenticationSession authSession; + try { + authSession = authenticatedSessionStore.getSession(moaSessionID); + + if(authSession == null) { + Logger.info("NO MOA Authentication data for ID " + moaSessionID); + return; + } + + authSession.setAuthenticated(false); + //HTTPSessionUtils.setHTTPSessionString(session, MOA_SESSION, null); // remove moa session from HTTP Session + + //log Session_Destroy to reversionslog + AuthenticationSessionExtensions sessionExtensions = authenticatedSessionStore.getAuthenticationSessionExtensions(moaSessionID); + revisionsLogger.logEvent(MOAIDEventConstants.SESSION_DESTROYED, sessionExtensions.getUniqueSessionId()); + + authenticatedSessionStore.destroySession(moaSessionID); + + //session.invalidate(); + + } catch (MOADatabaseException e) { + Logger.info("NO MOA Authentication data for ID " + moaSessionID); + return; + } + + } + + /** - * Checks if this request can authenticate a MOA Session + * Authenticates the authentication request {pendingReq}, which is actually processed + * + * @param httpReq HttpServletRequest + * @param httpResp HttpServletResponse + * @param protocolRequest Authentication request which is actually in process + * + * @return Return already authenticated MOASession if exists, otherwise return null + * @throws MOADatabaseException + * @throws MOAIDException + * @throws IOException + * @throws ServletException * - * @param request - * @param response - * @return */ - public boolean tryPerformAuthentication(HttpServletRequest request, - HttpServletResponse response) { + public AuthenticationSession doAuthentication(HttpServletRequest httpReq, + HttpServletResponse httpResp, RequestImpl pendingReq) throws MOADatabaseException, ServletException, IOException, MOAIDException { + + //generic authentication request validation + if (pendingReq.isPassiv() + && pendingReq.forceAuth()) { + // conflict! + throw new NoPassivAuthenticationException(); + } - String sessionID = (String) request.getParameter(PARAM_SESSIONID); - if (sessionID != null) { - Logger.debug("Find MOASession: " + sessionID); - AuthenticationSession authSession; - try { - authSession = AuthenticationSessionStoreage.getSession(sessionID); - - if (authSession != null) { - Logger.info("MOASession found! A: " - + authSession.isAuthenticated() + ", AU " - + authSession.isAuthenticatedUsed()); - if (authSession.isAuthenticated() - && !authSession.isAuthenticatedUsed()) { - authSession.setAuthenticatedUsed(true); - - AuthenticationSessionStoreage.storeSession(authSession); - - return true; // got authenticated - } - } + //get SSO cookie from http request + String ssoId = ssoManager.getSSOSessionID(httpReq); + + //check if interfederation IDP is requested + ssoManager.checkInterfederationIsRequested(httpReq, httpResp, pendingReq); + + //check if SSO session cookie is already used + if (ssoId != null) { + String correspondingMOASession = ssoManager.existsOldSSOSession(ssoId); - } catch (MOADatabaseException e) { - return false; - } catch (BuildException e) { + if (correspondingMOASession != null) { + Logger.warn("Request sends an old SSO Session ID("+ssoId+")! " + + "Invalidate the corresponding MOASession with ID="+ correspondingMOASession); + + revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), + pendingReq, MOAIDEventConstants.AUTHPROCESS_SSO_INVALID); + + authenticatedSessionStore.destroySession(correspondingMOASession); + ssoManager.deleteSSOSessionID(httpReq, httpResp); + } + } + + //check if SSO Session is valid + boolean isValidSSOSession = ssoManager.isValidSSOSession(ssoId, pendingReq); + + // check if Service-Provider allows SSO sessions + IOAAuthParameters oaParam = pendingReq.getOnlineApplicationConfiguration(); + boolean useSSOOA = oaParam.useSSO() || oaParam.isInderfederationIDP(); + + revisionsLogger.logEvent(oaParam, + pendingReq, MOAIDEventConstants.AUTHPROCESS_SERVICEPROVIDER, pendingReq.getOAURL()); + + //if a legacy request is used SSO should not be allowed in case of mandate authentication + boolean isUseMandateRequested = LegacyHelper.isUseMandateRequested(httpReq); + + //check if SSO is allowed for the actually executed request + //INFO: Actually, useMandate disables SSO functionality!!!!! + boolean isSSOAllowed = (useSSOOA && !isUseMandateRequested); + pendingReq.setNeedSingleSignOnFunctionality(isSSOAllowed); + + //get MOASession from SSO-Cookie if SSO is allowed + AuthenticationSession moaSession = null; + if (isValidSSOSession && isSSOAllowed) { + String moasessionID = ssoManager.getMOASession(ssoId); + moaSession = authenticatedSessionStore.getSession(moasessionID); + + if (moaSession == null) + Logger.info("No MOASession FOUND with provided SSO-Cookie."); + + else { + Logger.debug("Found authenticated MOASession with provided SSO-Cookie."); + revisionsLogger.logEvent(oaParam, pendingReq, MOAIDEventConstants.AUTHPROCESS_SSO); + + } + } + + //check if session is already authenticated + boolean isSessionAuthenticated = tryPerformAuthentication((RequestImpl) pendingReq, moaSession); + + //force new authentication authentication process + if (pendingReq.forceAuth()) { + startAuthenticationProcess(httpReq, httpResp, pendingReq); + return null; + + //perform SSO-Consents evaluation if it it required + } else if (isSessionAuthenticated && oaParam.useSSOQuestion()) { + sendSingleSignOnConsentsEvaluation(httpReq, httpResp, pendingReq); + return null; + + } else if (pendingReq.isPassiv()) { + if (isSessionAuthenticated) { + // Passive authentication ok! + revisionsLogger.logEvent(oaParam, pendingReq, MOAIDEventConstants.AUTHPROCESS_FINISHED); + return moaSession; + + } else { + throw new NoPassivAuthenticationException(); + + } + } else { + if (isSessionAuthenticated) { + // Is authenticated .. proceed + revisionsLogger.logEvent(oaParam, + pendingReq, MOAIDEventConstants.AUTHPROCESS_FINISHED); + return moaSession; + + } else { + // Start authentication! + startAuthenticationProcess(httpReq, httpResp, pendingReq); + return null; + } + } + } + + /** + * Checks if a authenticated MOASession already exists and if {protocolRequest} is authenticated + * + * @param protocolRequest Authentication request which is actually in process + * @param moaSession MOASession with authentication information or null if no active MOASession exists + * + * @return true if session is already authenticated, otherwise false + * @throws MOAIDException + */ + private boolean tryPerformAuthentication(RequestImpl protocolRequest, AuthenticationSession moaSession) { + + //if no MOASession exist -> authentication is required + if (moaSession == null) { + return false; + + } else { + //if MOASession is Found but not authenticated --> authentication is required + if (!moaSession.isAuthenticated()) { return false; } + + //if MOASession is already authenticated and protocol-request is authenticated + // --> no authentication is required any more + else if (moaSession.isAuthenticated() && protocolRequest.isAuthenticated()) { + return true; + + // if MOASession is authenticated and SSO is allowed --> authenticate pendingRequest + } else if (!protocolRequest.isAuthenticated() + && moaSession.isAuthenticated() && protocolRequest.needSingleSignOnFunctionality()) { + Logger.debug("Found active MOASession and SSO is allowed --> pendingRequest is authenticted"); + protocolRequest.setAuthenticated(true); + protocolRequest.setMOASessionIdentifier(moaSession.getSessionID()); + return true; + + } + + // force authentication as backup solution + else { + Logger.warn("Authentication-required check find an unsuspected state --> force authentication"); + return false; + + } } - return false; } - public void performSingleLogOut(HttpServletRequest httpReq, - HttpServletResponse httpResp, AuthenticationSession session, PVPTargetConfiguration pvpReq) throws MOAIDException { + private void startAuthenticationProcess(HttpServletRequest httpReq, + HttpServletResponse httpResp, RequestImpl pendingReq) + throws ServletException, IOException, MOAIDException { + + Logger.info("Starting authentication ..."); + revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), + pendingReq, MOAIDEventConstants.AUTHPROCESS_START); + + //is legacy allowed + List<String> legacyallowed_prot = authConfig.getLegacyAllowedProtocols(); + boolean legacyallowed = legacyallowed_prot.contains(pendingReq.requestedModule()); + + //check legacy request parameter + boolean legacyparamavail = ParamValidatorUtils.areAllLegacyParametersAvailable(httpReq); + + //create MOASession object + AuthenticationSession moasession; + try { + moasession = authenticatedSessionStore.createSession(pendingReq); + pendingReq.setMOASessionIdentifier(moasession.getSessionID()); + + } catch (MOADatabaseException e1) { + Logger.error("Database Error! MOASession can not be created!"); + throw new MOAIDException("init.04", new Object[] {}); + + } + + //create authentication process execution context + ExecutionContext executionContext = new ExecutionContextImpl(); + + //set interfederation authentication flag + executionContext.put(MOAIDAuthConstants.PROCESSCONTEXT_PERFORM_INTERFEDERATION_AUTH, + MiscUtil.isNotEmpty( + pendingReq.getGenericData(RequestImpl.DATAID_INTERFEDERATIOIDP_URL, String.class))); + + //set legacy mode or BKU-selection flags + boolean leagacyMode = (legacyallowed && legacyparamavail); + executionContext.put(MOAIDAuthConstants.PROCESSCONTEXT_ISLEGACYREQUEST, leagacyMode); + executionContext.put(MOAIDAuthConstants.PROCESSCONTEXT_PERFORM_BKUSELECTION, !leagacyMode + && MiscUtil.isEmpty(pendingReq.getGenericData(RequestImpl.DATAID_INTERFEDERATIOIDP_URL, String.class))); + + //add leagcy parameters to context + if (leagacyMode) { + Enumeration<String> reqParamNames = httpReq.getParameterNames(); + while(reqParamNames.hasMoreElements()) { + String paramName = reqParamNames.nextElement(); + if (MiscUtil.isNotEmpty(paramName) && + MOAIDAuthConstants.LEGACYPARAMETERWHITELIST.contains(paramName)) + executionContext.put(paramName, + StringEscapeUtils.escapeHtml(httpReq.getParameter(paramName))); + + } + } + + //start process engine + startProcessEngine(pendingReq, executionContext); + + } + + private void sendSingleSignOnConsentsEvaluation(HttpServletRequest request, + HttpServletResponse response, RequestImpl pendingReq) + throws ServletException, IOException, MOAIDException { + + Logger.info("Start SSO user-consents evaluation ..."); + + //set authenticated flag to false, because user consents is required + pendingReq.setAuthenticated(false); + + //create execution context + ExecutionContext executionContext = new ExecutionContextImpl(); + executionContext.put(SingleSignOnConsentsModuleImpl.PARAM_SSO_CONSENTS_EVALUATION, true); + + //start process engine + startProcessEngine(pendingReq, executionContext); + + } + + private void startProcessEngine(RequestImpl pendingReq, ExecutionContext executionContext) throws MOAIDException { + try { + //put pending-request ID on execurtionContext + executionContext.put(MOAIDAuthConstants.PARAM_TARGET_PENDINGREQUESTID, pendingReq.getRequestID()); + + // create process instance + String processDefinitionId = ModuleRegistration.getInstance().selectProcess(executionContext); + + if (processDefinitionId == null) { + Logger.warn("No suitable process found for SessionID " + pendingReq.getRequestID() ); + throw new MOAIDException("process.02",new Object[] { + pendingReq.getRequestID()}); + } + + String processInstanceId = processEngine.createProcessInstance(processDefinitionId, executionContext); + + // keep process instance id in protocol pending-request + pendingReq.setProcessInstanceId(processInstanceId); + + //store pending-request + requestStoreage.storePendingRequest(pendingReq); + + // start process + processEngine.start(pendingReq); + + } catch (ProcessExecutionException e) { + Throwable cause = e.getCause(); + if (cause != null && cause instanceof TaskExecutionException) { + Throwable taskCause = cause.getCause(); + if (taskCause != null && taskCause instanceof MOAIDException) { + MOAIDException moaTaskCause = (MOAIDException) taskCause; + Logger.warn(taskCause); + throw moaTaskCause; + + } + } + + throw new MOAIDException("process.01", new Object[] { pendingReq.getProcessInstanceId(), pendingReq.getRequestID() }, e); + } + } + + private void performSingleLogOut(HttpServletRequest httpReq, + HttpServletResponse httpResp, AuthenticationSession session, PVPTargetConfiguration pvpReq, String authURL) throws MOAIDException { String pvpSLOIssuer = null; String inboundRelayState = null; @@ -176,26 +445,25 @@ public class AuthenticationManager extends MOAIDAuthConstants { LogoutRequest logOutReq = (LogoutRequest) samlReq.getSamlRequest(); pvpSLOIssuer = logOutReq.getIssuer().getValue(); inboundRelayState = samlReq.getRelayState(); + } - SSOManager ssomanager = SSOManager.getInstance(); - //store active OAs to SLOContaine - List<OASessionStore> dbOAs = AuthenticationSessionStoreage.getAllActiveOAFromMOASession(session); - List<InterfederationSessionStore> dbIDPs = AuthenticationSessionStoreage.getAllActiveIDPsFromMOASession(session); + List<OASessionStore> dbOAs = authenticatedSessionStore.getAllActiveOAFromMOASession(session); + List<InterfederationSessionStore> dbIDPs = authenticatedSessionStore.getAllActiveIDPsFromMOASession(session); SLOInformationContainer sloContainer = new SLOInformationContainer(); - sloContainer.setSloRequest(pvpReq); - sloContainer.parseActiveIDPs(dbIDPs, pvpSLOIssuer); - sloContainer.parseActiveOAs(dbOAs, pvpSLOIssuer); + sloContainer.setSloRequest(pvpReq); + sloBuilder.parseActiveIDPs(sloContainer, dbIDPs, pvpSLOIssuer); + sloBuilder.parseActiveOAs(sloContainer, dbOAs, pvpSLOIssuer); //terminate MOASession try { - AuthenticationSessionStoreage.destroySession(session.getSessionID()); - ssomanager.deleteSSOSessionID(httpReq, httpResp); + authenticatedSessionStore.destroySession(session.getSessionID()); + ssoManager.deleteSSOSessionID(httpReq, httpResp); } catch (MOADatabaseException e) { Logger.warn("Delete MOASession FAILED."); - sloContainer.putFailedOA(AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix()); + sloContainer.putFailedOA(pvpReq.getAuthURL()); } @@ -203,7 +471,7 @@ public class AuthenticationManager extends MOAIDAuthConstants { Iterator<String> nextOAInterator = sloContainer.getNextBackChannelOA(); while (nextOAInterator.hasNext()) { SLOInformationImpl sloDescr = sloContainer.getBackChannelOASessionDescripten(nextOAInterator.next()); - LogoutRequest sloReq = SingleLogOutBuilder.buildSLORequestMessage(sloDescr); + LogoutRequest sloReq = sloBuilder.buildSLORequestMessage(sloDescr); try { List<XMLObject> soapResp = MOASAMLSOAPClient.send(sloDescr.getServiceURL(), sloReq); @@ -219,16 +487,20 @@ public class AuthenticationManager extends MOAIDAuthConstants { + " FAILED. NO LogOut response received."); sloContainer.putFailedOA(sloReq.getIssuer().getValue()); + } else { + samlVerificationEngine.verifySLOResponse(sloResp, + TrustEngineFactory.getSignatureKnownKeysTrustEngine()); + } - - SingleLogOutBuilder.checkStatusCode(sloContainer, sloResp); + + sloBuilder.checkStatusCode(sloContainer, sloResp); } catch (SOAPException e) { Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue() + " FAILED.", e); sloContainer.putFailedOA(sloReq.getIssuer().getValue()); - } catch (SecurityException e) { + } catch (SecurityException | InvalidProtocolRequestException e) { Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue() + " FAILED.", e); sloContainer.putFailedOA(sloReq.getIssuer().getValue()); @@ -244,9 +516,9 @@ public class AuthenticationManager extends MOAIDAuthConstants { Collection<Entry<String, SLOInformationImpl>> sloDescr = sloContainer.getFrontChannelOASessionDescriptions(); List<String> sloReqList = new ArrayList<String>(); for (Entry<String, SLOInformationImpl> el : sloDescr) { - LogoutRequest sloReq = SingleLogOutBuilder.buildSLORequestMessage(el.getValue()); + LogoutRequest sloReq = sloBuilder.buildSLORequestMessage(el.getValue()); try { - sloReqList.add(SingleLogOutBuilder.getFrontChannelSLOMessageURL(el.getValue().getServiceURL(), el.getValue().getBinding(), + sloReqList.add(sloBuilder.getFrontChannelSLOMessageURL(el.getValue().getServiceURL(), el.getValue().getBinding(), sloReq, httpReq, httpResp, relayState)); } catch (Exception e) { @@ -256,9 +528,13 @@ public class AuthenticationManager extends MOAIDAuthConstants { } } - AssertionStorage.getInstance().put(relayState, sloContainer); + //put SLO process-information into transaction storage + transactionStorage.put(relayState, sloContainer); + + if (MiscUtil.isEmpty(authURL)) + authURL = pvpReq.getAuthURL(); - String timeOutURL = AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix() + String timeOutURL = authURL + "/idpSingleLogout" + "?restart=" + relayState; @@ -266,15 +542,15 @@ public class AuthenticationManager extends MOAIDAuthConstants { context.put("redirectURLs", sloReqList); context.put("timeoutURL", timeOutURL); context.put("timeout", SLOTIMEOUT); - ssomanager.printSingleLogOutInfo(context, httpResp); + ssoManager.printSingleLogOutInfo(context, httpResp); } else { if (pvpReq != null) { //send SLO response to SLO request issuer - SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq); - LogoutResponse message = SingleLogOutBuilder.buildSLOResponseMessage(sloService, pvpReq, sloContainer.getSloFailedOAs()); - SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, inboundRelayState); + SingleLogoutService sloService = sloBuilder.getResponseSLODescriptor(pvpReq); + LogoutResponse message = sloBuilder.buildSLOResponseMessage(sloService, pvpReq, sloContainer.getSloFailedOAs()); + sloBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, inboundRelayState); } else { //print SLO information directly @@ -286,7 +562,7 @@ public class AuthenticationManager extends MOAIDAuthConstants { else context.put("errorMsg", MOAIDMessageProvider.getInstance().getMessage("slo.01", null)); - ssomanager.printSingleLogOutInfo(context, httpResp); + ssoManager.printSingleLogOutInfo(context, httpResp); } @@ -295,16 +571,16 @@ public class AuthenticationManager extends MOAIDAuthConstants { } catch (MOADatabaseException e) { Logger.error("MOA AssertionDatabase ERROR", e); if (pvpReq != null) { - SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq); - LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI); - SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, inboundRelayState); + SingleLogoutService sloService = sloBuilder.getResponseSLODescriptor(pvpReq); + LogoutResponse message = sloBuilder.buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI); + sloBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, inboundRelayState); }else { //print SLO information directly VelocityContext context = new VelocityContext(); context.put("errorMsg", MOAIDMessageProvider.getInstance().getMessage("slo.01", null)); - ssomanager.printSingleLogOutInfo(context, httpResp); + ssoManager.printSingleLogOutInfo(context, httpResp); } @@ -313,408 +589,4 @@ public class AuthenticationManager extends MOAIDAuthConstants { e.printStackTrace(); } } - - public void performOnlyIDPLogOut(HttpServletRequest request, - HttpServletResponse response, String moaSessionID) { - Logger.info("Logout"); - - if(moaSessionID == null) { - moaSessionID = (String) request.getParameter(PARAM_SESSIONID); - } - - if(moaSessionID == null) { - Logger.info("NO MOA Session to logout"); - return; - } - - AuthenticationSession authSession; - try { - authSession = AuthenticationSessionStoreage - .getSession(moaSessionID); - - if(authSession == null) { - Logger.info("NO MOA Authentication data for ID " + moaSessionID); - return; - } - - authSession.setAuthenticated(false); - //HTTPSessionUtils.setHTTPSessionString(session, MOA_SESSION, null); // remove moa session from HTTP Session - - //log Session_Destroy to reversionslog - AuthenticationSessionExtensions sessionExtensions = AuthenticationSessionStoreage.getAuthenticationSessionExtensions(moaSessionID); - MOAReversionLogger.getInstance().logEvent(MOAIDEventConstants.SESSION_DESTROYED, sessionExtensions.getUniqueSessionId()); - - AuthenticationSessionStoreage.destroySession(moaSessionID); - - //session.invalidate(); - - } catch (MOADatabaseException e) { - Logger.info("NO MOA Authentication data for ID " + moaSessionID); - return; - } - - } - - public void doAuthentication(HttpServletRequest request, - HttpServletResponse response, IRequest target) - throws ServletException, IOException, MOAIDException { - - Logger.info("Starting authentication ..."); - MOAReversionLogger.getInstance().logEvent(target.getOnlineApplicationConfiguration(), - target, MOAIDEventConstants.AUTHPROCESS_START); - - if (MiscUtil.isEmpty(target.getRequestedIDP())) { - perfomLocalAuthentication(request, response, target); - - } else { - Logger.info("Use IDP " + target.getRequestedIDP() + " for authentication ..."); - MOAReversionLogger.getInstance().logEvent(target.getOnlineApplicationConfiguration(), - target, MOAIDEventConstants.AUTHPROCESS_INTERFEDERATION); - buildPVP21AuthenticationRequest(request, response, target); - - } - } - - public void sendTransmitAssertionQuestion(HttpServletRequest request, - HttpServletResponse response, IRequest target, OAAuthParameter oaParam) - throws ServletException, IOException, MOAIDException { - - String form = SendAssertionFormBuilder.buildForm(target.requestedModule(), - target.requestedAction(), target.getRequestID(), oaParam, - AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix()); - - MOAReversionLogger.getInstance().logEvent(target.getOnlineApplicationConfiguration(), - target, MOAIDEventConstants.AUTHPROCESS_SSO_ASK_USER_START); - - response.setContentType("text/html;charset=UTF-8"); - PrintWriter out = new PrintWriter(response.getOutputStream()); - out.print(form); - out.flush(); - } - - private void buildPVP21AuthenticationRequest(HttpServletRequest request, - HttpServletResponse response, IRequest target) - throws ServletException, IOException, MOAIDException { - - boolean requiredLocalAuthentication = true; - - Logger.debug("Build PVP 2.1 authentication request"); - - //get IDP metadata - - OAAuthParameter idp = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(target.getRequestedIDP()); - OAAuthParameter sp = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(target.getOAURL()); - - if (!idp.isInderfederationIDP() || !idp.isInboundSSOInterfederationAllowed()) { - Logger.info("Requested interfederation IDP " + target.getRequestedIDP() + " is not valid for interfederation."); - Logger.debug("isInderfederationIDP:" + String.valueOf(idp.isInderfederationIDP()) - + " isInboundSSOAllowed:" + String.valueOf(idp.isInboundSSOInterfederationAllowed())); - Logger.info("Switch to local authentication on this IDP ... "); - - perfomLocalAuthentication(request, response, target); - return; - - } - - try { - EntityDescriptor idpEntity = MOAMetadataProvider.getInstance(). - getEntityDescriptor(target.getRequestedIDP()); - - if (idpEntity != null ) { - - //fetch endpoint from IDP metadata - SingleSignOnService redirectEndpoint = null; - for (SingleSignOnService sss : - idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS).getSingleSignOnServices()) { - - // use POST binding as default if it exists - //TODO: maybe use RedirectBinding as default - if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { - redirectEndpoint = sss; - - } else if ( sss.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI) && - redirectEndpoint == null ) - redirectEndpoint = sss; - } - - if (redirectEndpoint != null) { - - AuthnRequest authReq = SAML2Utils - .createSAMLObject(AuthnRequest.class); - SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator(); - authReq.setID(gen.generateIdentifier()); - - //send passive AuthnRequest - authReq.setIsPassive(idp.isPassivRequestUsedForInterfederation()); - - authReq.setAssertionConsumerServiceIndex(0); - authReq.setIssueInstant(new DateTime()); - Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); - String serviceURL = PVPConfiguration.getInstance().getIDPPublicPath(); - issuer.setValue(serviceURL); - - issuer.setFormat(NameIDType.ENTITY); - authReq.setIssuer(issuer); - NameIDPolicy policy = SAML2Utils - .createSAMLObject(NameIDPolicy.class); - policy.setAllowCreate(true); - policy.setFormat(NameID.TRANSIENT); - authReq.setNameIDPolicy(policy); - - authReq.setDestination(redirectEndpoint.getLocation()); - - RequestedAuthnContext reqAuthContext = - SAML2Utils.createSAMLObject(RequestedAuthnContext.class); - - AuthnContextClassRef authnClassRef = - SAML2Utils.createSAMLObject(AuthnContextClassRef.class); - - //check if STORK protocol module is in ClassPath - Object storkRequst = null; - Integer storkSecClass = null; - try { - storkRequst = Class.forName("at.gv.egovernment.moa.id.protocols.stork2.MOASTORKRequest").newInstance(); - if (storkRequst != null && - target.getClass().isInstance(storkRequst)) { - Object storkAuthnRequest = target.getClass().getMethod("getStorkAuthnRequest", null).invoke(target, null); - storkSecClass = (Integer) storkAuthnRequest.getClass().getMethod("getQaa", null).invoke(storkAuthnRequest, null); - - } - - } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | java.lang.SecurityException ex) { - - - } - - - if (sp != null && sp.isSTORKPVPGateway()){ - //use PVP SecClass instead of STORK QAA level - String secClass = null; - if (storkRequst != null && - target.getClass().isInstance(storkRequst)) { - - try { - secClass = PVPtoSTORKMapper.getInstance().mapToSecClass( - PVPConstants.STORK_QAA_PREFIX + String.valueOf(storkSecClass)); - - } catch (Exception e) { - Logger.warn("STORK-QAA level can not read from STORK request. Use default QAA 4", e); - - } - } - - if (MiscUtil.isNotEmpty(secClass)) - authnClassRef.setAuthnContextClassRef(secClass); - else - authnClassRef.setAuthnContextClassRef("http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-3"); - - } else { - if (storkRequst != null && - target.getClass().isInstance(storkRequst)) { - //use requested QAA level from STORK request - try { - authnClassRef.setAuthnContextClassRef( - PVPConstants.STORK_QAA_PREFIX + String.valueOf(storkSecClass)); - Logger.debug("Use STORK-QAA level " + authnClassRef.getAuthnContextClassRef() - + " from STORK request"); - - } catch (Exception e) { - Logger.warn("STORK-QAA level can not read from STORK request. Use default QAA 4", e); - - } - - } - - if (MiscUtil.isEmpty(authnClassRef.getAuthnContextClassRef())) - authnClassRef.setAuthnContextClassRef("http://www.stork.gov.eu/1.0/citizenQAALevel/4"); - - } - - reqAuthContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM); - reqAuthContext.getAuthnContextClassRefs().add(authnClassRef); - authReq.setRequestedAuthnContext(reqAuthContext); - - IEncoder binding = null; - if (redirectEndpoint.getBinding().equals( - SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { - binding = new RedirectBinding(); - - } else if (redirectEndpoint.getBinding().equals( - SAMLConstants.SAML2_POST_BINDING_URI)) { - binding = new PostBinding(); - - } - - binding.encodeRequest(request, response, authReq, - redirectEndpoint.getLocation(), target.getRequestID()); - - //build and send request without an error - requiredLocalAuthentication = false; - - MOAReversionLogger.getInstance().logEvent(target.getOnlineApplicationConfiguration(), - target, MOAIDEventConstants.AUTHPROCESS_INTERFEDERATION_IDP, idpEntity.getEntityID()); - - - } else { - Logger.warn("Requested IDP " + target.getRequestedIDP() - + " does not support POST or Redirect Binding."); - - } - - } else { - Logger.warn("Requested IDP " + target.getRequestedIDP() - + " is not found in InterFederation configuration"); - - } - - } catch (MetadataProviderException e) { - Logger.error("IDP metadata error." , e); - - } catch (NoSuchAlgorithmException e) { - Logger.error("Build IDP authentication request FAILED.", e); - - } catch (MessageEncodingException e) { - Logger.error("Build IDP authentication request FAILED.", e); - - } catch (SecurityException e) { - Logger.error("Build IDP authentication request FAILED.", e); - - } - - if (requiredLocalAuthentication) { - Logger.info("Switch to local authentication on this IDP ... "); - if (idp.isPerformLocalAuthenticationOnInterfederationError()) - perfomLocalAuthentication(request, response, target); - - else - throw new AuthenticationException("auth.29", new String[]{target.getRequestedIDP()}); - } - } - - - private void perfomLocalAuthentication(HttpServletRequest request, - HttpServletResponse response, IRequest target) - throws ServletException, IOException, MOAIDException { - Logger.debug("Starting authentication on this IDP ..."); - - response.setHeader(MOAIDAuthConstants.HEADER_EXPIRES, MOAIDAuthConstants.HEADER_VALUE_EXPIRES); - response.setHeader(MOAIDAuthConstants.HEADER_PRAGMA, MOAIDAuthConstants.HEADER_VALUE_PRAGMA); - response.setHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL, MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL); - response.addHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL, MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL_IE); - - List<String> legacyallowed_prot = AuthConfigurationProviderFactory.getInstance().getLegacyAllowedProtocols(); - - //is legacy allowed - boolean legacyallowed = legacyallowed_prot.contains(target.requestedModule()); - - //check legacy request parameter - boolean legacyparamavail = ParamValidatorUtils.areAllLegacyParametersAvailable(request); - - AuthenticationSession moasession; - try { - //check if an MOASession exists and if not create an new MOASession - //moasession = getORCreateMOASession(request); - moasession = AuthenticationSessionStoreage.createSession(target); - - } catch (MOADatabaseException e1) { - Logger.error("Database Error! MOASession can not be created!"); - throw new MOAIDException("init.04", new Object[] {}); - } - - try { - - if (legacyallowed && legacyparamavail) { - - // create execution context - ExecutionContext executionContext = new ExecutionContextImpl(); - executionContext.put(MOAIDAuthConstants.PARAM_SESSIONID, moasession.getSessionID()); - executionContext.put("pendingRequestID", target.getRequestID()); - - executionContext.put("isLegacyRequest", true); - - Enumeration<String> reqParamNames = request.getParameterNames(); - while(reqParamNames.hasMoreElements()) { - String paramName = reqParamNames.nextElement(); - if (MiscUtil.isNotEmpty(paramName)) - executionContext.put(paramName, request.getParameter(paramName)); - - } - - // create process instance - String processDefinitionId = ModuleRegistration.getInstance().selectProcess(executionContext); - - if (processDefinitionId == null) { - Logger.warn("No suitable process found for SessionID " + moasession.getSessionID() ); - throw new MOAIDException("process.02",new Object[] { - moasession.getSessionID()}); - } - - String processInstanceId = processEngine.createProcessInstance(processDefinitionId, executionContext); - - // keep process instance id in moa session - moasession.setProcessInstanceId(processInstanceId); - - // make sure moa session has been persisted before running the process - try { - AuthenticationSessionStoreage.storeSession(moasession); - } catch (MOADatabaseException e) { - Logger.error("Database Error! MOASession is not stored!"); - throw new MOAIDException("init.04", new Object[] { - moasession.getSessionID()}); - } - - // start process - processEngine.start(processInstanceId); - - } else { - MOAReversionLogger.getInstance().logEvent(target.getOnlineApplicationConfiguration(), - target, MOAIDEventConstants.AUTHPROCESS_BKUSELECTION_INIT); - - //load Parameters from OnlineApplicationConfiguration - OAAuthParameter oaParam = AuthConfigurationProviderFactory.getInstance() - .getOnlineApplicationParameter(target.getOAURL()); - - if (oaParam == null) { - throw new AuthenticationException("auth.00", new Object[] { target.getOAURL() }); - } - - else { - - //check if an MOASession exists and if not create an new MOASession - //moasession = getORCreateMOASession(request); - - //set OnlineApplication configuration in Session - moasession.setOAURLRequested(target.getOAURL()); - moasession.setAction(target.requestedAction()); - moasession.setModul(target.requestedModule()); - } - - //Build authentication form - - - String publicURLPreFix = AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix(); - String loginForm = LoginFormBuilder.buildLoginForm(target.requestedModule(), - target.requestedAction(), oaParam, publicURLPreFix, moasession.getSessionID()); - - //store MOASession - try { - AuthenticationSessionStoreage.storeSession(moasession, target.getRequestID()); - } catch (MOADatabaseException e) { - Logger.error("Database Error! MOASession is not stored!"); - throw new MOAIDException("init.04", new Object[] { - moasession.getSessionID()}); - } - - //set MOAIDSession - //request.getSession().setAttribute(MOA_SESSION, moasession.getSessionID()); - - response.setContentType("text/html;charset=UTF-8"); - PrintWriter out = new PrintWriter(response.getOutputStream()); - out.print(loginForm); - out.flush(); - } - } catch (ProcessExecutionException e) { - throw new MOAIDException("process.01", new Object[] { moasession.getProcessInstanceId(), moasession }, e); - } - } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/IAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/IAction.java index fda92d71a..7833e795e 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/IAction.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/IAction.java @@ -25,9 +25,7 @@ package at.gv.egovernment.moa.id.moduls; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; -import at.gv.egovernment.moa.id.data.AuthenticationData; import at.gv.egovernment.moa.id.data.IAuthData; import at.gv.egovernment.moa.id.data.SLOInformationInterface; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/IModulInfo.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/IModulInfo.java index bdbb1b458..79e52f6e1 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/IModulInfo.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/IModulInfo.java @@ -25,22 +25,12 @@ package at.gv.egovernment.moa.id.moduls; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import at.gv.egovernment.moa.id.auth.exception.MOAIDException; public interface IModulInfo { //public List<ServletInfo> getServlets(); public String getName(); public String getPath(); - - public IAction getAction(String action); - - public IRequest preProcess(HttpServletRequest request, - HttpServletResponse response, String action, String sessionID, String transactionID) - throws MOAIDException; - - public IAction canHandleRequest(HttpServletRequest request, - HttpServletResponse response); - + public boolean generateErrorMessage(Throwable e, HttpServletRequest request, HttpServletResponse response, IRequest protocolRequest) throws Throwable; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/IRequest.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/IRequest.java index 6f43b3ee7..f5d381e42 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/IRequest.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/IRequest.java @@ -22,32 +22,157 @@ *******************************************************************************/ package at.gv.egovernment.moa.id.moduls; -import java.util.Date; -import java.util.List; - -import org.opensaml.saml2.core.Attribute; - +import at.gv.egovernment.moa.id.auth.exception.SessionDataStorageException; import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; -import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOAResponse; public interface IRequest { + + /** + * Indicates the module, which implements this authentication protocol. + * The class, which is referenced, had to implement the 'IModulInfo' interface. + * + * @return Full-qualified name of the class which implements this protocol + */ + public String requestedModule(); + + /** + * Indicates the protocol specific action, which should executed if the request is processed. + * The class, which is referenced, had to implement the 'IAction' interface. + * + * @return Full-qualified name of the class which implements the action + */ + public String requestedAction(); + + /** + * Unique identifier, which indicates the service provider. + * In case of SAML1 protocol, it is the OA http-GET parameter + * + * @return Unique identifier for the service provider + */ public String getOAURL(); + + /** + * Indicates the passive flag in authentication requests. + * If the passive flag is set, the identification and authentication process + * failed if no active SSO session is found. + * + * @return true, if the is passive flag is set in authentication request, otherwise false + */ public boolean isPassiv(); + + /** + * Indicates the force authentication flag in authentication request + * If this flag is set, a new identification and authentication process + * is carried out in any case. + * + * @return true, if the force authentication flag is set, otherwise false + */ public boolean forceAuth(); - public boolean isSSOSupported(); - public String requestedModule(); - public String requestedAction(); - public void setModule(String module); - public void setAction(String action); - public String getTarget(); - public void setRequestID(String id); - public String getRequestID(); - public String getSessionIdentifier(); - public void setSessionIdentifier(String sessionIdentifier); - public String getRequestedIDP(); - public MOAResponse getInterfederationResponse(); - public List<Attribute> getRequestedAttributes(); - public IOAAuthParameters getOnlineApplicationConfiguration(); - //public void setTarget(); + + /** + * Returns a generic request-data object with is stored with a specific identifier + * + * @param key The specific identifier of the request-data object + * @return The request-data object or null if no data is found with this key + */ + public Object getGenericData(String key); + + /** + * Returns a generic request-data object with is stored with a specific identifier + * + * @param key The specific identifier of the request-data object + * @param clazz The class type which is stored with this key + * @return The request-data object or null if no data is found with this key + */ + public <T> T getGenericData(String key, final Class<T> clazz); + + /** + * Store a generic data-object to request with a specific identifier + * + * @param key Identifier for this data-object + * @param object Generic data-object which should be stored. This data-object had to be implement the 'java.io.Serializable' interface + * @throws SessionDataStorageException Error message if the data-object can not stored to generic request-data storage + */ + public void setGenericDataToSession(String key, Object object) throws SessionDataStorageException; + + /** + * Hold the identifier of this request object. + * This identifier can be used to load the request from request storage + * + * @return Request identifier + */ + public String getRequestID(); + + + /** + * Hold the identifier of the MOASession which is associated with this request + * + * @return MOASession identifier if a associated session exists, otherwise null + */ + public String getMOASessionIdentifier(); + + + /** + * Holds a unique transaction identifier, which could be used for looging + * This transaction identifier is unique for a single identification and authentication process + * + * @return Unique transaction identifier. + */ + public String getUniqueTransactionIdentifier(); + + /** + * Holds a unique session identifier, which could be used for logging + * This session identifier is unique for the full Single Sign-On session time + * + * @return Unique session identifier + */ + public String getUniqueSessionIdentifier(); + + + /** + * Hold the identifier if the process instance, which is associated with this request + * + * @return ProcessInstanceID if this request is associated with a authentication process, otherwise null + */ + public String getProcessInstanceId(); + + + /** + * get the IDP URL PreFix, which was used for authentication request + * + * @return IDP URL PreFix <String>. The URL prefix always ends without / + */ + public String getAuthURL(); + public String getAuthURLWithOutSlash(); + + /** + * Indicates if this pending request needs authentication + * + * @return true if this request needs authentication, otherwise false + */ + public boolean isNeedAuthentication(); + + /** + * Indicates, if this pending request needs Single Sign-On (SSO) functionality + * + * @return true if this request needs SSO, otherwise false + */ + public boolean needSingleSignOnFunctionality(); + public void setNeedSingleSignOnFunctionality(boolean needSSO); + + /** + * Indicates, if this pending request is already authenticated + * + * @return true if this request is already authenticated, otherwise false + */ + public boolean isAuthenticated(); + public void setAuthenticated(boolean isAuthenticated); + + /** + * Get get Service-Provider configuration which is associated with this request. + * + * @return Service-Provider configuration + */ + public IOAAuthParameters getOnlineApplicationConfiguration(); } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/ServletType.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/IRequestStorage.java index c8fbfb558..d26af89a2 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/ServletType.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/IRequestStorage.java @@ -1,4 +1,4 @@ -/******************************************************************************* +/* * Copyright 2014 Federal Chancellery Austria * MOA-ID has been developed in a cooperation between BRZ, the Federal * Chancellery Austria - ICT staff unit, and Graz University of Technology. @@ -19,9 +19,24 @@ * 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.egovernment.moa.id.moduls; -public enum ServletType { - UNAUTH, AUTH, NONE +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; + +/** + * @author tlenz + * + */ +public interface IRequestStorage { + + public IRequest getPendingRequest(String pendingReqID); + + public void storePendingRequest(IRequest pendingRequest) throws MOAIDException; + + public void removePendingRequest(String requestID); + + public String changePendingRequestID(IRequest pendingRequest) throws MOAIDException, MOADatabaseException; + } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/ModulStorage.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/ModulStorage.java deleted file mode 100644 index e65d77326..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/ModulStorage.java +++ /dev/null @@ -1,94 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 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: - * http://www.osor.eu/eupl/ - * - * 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.egovernment.moa.id.moduls; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.ServiceLoader; - -import at.gv.egovernment.moa.logging.Logger; - -public class ModulStorage { - -// private static final String[] modulClasses = new String[]{ -//// "at.gv.egovernment.moa.id.protocols.saml1.SAML1Protocol", -// "at.gv.egovernment.moa.id.protocols.pvp2x.PVP2XProtocol", -// "at.gv.egovernment.moa.id.protocols.stork2.STORKProtocol", -// "at.gv.egovernment.moa.id.protocols.oauth20.protocol.OAuth20Protocol" -// }; - - private static ServiceLoader<IModulInfo> protocolModuleLoader = - ServiceLoader.load(IModulInfo.class); - private static List<IModulInfo> registeredModules = new ArrayList<IModulInfo>(); - - - public static List<IModulInfo> getAllModules() { - return registeredModules; - } - - public static IModulInfo getModuleByPath(String modname) { - Iterator<IModulInfo> it = registeredModules.iterator(); - while (it.hasNext()) { - IModulInfo info = it.next(); - if (info.getPath().equals(modname)) { - return info; - } - } - return null; - } - - static { - Logger.info("Loading protocol modules:"); - if (protocolModuleLoader != null ) { - Iterator<IModulInfo> moduleLoaderInterator = protocolModuleLoader.iterator(); - while (moduleLoaderInterator.hasNext()) { - try { - IModulInfo modul = moduleLoaderInterator.next(); - Logger.info("Loading Modul Information: " + modul.getName()); - registeredModules.add(modul); - - } catch(Throwable e) { - Logger.error("Check configuration! " + "Some protocol modul" + - " is not a valid IModulInfo", e); - } - } - } - -// for(int i = 0; i < modulClasses.length; i++) { -// String modulClassName = modulClasses[i]; -// try { -// @SuppressWarnings("unchecked") -// Class<IModulInfo> moduleClass = (Class<IModulInfo>)Class.forName(modulClassName); -// IModulInfo module = moduleClass.newInstance(); -// Logger.info("Loading Modul Information: " + module.getName()); -// registeredModules.add(module); -// } catch(Throwable e) { -// Logger.error("Check configuration! " + modulClassName + -// " is not a valid IModulInfo", e); -// } -// } - Logger.info("Loading modules done"); - } - -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/ModulUtils.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/ModulUtils.java deleted file mode 100644 index 99b7f4217..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/ModulUtils.java +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 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: - * http://www.osor.eu/eupl/ - * - * 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.egovernment.moa.id.moduls; - -import at.gv.egovernment.moa.id.entrypoints.DispatcherServlet; - - -public class ModulUtils { - - public static final String UNAUTHDISPATCHER = "dispatcher"; - public static final String AUTHDISPATCHER = "dispatcher"; - - public static String buildUnauthURL(String modul, String action, String pendingRequestID) { - return UNAUTHDISPATCHER + "?" + - DispatcherServlet.PARAM_TARGET_MODULE + "=" + modul + "&" + - DispatcherServlet.PARAM_TARGET_ACTION + "=" + action + "&" + - DispatcherServlet.PARAM_TARGET_PENDINGREQUESTID + "=" + pendingRequestID; - } - - public static String buildAuthURL(String modul, String action, String pendingRequestID) { - return AUTHDISPATCHER + - "?" + DispatcherServlet.PARAM_TARGET_MODULE + "=" + modul + "&" + - DispatcherServlet.PARAM_TARGET_ACTION + "=" + action + "&" + - DispatcherServlet.PARAM_TARGET_PENDINGREQUESTID + "=" + pendingRequestID; - } -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/RequestImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/RequestImpl.java index 26fb7bd29..961700651 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/RequestImpl.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/RequestImpl.java @@ -23,38 +23,150 @@ package at.gv.egovernment.moa.id.moduls; import java.io.Serializable; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; -import org.opensaml.saml2.core.Attribute; +import javax.servlet.http.HttpServletRequest; +import at.gv.egovernment.moa.id.advancedlogging.TransactionIDUtils; +import at.gv.egovernment.moa.id.auth.exception.SessionDataStorageException; +import at.gv.egovernment.moa.id.commons.MOAIDConstants; +import at.gv.egovernment.moa.id.config.ConfigurationException; +import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; -import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOAResponse; +import at.gv.egovernment.moa.id.util.HTTPUtils; +import at.gv.egovernment.moa.id.util.Random; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; public abstract class RequestImpl implements IRequest, Serializable{ - - private static final long serialVersionUID = 1L; + + public static final String DATAID_INTERFEDERATIOIDP_URL = "interIDPURL"; + public static final String DATAID_INTERFEDERATIOIDP_RESPONSE = "interIDPResponse"; + public static final String DATAID_REQUESTED_ATTRIBUTES = "requestedAttributes"; - private String oaURL; - private boolean passiv = false; - private boolean force = false; - private boolean ssosupport = false; + private static final long serialVersionUID = 1L; + private String module = null; private String action = null; - private String target = null; + private String requestID; - private String sessionIdentifier; + private String moaSessionIdentifier; + private String processInstanceId; + + private String uniqueTransactionIdentifer; + private String uniqueSessionIdentifer; + + private String oaURL; + private String authURL = null; + private IOAAuthParameters OAConfiguration = null; - //MOA-ID interfederation - private String requestedIDP = null; - private MOAResponse response = null; + private boolean passiv = false; + private boolean force = false; + + private boolean needAuthentication = true; + private boolean isAuthenticated = false; + private boolean needSSO = false; + + + private Map<String, Object> genericDataStorage = new HashMap<String, Object>(); + + /** + * @throws ConfigurationException + * + */ + public final void initialize(HttpServletRequest req) throws ConfigurationException { + //set requestID + requestID = Random.nextRandom(); + + //set unique transaction identifier for logging + uniqueTransactionIdentifer = Random.nextRandom(); + TransactionIDUtils.setTransactionId(uniqueTransactionIdentifer); + + + //check if End-Point is valid + String authURLString = HTTPUtils.extractAuthURLFromRequest(req); + URL authURL; + try { + authURL = new URL(authURLString); + + } catch (MalformedURLException e) { + Logger.error("IDP AuthenticationServiceURL Prefix is not a valid URL." + authURLString, e); + throw new ConfigurationException("1299", null, e); + + } + + AuthConfiguration config = AuthConfigurationProviderFactory.getInstance(); + List<String> configuredPublicURLPrefix = config.getPublicURLPrefix(); + + if (!config.isVirtualIDPsEnabled()) { + Logger.trace("Virtual IDPs are disabled. Use default IDP PublicURLPrefix from configuration: " + configuredPublicURLPrefix.get(0)); + this.authURL = configuredPublicURLPrefix.get(0); + + } else { + Logger.debug("Extract AuthenticationServiceURL: " + authURLString); + URL resultURL = null; + + for (String el : configuredPublicURLPrefix) { + try { + URL configuredURL = new URL(el); + + //get Ports from URL + int configPort = configuredURL.getPort(); + if (configPort == -1) + configPort = configuredURL.getDefaultPort(); + + int authURLPort = authURL.getPort(); + if (authURLPort == -1) + authURLPort = authURL.getDefaultPort(); + + //check AuthURL against ConfigurationURL + if (configuredURL.getHost().equals(authURL.getHost()) && + configPort == authURLPort && + configuredURL.getPath().equals(authURL.getPath())) { + Logger.debug("Select configurated PublicURLPrefix: " + configuredURL + + " for authURL: " + authURLString); + resultURL = configuredURL; + } + + } catch (MalformedURLException e) { + Logger.error("Configurated IDP PublicURLPrefix is not a valid URL." + el); + + } + } + + if (resultURL == null) { + Logger.warn("Extract AuthenticationServiceURL: " + authURL + " is NOT found in configuration."); + throw new ConfigurationException("config.25", new Object[]{authURLString}); + + } else { + this.authURL = resultURL.toExternalForm(); + + } + } + + //set unique session identifier + String uniqueID = (String) req.getAttribute(MOAIDConstants.UNIQUESESSIONIDENTIFIER); + if (MiscUtil.isNotEmpty(uniqueID)) + uniqueSessionIdentifer = uniqueID; + + else + Logger.warn("No unique session-identifier FOUND, but it should be allready set into request!?!"); + + } /** * This method map the protocol specific requested attributes to PVP 2.1 attributes. * - * @return List of PVP 2.1 attributes with maps all protocol specific attributes + * @return List of PVP 2.1 attribute names with maps all protocol specific attributes */ - public abstract List<Attribute> getRequestedAttributes(); + public abstract Collection<String> getRequestedAttributes(); public void setOAURL(String value) { oaURL = value; @@ -80,93 +192,195 @@ public abstract class RequestImpl implements IRequest, Serializable{ this.force = force; } - public boolean isSSOSupported() { - return ssosupport; - } - - public String requestedModule() { - return module; - } - public String requestedAction() { return action; } - public void setSsosupport(boolean ssosupport) { - this.ssosupport = ssosupport; + public void setAction(String action) { + this.action = action; + } + + /** + * @return the module + */ + public String requestedModule() { + return module; } + /** + * @param module the module to set + */ public void setModule(String module) { this.module = module; } - public void setAction(String action) { - this.action = action; + public void setRequestID(String id) { + this.requestID = id; + } - public String getTarget() { - return target; + public String getRequestID() { + return requestID; } - public void setTarget(String target) { - this.target = target; + public String getMOASessionIdentifier() { + return this.moaSessionIdentifier; + } - - public void setRequestID(String id) { - this.requestID = id; + + public void setMOASessionIdentifier(String moaSessionIdentifier) { + this.moaSessionIdentifier = moaSessionIdentifier; + + } + + public IOAAuthParameters getOnlineApplicationConfiguration() { + return this.OAConfiguration; + + } + + public void setOnlineApplicationConfiguration(IOAAuthParameters oaConfig) { + this.OAConfiguration = oaConfig; } - public String getRequestID() { - return requestID; + public String getUniqueTransactionIdentifier() { + return this.uniqueTransactionIdentifer; + + } + + public String getUniqueSessionIdentifier() { + return this.uniqueSessionIdentifer; + + } + + public String getProcessInstanceId() { + return this.processInstanceId; + + } + + public void setUniqueTransactionIdentifier(String id) { + this.uniqueTransactionIdentifer = id; + + } + + public void setUniqueSessionIdentifier(String id) { + this.uniqueSessionIdentifer = id; + + } + + public void setProcessInstanceId(String id) { + this.processInstanceId = id; + + } + + /** + * @return the authURL + */ + public String getAuthURL() { + return authURL; + } + + public String getAuthURLWithOutSlash() { + if (authURL.endsWith("/")) + return authURL.substring(0, authURL.length()-1); + else + return authURL; + } - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.moduls.IRequest#getRequestedIDP() + /** + * @return the needAuthentication */ - @Override - public String getRequestedIDP() { - return requestedIDP; + public boolean isNeedAuthentication() { + return needAuthentication; } /** - * @param requestedIDP the requestedIDP to set + * @param needAuthentication the needAuthentication to set */ - public void setRequestedIDP(String requestedIDP) { - this.requestedIDP = requestedIDP; + public void setNeedAuthentication(boolean needAuthentication) { + this.needAuthentication = needAuthentication; } /** - * @return the response + * @return the isAuthenticated */ - public MOAResponse getInterfederationResponse() { - return response; + public boolean isAuthenticated() { + return isAuthenticated; } /** - * @param response the response to set + * @param isAuthenticated the isAuthenticated to set */ - public void setInterfederationResponse(MOAResponse response) { - this.response = response; + public void setAuthenticated(boolean isAuthenticated) { + this.isAuthenticated = isAuthenticated; } - - public String getSessionIdentifier() { - return this.sessionIdentifier; + + public boolean needSingleSignOnFunctionality() { + return needSSO; + } + public void setNeedSingleSignOnFunctionality(boolean needSSO) { + this.needSSO = needSSO; } - public void setSessionIdentifier(String sessionIdentifier) { - this.sessionIdentifier = sessionIdentifier; + public Object getGenericData(String key) { + if (MiscUtil.isNotEmpty(key)) { + return genericDataStorage.get(key); + + } + Logger.warn("Can not load generic request-data with key='null'"); + return null; } - public IOAAuthParameters getOnlineApplicationConfiguration() { - return this.OAConfiguration; - + public <T> T getGenericData(String key, final Class<T> clazz) { + if (MiscUtil.isNotEmpty(key)) { + Object data = genericDataStorage.get(key); + + if (data == null) + return null; + + try { + @SuppressWarnings("unchecked") + T test = (T) data; + return test; + + } catch (Exception e) { + Logger.warn("Generic request-data object can not be casted to requested type", e); + return null; + + } + + } + + Logger.warn("Can not load generic request-data with key='null'"); + return null; + } - public void setOnlineApplicationConfiguration(IOAAuthParameters oaConfig) { - this.OAConfiguration = oaConfig; + public void setGenericDataToSession(String key, Object object) throws SessionDataStorageException { + if (MiscUtil.isEmpty(key)) { + Logger.warn("Generic request-data can not be stored with a 'null' key"); + throw new SessionDataStorageException("Generic request-data can not be stored with a 'null' key", null); + + } + + if (object != null) { + if (!Serializable.class.isInstance(object)) { + Logger.warn("Generic request-data can only store objects which implements the 'Seralizable' interface"); + throw new SessionDataStorageException("Generic request-data can only store objects which implements the 'Seralizable' interface", null); + + } + } + + if (genericDataStorage.containsKey(key)) + Logger.debug("Overwrite generic request-data with key:" + key); + else + Logger.trace("Add generic request-data with key:" + key + " to session."); + + genericDataStorage.put(key, object); } + } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/RequestStorage.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/RequestStorage.java index f0b12431a..c49df43fa 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/RequestStorage.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/RequestStorage.java @@ -22,39 +22,52 @@ *******************************************************************************/ package at.gv.egovernment.moa.id.moduls; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + import at.gv.egovernment.moa.id.advancedlogging.TransactionIDUtils; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; -import at.gv.egovernment.moa.id.storage.AssertionStorage; +import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStoreDAO; +import at.gv.egovernment.moa.id.storage.ITransactionStorage; +import at.gv.egovernment.moa.id.util.Random; import at.gv.egovernment.moa.logging.Logger; -public class RequestStorage { +@Service("RequestStorage") +public class RequestStorage implements IRequestStorage{ - public static IRequest getPendingRequest(String pendingReqID) { + @Autowired ITransactionStorage transactionStorage; + @Autowired ProcessInstanceStoreDAO processInstanceStore; + + @Override + public IRequest getPendingRequest(String pendingReqID) { try { - AssertionStorage storage = AssertionStorage.getInstance(); - IRequest pendingRequest = storage.get(pendingReqID, IRequest.class); - + IRequest pendingRequest = transactionStorage.get(pendingReqID, IRequest.class); + if (pendingRequest == null) { + Logger.info("No PendingRequst found with pendingRequestID " + pendingReqID); + return null; + + } + //set transactionID and sessionID to Logger - TransactionIDUtils.setTransactionId(((IRequest)pendingRequest).getRequestID()); - TransactionIDUtils.setSessionId(((IRequest)pendingRequest).getSessionIdentifier()); + TransactionIDUtils.setTransactionId(pendingRequest.getUniqueTransactionIdentifier()); + TransactionIDUtils.setSessionId(pendingRequest.getUniqueSessionIdentifier()); return pendingRequest; - } catch (MOADatabaseException e) { + } catch (MOADatabaseException | NullPointerException e) { Logger.info("No PendingRequst found with pendingRequestID " + pendingReqID); return null; } } - public static void setPendingRequest(Object pendingRequest) throws MOAIDException { - try { - AssertionStorage storage = AssertionStorage.getInstance(); - + @Override + public void storePendingRequest(IRequest pendingRequest) throws MOAIDException { + try { if (pendingRequest instanceof IRequest) { - storage.put(((IRequest)pendingRequest).getRequestID(), pendingRequest); + transactionStorage.put(((IRequest)pendingRequest).getRequestID(), pendingRequest); } else { throw new MOAIDException("auth.20", null); @@ -69,12 +82,53 @@ public class RequestStorage { } - public static void removePendingRequest(String requestID) { + @Override + public void removePendingRequest(String requestID) { if (requestID != null) { - AssertionStorage storage = AssertionStorage.getInstance(); - storage.remove(requestID); + //remove process-management execution instance + try { + IRequest pendingReq = getPendingRequest(requestID); + + if (pendingReq != null && + pendingReq.getProcessInstanceId() != null) { + processInstanceStore.remove(pendingReq.getProcessInstanceId()); + + } + + } catch (MOADatabaseException e) { + Logger.warn("Removing process associated with pending-request:" + requestID + " FAILED.", e); + + } + + transactionStorage.remove(requestID); + + } + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.storage.IRequestStorage#changePendingRequestID(at.gv.egovernment.moa.id.moduls.IRequest) + */ + @Override + public String changePendingRequestID(IRequest pendingRequest) throws MOAIDException, MOADatabaseException { + + if (pendingRequest instanceof RequestImpl) { + String newRequestID = Random.nextRandom(); + String oldRequestID = pendingRequest.getRequestID(); + + Logger.debug("Change pendingRequestID from " + pendingRequest.getRequestID() + + " to " + newRequestID); + + ((RequestImpl)pendingRequest).setRequestID(newRequestID); + transactionStorage.changeKey(oldRequestID, newRequestID, pendingRequest); + + return newRequestID; + + } else { + Logger.error("PendingRequest object is not of type 'RequestImpl.class'"); + throw new MOAIDException("internal.00", null); } + } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/SSOManager.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/SSOManager.java index 2a618272f..89d50425b 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/SSOManager.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/SSOManager.java @@ -40,23 +40,27 @@ import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.hibernate.Query; import org.hibernate.Session; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionExtensions; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.exception.SessionDataStorageException; import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils; import at.gv.egovernment.moa.id.commons.db.dao.session.AuthenticatedSessionStore; import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore; import at.gv.egovernment.moa.id.commons.db.dao.session.OldSSOSessionIDStore; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; import at.gv.egovernment.moa.id.config.ConfigurationException; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; -import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; +import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; +import at.gv.egovernment.moa.id.storage.IAuthenticationSessionStoreage; import at.gv.egovernment.moa.id.util.Random; import at.gv.egovernment.moa.id.util.VelocityProvider; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; +@Service("MOAID_SSOManager") public class SSOManager { private static final String HTMLTEMPLATESDIR = "htmlTemplates/"; @@ -65,27 +69,29 @@ public class SSOManager { private static final String SSOCOOKIE = "MOA_ID_SSO"; private static final String SSOINTERFEDERATION = "MOA_INTERFEDERATION_SSO"; - private static final int DEFAULTSSOTIMEOUT = 15 * 60; // sec - private static final int INTERFEDERATIONCOOKIEMAXAGE = 5 * 60;// sec + + @Autowired private IAuthenticationSessionStoreage authenticatedSessionStore; + @Autowired protected AuthConfiguration authConfig; - private static SSOManager instance = null; - - public static SSOManager getInstance() { - if (instance == null) { - instance = new SSOManager(); - - } - - return instance; - } - + /** + * Check if interfederation IDP is requested via HTTP GET parameter or if interfederation cookie exists. + * Set the requested interfederation IDP as attribte of the {protocolRequest} + * + * @param httpReq HttpServletRequest + * @param httpResp HttpServletResponse + * @param protocolRequest Authentication request which is actually in process + * @throws SessionDataStorageException + * + **/ public void checkInterfederationIsRequested(HttpServletRequest httpReq, HttpServletResponse httpResp, - IRequest protocolRequest) { + IRequest protocolRequest) throws SessionDataStorageException { String interIDP = httpReq.getParameter(MOAIDAuthConstants.INTERFEDERATION_IDP); - if (MiscUtil.isNotEmpty(protocolRequest.getRequestedIDP())) { - Logger.debug("Protocolspecific preprocessing already set interfederation IDP " + protocolRequest.getRequestedIDP()); + String interfederationIDP = + protocolRequest.getGenericData(RequestImpl.DATAID_INTERFEDERATIOIDP_URL, String.class); + if (MiscUtil.isNotEmpty(interfederationIDP)) { + Logger.debug("Protocolspecific preprocessing already set interfederation IDP " + interfederationIDP); return; } @@ -95,14 +101,14 @@ public class SSOManager { RequestImpl moaReq = (RequestImpl) protocolRequest; if (MiscUtil.isNotEmpty(interIDP)) { Logger.info("Receive SSO request for interfederation IDP " + interIDP); - moaReq.setRequestedIDP(interIDP); + moaReq.setGenericDataToSession(RequestImpl.DATAID_INTERFEDERATIOIDP_URL, interIDP); } else { //check if IDP cookie is set String cookie = getValueFromCookie(httpReq, SSOINTERFEDERATION); if (MiscUtil.isNotEmpty(cookie)) { Logger.info("Receive SSO request for interfederated IDP from Cookie " + cookie); - moaReq.setRequestedIDP(cookie); + moaReq.setGenericDataToSession(RequestImpl.DATAID_INTERFEDERATIOIDP_URL, cookie); deleteCookie(httpReq, httpResp, SSOINTERFEDERATION); } @@ -120,7 +126,7 @@ public class SSOManager { } - public boolean isValidSSOSession(String ssoSessionID, IRequest protocolRequest) throws ConfigurationException { + public boolean isValidSSOSession(String ssoSessionID, IRequest protocolRequest) throws ConfigurationException, SessionDataStorageException { // search SSO Session if (ssoSessionID == null) { @@ -128,7 +134,7 @@ public class SSOManager { return false; } - AuthenticatedSessionStore storedSession = AuthenticationSessionStoreage.isValidSessionWithSSOID(ssoSessionID, null); + AuthenticatedSessionStore storedSession = authenticatedSessionStore.isValidSessionWithSSOID(ssoSessionID); if (storedSession == null) return false; @@ -137,7 +143,7 @@ public class SSOManager { //check if session is out of lifetime Date now = new Date(); - long maxSSOSessionTime = AuthConfigurationProviderFactory.getInstance().getSSOCreatedTimeOut() * 1000; + long maxSSOSessionTime = authConfig.getSSOCreatedTimeOut() * 1000; Date ssoSessionValidTo = new Date(storedSession.getCreated().getTime() + maxSSOSessionTime); if (now.after(ssoSessionValidTo)) { Logger.info("Found outdated SSO session information. Start reauthentication process ... "); @@ -150,12 +156,16 @@ public class SSOManager { storedSession.isInterfederatedSSOSession() && !storedSession.isAuthenticated()) { - if (MiscUtil.isEmpty(((RequestImpl) protocolRequest).getRequestedIDP())) { - InterfederationSessionStore selectedIDP = AuthenticationSessionStoreage.searchInterfederatedIDPFORSSOWithMOASession(storedSession.getSessionid()); + String interfederationIDP = + protocolRequest.getGenericData(RequestImpl.DATAID_INTERFEDERATIOIDP_URL, String.class); + + if (MiscUtil.isEmpty(interfederationIDP)) { + InterfederationSessionStore selectedIDP = authenticatedSessionStore.searchInterfederatedIDPFORSSOWithMOASession(storedSession.getSessionid()); if (selectedIDP != null) { //no local SSO session exist -> request interfederated IDP - ((RequestImpl) protocolRequest).setRequestedIDP(selectedIDP.getIdpurlprefix()); + protocolRequest.setGenericDataToSession( + RequestImpl.DATAID_INTERFEDERATIOIDP_URL, selectedIDP.getIdpurlprefix()); } else { Logger.warn("MOASession is marked as interfederated SSO session but no interfederated IDP is found. Switch to local authentication ..."); @@ -174,16 +184,17 @@ public class SSOManager { } public String getMOASession(String ssoSessionID) { - return AuthenticationSessionStoreage.getMOASessionSSOID(ssoSessionID); + return authenticatedSessionStore.getMOASessionSSOID(ssoSessionID); } + //TODO: refactor for faster DB access public String getUniqueSessionIdentifier(String ssoSessionID) { try { if (MiscUtil.isNotEmpty(ssoSessionID)) { - String moaSessionID = AuthenticationSessionStoreage.getMOASessionSSOID(ssoSessionID); + String moaSessionID = authenticatedSessionStore.getMOASessionSSOID(ssoSessionID); if (MiscUtil.isNotEmpty(moaSessionID)) { - AuthenticationSessionExtensions extSessionInformation = AuthenticationSessionStoreage.getAuthenticationSessionExtensions(moaSessionID); + AuthenticationSessionExtensions extSessionInformation = authenticatedSessionStore.getAuthenticationSessionExtensions(moaSessionID); return extSessionInformation.getUniqueSessionId(); } @@ -253,14 +264,6 @@ public class SSOManager { } public void setSSOSessionID(HttpServletRequest httpReq, HttpServletResponse httpResp, String ssoId) { - int ssoTimeOut; - try { - ssoTimeOut = (int) AuthConfigurationProviderFactory.getInstance().getSSOCreatedTimeOut(); - - } catch (ConfigurationException e) { - Logger.info("SSO Timeout can not be loaded from MOA-ID configuration. Use default Timeout with " + DEFAULTSSOTIMEOUT); - ssoTimeOut = DEFAULTSSOTIMEOUT; - } setCookie(httpReq, httpResp, SSOCOOKIE, ssoId, -1); } @@ -285,12 +288,12 @@ public class SSOManager { if (MiscUtil.isNotEmpty(ssoSessionID)) { - AuthenticatedSessionStore storedSession = AuthenticationSessionStoreage.isValidSessionWithSSOID(ssoSessionID, null); + AuthenticatedSessionStore storedSession = authenticatedSessionStore.isValidSessionWithSSOID(ssoSessionID); if (storedSession == null) return false; - InterfederationSessionStore selectedIDP = AuthenticationSessionStoreage.searchInterfederatedIDPFORSSOWithMOASessionIDPID(storedSession.getSessionid(), entityID); + InterfederationSessionStore selectedIDP = authenticatedSessionStore.searchInterfederatedIDPFORSSOWithMOASessionIDPID(storedSession.getSessionid(), entityID); if (selectedIDP != null) { //no local SSO session exist -> request interfederated IDP @@ -317,7 +320,7 @@ public class SSOManager { InputStream is = null; String pathLocation = null; try { - String rootconfigdir = AuthConfigurationProviderFactory.getInstance().getRootConfigFileDir(); + String rootconfigdir = authConfig.getRootConfigFileDir(); pathLocation = rootconfigdir + HTMLTEMPLATESDIR + HTMLTEMPLATEFULL; File file = new File(new URI(pathLocation)); is = new FileInputStream(file); @@ -359,7 +362,7 @@ public class SSOManager { BufferedReader reader = new BufferedReader(new InputStreamReader(is )); //set default elements to velocity context - context.put("contextpath", AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix()); + context.put("contextpath", authConfig.getPublicURLPrefix()); StringWriter writer = new StringWriter(); //velocityEngine.evaluate(context, writer, "SLO_Template", reader); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngine.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngine.java index 5cf84abed..b68f170c8 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngine.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngine.java @@ -3,6 +3,7 @@ package at.gv.egovernment.moa.id.process; import java.io.InputStream; +import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.id.process.api.ExecutionContext; import at.gv.egovernment.moa.id.process.model.ProcessDefinition; @@ -61,6 +62,17 @@ public interface ProcessEngine { */ String createProcessInstance(String processDefinitionId) throws ProcessExecutionException; + + /** + * Delete a process instance + * + * @param processInstanceId + * The identifier of the respective process. + * @throws ProcessExecutionException + * Thrown in case of error, e.g. when a {@code processInstanceId} is referenced that does not exist. + */ + void deleteProcessInstance(String processInstanceId) throws ProcessExecutionException; + /** * Returns the process instance with a given {@code processInstanceId}. * @@ -75,24 +87,24 @@ public interface ProcessEngine { ProcessInstance getProcessInstance(String processInstanceId); /** - * Starts the process using the given {@code processInstanceId}. + * Starts the process using the given {@code pendingReq}. * - * @param processInstanceId - * The process instance id. + * @param pendingReq + * The protocol request for which a process should be started. * @throws ProcessExecutionException * Thrown in case of error. */ - void start(String processInstanceId) throws ProcessExecutionException; + void start(IRequest pendingReq) throws ProcessExecutionException; /** * Resumes process execution after an asynchronous task has been executed. * - * @param processInstanceId + * @param pendingReq * The process instance id. * @throws ProcessExecutionException * Thrown in case of error. */ - void signal(String processInstanceId) throws ProcessExecutionException; + void signal(IRequest pendingReq) throws ProcessExecutionException; }
\ No newline at end of file diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngineImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngineImpl.java index 096e5ee9e..437eee63c 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngineImpl.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngineImpl.java @@ -12,22 +12,25 @@ import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; -import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.id.process.api.ExecutionContext; import at.gv.egovernment.moa.id.process.api.ExpressionEvaluationContext; import at.gv.egovernment.moa.id.process.api.ExpressionEvaluator; import at.gv.egovernment.moa.id.process.api.Task; import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStore; import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStoreDAO; -import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStoreDAOImpl; import at.gv.egovernment.moa.id.process.model.EndEvent; import at.gv.egovernment.moa.id.process.model.ProcessDefinition; import at.gv.egovernment.moa.id.process.model.ProcessNode; import at.gv.egovernment.moa.id.process.model.StartEvent; import at.gv.egovernment.moa.id.process.model.TaskInfo; import at.gv.egovernment.moa.id.process.model.Transition; +import at.gv.egovernment.moa.util.MiscUtil; /** * Process engine implementation allowing starting and continuing processes as well as providing means for cleanup actions. @@ -36,10 +39,11 @@ public class ProcessEngineImpl implements ProcessEngine { private Logger log = LoggerFactory.getLogger(getClass()); + @Autowired ProcessInstanceStoreDAO piStoreDao; + @Autowired ApplicationContext context; + private ProcessDefinitionParser pdp = new ProcessDefinitionParser(); - ProcessInstanceStoreDAO piStoreDao = ProcessInstanceStoreDAOImpl.getInstance(); - private Map<String, ProcessDefinition> processDefinitions = new ConcurrentHashMap<String, ProcessDefinition>(); private final static String MDC_CTX_PI_NAME = "processInstanceId"; @@ -114,10 +118,16 @@ public class ProcessEngineImpl implements ProcessEngine { } @Override - public void start(String processInstanceId) throws ProcessExecutionException { - + public void start(IRequest pendingReq) throws ProcessExecutionException { try { - ProcessInstance pi = loadProcessInstance(processInstanceId); + if (MiscUtil.isEmpty(pendingReq.getProcessInstanceId())) { + log.error("Pending-request with id:" + pendingReq.getRequestID() + + " includes NO 'ProcessInstanceId'"); + throw new ProcessExecutionException("Pending-request with id:" + pendingReq.getRequestID() + + " includes NO 'ProcessInstanceId'"); + } + + ProcessInstance pi = loadProcessInstance(pendingReq.getProcessInstanceId()); MDC.put(MDC_CTX_PI_NAME, pi.getId()); @@ -127,9 +137,12 @@ public class ProcessEngineImpl implements ProcessEngine { log.info("Starting process instance '{}'.", pi.getId()); // execute process pi.setState(ProcessInstanceState.STARTED); - execute(pi); + execute(pi, pendingReq); - saveOrUpdateProcessInstance(pi); + //store ProcessInstance if it is not already ended + if (!ProcessInstanceState.ENDED.equals(pi.getState())) + saveOrUpdateProcessInstance(pi); + } catch (MOADatabaseException e) { throw new ProcessExecutionException("Unable to load/save process instance.", e); @@ -139,10 +152,17 @@ public class ProcessEngineImpl implements ProcessEngine { } @Override - public void signal(String processInstanceId) throws ProcessExecutionException { + public void signal(IRequest pendingReq) throws ProcessExecutionException { try { - ProcessInstance pi = loadProcessInstance(processInstanceId); + if (MiscUtil.isEmpty(pendingReq.getProcessInstanceId())) { + log.error("Pending-request with id:" + pendingReq.getRequestID() + + " includes NO 'ProcessInstanceId'"); + throw new ProcessExecutionException("Pending-request with id:" + pendingReq.getRequestID() + + " includes NO 'ProcessInstanceId'"); + } + + ProcessInstance pi = loadProcessInstance(pendingReq.getProcessInstanceId()); MDC.put(MDC_CTX_PI_NAME, pi.getId()); @@ -152,9 +172,16 @@ public class ProcessEngineImpl implements ProcessEngine { log.info("Waking up process instance '{}'.", pi.getId()); pi.setState(ProcessInstanceState.STARTED); - execute(pi); - saveOrUpdateProcessInstance(pi); + //put pending-request ID on execution-context because it could be changed + pi.getExecutionContext().put(MOAIDAuthConstants.PARAM_TARGET_PENDINGREQUESTID, pendingReq.getRequestID()); + + execute(pi, pendingReq); + + //store ProcessInstance if it is not already ended + if (!ProcessInstanceState.ENDED.equals(pi.getState())) + saveOrUpdateProcessInstance(pi); + } catch (MOADatabaseException e) { throw new ProcessExecutionException("Unable to load/save process instance.", e); @@ -176,17 +203,21 @@ public class ProcessEngineImpl implements ProcessEngine { if (clazz != null) { log.debug("Instantiating task implementing class '{}'.", clazz); - Class<?> instanceClass = null; + Object instanceClass = null; try { - instanceClass = Class.forName(clazz, true, Thread.currentThread().getContextClassLoader()); + instanceClass = context.getBean(clazz); + } catch (Exception e) { throw new ProcessExecutionException("Unable to get class '" + clazz + "' associated with task '" + ti.getId() + "' .", e); + } - if (!Task.class.isAssignableFrom(instanceClass)) { + if (instanceClass == null || !(instanceClass instanceof Task)) { throw new ProcessExecutionException("Class '" + clazz + "' associated with task '" + ti.getId() + "' is not assignable to " + Task.class.getName() + "."); + } try { - task = (Task) instanceClass.newInstance(); + task = (Task) instanceClass; + } catch (Exception e) { throw new ProcessExecutionException("Unable to instantiate class '" + clazz + "' associated with task '" + ti.getId() + "' .", e); } @@ -198,9 +229,10 @@ public class ProcessEngineImpl implements ProcessEngine { /** * Starts/executes a given process instance. * @param pi The process instance. + * @param pendingReq * @throws ProcessExecutionException Thrown in case of error. */ - private void execute(final ProcessInstance pi) throws ProcessExecutionException { + private void execute(final ProcessInstance pi, IRequest pendingReq) throws ProcessExecutionException { if (ProcessInstanceState.ENDED.equals(pi.getState())) { throw new ProcessExecutionException("Process for instance '" + pi.getId() + "' has already been ended."); } @@ -221,7 +253,7 @@ public class ProcessEngineImpl implements ProcessEngine { try { log.info("Executing task implementation for task '{}'.", ti.getId()); log.debug("Execution context before task execution: {}", pi.getExecutionContext().keySet()); - task.execute(pi.getExecutionContext()); + pendingReq = task.execute(pendingReq, pi.getExecutionContext()); log.info("Returned from execution of task '{}'.", ti.getId()); log.debug("Execution context after task execution: {}", pi.getExecutionContext().keySet()); } catch (Throwable t) { @@ -239,8 +271,10 @@ public class ProcessEngineImpl implements ProcessEngine { try { piStoreDao.remove(pi.getId()); + } catch (MOADatabaseException e) { throw new ProcessExecutionException("Unable to remove process instance.", e); + } pi.setState(ProcessInstanceState.ENDED); log.debug("Final process context: {}", pi.getExecutionContext().keySet()); @@ -278,7 +312,7 @@ public class ProcessEngineImpl implements ProcessEngine { // continue execution in case of StartEvent or Task if (processNode instanceof StartEvent || processNode instanceof TaskInfo) { - execute(pi); + execute(pi, pendingReq); } } @@ -352,5 +386,25 @@ public class ProcessEngineImpl implements ProcessEngine { return pi; } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.process.ProcessEngine#deleteProcessInstance(java.lang.String) + */ + @Override + public void deleteProcessInstance(String processInstanceId) throws ProcessExecutionException { + if (MiscUtil.isEmpty(processInstanceId)) { + throw new ProcessExecutionException("Unable to remove process instance: ProcessInstanceId is empty"); + + } + + try { + piStoreDao.remove(processInstanceId); + + } catch (MOADatabaseException e) { + throw new ProcessExecutionException("Unable to remove process instance.", e); + + } + + } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/Task.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/Task.java index 343b8fe0c..88048d23e 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/Task.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/Task.java @@ -1,6 +1,7 @@ package at.gv.egovernment.moa.id.process.api; import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.moduls.IRequest; /** @@ -13,11 +14,13 @@ public interface Task { /** * Executes this task. - * + * @param pendingReq + * Provides the current processed protocol request * @param executionContext * Provides execution related information. + * @return The pending-request object, because Process-management works recursive * @throws Exception An exception upon task execution. */ - void execute(ExecutionContext executionContext) throws TaskExecutionException; + IRequest execute(IRequest pendingReq, ExecutionContext executionContext) throws TaskExecutionException; } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAOImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAOImpl.java index a75a5de8c..577e971db 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAOImpl.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAOImpl.java @@ -6,6 +6,7 @@ import org.hibernate.Transaction; import org.hibernate.criterion.Restrictions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; @@ -14,16 +15,11 @@ import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; * Database backed implementation of the {@link ProcessInstanceStoreDAO} * interface. */ +@Service("ProcessInstanceStoreage") public class ProcessInstanceStoreDAOImpl implements ProcessInstanceStoreDAO { private Logger log = LoggerFactory.getLogger(getClass()); - private static ProcessInstanceStoreDAO instance = new ProcessInstanceStoreDAOImpl(); - - public static ProcessInstanceStoreDAO getInstance() { - return instance; - } - @Override public void saveOrUpdate(ProcessInstanceStore pIStore) throws MOADatabaseException { try { diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/MoaIdTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/MoaIdTask.java index fb75fc8d7..b60434b2a 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/MoaIdTask.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/MoaIdTask.java @@ -9,6 +9,7 @@ import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.filter.RequestContextFilter; import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.id.process.api.ExecutionContext; import at.gv.egovernment.moa.id.process.api.Task; @@ -32,6 +33,7 @@ import at.gv.egovernment.moa.id.process.api.Task; * </pre> * * @author tknall + * @author tlenz * */ public abstract class MoaIdTask implements Task { @@ -55,8 +57,31 @@ public abstract class MoaIdTask implements Task { public abstract void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) throws TaskExecutionException; + /** + * Executes the task providing the underlying {@link ExecutionContext} {@code executionContext} + * and the {@link IRequest} {@code pendingReq }as well as the + * respective {@link HttpServletRequest} and {@link HttpServletResponse}. + * + * This method sets the pending-request object of the task implementation and starts the + * {@code execute} method of the task + * + * @param pendingReq The pending-request object (never {@code null}). + * @param executionContext The execution context (never {@code null}). + * @param request The HttpServletRequest (never {@code null}). + * @param response The HttpServletResponse (never {@code null}). + * @return The pending-request object, because Process-management works recursive + * + * @throws IllegalStateException + * Thrown in case the task is being run within the required environment. Refer to javadoc for + * further information. + * @throws Exception + * Thrown in case of error executing the task. + */ + protected abstract IRequest internalExecute(IRequest pendingReq, ExecutionContext executionContext, HttpServletRequest request, + HttpServletResponse response) throws TaskExecutionException; + @Override - public void execute(ExecutionContext executionContext) throws TaskExecutionException { + public IRequest execute(IRequest pendingReq, ExecutionContext executionContext) throws TaskExecutionException { RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); if (requestAttributes != null && requestAttributes instanceof ServletRequestAttributes) { HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest(); @@ -65,7 +90,7 @@ public abstract class MoaIdTask implements Task { throw new IllegalStateException( "Spring's RequestContextHolder did not provide HttpServletResponse. Did you forget to set the required org.springframework.web.filter.RequestContextFilter in your web.xml."); } - execute(executionContext, request, response); + return internalExecute(pendingReq, executionContext, request, response); } else { throw new IllegalStateException("Task needs to be executed within a Spring web environment."); } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/AbstractAuthProtocolModulController.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/AbstractAuthProtocolModulController.java new file mode 100644 index 000000000..bb89f2e03 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/AbstractAuthProtocolModulController.java @@ -0,0 +1,272 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.protocols; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; + +import at.gv.egovernment.moa.id.auth.builder.AuthenticationDataBuilder; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; +import at.gv.egovernment.moa.id.auth.servlet.AbstractController; +import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; +import at.gv.egovernment.moa.id.data.IAuthData; +import at.gv.egovernment.moa.id.data.SLOInformationInterface; +import at.gv.egovernment.moa.id.moduls.AuthenticationManager; +import at.gv.egovernment.moa.id.moduls.IAction; +import at.gv.egovernment.moa.id.moduls.IModulInfo; +import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.id.moduls.RequestImpl; +import at.gv.egovernment.moa.id.moduls.SSOManager; +import at.gv.egovernment.moa.id.storage.IAuthenticationSessionStoreage; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; + +/** + * @author tlenz + * + */ + +public abstract class AbstractAuthProtocolModulController extends AbstractController implements IModulInfo { + + public static final String FINALIZEPROTOCOL_ENDPOINT = "finalizeAuthProtocol"; + + @Autowired protected ApplicationContext applicationContext; + @Autowired private SSOManager ssomanager; + @Autowired protected AuthenticationManager authmanager; + @Autowired protected IAuthenticationSessionStoreage authenticatedSessionStorage; + @Autowired private AuthenticationDataBuilder authDataBuilder; + + /** + * Initialize an authentication process for this protocol request + * + * @param httpReq HttpServletRequest + * @param httpResp HttpServletResponse + * @param protocolRequest Authentication request which is actually in process + * @throws IOException + */ + protected void performAuthentication(HttpServletRequest req, HttpServletResponse resp, + RequestImpl pendingReq) throws IOException { + try { + if (pendingReq.isNeedAuthentication()) { + //request needs authentication --> start authentication process ... + + //load Parameters from OnlineApplicationConfiguration + IOAAuthParameters oaParam = pendingReq.getOnlineApplicationConfiguration(); + + if (oaParam == null) { + throw new AuthenticationException("auth.00", new Object[] { pendingReq.getOAURL() }); + } + + + AuthenticationSession moaSession = authmanager.doAuthentication(req, resp, pendingReq); + if (moaSession != null) { + //authenticated MOASession already exists --> protocol-specific postProcessing can start directly + finalizeAuthenticationProcess(req, resp, pendingReq, moaSession); + + } + + } else { + executeProtocolSpecificAction(req, resp, pendingReq, null); + + } + + } catch (Exception e) { + buildProtocolSpecificErrorResponse(e, req, resp, pendingReq); + + } + } + + /** + * Finalize the requested protocol operation + * + * @param httpReq HttpServletRequest + * @param httpResp HttpServletResponse + * @param protocolRequest Authentication request which is actually in process + * @param moaSession MOASession object, which is used to generate the protocol specific authentication information + * @throws Exception + */ + protected void finalizeAuthenticationProcess(HttpServletRequest req, HttpServletResponse resp, + IRequest pendingReq, AuthenticationSession moaSession) throws Exception { + + String newSSOSessionId = null; + + //if Single Sign-On functionality is enabled for this request + if (pendingReq.needSingleSignOnFunctionality()) { + + //Store SSO information into database + newSSOSessionId = ssomanager.createSSOSessionInformations(moaSession.getSessionID(), + pendingReq.getOAURL()); + + //set SSO cookie to response + if (MiscUtil.isNotEmpty(newSSOSessionId)) { + ssomanager.setSSOSessionID(req, resp, newSSOSessionId); + + } else { + ssomanager.deleteSSOSessionID(req, resp); + + } + + } + + //build authenticationdata from session information and OA configuration + IAuthData authData = authDataBuilder.buildAuthenticationData(pendingReq, moaSession); + + //execute the protocol-specific action + SLOInformationInterface sloInformation = executeProtocolSpecificAction(req, resp, pendingReq, authData); + + //check if SSO + boolean isSSOCookieSetted = MiscUtil.isNotEmpty(newSSOSessionId); + + //Store OA specific SSO session information if an SSO cookie is set + if (isSSOCookieSetted) { + try { + authenticatedSessionStorage.addSSOInformation(moaSession.getSessionID(), + newSSOSessionId, sloInformation, pendingReq); + + } catch (AuthenticationException e) { + Logger.warn("SSO Session information can not be stored -> SSO is not enabled!"); + authmanager.performOnlyIDPLogOut(req, resp, moaSession.getSessionID()); + + } + + } else { + //remove MOASession from database + authmanager.performOnlyIDPLogOut(req, resp, moaSession.getSessionID()); + + } + + //Advanced statistic logging + statisticLogger.logSuccessOperation(pendingReq, authData, isSSOCookieSetted); + + } + + /** + * Executes the requested protocol action + * + * @param httpReq HttpServletRequest + * @param httpResp HttpServletResponse + * @param protocolRequest Authentication request which is actually in process + * @param authData Service-provider specific authentication data + * + * @return Return Single LogOut information or null if protocol supports no SSO + * + * @throws Exception + */ + private SLOInformationInterface executeProtocolSpecificAction(HttpServletRequest httpReq, HttpServletResponse httpResp, + IRequest pendingReq, IAuthData authData) throws Exception { + try { + // request needs no authentication --> start request processing + Class<?> clazz = Class.forName(pendingReq.requestedAction()); + if (clazz == null || + !IAction.class.isAssignableFrom(clazz)) { + Logger.fatal("Requested protocol-action processing Class is NULL or does not implement the IAction interface."); + throw new Exception("Requested protocol-action processing Class is NULL or does not implement the IAction interface."); + + } + + IAction protocolAction = (IAction) applicationContext.getBean(clazz); + return protocolAction.processRequest(pendingReq, httpReq, httpResp, authData); + + } catch (ClassNotFoundException e) { + Logger.fatal("Requested Auth. protocol processing Class is NULL or does not implement the IAction interface."); + throw new Exception("Requested Auth. protocol processing Class is NULL or does not implement the IAction interface."); + } + + } + + protected void buildProtocolSpecificErrorResponse(Throwable throwable, HttpServletRequest req, + HttpServletResponse resp, IRequest protocolRequest) throws IOException { + try { + + Class<?> clazz = Class.forName(protocolRequest.requestedModule()); + if (clazz == null || + !clazz.isInstance(IModulInfo.class)) { + Logger.fatal("Requested protocol module Class is NULL or does not implement the IModulInfo interface."); + throw new Exception("Requested protocol module Class is NULL or does not implement the IModulInfo interface."); + + } + + IModulInfo handlingModule = (IModulInfo) applicationContext.getBean(clazz); + + if (handlingModule.generateErrorMessage( + throwable, req, resp, protocolRequest)) { + + //log Error to technical log + logExceptionToTechnicalLog(throwable); + + //log Error Message + statisticLogger.logErrorOperation(throwable, protocolRequest); + + //remove MOASession + AuthenticationSession moaSession = authenticatedSessionStorage.getSession( + protocolRequest.getMOASessionIdentifier()); + if (moaSession != null) + authmanager.performOnlyIDPLogOut(req, resp, moaSession.getSessionID()); + + return; + + } else { + handleErrorNoRedirect(throwable, req, resp, true); + + } + + } catch (Throwable e) { + Logger.error(e); + handleErrorNoRedirect(throwable, req, resp, true); + + } + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.moduls.IModulInfo#getName() + */ + @Override + public abstract String getName(); + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.moduls.IModulInfo#getPath() + */ + @Override + public abstract String getPath(); + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.moduls.IModulInfo#generateErrorMessage(java.lang.Throwable, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, at.gv.egovernment.moa.id.moduls.IRequest) + */ + @Override + public abstract boolean generateErrorMessage(Throwable e, HttpServletRequest request, HttpServletResponse response, + IRequest protocolRequest) throws Throwable; + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.moduls.IModulInfo#validate(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, at.gv.egovernment.moa.id.moduls.IRequest) + */ + @Override + public abstract boolean validate(HttpServletRequest request, HttpServletResponse response, IRequest pending); + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/ProtocolFinalizationController.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/ProtocolFinalizationController.java new file mode 100644 index 000000000..8c3f2c946 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/ProtocolFinalizationController.java @@ -0,0 +1,201 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.protocols; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; +import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; +import at.gv.egovernment.moa.id.util.ParamValidatorUtils; +import at.gv.egovernment.moa.logging.Logger; + +/** + * @author tlenz + * + */ +@Controller +public class ProtocolFinalizationController extends AbstractAuthProtocolModulController { + + @RequestMapping(value = "/finalizeAuthProtocol", method = {RequestMethod.GET}) + public void finalizeAuthProtocol(HttpServletRequest req, HttpServletResponse resp) throws MOAIDException, IOException { + + //read pendingRequest from http request + Object idObject = req.getParameter(PARAM_TARGET_PENDINGREQUESTID); + IRequest pendingReq = null; + String pendingRequestID = null; + if (idObject != null && (idObject instanceof String)) { + pendingRequestID = (String) idObject; + pendingReq = requestStorage.getPendingRequest(pendingRequestID); + + } + + //receive an authentication error + String errorid = req.getParameter(ERROR_CODE_PARAM); + if (errorid != null) { + try { + //load stored exception from database + Throwable throwable = transactionStorage.get(errorid, Throwable.class); + transactionStorage.remove(errorid); + + if (throwable != null) { + if (pendingReq != null) { + revisionsLogger.logEvent(pendingReq, MOAIDEventConstants.TRANSACTION_ERROR); + + //build protocol-specific error message if possible + buildProtocolSpecificErrorResponse(throwable, req, resp, pendingReq); + + //log Error Message + statisticLogger.logErrorOperation(throwable, pendingReq); + + //get MOASession for this pendingRequest + AuthenticationSession moaSession = + authenticatedSessionStorage.getSession( + pendingReq.getMOASessionIdentifier()); + + //remove MOASession if someone is found + if (moaSession != null) + authmanager.performOnlyIDPLogOut(req, resp, moaSession.getSessionID()); + + return; + + } else { + handleErrorNoRedirect(throwable, req, resp, true); + + } + } else { + handleErrorNoRedirect(new Exception( + MOAIDMessageProvider.getInstance().getMessage("auth.26", null)), + req, resp, false); + + } + + } catch (Throwable e) { + Logger.error(e); + + handleErrorNoRedirect(e, req, resp, false); + + } + + // receive a pending request + } else { + if (pendingReq == null) { + Logger.error("No PendingRequest with ID " + pendingRequestID + " found.!"); + handleErrorNoRedirect(new MOAIDException("auth.28", new Object[]{pendingRequestID}), req, resp, false); + return; + + } + try { + Logger.debug("Finalize PendingRequest with ID " + pendingRequestID); + + //get MOASession from database + String sessionID = pendingReq.getMOASessionIdentifier(); + + // check parameter + if (!ParamValidatorUtils.isValidSessionID(sessionID)) { + throw new WrongParametersException("FinalizeAuthProtocol", PARAM_SESSIONID, "auth.12"); + + } + + //load MOASession from database + AuthenticationSession moaSession = authenticatedSessionStorage.getSession(sessionID); + if (moaSession == null) { + Logger.error("No MOASession with ID " + sessionID + " found.!"); + handleErrorNoRedirect(new MOAIDException("auth.02", new Object[]{sessionID}), req, resp, true); + return; + + } + + //check if MOASession and pending-request are authenticated + if (moaSession.isAuthenticated() && pendingReq.isAuthenticated()) { + finalizeAuthenticationProcess(req, resp, pendingReq, moaSession); + + } else { + Logger.error("MOASession oder Pending-Request are not authenticated --> Abort authentication process!"); + handleErrorNoRedirect(new MOAIDException("auth.20", null), req, resp, true); + return; + + } + + } catch (Exception e) { + Logger.error("Finalize authentication protocol FAILED." , e); + buildProtocolSpecificErrorResponse(e, req, resp, pendingReq); + + } + } + + //remove pending-request + if (pendingReq != null) + requestStorage.removePendingRequest(pendingReq.getRequestID()); + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.AbstractProtocolModulController#getName() + */ + @Override + public String getName() { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.AbstractProtocolModulController#getPath() + */ + @Override + public String getPath() { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.AbstractProtocolModulController#generateErrorMessage(java.lang.Throwable, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, at.gv.egovernment.moa.id.moduls.IRequest) + */ + @Override + public boolean generateErrorMessage(Throwable e, HttpServletRequest request, HttpServletResponse response, + IRequest protocolRequest) throws Throwable { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.AbstractProtocolModulController#validate(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, at.gv.egovernment.moa.id.moduls.IRequest) + */ + @Override + public boolean validate(HttpServletRequest request, HttpServletResponse response, IRequest pending) { + // TODO Auto-generated method stub + return false; + } + + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/AttributQueryAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/AttributQueryAction.java index 9f8b6610f..bd6399377 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/AttributQueryAction.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/AttributQueryAction.java @@ -24,6 +24,7 @@ package at.gv.egovernment.moa.id.protocols.pvp2x; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import javax.servlet.http.HttpServletRequest; @@ -36,8 +37,8 @@ import org.opensaml.saml2.core.AttributeQuery; import org.opensaml.saml2.core.Response; import org.opensaml.ws.message.encoder.MessageEncodingException; import org.opensaml.xml.security.SecurityException; - -import java.util.Arrays; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import at.gv.egovernment.moa.id.auth.builder.AuthenticationDataBuilder; import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; @@ -51,15 +52,21 @@ import at.gv.egovernment.moa.id.protocols.pvp2x.builder.AuthResponseBuilder; import at.gv.egovernment.moa.id.protocols.pvp2x.builder.assertion.PVP2AssertionBuilder; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AttributQueryException; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; -import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; +import at.gv.egovernment.moa.id.protocols.pvp2x.signer.IDPCredentialProvider; +import at.gv.egovernment.moa.id.storage.IAuthenticationSessionStoreage; import at.gv.egovernment.moa.logging.Logger; /** * @author tlenz * */ +@Service("AttributQueryAction") public class AttributQueryAction implements IAction { + @Autowired IAuthenticationSessionStoreage authenticationSessionStorage; + @Autowired private AuthenticationDataBuilder authDataBuilder; + @Autowired private IDPCredentialProvider pvpCredentials; + private final static List<String> DEFAULTSTORKATTRIBUTES = Arrays.asList( new String[]{PVPConstants.EID_STORK_TOKEN_NAME}); @@ -86,7 +93,7 @@ public class AttributQueryAction implements IAction { //load moaSession String nameID = attrQuery.getSubject().getNameID().getValue(); - AuthenticationSession session = AuthenticationSessionStoreage.getSessionWithUserNameID(nameID); + AuthenticationSession session = authenticationSessionStorage.getSessionWithUserNameID(nameID); if (session == null) { Logger.warn("AttributeQuery nameID does not match to an active single sign-on session."); throw new AttributQueryException("AttributeQuery nameID does not match to an active single sign-on session.", null); @@ -96,20 +103,21 @@ public class AttributQueryAction implements IAction { DateTime date = new DateTime(); //generate authData - authData = AuthenticationDataBuilder.buildAuthenticationData(req, session, attrQuery.getAttributes()); + authData = authDataBuilder.buildAuthenticationData(req, session, attrQuery.getAttributes()); //add default attributes in case of mandates or STORK is in use List<String> attrList = addDefaultAttributes(attrQuery, authData); //build PVP 2.1 assertion - Assertion assertion = PVP2AssertionBuilder.buildAssertion(attrQuery, attrList, authData, date, authData.getSessionIndex()); + Assertion assertion = PVP2AssertionBuilder.buildAssertion(req, attrQuery, attrList, authData, date, authData.getSessionIndex()); //build PVP 2.1 response - Response authResponse = AuthResponseBuilder.buildResponse(attrQuery, date, assertion); + Response authResponse = AuthResponseBuilder.buildResponse(req.getAuthURL(), attrQuery, date, assertion); try { SoapBinding decoder = new SoapBinding(); - decoder.encodeRespone(httpReq, httpResp, authResponse, null, null); + decoder.encodeRespone(httpReq, httpResp, authResponse, null, null, + pvpCredentials.getIDPAssertionSigningCredential()); return null; } catch (MessageEncodingException e) { diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/AuthenticationAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/AuthenticationAction.java index 04b7854b1..21f505bf1 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/AuthenticationAction.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/AuthenticationAction.java @@ -25,27 +25,99 @@ package at.gv.egovernment.moa.id.protocols.pvp2x; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.joda.time.DateTime; +import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.saml2.core.Assertion; +import org.opensaml.saml2.core.AuthnRequest; +import org.opensaml.saml2.core.Response; +import org.opensaml.saml2.metadata.AssertionConsumerService; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.ws.message.encoder.MessageEncodingException; +import org.opensaml.xml.security.SecurityException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + import at.gv.egovernment.moa.id.auth.exception.MOAIDException; import at.gv.egovernment.moa.id.data.IAuthData; import at.gv.egovernment.moa.id.data.SLOInformationImpl; import at.gv.egovernment.moa.id.data.SLOInformationInterface; import at.gv.egovernment.moa.id.moduls.IAction; import at.gv.egovernment.moa.id.moduls.IRequest; -import at.gv.egovernment.moa.id.protocols.pvp2x.requestHandler.RequestManager; +import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder; +import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding; +import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding; +import at.gv.egovernment.moa.id.protocols.pvp2x.builder.AuthResponseBuilder; +import at.gv.egovernment.moa.id.protocols.pvp2x.builder.assertion.PVP2AssertionBuilder; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.BindingNotSupportedException; +import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; +import at.gv.egovernment.moa.id.protocols.pvp2x.signer.IDPCredentialProvider; +import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; +import at.gv.egovernment.moa.logging.Logger; +@Service("PVPAuthenticationRequestAction") public class AuthenticationAction implements IAction { - + @Autowired IDPCredentialProvider pvpCredentials; + public SLOInformationInterface processRequest(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp, IAuthData authData) throws MOAIDException { PVPTargetConfiguration pvpRequest = (PVPTargetConfiguration) req; - SLOInformationImpl sloInformation = (SLOInformationImpl) RequestManager.getInstance().handle(pvpRequest, httpReq, httpResp, authData); + //get basic information + MOARequest moaRequest = (MOARequest) pvpRequest.getRequest(); + AuthnRequest authnRequest = (AuthnRequest) moaRequest.getSamlRequest(); + EntityDescriptor peerEntity = moaRequest.getEntityMetadata(); + + AssertionConsumerService consumerService = + SAML2Utils.createSAMLObject(AssertionConsumerService.class); + consumerService.setBinding(pvpRequest.getBinding()); + consumerService.setLocation(pvpRequest.getConsumerURL()); + + DateTime date = new DateTime(); + + SLOInformationImpl sloInformation = new SLOInformationImpl(); + + //build Assertion + Assertion assertion = PVP2AssertionBuilder.buildAssertion(pvpRequest, authnRequest, authData, + peerEntity, date, consumerService, sloInformation); + + Response authResponse = AuthResponseBuilder.buildResponse(pvpRequest.getAuthURL(), authnRequest, date, assertion); + + IEncoder binding = null; - //set protocol type - sloInformation.setProtocolType(req.requestedModule()); + if (consumerService.getBinding().equals( + SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { + binding = new RedirectBinding(); + + } else if (consumerService.getBinding().equals( + SAMLConstants.SAML2_POST_BINDING_URI)) { + binding = new PostBinding(); + + } + + if (binding == null) { + throw new BindingNotSupportedException(consumerService.getBinding()); + } + + try { + binding.encodeRespone(httpReq, httpResp, authResponse, + consumerService.getLocation(), moaRequest.getRelayState(), + pvpCredentials.getIDPAssertionSigningCredential()); + + //set protocol type + sloInformation.setProtocolType(req.requestedModule()); + return sloInformation; + + } catch (MessageEncodingException e) { + Logger.error("Message Encoding exception", e); + throw new MOAIDException("pvp2.01", null, e); + + } catch (SecurityException e) { + Logger.error("Security exception", e); + throw new MOAIDException("pvp2.01", null, e); + + } - return sloInformation; } public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, @@ -54,7 +126,8 @@ public class AuthenticationAction implements IAction { } public String getDefaultActionName() { - return (PVP2XProtocol.REDIRECT); + return "PVPAuthenticationRequestAction"; + } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java index 1b187d82e..15fe1e9d7 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java @@ -22,150 +22,44 @@ *******************************************************************************/ package at.gv.egovernment.moa.id.protocols.pvp2x; -import java.io.StringWriter; -import java.util.List; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; -import org.joda.time.DateTime; -import org.opensaml.Configuration; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.core.NameIDType; -import org.opensaml.saml2.metadata.AssertionConsumerService; -import org.opensaml.saml2.metadata.AttributeConsumingService; -import org.opensaml.saml2.metadata.ContactPerson; -import org.opensaml.saml2.metadata.EntitiesDescriptor; -import org.opensaml.saml2.metadata.EntityDescriptor; -import org.opensaml.saml2.metadata.IDPSSODescriptor; -import org.opensaml.saml2.metadata.KeyDescriptor; -import org.opensaml.saml2.metadata.LocalizedString; -import org.opensaml.saml2.metadata.NameIDFormat; -import org.opensaml.saml2.metadata.RoleDescriptor; -import org.opensaml.saml2.metadata.SPSSODescriptor; -import org.opensaml.saml2.metadata.ServiceName; -import org.opensaml.saml2.metadata.SingleLogoutService; -import org.opensaml.saml2.metadata.SingleSignOnService; -import org.opensaml.xml.io.Marshaller; -import org.opensaml.xml.security.SecurityException; -import org.opensaml.xml.security.SecurityHelper; -import org.opensaml.xml.security.credential.Credential; -import org.opensaml.xml.security.credential.UsageType; -import org.opensaml.xml.security.keyinfo.KeyInfoGenerator; -import org.opensaml.xml.security.x509.X509Credential; -import org.opensaml.xml.security.x509.X509KeyInfoGeneratorFactory; -import org.opensaml.xml.signature.Signature; -import org.opensaml.xml.signature.Signer; -import org.w3c.dom.Document; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; -import at.gv.egovernment.moa.id.config.ConfigurationException; import at.gv.egovernment.moa.id.data.IAuthData; import at.gv.egovernment.moa.id.data.SLOInformationInterface; import at.gv.egovernment.moa.id.moduls.IAction; import at.gv.egovernment.moa.id.moduls.IRequest; -import at.gv.egovernment.moa.id.protocols.pvp2x.builder.PVPAttributeBuilder; -import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration; -import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialProvider; -import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialsNotAvailableException; -import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; +import at.gv.egovernment.moa.id.protocols.pvp2x.builder.PVPMetadataBuilder; +import at.gv.egovernment.moa.id.protocols.pvp2x.config.IDPPVPMetadataConfiguration; +import at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPMetadataBuilderConfiguration; +import at.gv.egovernment.moa.id.protocols.pvp2x.signer.IDPCredentialProvider; import at.gv.egovernment.moa.logging.Logger; +@Service("pvpMetadataService") public class MetadataAction implements IAction { - private static final int VALIDUNTIL_IN_HOURS = 24; - + + + @Autowired private MOAReversionLogger revisionsLogger; + @Autowired private IDPCredentialProvider credentialProvider; + @Autowired private PVPMetadataBuilder metadatabuilder; + public SLOInformationInterface processRequest(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp, IAuthData authData) throws MOAIDException { try { - - MOAReversionLogger.getInstance().logEvent(req, MOAIDEventConstants.AUTHPROTOCOL_PVP_METADATA); - - EntitiesDescriptor idpEntitiesDescriptor = - SAML2Utils.createSAMLObject(EntitiesDescriptor.class); - - idpEntitiesDescriptor.setName(PVPConfiguration.getInstance().getIDPIssuerName()); - - idpEntitiesDescriptor.setID(SAML2Utils.getSecureIdentifier()); - - DateTime date = new DateTime(); + revisionsLogger.logEvent(req, MOAIDEventConstants.AUTHPROTOCOL_PVP_METADATA); - idpEntitiesDescriptor.setValidUntil(date.plusHours(VALIDUNTIL_IN_HOURS)); - - EntityDescriptor idpEntityDescriptor = SAML2Utils - .createSAMLObject(EntityDescriptor.class); - - idpEntitiesDescriptor.getEntityDescriptors().add(idpEntityDescriptor); + //build metadata + IPVPMetadataBuilderConfiguration metadataConfig = + new IDPPVPMetadataConfiguration(req.getAuthURLWithOutSlash(), credentialProvider); - //TODO: maybe change EntityID to Metadata URL - //idpEntityDescriptor - // .setEntityID(PVPConfiguration.getInstance().getIDPSSOMetadataService()); - - idpEntityDescriptor - .setEntityID(PVPConfiguration.getInstance().getIDPPublicPath()); - - idpEntityDescriptor.setValidUntil(date.plusDays(VALIDUNTIL_IN_HOURS)); - - List<ContactPerson> persons = PVPConfiguration.getInstance() - .getIDPContacts(); - - idpEntityDescriptor.getContactPersons().addAll(persons); - - idpEntityDescriptor.setOrganization(PVPConfiguration.getInstance() - .getIDPOrganisation()); - - X509KeyInfoGeneratorFactory keyInfoFactory = new X509KeyInfoGeneratorFactory(); - //keyInfoFactory.setEmitPublicKeyValue(true); - keyInfoFactory.setEmitEntityIDAsKeyName(true); - keyInfoFactory.setEmitEntityCertificate(true); - - KeyInfoGenerator keyInfoGenerator = keyInfoFactory.newInstance(); - - Credential metadataSigningCredential = CredentialProvider.getIDPMetaDataSigningCredential(); - Signature signature = CredentialProvider - .getIDPSignature(metadataSigningCredential); - - //set KeyInfo Element - SecurityHelper.prepareSignatureParams(signature, metadataSigningCredential, null, null); - - idpEntitiesDescriptor.setSignature(signature); - - //set IDP metadata - idpEntityDescriptor.getRoleDescriptors().add(generateIDPMetadata(keyInfoGenerator)); - - //set SP metadata for interfederation - idpEntityDescriptor.getRoleDescriptors().add(generateSPMetadata(keyInfoGenerator)); - - DocumentBuilder builder; - DocumentBuilderFactory factory = DocumentBuilderFactory - .newInstance(); - - builder = factory.newDocumentBuilder(); - Document document = builder.newDocument(); - Marshaller out = Configuration.getMarshallerFactory() - .getMarshaller(idpEntitiesDescriptor); - out.marshall(idpEntitiesDescriptor, document); - - Signer.signObject(signature); - - Transformer transformer = TransformerFactory.newInstance() - .newTransformer(); - - StringWriter sw = new StringWriter(); - StreamResult sr = new StreamResult(sw); - DOMSource source = new DOMSource(document); - transformer.transform(source, sr); - sw.close(); - - String metadataXML = sw.toString(); + String metadataXML = metadatabuilder.buildPVPMetadata(metadataConfig); Logger.debug("METADATA: " + metadataXML); httpResp.setContentType("text/xml"); @@ -186,232 +80,12 @@ public class MetadataAction implements IAction { return false; } + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.moduls.IAction#getDefaultActionName() + */ + @Override public String getDefaultActionName() { - return (PVP2XProtocol.METADATA); + return "IDP - PVP Metadata action"; } - private RoleDescriptor generateSPMetadata(KeyInfoGenerator keyInfoGenerator) throws CredentialsNotAvailableException, SecurityException, ConfigurationException { - - Logger.debug("Set SP Metadata key information"); - - SPSSODescriptor spSSODescriptor = SAML2Utils - .createSAMLObject(SPSSODescriptor.class); - - spSSODescriptor.setAuthnRequestsSigned(true); - spSSODescriptor.setWantAssertionsSigned(false); - - - //Set AuthRequest Signing certificate - X509Credential authcredential = CredentialProvider.getIDPAssertionSigningCredential(); - - KeyDescriptor signKeyDescriptor = SAML2Utils - .createSAMLObject(KeyDescriptor.class); - signKeyDescriptor.setUse(UsageType.SIGNING); - signKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(authcredential)); - spSSODescriptor.getKeyDescriptors().add(signKeyDescriptor); - - - //set AuthRequest encryption certificate - - X509Credential authEncCredential = CredentialProvider.getIDPAssertionEncryptionCredential(); - - if (authEncCredential != null) { - KeyDescriptor encryKeyDescriptor = SAML2Utils - .createSAMLObject(KeyDescriptor.class); - encryKeyDescriptor.setUse(UsageType.ENCRYPTION); - encryKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(authEncCredential)); - spSSODescriptor.getKeyDescriptors().add(encryKeyDescriptor); - - } else { - Logger.warn("No Assertion Encryption-Key defined. This setting is not recommended!"); - - } - - NameIDFormat persistentnameIDFormat = SAML2Utils.createSAMLObject(NameIDFormat.class); - persistentnameIDFormat.setFormat(NameIDType.PERSISTENT); - - spSSODescriptor.getNameIDFormats().add(persistentnameIDFormat); - - NameIDFormat transientnameIDFormat = SAML2Utils.createSAMLObject(NameIDFormat.class); - transientnameIDFormat.setFormat(NameIDType.TRANSIENT); - - spSSODescriptor.getNameIDFormats().add(transientnameIDFormat); - - NameIDFormat unspecifiednameIDFormat = SAML2Utils.createSAMLObject(NameIDFormat.class); - unspecifiednameIDFormat.setFormat(NameIDType.UNSPECIFIED); - - spSSODescriptor.getNameIDFormats().add(unspecifiednameIDFormat); - - //add assertion consumer services - AssertionConsumerService postassertionConsumerService = - SAML2Utils.createSAMLObject(AssertionConsumerService.class); - postassertionConsumerService.setIndex(0); - postassertionConsumerService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI); - postassertionConsumerService.setLocation(PVPConfiguration - .getInstance().getSPSSOPostService()); - postassertionConsumerService.setIsDefault(true); - spSSODescriptor.getAssertionConsumerServices().add(postassertionConsumerService); - - AssertionConsumerService redirectassertionConsumerService = - SAML2Utils.createSAMLObject(AssertionConsumerService.class); - redirectassertionConsumerService.setIndex(1); - redirectassertionConsumerService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); - redirectassertionConsumerService.setLocation(PVPConfiguration - .getInstance().getSPSSORedirectService()); - spSSODescriptor.getAssertionConsumerServices().add(redirectassertionConsumerService); - - - //add SLO descriptor -// SingleLogoutService postSLOService = -// SAML2Utils.createSAMLObject(SingleLogoutService.class); -// postSLOService.setLocation(PVPConfiguration -// .getInstance().getIDPSSOPostService()); -// postSLOService -// .setBinding(SAMLConstants.SAML2_POST_BINDING_URI); -// spSSODescriptor.getSingleLogoutServices().add(postSLOService); - - SingleLogoutService redirectSLOService = - SAML2Utils.createSAMLObject(SingleLogoutService.class); - redirectSLOService.setLocation(PVPConfiguration - .getInstance().getSPSSORedirectService()); - redirectSLOService - .setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); - spSSODescriptor.getSingleLogoutServices().add(redirectSLOService); - - - spSSODescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS); - - AttributeConsumingService attributeService = - SAML2Utils.createSAMLObject(AttributeConsumingService.class); - - attributeService.setIndex(0); - attributeService.setIsDefault(true); - ServiceName serviceName = SAML2Utils.createSAMLObject(ServiceName.class); - serviceName.setName(new LocalizedString("Default Service", "de")); - attributeService.getNames().add(serviceName); - - return spSSODescriptor; - } - - private IDPSSODescriptor generateIDPMetadata(KeyInfoGenerator keyInfoGenerator) throws ConfigurationException, CredentialsNotAvailableException, SecurityException { - - -// //set SignatureMethode -// signature.setSignatureAlgorithm(PVPConstants.DEFAULT_SIGNING_METHODE); -// -// //set DigestMethode -// List<ContentReference> contentList = signature.getContentReferences(); -// for (ContentReference content : contentList) { -// -// if (content instanceof SAMLObjectContentReference) { -// -// SAMLObjectContentReference el = (SAMLObjectContentReference) content; -// el.setDigestAlgorithm(PVPConstants.DEFAULT_DIGESTMETHODE); -// -// } -// } - - -// KeyInfoBuilder metadataKeyInfoBuilder = new KeyInfoBuilder(); -// KeyInfo metadataKeyInfo = metadataKeyInfoBuilder.buildObject(); -// //KeyInfoHelper.addCertificate(metadataKeyInfo, metadataSigningCredential.); -// signature.setKeyInfo(metadataKeyInfo ); - - - IDPSSODescriptor idpSSODescriptor = SAML2Utils - .createSAMLObject(IDPSSODescriptor.class); - - idpSSODescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS); - - idpSSODescriptor.setWantAuthnRequestsSigned(true); - - if (PVPConfiguration.getInstance().getIDPSSOPostService() != null) { - //add SSO descriptor - SingleSignOnService postSingleSignOnService = SAML2Utils - .createSAMLObject(SingleSignOnService.class); - postSingleSignOnService.setLocation(PVPConfiguration - .getInstance().getIDPSSOPostService()); - postSingleSignOnService - .setBinding(SAMLConstants.SAML2_POST_BINDING_URI); - idpSSODescriptor.getSingleSignOnServices().add( - postSingleSignOnService); - - //add SLO descriptor -// SingleLogoutService postSLOService = -// SAML2Utils.createSAMLObject(SingleLogoutService.class); -// postSLOService.setLocation(PVPConfiguration -// .getInstance().getIDPSSOPostService()); -// postSLOService -// .setBinding(SAMLConstants.SAML2_POST_BINDING_URI); -// idpSSODescriptor.getSingleLogoutServices().add(postSLOService); - - } - - if (PVPConfiguration.getInstance().getIDPSSORedirectService() != null) { - //add SSO descriptor - SingleSignOnService redirectSingleSignOnService = SAML2Utils - .createSAMLObject(SingleSignOnService.class); - redirectSingleSignOnService.setLocation(PVPConfiguration - .getInstance().getIDPSSORedirectService()); - redirectSingleSignOnService - .setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); - idpSSODescriptor.getSingleSignOnServices().add( - redirectSingleSignOnService); - - //add SLO descriptor - SingleLogoutService redirectSLOService = - SAML2Utils.createSAMLObject(SingleLogoutService.class); - redirectSLOService.setLocation(PVPConfiguration - .getInstance().getIDPSSORedirectService()); - redirectSLOService - .setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); - idpSSODescriptor.getSingleLogoutServices().add(redirectSLOService); - } - - /*if (PVPConfiguration.getInstance().getIDPResolveSOAPService() != null) { - ArtifactResolutionService artifactResolutionService = SAML2Utils - .createSAMLObject(ArtifactResolutionService.class); - - artifactResolutionService - .setBinding(SAMLConstants.SAML2_SOAP11_BINDING_URI); - artifactResolutionService.setLocation(PVPConfiguration - .getInstance().getIDPResolveSOAPService()); - - artifactResolutionService.setIndex(0); - - idpSSODescriptor.getArtifactResolutionServices().add( - artifactResolutionService); - }*/ - - //set assertion signing key - Credential assertionSigingCredential = CredentialProvider - .getIDPAssertionSigningCredential(); - - KeyDescriptor signKeyDescriptor = SAML2Utils - .createSAMLObject(KeyDescriptor.class); - signKeyDescriptor.setUse(UsageType.SIGNING); - signKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(assertionSigingCredential)); - idpSSODescriptor.getKeyDescriptors().add(signKeyDescriptor); - - idpSSODescriptor.getAttributes().addAll(PVPAttributeBuilder.buildSupportedEmptyAttributes()); - - NameIDFormat persistenNameIDFormat = SAML2Utils.createSAMLObject(NameIDFormat.class); - persistenNameIDFormat.setFormat(NameIDType.PERSISTENT); - - idpSSODescriptor.getNameIDFormats().add(persistenNameIDFormat); - - NameIDFormat transientNameIDFormat = SAML2Utils.createSAMLObject(NameIDFormat.class); - transientNameIDFormat.setFormat(NameIDType.TRANSIENT); - - idpSSODescriptor.getNameIDFormats().add(transientNameIDFormat); - - NameIDFormat unspecifiedNameIDFormat = SAML2Utils.createSAMLObject(NameIDFormat.class); - unspecifiedNameIDFormat.setFormat(NameIDType.UNSPECIFIED); - - idpSSODescriptor.getNameIDFormats().add(unspecifiedNameIDFormat); - - return idpSSODescriptor; - - } - } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVP2XProtocol.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVP2XProtocol.java index 0c7502003..08d9f67b6 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVP2XProtocol.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVP2XProtocol.java @@ -22,15 +22,11 @@ *******************************************************************************/ package at.gv.egovernment.moa.id.protocols.pvp2x; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; +import java.util.Arrays; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.xml.transform.TransformerException; import org.apache.commons.lang.StringEscapeUtils; import org.joda.time.DateTime; @@ -51,15 +47,15 @@ import org.opensaml.saml2.metadata.AttributeConsumingService; import org.opensaml.saml2.metadata.EntityDescriptor; import org.opensaml.saml2.metadata.SPSSODescriptor; import org.opensaml.ws.security.SecurityPolicyException; -import org.opensaml.xml.io.MarshallingException; import org.opensaml.xml.security.SecurityException; +import org.opensaml.xml.security.x509.X509Credential; import org.opensaml.xml.signature.SignableXMLObject; - -import java.util.Arrays; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; -import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger; -import at.gv.egovernment.moa.id.advancedlogging.TransactionIDUtils; import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; import at.gv.egovernment.moa.id.auth.exception.InvalidProtocolRequestException; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; @@ -67,21 +63,13 @@ import at.gv.egovernment.moa.id.auth.exception.ProtocolNotActiveException; import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; -import at.gv.egovernment.moa.id.moduls.IAction; -import at.gv.egovernment.moa.id.moduls.IModulInfo; import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.id.moduls.NoPassivAuthenticationException; -import at.gv.egovernment.moa.id.moduls.RequestImpl; -import at.gv.egovernment.moa.id.moduls.RequestStorage; -import at.gv.egovernment.moa.id.moduls.SSOManager; -import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IDecoder; +import at.gv.egovernment.moa.id.protocols.AbstractAuthProtocolModulController; import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder; -import at.gv.egovernment.moa.id.protocols.pvp2x.binding.SoapBinding; -import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessage; -import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; -import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOAResponse; import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding; import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding; +import at.gv.egovernment.moa.id.protocols.pvp2x.binding.SoapBinding; import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AssertionValidationExeption; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AttributQueryException; @@ -92,19 +80,28 @@ import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NameIDFormatNotSuppor import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NoMetadataInformationException; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.PVP2Exception; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.SLOException; +import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessage; +import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; +import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOAResponse; +import at.gv.egovernment.moa.id.protocols.pvp2x.signer.IDPCredentialProvider; import at.gv.egovernment.moa.id.protocols.pvp2x.utils.CheckMandateAttributes; import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; import at.gv.egovernment.moa.id.protocols.pvp2x.validation.AuthnRequestValidator; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.SAMLVerificationEngine; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.TrustEngineFactory; import at.gv.egovernment.moa.id.util.ErrorResponseUtils; +import at.gv.egovernment.moa.id.util.HTTPUtils; import at.gv.egovernment.moa.id.util.ParamValidatorUtils; import at.gv.egovernment.moa.id.util.VelocityLogAdapter; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; -public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { +@Controller +public class PVP2XProtocol extends AbstractAuthProtocolModulController { + @Autowired IDPCredentialProvider pvpCredentials; + @Autowired SAMLVerificationEngine samlVerificationEngine; + public static final String NAME = PVP2XProtocol.class.getName(); public static final String PATH = "id_pvp2x"; @@ -119,41 +116,15 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { public static final String ENDPOINT_SP = "sp"; public static final String PARAMETER_ENDPOINT = "endpointtype"; - - private static List<IDecoder> decoder = new ArrayList<IDecoder>(); - - private static HashMap<String, IAction> actions = new HashMap<String, IAction>(); - + public static final List<String> DEFAULTREQUESTEDATTRFORINTERFEDERATION = Arrays.asList( new String[] { PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME }); - static { - decoder.add(new PostBinding()); - decoder.add(new RedirectBinding()); - decoder.add(new SoapBinding()); - - actions.put(REDIRECT, new AuthenticationAction()); - actions.put(POST, new AuthenticationAction()); - actions.put(METADATA, new MetadataAction()); - actions.put(ATTRIBUTEQUERY, new AttributQueryAction()); - actions.put(SINGLELOGOUT, new SingleLogOutAction()); - - //TODO: insert getArtifact action - - instance = new PVP2XProtocol(); - + static { new VelocityLogAdapter(); - } - - private static PVP2XProtocol instance = null; - - public static PVP2XProtocol getInstance() { - if (instance == null) { - instance = new PVP2XProtocol(); - } - return instance; + } public String getName() { @@ -163,162 +134,177 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { public String getPath() { return PATH; } - - private IDecoder findDecoder(String action, HttpServletRequest req) { - Iterator<IDecoder> decoderIT = decoder.iterator(); - while (decoderIT.hasNext()) { - IDecoder decoder = decoderIT.next(); - if (decoder.handleDecode(action, req)) { - return decoder; - } - } - - return null; - } - - private boolean isServiceProviderEndPointUsed(HttpServletRequest req) throws InvalidProtocolRequestException { - Object obj = req.getParameter(PARAMETER_ENDPOINT); - if (obj instanceof String) { - String param = (String) obj; - if (MiscUtil.isNotEmpty(param)) { - if (ENDPOINT_IDP.equals(param)) - return false; - - else if (ENDPOINT_SP.equals(param)) - return true; - } - } - - Logger.error("No valid PVP 2.1 entpoint descriptor"); - throw new InvalidProtocolRequestException("pvp2.20", new Object[] {}); - } public PVP2XProtocol() { super(); } - - public IRequest preProcess(HttpServletRequest request, - HttpServletResponse response, String action, - String sessionId, String transactionId) throws MOAIDException { - - if (!AuthConfigurationProviderFactory.getInstance().getAllowedProtocols().isPVP21Active()) { + //PVP2.x metadata end-point + @RequestMapping(value = "/pvp2/metadata", method = {RequestMethod.POST, RequestMethod.GET}) + public void PVPMetadataRequest(HttpServletRequest req, HttpServletResponse resp) throws MOAIDException { + if (!authConfig.getAllowedProtocols().isPVP21Active()) { Logger.info("PVP2.1 is deaktivated!"); throw new ProtocolNotActiveException("auth.22", new java.lang.Object[] { NAME }); } + //create pendingRequest object + PVPTargetConfiguration pendingReq = applicationContext.getBean(PVPTargetConfiguration.class); + pendingReq.initialize(req); + pendingReq.setModule(NAME); + + revisionsLogger.logEvent( + pendingReq.getUniqueSessionIdentifier(), + pendingReq.getUniqueTransactionIdentifier(), + MOAIDEventConstants.TRANSACTION_IP, + req.getRemoteAddr()); + + MetadataAction metadataAction = applicationContext.getBean(MetadataAction.class); + metadataAction.processRequest(pendingReq, + req, resp, null); - - if(METADATA.equals(action)) { - return new PVPTargetConfiguration(); + } + + //PVP2.x IDP POST-Binding end-point + @RequestMapping(value = "/pvp2/post", method = {RequestMethod.POST}) + public void PVPIDPPostRequest(HttpServletRequest req, HttpServletResponse resp) throws MOAIDException { + if (!authConfig.getAllowedProtocols().isPVP21Active()) { + Logger.info("PVP2.1 is deaktivated!"); + throw new ProtocolNotActiveException("auth.22", new java.lang.Object[] { NAME }); } - IDecoder decoder = findDecoder(action, request); - if (decoder == null) { - return null; + try { + //create pendingRequest object + PVPTargetConfiguration pendingReq = applicationContext.getBean(PVPTargetConfiguration.class); + pendingReq.initialize(req); + pendingReq.setModule(NAME); + + revisionsLogger.logEvent(MOAIDEventConstants.SESSION_CREATED, pendingReq.getUniqueSessionIdentifier()); + revisionsLogger.logEvent(MOAIDEventConstants.TRANSACTION_CREATED, pendingReq.getUniqueTransactionIdentifier()); + revisionsLogger.logEvent( + pendingReq.getUniqueSessionIdentifier(), + pendingReq.getUniqueTransactionIdentifier(), + MOAIDEventConstants.TRANSACTION_IP, + req.getRemoteAddr()); + + //get POST-Binding decoder implementation + InboundMessage msg = (InboundMessage) new PostBinding().decode(req, resp, false); + pendingReq.setRequest(msg); + + //preProcess Message + preProcess(req, resp, pendingReq); + + } catch (SecurityPolicyException e) { + String samlRequest = req.getParameter("SAMLRequest"); + Logger.warn("Receive INVALID protocol request: " + samlRequest, e); + throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); + + } catch (SecurityException e) { + String samlRequest = req.getParameter("SAMLRequest"); + Logger.warn("Receive INVALID protocol request: " + samlRequest, e); + throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()}); + + } catch (Throwable e) { + String samlRequest = req.getParameter("SAMLRequest"); + Logger.warn("Receive INVALID protocol request: " + samlRequest, e); + + throw new MOAIDException(e.getMessage(), new Object[] {}); + } + } + + //PVP2.x IDP Redirect-Binding end-point + @RequestMapping(value = "/pvp2/redirect", method = {RequestMethod.GET}) + public void PVPIDPRedirecttRequest(HttpServletRequest req, HttpServletResponse resp) throws MOAIDException { + if (!AuthConfigurationProviderFactory.getInstance().getAllowedProtocols().isPVP21Active()) { + Logger.info("PVP2.1 is deaktivated!"); + throw new ProtocolNotActiveException("auth.22", new java.lang.Object[] { NAME }); + } + try { + //create pendingRequest object + PVPTargetConfiguration pendingReq = applicationContext.getBean(PVPTargetConfiguration.class); + pendingReq.initialize(req); + pendingReq.setModule(NAME); + + revisionsLogger.logEvent(MOAIDEventConstants.SESSION_CREATED, pendingReq.getUniqueSessionIdentifier()); + revisionsLogger.logEvent(MOAIDEventConstants.TRANSACTION_CREATED, pendingReq.getUniqueTransactionIdentifier()); + revisionsLogger.logEvent( + pendingReq.getUniqueSessionIdentifier(), + pendingReq.getUniqueTransactionIdentifier(), + MOAIDEventConstants.TRANSACTION_IP, + req.getRemoteAddr()); + + //get POST-Binding decoder implementation + InboundMessage msg = (InboundMessage) new RedirectBinding().decode(req, resp, false); + pendingReq.setRequest(msg); + + //preProcess Message + preProcess(req, resp, pendingReq); - InboundMessage msg = (InboundMessage) decoder.decode(request, response, isServiceProviderEndPointUsed(request)); + } catch (SecurityPolicyException e) { + String samlRequest = req.getParameter("SAMLRequest"); + Logger.warn("Receive INVALID protocol request: " + samlRequest, e); + throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); + } catch (SecurityException e) { + String samlRequest = req.getParameter("SAMLRequest"); + Logger.warn("Receive INVALID protocol request: " + samlRequest, e); + throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()}); + + } catch (Throwable e) { + String samlRequest = req.getParameter("SAMLRequest"); + Logger.warn("Receive INVALID protocol request: " + samlRequest, e); + + throw new MOAIDException(e.getMessage(), new Object[] {}); + } + } + + + + + public void preProcess(HttpServletRequest request, + HttpServletResponse response, PVPTargetConfiguration pendingReq) throws Throwable { + + InboundMessage msg = pendingReq.getRequest(); + if (MiscUtil.isEmpty(msg.getEntityID())) { throw new InvalidProtocolRequestException("pvp2.20", new Object[] {}); } if(!msg.isVerified()) { - SAMLVerificationEngine engine = new SAMLVerificationEngine(); - engine.verify(msg, TrustEngineFactory.getSignatureKnownKeysTrustEngine()); + samlVerificationEngine.verify(msg, TrustEngineFactory.getSignatureKnownKeysTrustEngine()); msg.setVerified(true); - + } if (msg instanceof MOARequest && ((MOARequest)msg).getSamlRequest() instanceof AuthnRequest) - return preProcessAuthRequest(request, response, (MOARequest) msg, sessionId, transactionId); + preProcessAuthRequest(request, response, pendingReq); else if (msg instanceof MOARequest && ((MOARequest)msg).getSamlRequest() instanceof AttributeQuery) - return preProcessAttributQueryRequest(request, response, (MOARequest) msg, sessionId, transactionId); + preProcessAttributQueryRequest(request, response, pendingReq); else if (msg instanceof MOARequest && ((MOARequest)msg).getSamlRequest() instanceof LogoutRequest) - return preProcessLogOut(request, response, msg, sessionId, transactionId); + preProcessLogOut(request, response, pendingReq); else if (msg instanceof MOAResponse && ((MOAResponse)msg).getResponse() instanceof LogoutResponse) - return preProcessLogOut(request, response, msg, sessionId, transactionId); - - else if (msg instanceof MOAResponse && - ((MOAResponse)msg).getResponse() instanceof Response) { - //load service provider AuthRequest from session - - IRequest obj = RequestStorage.getPendingRequest(msg.getRelayState()); - if (obj instanceof RequestImpl) { - RequestImpl iReqSP = (RequestImpl) obj; - - MOAReversionLogger.getInstance().logEvent(iReqSP, MOAIDEventConstants.AUTHPROTOCOL_PVP_REQUEST_AUTHRESPONSE); - - MOAResponse processedMsg = preProcessAuthResponse((MOAResponse) msg); - - if ( processedMsg != null ) { - iReqSP.setInterfederationResponse(processedMsg); - - MOAReversionLogger.getInstance().logEvent(iReqSP, MOAIDEventConstants.AUTHPROCESS_INTERFEDERATION_REVEIVED); - - Logger.info("Receive a valid assertion from IDP " + msg.getEntityID() - + ". Switch to original transaction with ID " + iReqSP.getRequestID()); - TransactionIDUtils.setTransactionId(iReqSP.getRequestID()); - TransactionIDUtils.setSessionId(iReqSP.getSessionIdentifier()); - - } else { - Logger.info("Interfederated IDP " + msg.getEntityID() + " has NO valid SSO session." - +". Switch back local authentication process ..."); - - SSOManager ssomanager = SSOManager.getInstance(); - ssomanager.removeInterfederatedSSOIDP(msg.getEntityID(), request); - - iReqSP.setRequestedIDP(null); - - } - - return iReqSP; - - } - - Logger.error("Stored PVP21 authrequest from service provider has an unsuppored type."); - return null; - - } else { + preProcessLogOut(request, response, pendingReq); + + else { Logger.error("Receive unsupported PVP21 message"); throw new MOAIDException("Unsupported PVP21 message", new Object[] {}); } - } catch (PVP2Exception e) { - throw e; - - } catch (SecurityPolicyException e) { - String samlRequest = request.getParameter("SAMLRequest"); - Logger.warn("Receive INVALID protocol request: " + samlRequest, e); - throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); - - } catch (SecurityException e) { - String samlRequest = request.getParameter("SAMLRequest"); - Logger.warn("Receive INVALID protocol request: " + samlRequest, e); - throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()}); - - } catch (InvalidProtocolRequestException e) { - String samlRequest = request.getParameter("SAMLRequest"); - Logger.warn("Receive INVALID protocol request: " + samlRequest, e); - throw e; + revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), + pendingReq, MOAIDEventConstants.AUTHPROTOCOL_TYPE, PATH); - } catch (Throwable e) { - String samlRequest = request.getParameter("SAMLRequest"); - Logger.warn("Receive INVALID protocol request: " + samlRequest, e); - - throw new MOAIDException(e.getMessage(), new Object[] {}); - } + //switch to session authentication + performAuthentication(request, response, pendingReq); } public boolean generateErrorMessage(Throwable e, @@ -387,7 +373,7 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { samlResponse.setIssueInstant(new DateTime()); Issuer nissuer = SAML2Utils.createSAMLObject(Issuer.class); - nissuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath()); + nissuer.setValue(pvpRequest.getAuthURLWithOutSlash()); nissuer.setFormat(NameID.ENTITY); samlResponse.setIssuer(nissuer); @@ -395,11 +381,7 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { if(pvpRequest.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { encoder = new RedirectBinding(); - - } else if(pvpRequest.getBinding().equals(SAMLConstants.SAML2_ARTIFACT_BINDING_URI)) { - // TODO: not supported YET!! - //binding = new ArtifactBinding(); - + } else if(pvpRequest.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { encoder = new PostBinding(); @@ -416,31 +398,13 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { if (pvpRequest.getRequest() != null) relayState = pvpRequest.getRequest().getRelayState(); + X509Credential signCred = pvpCredentials.getIDPAssertionSigningCredential(); + encoder.encodeRespone(request, response, samlResponse, pvpRequest.getConsumerURL(), - relayState); + relayState, signCred); return true; } - public IAction getAction(String action) { - return actions.get(action); - } - - public IAction canHandleRequest(HttpServletRequest request, - HttpServletResponse response) { - if(request.getParameter("SAMLRequest") != null && request.getMethod().equals("GET")) { - return getAction(REDIRECT); - - } else if(request.getParameter("SAMLRequest") != null && request.getMethod().equals("POST")) { - return getAction(POST); - - } - - if(METADATA.equals(request.getParameter("action"))) { - return getAction(METADATA); - } - return null; - } - public boolean validate(HttpServletRequest request, HttpServletResponse response, IRequest pending) { @@ -456,12 +420,10 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { * @return * @throws MOAIDException */ - private IRequest preProcessLogOut(HttpServletRequest request, - HttpServletResponse response, InboundMessage inMsg, - String sessionId, String transactionId) throws MOAIDException { + private void preProcessLogOut(HttpServletRequest request, + HttpServletResponse response, PVPTargetConfiguration pendingReq) throws MOAIDException { - PVPTargetConfiguration config = new PVPTargetConfiguration(); - + InboundMessage inMsg = pendingReq.getRequest(); MOARequest msg; if (inMsg instanceof MOARequest && ((MOARequest)inMsg).getSamlRequest() instanceof LogoutRequest) { @@ -480,11 +442,11 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { Logger.info("Dispatch PVP2 SingleLogOut: OAURL=" + oaURL + " Binding=" + msg.getRequestBinding()); - config.setOAURL(oaURL); - config.setOnlineApplicationConfiguration(oa); - config.setBinding(msg.getRequestBinding()); + pendingReq.setOAURL(oaURL); + pendingReq.setOnlineApplicationConfiguration(oa); + pendingReq.setBinding(msg.getRequestBinding()); - MOAReversionLogger.getInstance().logEvent(sessionId, transactionId, MOAIDEventConstants.AUTHPROTOCOL_PVP_REQUEST_SLO); + revisionsLogger.logEvent(pendingReq, MOAIDEventConstants.AUTHPROTOCOL_PVP_REQUEST_SLO); @@ -496,13 +458,24 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { Logger.debug("PreProcess SLO Response from " + resp.getIssuer()); - if (!resp.getDestination().startsWith( - PVPConfiguration.getInstance().getIDPPublicPath())) { + List<String> allowedPublicURLPrefix = + AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix(); + boolean isAllowedDestination = false; + + for (String prefix : allowedPublicURLPrefix) { + if (!resp.getDestination().startsWith( + prefix)) { + isAllowedDestination = true; + break; + } + } + + if (!isAllowedDestination) { Logger.warn("PVP 2.1 single logout response destination does not match to IDP URL"); throw new AssertionValidationExeption("PVP 2.1 single logout response destination does not match to IDP URL", null); } - + //TODO: check if relayState exists inMsg.getRelayState(); @@ -511,29 +484,32 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { throw new MOAIDException("Unsupported request", new Object[] {}); - config.setRequest(inMsg); - config.setAction(SINGLELOGOUT); - return config; + pendingReq.setRequest(inMsg); + pendingReq.setAction(SINGLELOGOUT); + + //Single LogOut Request needs no authentication + pendingReq.setNeedAuthentication(false); + + //set protocol action, which should be executed + pendingReq.setAction(SingleLogOutAction.class.getName()); } /** * PreProcess AttributeQuery request * @param request * @param response - * @param moaRequest - * @return + * @param pendingReq * @throws Throwable */ - private IRequest preProcessAttributQueryRequest(HttpServletRequest request, - HttpServletResponse response, MOARequest moaRequest, - String sessionId, String transactionId) throws Throwable { - + private void preProcessAttributQueryRequest(HttpServletRequest request, + HttpServletResponse response, PVPTargetConfiguration pendingReq) throws Throwable { + MOARequest moaRequest = ((MOARequest)pendingReq.getRequest()); AttributeQuery attrQuery = (AttributeQuery) moaRequest.getSamlRequest(); moaRequest.setEntityID(attrQuery.getIssuer().getValue()); //validate destination String destinaten = attrQuery.getDestination(); - if (!PVPConfiguration.getInstance().getIDPAttributeQueryService().equals(destinaten)) { + if (!PVPConfiguration.getInstance().getIDPAttributeQueryService(HTTPUtils.extractAuthURLFromRequest(request)).equals(destinaten)) { Logger.warn("AttributeQuery destination does not match IDP AttributeQueryService URL"); throw new AttributQueryException("AttributeQuery destination does not match IDP AttributeQueryService URL", null); @@ -558,35 +534,40 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { } - PVPTargetConfiguration config = new PVPTargetConfiguration(); - config.setRequest(moaRequest); - config.setOAURL(moaRequest.getEntityID()); - config.setOnlineApplicationConfiguration(oa); - config.setBinding(SAMLConstants.SAML2_SOAP11_BINDING_URI); + pendingReq.setRequest(moaRequest); + pendingReq.setOAURL(moaRequest.getEntityID()); + pendingReq.setOnlineApplicationConfiguration(oa); + pendingReq.setBinding(SAMLConstants.SAML2_SOAP11_BINDING_URI); + + //Attribute-Query Request needs authentication + pendingReq.setNeedAuthentication(true); + + //set protocol action, which should be executed after authentication + pendingReq.setAction(AttributQueryAction.class.getName()); + + //write revisionslog entry + revisionsLogger.logEvent(pendingReq, MOAIDEventConstants.AUTHPROTOCOL_PVP_REQUEST_ATTRIBUTQUERY); - MOAReversionLogger.getInstance().logEvent(sessionId, transactionId, MOAIDEventConstants.AUTHPROTOCOL_PVP_REQUEST_ATTRIBUTQUERY); - return config; } /** * PreProcess Authn request * @param request * @param response - * @param moaRequest - * @return + * @param pendingReq * @throws Throwable */ - private IRequest preProcessAuthRequest(HttpServletRequest request, - HttpServletResponse response, MOARequest moaRequest, - String sessionId, String transactionId) throws Throwable { - + private void preProcessAuthRequest(HttpServletRequest request, + HttpServletResponse response, PVPTargetConfiguration pendingReq) throws Throwable { + + MOARequest moaRequest = ((MOARequest)pendingReq.getRequest()); SignableXMLObject samlReq = moaRequest.getSamlRequest(); if(!(samlReq instanceof AuthnRequest)) { throw new MOAIDException("Unsupported request", new Object[] {}); } - + EntityDescriptor metadata = moaRequest.getEntityMetadata(); if(metadata == null) { throw new NoMetadataInformationException(); @@ -611,10 +592,25 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { AssertionConsumerService consumerService = null; if (MiscUtil.isNotEmpty(authnRequest.getAssertionConsumerServiceURL()) && MiscUtil.isNotEmpty(authnRequest.getProtocolBinding())) { - //use AssertionConsumerServiceURL from request - consumerService = SAML2Utils.createSAMLObject(AssertionConsumerService.class); - consumerService.setBinding(authnRequest.getProtocolBinding()); - consumerService.setLocation(authnRequest.getAssertionConsumerServiceURL()); + //use AssertionConsumerServiceURL from request + + //check requested AssertionConsumingService URL against metadata + List<AssertionConsumerService> metadataAssertionServiceList = spSSODescriptor.getAssertionConsumerServices(); + for (AssertionConsumerService service : metadataAssertionServiceList) { + if (authnRequest.getProtocolBinding().equals(service.getBinding()) + && authnRequest.getAssertionConsumerServiceURL().equals(service.getLocation())) { + consumerService = SAML2Utils.createSAMLObject(AssertionConsumerService.class); + consumerService.setBinding(authnRequest.getProtocolBinding()); + consumerService.setLocation(authnRequest.getAssertionConsumerServiceURL()); + Logger.debug("Requested AssertionConsumerServiceURL is valid."); + } + } + + if (consumerService == null) { + throw new InvalidAssertionConsumerServiceException(authnRequest.getAssertionConsumerServiceURL()); + + } + } else { //use AssertionConsumerServiceIndex and select consumerService from metadata @@ -633,9 +629,10 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { if (consumerService == null) { throw new InvalidAssertionConsumerServiceException(aIdx); - } + } } + //select AttributeConsumingService from request AttributeConsumingService attributeConsumer = null; Integer aIdx = authnRequest.getAttributeConsumingServiceIndex(); @@ -669,59 +666,24 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { Logger.info("Dispatch PVP2 AuthnRequest: OAURL=" + oaURL + " Binding=" + consumerService.getBinding()); - PVPTargetConfiguration config = new PVPTargetConfiguration(); - config.setOAURL(oaURL); - config.setOnlineApplicationConfiguration(oa); - config.setBinding(consumerService.getBinding()); - config.setRequest(moaRequest); - config.setConsumerURL(consumerService.getLocation()); + pendingReq.setOAURL(oaURL); + pendingReq.setOnlineApplicationConfiguration(oa); + pendingReq.setBinding(consumerService.getBinding()); + pendingReq.setRequest(moaRequest); + pendingReq.setConsumerURL(consumerService.getLocation()); //parse AuthRequest - config.setPassiv(authReq.isPassive()); - config.setForce(authReq.isForceAuthn()); + pendingReq.setPassiv(authReq.isPassive()); + pendingReq.setForce(authReq.isForceAuthn()); + //AuthnRequest needs authentication + pendingReq.setNeedAuthentication(true); - MOAReversionLogger.getInstance().logEvent(sessionId, transactionId, MOAIDEventConstants.AUTHPROTOCOL_PVP_REQUEST_AUTHREQUEST); + //set protocol action, which should be executed after authentication + pendingReq.setAction(AuthenticationAction.class.getName()); - return config; - } - - /** - * PreProcess AuthResponse and Assertion - * @param msg - */ - private MOAResponse preProcessAuthResponse(MOAResponse msg) { - Logger.debug("Start PVP21 assertion processing... "); - Response samlResp = (Response) msg.getResponse(); - - try { - if (samlResp.getStatus().getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) { - - //validate PVP 2.1 assertion - SAMLVerificationEngine.validateAssertion(samlResp, true); - - msg.setSAMLMessage(SAML2Utils.asDOMDocument(samlResp).getDocumentElement()); - return msg; - - } else { - Logger.debug("Receive StatusCode " + samlResp.getStatus().getStatusCode().getValue() - + " from interfederated IDP."); - - } - - } catch (IOException e) { - Logger.warn("Interfederation response marshaling FAILED.", e); - - } catch (MarshallingException e) { - Logger.warn("Interfederation response marshaling FAILED.", e); - - } catch (TransformerException e) { - Logger.warn("Interfederation response marshaling FAILED.", e); - - } catch (AssertionValidationExeption e) { - //error is already logged, to nothing - } + //write revisionslog entry + revisionsLogger.logEvent(pendingReq, MOAIDEventConstants.AUTHPROTOCOL_PVP_REQUEST_AUTHREQUEST); - return null; } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPAssertionStorage.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPAssertionStorage.java index 5062646b6..0dd309154 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPAssertionStorage.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPAssertionStorage.java @@ -25,27 +25,20 @@ package at.gv.egovernment.moa.id.protocols.pvp2x; import org.opensaml.common.SAMLObject; import org.opensaml.common.binding.artifact.SAMLArtifactMap; import org.opensaml.xml.io.MarshallingException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; import at.gv.egovernment.moa.id.protocols.pvp2x.utils.StoredAssertion; -import at.gv.egovernment.moa.id.storage.AssertionStorage; +import at.gv.egovernment.moa.id.storage.ITransactionStorage; +@Service("PVPAssertionStorage") public class PVPAssertionStorage implements SAMLArtifactMap { - - private static PVPAssertionStorage instance = null; - - public static PVPAssertionStorage getInstance() { - if(instance == null) { - instance = new PVPAssertionStorage(); - } - return instance; - } - - //private Map<String, SAMLArtifactMapEntry> assertions = new HashMap<String, SAMLArtifactMapEntry>(); - private AssertionStorage assertions = AssertionStorage.getInstance(); + @Autowired private ITransactionStorage transactionStorage; + public boolean contains(String artifact) { - return assertions.containsKey(artifact); + return transactionStorage.containsKey(artifact); } public void put(String artifact, String relyingPartyId, String issuerId, @@ -56,7 +49,7 @@ public class PVPAssertionStorage implements SAMLArtifactMap { samlMessage); try { - assertions.put(artifact, assertion); + transactionStorage.put(artifact, assertion); } catch (MOADatabaseException e) { // TODO Insert Error Handling, if Assertion could not be stored @@ -66,7 +59,7 @@ public class PVPAssertionStorage implements SAMLArtifactMap { public SAMLArtifactMapEntry get(String artifact) { try { - return assertions.get(artifact, SAMLArtifactMapEntry.class); + return transactionStorage.get(artifact, SAMLArtifactMapEntry.class); } catch (MOADatabaseException e) { // TODO Insert Error Handling, if Assertion could not be read @@ -76,7 +69,7 @@ public class PVPAssertionStorage implements SAMLArtifactMap { } public void remove(String artifact) { - assertions.remove(artifact); + transactionStorage.remove(artifact); } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPTargetConfiguration.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPTargetConfiguration.java index 74b20356e..27773a248 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPTargetConfiguration.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPTargetConfiguration.java @@ -22,28 +22,28 @@ *******************************************************************************/ package at.gv.egovernment.moa.id.protocols.pvp2x; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.core.Attribute; import org.opensaml.saml2.core.impl.AuthnRequestImpl; import org.opensaml.saml2.metadata.AttributeConsumingService; import org.opensaml.saml2.metadata.RequestedAttribute; import org.opensaml.saml2.metadata.SPSSODescriptor; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; -import at.gv.egovernment.moa.id.config.ConfigurationException; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; -import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; import at.gv.egovernment.moa.id.moduls.RequestImpl; -import at.gv.egovernment.moa.id.protocols.pvp2x.builder.AttributQueryBuilder; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NoMetadataInformationException; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessage; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; -import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOAResponse; import at.gv.egovernment.moa.logging.Logger; +@Component("PVPTargetConfiguration") +@Scope(value = BeanDefinition.SCOPE_PROTOTYPE) public class PVPTargetConfiguration extends RequestImpl { private static final long serialVersionUID = 4889919265919638188L; @@ -81,15 +81,13 @@ public class PVPTargetConfiguration extends RequestImpl { * @see at.gv.egovernment.moa.id.moduls.RequestImpl#getRequestedAttributes() */ @Override - public List<Attribute> getRequestedAttributes() { + public Collection<String> getRequestedAttributes() { Map<String, String> reqAttr = new HashMap<String, String>(); for (String el : PVP2XProtocol.DEFAULTREQUESTEDATTRFORINTERFEDERATION) reqAttr.put(el, ""); - try { - OAAuthParameter oa = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(getOAURL()); - + try { SPSSODescriptor spSSODescriptor = getRequest().getEntityMetadata().getSPSSODescriptor(SAMLConstants.SAML20P_NS); if (spSSODescriptor.getAttributeConsumingServices() != null && spSSODescriptor.getAttributeConsumingServices().size() > 0) { @@ -125,15 +123,13 @@ public class PVPTargetConfiguration extends RequestImpl { reqAttr.put(attr.getName(), ""); } - return AttributQueryBuilder.buildSAML2AttributeList(oa, reqAttr.keySet().iterator()); + //return attributQueryBuilder.buildSAML2AttributeList(this.getOnlineApplicationConfiguration(), reqAttr.keySet().iterator()); + return reqAttr.keySet(); } catch (NoMetadataInformationException e) { Logger.warn("NO metadata found for Entity " + getRequest().getEntityID()); return null; - } catch (ConfigurationException e) { - Logger.error("Load configuration for OA " + getOAURL() + " FAILED", e); - return null; } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java index b567798fa..5afa10a72 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java @@ -23,42 +23,22 @@ package at.gv.egovernment.moa.id.protocols.pvp2x; import java.io.Serializable; -import java.io.StringWriter; import java.io.UnsupportedEncodingException; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; import java.util.List; -import java.util.Map.Entry; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.SerializationUtils; -import org.apache.velocity.Template; -import org.apache.velocity.VelocityContext; -import org.apache.velocity.app.VelocityEngine; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction; -import org.opensaml.common.SAMLObject; -import org.opensaml.common.binding.BasicSAMLMessageContext; -import org.opensaml.common.xml.SAMLConstants; import org.opensaml.saml2.core.LogoutRequest; import org.opensaml.saml2.core.LogoutResponse; -import org.opensaml.saml2.core.RequestAbstractType; -import org.opensaml.saml2.core.Status; -import org.opensaml.saml2.core.StatusCode; -import org.opensaml.saml2.core.StatusResponseType; import org.opensaml.saml2.metadata.SingleLogoutService; -import org.opensaml.saml2.metadata.impl.SingleLogoutServiceBuilder; -import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.opensaml.ws.soap.common.SOAPException; -import org.opensaml.xml.XMLObject; -import org.opensaml.xml.security.SecurityException; -import org.opensaml.xml.security.x509.X509Credential; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; @@ -67,35 +47,23 @@ import at.gv.egovernment.moa.id.auth.exception.MOAIDException; import at.gv.egovernment.moa.id.auth.servlet.RedirectServlet; import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils; import at.gv.egovernment.moa.id.commons.db.dao.session.AssertionStore; -import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore; -import at.gv.egovernment.moa.id.commons.db.dao.session.OASessionStore; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.id.data.IAuthData; +import at.gv.egovernment.moa.id.data.ISLOInformationContainer; import at.gv.egovernment.moa.id.data.SLOInformationContainer; -import at.gv.egovernment.moa.id.data.SLOInformationImpl; import at.gv.egovernment.moa.id.data.SLOInformationInterface; import at.gv.egovernment.moa.id.moduls.AuthenticationManager; import at.gv.egovernment.moa.id.moduls.IAction; import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.id.moduls.SSOManager; -import at.gv.egovernment.moa.id.opemsaml.MOAStringRedirectDeflateEncoder; -import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder; -import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding; -import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding; import at.gv.egovernment.moa.id.protocols.pvp2x.builder.SingleLogOutBuilder; -import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.BindingNotSupportedException; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.SLOException; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOAResponse; -import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialProvider; -import at.gv.egovernment.moa.id.protocols.pvp2x.utils.MOASAMLSOAPClient; -import at.gv.egovernment.moa.id.storage.AssertionStorage; -import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; +import at.gv.egovernment.moa.id.storage.IAuthenticationSessionStoreage; +import at.gv.egovernment.moa.id.storage.ITransactionStorage; import at.gv.egovernment.moa.id.util.Random; -import at.gv.egovernment.moa.id.util.VelocityProvider; import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.MessageProvider; import at.gv.egovernment.moa.util.MiscUtil; import at.gv.egovernment.moa.util.URLEncoder; @@ -103,8 +71,16 @@ import at.gv.egovernment.moa.util.URLEncoder; * @author tlenz * */ +@Service("pvpSingleLogOutService") public class SingleLogOutAction implements IAction { + @Autowired private SSOManager ssomanager; + @Autowired private AuthenticationManager authManager; + @Autowired private IAuthenticationSessionStoreage authenticationSessionStorage; + @Autowired private ITransactionStorage transactionStorage; + @Autowired private SingleLogOutBuilder sloBuilder; + + /* (non-Javadoc) * @see at.gv.egovernment.moa.id.moduls.IAction#processRequest(at.gv.egovernment.moa.id.moduls.IRequest, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, at.gv.egovernment.moa.id.data.IAuthData) */ @@ -122,7 +98,7 @@ public class SingleLogOutAction implements IAction { LogoutRequest logOutReq = (LogoutRequest) samlReq.getSamlRequest(); AuthenticationSession session = - AuthenticationSessionStoreage.searchMOASessionWithNameIDandOAID( + authenticationSessionStorage.searchMOASessionWithNameIDandOAID( logOutReq.getIssuer().getValue(), logOutReq.getNameID().getValue()); @@ -131,36 +107,34 @@ public class SingleLogOutAction implements IAction { + logOutReq.getNameID().getValue() + " and OA " + logOutReq.getIssuer().getValue()); Logger.info("Search active SSO session with SSO session cookie"); - SSOManager ssomanager = SSOManager.getInstance(); String ssoID = ssomanager.getSSOSessionID(httpReq); if (MiscUtil.isEmpty(ssoID)) { - Logger.warn("Can not find active Session. Single LogOut not possible!"); - SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq); - //LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI); - LogoutResponse message = SingleLogOutBuilder.buildSLOResponseMessage(sloService, pvpReq, null); + Logger.info("Can not find active Session. Single LogOut not possible!"); + SingleLogoutService sloService = sloBuilder.getResponseSLODescriptor(pvpReq); + //LogoutResponse message = sloBuilder.buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI); + LogoutResponse message = sloBuilder.buildSLOResponseMessage(sloService, pvpReq, null); Logger.info("Sending SLO success message to requester ..."); - SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState()); + sloBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState()); return null; } else { String moasession = ssomanager.getMOASession(ssoID); try { - session = AuthenticationSessionStoreage.getSession(moasession); + session = authenticationSessionStorage.getSession(moasession); } catch (MOADatabaseException e) { - Logger.warn("Can not find active Session. Single LogOut not possible!"); - SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq); - //LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI); - LogoutResponse message = SingleLogOutBuilder.buildSLOResponseMessage(sloService, pvpReq, null); + Logger.info("Can not find active Session. Single LogOut not possible!"); + SingleLogoutService sloService = sloBuilder.getResponseSLODescriptor(pvpReq); + //LogoutResponse message = sloBuilder.buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI); + LogoutResponse message = sloBuilder.buildSLOResponseMessage(sloService, pvpReq, null); Logger.info("Sending SLO success message to requester ..."); - SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState()); + sloBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState()); return null; } } } - - AuthenticationManager authManager = AuthenticationManager.getInstance(); + authManager.performSingleLogOut(httpReq, httpResp, session, pvpReq); } else if (pvpReq.getRequest() instanceof MOAResponse && @@ -204,10 +178,10 @@ public class SingleLogOutAction implements IAction { Object data = SerializationUtils.deserialize(element.getAssertion()); if (data instanceof SLOInformationContainer) { - SLOInformationContainer sloContainer = (SLOInformationContainer) data; + ISLOInformationContainer sloContainer = (ISLOInformationContainer) data; //check status - SingleLogOutBuilder.checkStatusCode(sloContainer, logOutResp); + sloBuilder.checkStatusCode(sloContainer, logOutResp); if (sloContainer.hasFrontChannelOA()) { try { @@ -253,13 +227,13 @@ public class SingleLogOutAction implements IAction { String redirectURL = null; if (sloContainer.getSloRequest() != null) { //send SLO response to SLO request issuer - SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(sloContainer.getSloRequest()); - LogoutResponse message = SingleLogOutBuilder.buildSLOResponseMessage(sloService, sloContainer.getSloRequest(), sloContainer.getSloFailedOAs()); - redirectURL = SingleLogOutBuilder.getFrontChannelSLOMessageURL(sloService, message, httpReq, httpResp, sloContainer.getSloRequest().getRequest().getRelayState()); + SingleLogoutService sloService = sloBuilder.getResponseSLODescriptor(sloContainer.getSloRequest()); + LogoutResponse message = sloBuilder.buildSLOResponseMessage(sloService, sloContainer.getSloRequest(), sloContainer.getSloFailedOAs()); + redirectURL = sloBuilder.getFrontChannelSLOMessageURL(sloService, message, httpReq, httpResp, sloContainer.getSloRequest().getRequest().getRelayState()); } else { //print SLO information directly - redirectURL = AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix() + "/idpSingleLogout"; + redirectURL = req.getAuthURL() + "/idpSingleLogout"; String artifact = Random.nextRandom(); @@ -270,12 +244,12 @@ public class SingleLogOutAction implements IAction { else statusCode = MOAIDAuthConstants.SLOSTATUS_ERROR; - AssertionStorage.getInstance().put(artifact, statusCode); + transactionStorage.put(artifact, statusCode); redirectURL = addURLParameter(redirectURL, MOAIDAuthConstants.PARAM_SLOSTATUS, artifact); } //redirect to Redirect Servlet - String url = AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix() + "/RedirectServlet"; + String url = req.getAuthURL() + "/RedirectServlet"; url = addURLParameter(url, RedirectServlet.REDIRCT_PARAM_URL, URLEncoder.encode(redirectURL, "UTF-8")); url = httpResp.encodeRedirectURL(url); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/ArtifactBinding.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/ArtifactBinding.java deleted file mode 100644 index 4d353ffcd..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/ArtifactBinding.java +++ /dev/null @@ -1,121 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 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: - * http://www.osor.eu/eupl/ - * - * 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.egovernment.moa.id.protocols.pvp2x.binding; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.velocity.app.VelocityEngine; -import org.apache.velocity.runtime.RuntimeConstants; -import org.opensaml.common.SAMLObject; -import org.opensaml.common.binding.BasicSAMLMessageContext; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.binding.encoding.HTTPArtifactEncoder; -import org.opensaml.saml2.core.RequestAbstractType; -import org.opensaml.saml2.core.StatusResponseType; -import org.opensaml.saml2.metadata.SingleSignOnService; -import org.opensaml.saml2.metadata.impl.SingleSignOnServiceBuilder; -import org.opensaml.ws.message.decoder.MessageDecodingException; -import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.opensaml.ws.transport.http.HttpServletResponseAdapter; -import org.opensaml.xml.security.SecurityException; -import org.opensaml.xml.security.credential.Credential; -import org.opensaml.xml.signature.Signature; - -import at.gv.egovernment.moa.id.protocols.pvp2x.PVPAssertionStorage; -import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessageInterface; -import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialProvider; -import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialsNotAvailableException; - -public class ArtifactBinding implements IDecoder, IEncoder { - - public void encodeRequest(HttpServletRequest req, HttpServletResponse resp, - RequestAbstractType request, String targetLocation, String relayState) - throws MessageEncodingException, SecurityException { - - } - - public void encodeRespone(HttpServletRequest req, HttpServletResponse resp, - StatusResponseType response, String targetLocation, String relayState) - throws MessageEncodingException, SecurityException { - try { - Credential credentials = CredentialProvider - .getIDPAssertionSigningCredential(); - - Signature signer = CredentialProvider.getIDPSignature(credentials); - response.setSignature(signer); - - VelocityEngine engine = new VelocityEngine(); - engine.setProperty(RuntimeConstants.ENCODING_DEFAULT, "UTF-8"); - engine.setProperty(RuntimeConstants.OUTPUT_ENCODING, "UTF-8"); - engine.setProperty(RuntimeConstants.ENCODING_DEFAULT, "UTF-8"); - engine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); - engine.setProperty("classpath.resource.loader.class", - "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); - engine.init(); - - HTTPArtifactEncoder encoder = new HTTPArtifactEncoder(engine, - "resources/templates/pvp_postbinding_template.html", - PVPAssertionStorage.getInstance()); - - encoder.setPostEncoding(false); - HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter( - resp, true); - BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>(); - SingleSignOnService service = new SingleSignOnServiceBuilder() - .buildObject(); - service.setBinding(SAMLConstants.SAML2_ARTIFACT_BINDING_URI); - service.setLocation(targetLocation); - context.setOutboundSAMLMessageSigningCredential(credentials); - context.setPeerEntityEndpoint(service); - context.setOutboundSAMLMessage(response); - context.setOutboundMessageTransport(responseAdapter); - - encoder.encode(context); - } catch (CredentialsNotAvailableException e) { - e.printStackTrace(); - throw new SecurityException(e); - - } catch (Exception e) { - throw new SecurityException(e); - } - } - - public InboundMessageInterface decode(HttpServletRequest req, - HttpServletResponse resp, boolean isSPEndPoint) throws MessageDecodingException, - SecurityException { - - return null; - } - - - public boolean handleDecode(String action, HttpServletRequest req) { - - return false; - } - - public String getSAML2BindingName() { - return SAMLConstants.SAML2_ARTIFACT_BINDING_URI; - } - -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/IEncoder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/IEncoder.java index de5548a44..3b2fb3687 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/IEncoder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/IEncoder.java @@ -29,24 +29,40 @@ import org.opensaml.saml2.core.RequestAbstractType; import org.opensaml.saml2.core.StatusResponseType; import org.opensaml.ws.message.encoder.MessageEncodingException; import org.opensaml.xml.security.SecurityException; +import org.opensaml.xml.security.credential.Credential; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.PVP2Exception; public interface IEncoder { + + /** + * + * @param req The http request + * @param resp The http response + * @param request The SAML2 request object + * @param targetLocation URL, where the request should be transmit + * @param relayState token for session handling + * @param credentials Credential to sign the request object + * @throws MessageEncodingException + * @throws SecurityException + * @throws PVP2Exception + */ public void encodeRequest(HttpServletRequest req, - HttpServletResponse resp, RequestAbstractType request, String targetLocation, String relayState) + HttpServletResponse resp, RequestAbstractType request, String targetLocation, String relayState, Credential credentials) throws MessageEncodingException, SecurityException, PVP2Exception; /** * Encoder SAML Response * @param req The http request * @param resp The http response - * @param response The repsonse object - * @param targetLocation + * @param response The SAML2 repsonse object + * @param targetLocation URL, where the request should be transmit + * @param relayState token for session handling + * @param credentials Credential to sign the response object * @throws MessageEncodingException * @throws SecurityException */ public void encodeRespone(HttpServletRequest req, - HttpServletResponse resp, StatusResponseType response, String targetLocation, String relayState) + HttpServletResponse resp, StatusResponseType response, String targetLocation, String relayState, Credential credentials) throws MessageEncodingException, SecurityException, PVP2Exception; } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/PostBinding.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/PostBinding.java index 65400444d..ebb4b2991 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/PostBinding.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/PostBinding.java @@ -28,53 +28,51 @@ import javax.servlet.http.HttpServletResponse; import org.apache.velocity.app.VelocityEngine; import org.opensaml.common.SAMLObject; import org.opensaml.common.binding.BasicSAMLMessageContext; -import org.opensaml.common.binding.SAMLMessageContext; import org.opensaml.common.xml.SAMLConstants; import org.opensaml.saml2.binding.decoding.HTTPPostDecoder; import org.opensaml.saml2.binding.encoding.HTTPPostEncoder; import org.opensaml.saml2.core.RequestAbstractType; -import org.opensaml.saml2.core.Response; import org.opensaml.saml2.core.StatusResponseType; import org.opensaml.saml2.metadata.IDPSSODescriptor; import org.opensaml.saml2.metadata.SPSSODescriptor; -import org.opensaml.saml2.metadata.SingleLogoutService; import org.opensaml.saml2.metadata.SingleSignOnService; import org.opensaml.saml2.metadata.impl.SingleSignOnServiceBuilder; import org.opensaml.ws.message.decoder.MessageDecodingException; import org.opensaml.ws.message.encoder.MessageEncodingException; +import org.opensaml.ws.security.SecurityPolicyResolver; +import org.opensaml.ws.security.provider.BasicSecurityPolicy; +import org.opensaml.ws.security.provider.StaticSecurityPolicyResolver; import org.opensaml.ws.transport.http.HttpServletRequestAdapter; import org.opensaml.ws.transport.http.HttpServletResponseAdapter; import org.opensaml.xml.parse.BasicParserPool; import org.opensaml.xml.security.SecurityException; import org.opensaml.xml.security.credential.Credential; -import org.opensaml.xml.security.x509.KeyStoreX509CredentialAdapter; -import org.opensaml.xml.security.x509.X509Credential; import at.gv.egovernment.moa.id.config.ConfigurationException; import at.gv.egovernment.moa.id.protocols.pvp2x.PVP2XProtocol; import at.gv.egovernment.moa.id.protocols.pvp2x.config.MOADefaultBootstrap; import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration; -import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.PVP2Exception; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessage; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessageInterface; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOAResponse; import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider; -import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialProvider; -import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialsNotAvailableException; +import at.gv.egovernment.moa.id.protocols.pvp2x.validation.MOAPVPSignedRequestPolicyRule; +import at.gv.egovernment.moa.id.protocols.pvp2x.verification.TrustEngineFactory; +import at.gv.egovernment.moa.id.util.HTTPUtils; import at.gv.egovernment.moa.id.util.VelocityProvider; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; public class PostBinding implements IDecoder, IEncoder { - + public void encodeRequest(HttpServletRequest req, HttpServletResponse resp, - RequestAbstractType request, String targetLocation, String relayState) + RequestAbstractType request, String targetLocation, String relayState, Credential credentials) throws MessageEncodingException, SecurityException { try { - X509Credential credentials = CredentialProvider - .getIDPAssertionSigningCredential(); +// X509Credential credentials = credentialProvider +// .getIDPAssertionSigningCredential(); //load default PVP security configurations MOADefaultBootstrap.initializeDefaultPVPConfiguration(); @@ -97,9 +95,9 @@ public class PostBinding implements IDecoder, IEncoder { encoder.encode(context); - } catch (CredentialsNotAvailableException e) { - e.printStackTrace(); - throw new SecurityException(e); +// } catch (CredentialsNotAvailableException e) { +// e.printStackTrace(); +// throw new SecurityException(e); } catch (Exception e) { e.printStackTrace(); throw new SecurityException(e); @@ -107,12 +105,12 @@ public class PostBinding implements IDecoder, IEncoder { } public void encodeRespone(HttpServletRequest req, HttpServletResponse resp, - StatusResponseType response, String targetLocation, String relayState) + StatusResponseType response, String targetLocation, String relayState, Credential credentials) throws MessageEncodingException, SecurityException { try { - X509Credential credentials = CredentialProvider - .getIDPAssertionSigningCredential(); +// X509Credential credentials = credentialProvider +// .getIDPAssertionSigningCredential(); //load default PVP security configurations MOADefaultBootstrap.initializeDefaultPVPConfiguration(); @@ -138,9 +136,9 @@ public class PostBinding implements IDecoder, IEncoder { context.setRelayState(relayState); encoder.encode(context); - } catch (CredentialsNotAvailableException e) { - e.printStackTrace(); - throw new SecurityException(e); +// } catch (CredentialsNotAvailableException e) { +// e.printStackTrace(); +// throw new SecurityException(e); } catch (Exception e) { e.printStackTrace(); throw new SecurityException(e); @@ -159,11 +157,11 @@ public class PostBinding implements IDecoder, IEncoder { //set metadata descriptor type if (isSPEndPoint) { messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME); - decode.setURIComparator(new MOAURICompare(PVPConfiguration.getInstance().getSPSSOPostService())); + decode.setURIComparator(new MOAURICompare(PVPConfiguration.getInstance().getSPSSOPostService(HTTPUtils.extractAuthURLFromRequest(req)))); } else { messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME); - decode.setURIComparator(new MOAURICompare(PVPConfiguration.getInstance().getIDPSSOPostService())); + decode.setURIComparator(new MOAURICompare(PVPConfiguration.getInstance().getIDPSSOPostService(HTTPUtils.extractAuthURLFromRequest(req)))); } } catch (ConfigurationException e) { @@ -171,7 +169,16 @@ public class PostBinding implements IDecoder, IEncoder { } messageContext.setMetadataProvider(MOAMetadataProvider.getInstance()); - + + //set security policy context + BasicSecurityPolicy policy = new BasicSecurityPolicy(); + policy.getPolicyRules().add( + new MOAPVPSignedRequestPolicyRule( + TrustEngineFactory.getSignatureKnownKeysTrustEngine(), + messageContext.getPeerEntityRole())); + SecurityPolicyResolver secResolver = new StaticSecurityPolicyResolver(policy); + messageContext.setSecurityPolicyResolver(secResolver); + decode.decode(messageContext); InboundMessage msg = null; @@ -197,8 +204,9 @@ public class PostBinding implements IDecoder, IEncoder { if (MiscUtil.isEmpty(msg.getEntityID())) Logger.info("No Metadata found for OA with EntityID " + messageContext.getInboundMessageIssuer()); } - - msg.setVerified(false); + + + msg.setVerified(true); msg.setRelayState(messageContext.getRelayState()); return msg; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/RedirectBinding.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/RedirectBinding.java index 9a505a7b0..0ff18d903 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/RedirectBinding.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/RedirectBinding.java @@ -27,7 +27,6 @@ import javax.servlet.http.HttpServletResponse; import org.opensaml.common.SAMLObject; import org.opensaml.common.binding.BasicSAMLMessageContext; -import org.opensaml.common.binding.SAMLMessageContext; import org.opensaml.common.xml.SAMLConstants; import org.opensaml.saml2.binding.decoding.HTTPRedirectDeflateDecoder; import org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder; @@ -48,7 +47,7 @@ import org.opensaml.ws.transport.http.HttpServletRequestAdapter; import org.opensaml.ws.transport.http.HttpServletResponseAdapter; import org.opensaml.xml.parse.BasicParserPool; import org.opensaml.xml.security.SecurityException; -import org.opensaml.xml.security.x509.X509Credential; +import org.opensaml.xml.security.credential.Credential; import at.gv.egovernment.moa.id.config.ConfigurationException; import at.gv.egovernment.moa.id.protocols.pvp2x.PVP2XProtocol; @@ -59,21 +58,20 @@ import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessageInterface import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOAResponse; import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider; -import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialProvider; -import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialsNotAvailableException; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.TrustEngineFactory; +import at.gv.egovernment.moa.id.util.HTTPUtils; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; public class RedirectBinding implements IDecoder, IEncoder { - + public void encodeRequest(HttpServletRequest req, HttpServletResponse resp, - RequestAbstractType request, String targetLocation, String relayState) + RequestAbstractType request, String targetLocation, String relayState, Credential credentials) throws MessageEncodingException, SecurityException { - try { - X509Credential credentials = CredentialProvider - .getIDPAssertionSigningCredential(); +// try { +// X509Credential credentials = credentialProvider +// .getIDPAssertionSigningCredential(); //load default PVP security configurations MOADefaultBootstrap.initializeDefaultPVPConfiguration(); @@ -95,18 +93,18 @@ public class RedirectBinding implements IDecoder, IEncoder { context.setRelayState(relayState); encoder.encode(context); - } catch (CredentialsNotAvailableException e) { - e.printStackTrace(); - throw new SecurityException(e); - } +// } catch (CredentialsNotAvailableException e) { +// e.printStackTrace(); +// throw new SecurityException(e); +// } } public void encodeRespone(HttpServletRequest req, HttpServletResponse resp, - StatusResponseType response, String targetLocation, String relayState) - throws MessageEncodingException, SecurityException { - try { - X509Credential credentials = CredentialProvider - .getIDPAssertionSigningCredential(); + StatusResponseType response, String targetLocation, String relayState, + Credential credentials) throws MessageEncodingException, SecurityException { +// try { +// X509Credential credentials = credentialProvider +// .getIDPAssertionSigningCredential(); //load default PVP security configurations MOADefaultBootstrap.initializeDefaultPVPConfiguration(); @@ -128,10 +126,10 @@ public class RedirectBinding implements IDecoder, IEncoder { context.setRelayState(relayState); encoder.encode(context); - } catch (CredentialsNotAvailableException e) { - e.printStackTrace(); - throw new SecurityException(e); - } +// } catch (CredentialsNotAvailableException e) { +// e.printStackTrace(); +// throw new SecurityException(e); +// } } public InboundMessageInterface decode(HttpServletRequest req, @@ -149,11 +147,11 @@ public class RedirectBinding implements IDecoder, IEncoder { //set metadata descriptor type if (isSPEndPoint) { messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME); - decode.setURIComparator(new MOAURICompare(PVPConfiguration.getInstance().getSPSSORedirectService())); + decode.setURIComparator(new MOAURICompare(PVPConfiguration.getInstance().getSPSSORedirectService(HTTPUtils.extractAuthURLFromRequest(req)))); } else { messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME); - decode.setURIComparator(new MOAURICompare(PVPConfiguration.getInstance().getIDPSSORedirectService())); + decode.setURIComparator(new MOAURICompare(PVPConfiguration.getInstance().getIDPSSORedirectService(HTTPUtils.extractAuthURLFromRequest(req)))); } } catch (ConfigurationException e) { diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/SoapBinding.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/SoapBinding.java index fee508d33..cc3553551 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/SoapBinding.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/SoapBinding.java @@ -29,7 +29,6 @@ import javax.servlet.http.HttpServletResponse; import org.opensaml.common.SAMLObject; import org.opensaml.common.binding.BasicSAMLMessageContext; -import org.opensaml.common.binding.SAMLMessageContext; import org.opensaml.common.xml.SAMLConstants; import org.opensaml.saml2.binding.encoding.HTTPSOAP11Encoder; import org.opensaml.saml2.core.RequestAbstractType; @@ -37,7 +36,6 @@ import org.opensaml.saml2.core.StatusResponseType; import org.opensaml.saml2.metadata.SPSSODescriptor; import org.opensaml.ws.message.decoder.MessageDecodingException; import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.opensaml.ws.soap.client.BasicSOAPMessageContext; import org.opensaml.ws.soap.soap11.Envelope; import org.opensaml.ws.soap.soap11.decoder.http.HTTPSOAP11Decoder; import org.opensaml.ws.transport.http.HttpServletRequestAdapter; @@ -47,22 +45,23 @@ import org.opensaml.xml.parse.BasicParserPool; import org.opensaml.xml.security.SecurityException; import org.opensaml.xml.security.credential.Credential; import org.opensaml.xml.signature.SignableXMLObject; +import org.springframework.beans.factory.annotation.Autowired; import at.gv.egovernment.moa.id.protocols.pvp2x.PVP2XProtocol; import at.gv.egovernment.moa.id.protocols.pvp2x.config.MOADefaultBootstrap; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AttributQueryException; -import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.BindingNotSupportedException; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.PVP2Exception; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessageInterface; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider; -import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialProvider; -import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialsNotAvailableException; +import at.gv.egovernment.moa.id.protocols.pvp2x.signer.IDPCredentialProvider; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; public class SoapBinding implements IDecoder, IEncoder { + @Autowired private IDPCredentialProvider credentialProvider; + public InboundMessageInterface decode(HttpServletRequest req, HttpServletResponse resp, boolean isSPEndPoint) throws MessageDecodingException, SecurityException, PVP2Exception { @@ -72,9 +71,23 @@ public class SoapBinding implements IDecoder, IEncoder { messageContext .setInboundMessageTransport(new HttpServletRequestAdapter( req)); - //messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME); messageContext.setMetadataProvider(MOAMetadataProvider.getInstance()); - + + //TODO: update in a futher version: + // requires a special SignedSOAPRequestPolicyRole because + // messageContext.getInboundMessage() is not directly signed + + //set security context +// BasicSecurityPolicy policy = new BasicSecurityPolicy(); +// policy.getPolicyRules().add( +// new MOAPVPSignedRequestPolicyRule( +// TrustEngineFactory.getSignatureKnownKeysTrustEngine(), +// SPSSODescriptor.DEFAULT_ELEMENT_NAME)); +// SecurityPolicyResolver resolver = new StaticSecurityPolicyResolver( +// policy); +// messageContext.setSecurityPolicyResolver(resolver); + + //decode message soapDecoder.decode(messageContext); Envelope inboundMessage = (Envelope) messageContext @@ -120,17 +133,17 @@ public class SoapBinding implements IDecoder, IEncoder { } public void encodeRequest(HttpServletRequest req, HttpServletResponse resp, - RequestAbstractType request, String targetLocation, String relayState) + RequestAbstractType request, String targetLocation, String relayState, Credential credentials) throws MessageEncodingException, SecurityException, PVP2Exception { } public void encodeRespone(HttpServletRequest req, HttpServletResponse resp, - StatusResponseType response, String targetLocation, String relayState) + StatusResponseType response, String targetLocation, String relayState, Credential credentials) throws MessageEncodingException, SecurityException, PVP2Exception { - try { - Credential credentials = CredentialProvider - .getIDPAssertionSigningCredential(); +// try { +// Credential credentials = credentialProvider +// .getIDPAssertionSigningCredential(); //load default PVP security configurations MOADefaultBootstrap.initializeDefaultPVPConfiguration(); @@ -144,10 +157,10 @@ public class SoapBinding implements IDecoder, IEncoder { context.setOutboundMessageTransport(responseAdapter); encoder.encode(context); - } catch (CredentialsNotAvailableException e) { - e.printStackTrace(); - throw new SecurityException(e); - } +// } catch (CredentialsNotAvailableException e) { +// e.printStackTrace(); +// throw new SecurityException(e); +// } } public String getSAML2BindingName() { diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/AttributQueryBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/AttributQueryBuilder.java index 91888df5c..9c097780b 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/AttributQueryBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/AttributQueryBuilder.java @@ -25,7 +25,6 @@ package at.gv.egovernment.moa.id.protocols.pvp2x.builder; import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import java.util.Set; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -46,17 +45,18 @@ import org.opensaml.xml.signature.Signature; import org.opensaml.xml.signature.SignatureConstants; import org.opensaml.xml.signature.SignatureException; import org.opensaml.xml.signature.Signer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import org.w3c.dom.Document; import at.gv.egovernment.moa.id.config.ConfigurationException; import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; -import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.SamlAttributeGenerator; import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AttributQueryException; -import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialProvider; import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialsNotAvailableException; +import at.gv.egovernment.moa.id.protocols.pvp2x.signer.IDPCredentialProvider; import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.Constants; @@ -65,9 +65,12 @@ import at.gv.egovernment.moa.util.Constants; * @author tlenz * */ +@Service("AttributQueryBuilder") public class AttributQueryBuilder { - public static List<Attribute> buildSAML2AttributeList(IOAAuthParameters oa, Iterator<String> iterator) { + @Autowired IDPCredentialProvider credentialProvider; + + public List<Attribute> buildSAML2AttributeList(IOAAuthParameters oa, Iterator<String> iterator) { Logger.debug("Build OA specific Attributes for AttributQuery request"); @@ -103,7 +106,7 @@ public class AttributQueryBuilder { } - public static AttributeQuery buildAttributQueryRequest(String nameID, + public AttributeQuery buildAttributQueryRequest(String nameID, String endpoint, List<Attribute> requestedAttributes) throws AttributQueryException { @@ -127,7 +130,7 @@ public class AttributQueryBuilder { query.setIssueInstant(now); Issuer nissuer = SAML2Utils.createSAMLObject(Issuer.class); - nissuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath()); + nissuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath().get(0)); nissuer.setFormat(NameID.ENTITY); query.setIssuer(nissuer); @@ -136,7 +139,7 @@ public class AttributQueryBuilder { query.setDestination(endpoint); - X509Credential idpSigningCredential = CredentialProvider.getIDPAssertionSigningCredential(); + X509Credential idpSigningCredential = credentialProvider.getIDPAssertionSigningCredential(); Signature signer = SAML2Utils.createSAMLObject(Signature.class); signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/AuthResponseBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/AuthResponseBuilder.java index 4959df16c..24c2626e3 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/AuthResponseBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/AuthResponseBuilder.java @@ -66,13 +66,15 @@ import at.gv.egovernment.moa.logging.Logger; */ public class AuthResponseBuilder { - public static Response buildResponse(RequestAbstractType req, DateTime date, Assertion assertion) throws InvalidAssertionEncryptionException, ConfigurationException { + public static Response buildResponse(String authURL, RequestAbstractType req, DateTime date, Assertion assertion) throws InvalidAssertionEncryptionException, ConfigurationException { Response authResponse = SAML2Utils.createSAMLObject(Response.class); Issuer nissuer = SAML2Utils.createSAMLObject(Issuer.class); //change to entity value from entity name to IDP EntityID (URL) - nissuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath()); + if (authURL.endsWith("/")) + authURL = authURL.substring(0, authURL.length()-1); + nissuer.setValue(authURL); nissuer.setFormat(NameID.ENTITY); authResponse.setIssuer(nissuer); authResponse.setInResponseTo(req.getID()); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/PVPAuthnRequestBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/PVPAuthnRequestBuilder.java new file mode 100644 index 000000000..312bb823d --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/PVPAuthnRequestBuilder.java @@ -0,0 +1,172 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.protocols.pvp2x.builder; + +import java.security.NoSuchAlgorithmException; + +import javax.servlet.http.HttpServletResponse; + +import org.joda.time.DateTime; +import org.opensaml.common.impl.SecureRandomIdentifierGenerator; +import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.saml2.core.AuthnContextClassRef; +import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration; +import org.opensaml.saml2.core.AuthnRequest; +import org.opensaml.saml2.core.Issuer; +import org.opensaml.saml2.core.NameIDPolicy; +import org.opensaml.saml2.core.NameIDType; +import org.opensaml.saml2.core.RequestedAuthnContext; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.SingleSignOnService; +import org.opensaml.ws.message.encoder.MessageEncodingException; +import org.opensaml.xml.security.SecurityException; +import org.springframework.stereotype.Service; + +import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder; +import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding; +import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding; +import at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPAuthnRequestBuilderConfiguruation; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AuthnRequestBuildException; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.PVP2Exception; +import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; +import at.gv.egovernment.moa.logging.Logger; + +/** + * @author tlenz + * + */ +@Service("PVPAuthnRequestBuilder") +public class PVPAuthnRequestBuilder { + + + /** + * Build a PVP2.x specific authentication request + * + * @param pendingReq Currently processed pendingRequest + * @param config AuthnRequest builder configuration, never null + * @param idpEntity SAML2 EntityDescriptor of the IDP, which receive this AuthnRequest, never null + * @param httpResp + * @throws NoSuchAlgorithmException + * @throws SecurityException + * @throws PVP2Exception + * @throws MessageEncodingException + */ + public void buildAuthnRequest(IRequest pendingReq, IPVPAuthnRequestBuilderConfiguruation config, + HttpServletResponse httpResp) throws NoSuchAlgorithmException, MessageEncodingException, PVP2Exception, SecurityException { + //get IDP Entity element from config + EntityDescriptor idpEntity = config.getIDPEntityDescriptor(); + + AuthnRequest authReq = SAML2Utils + .createSAMLObject(AuthnRequest.class); + + //select SingleSignOn Service endpoint from IDP metadata + SingleSignOnService endpoint = null; + for (SingleSignOnService sss : + idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS).getSingleSignOnServices()) { + + // use POST binding as default if it exists + if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { + endpoint = sss; + + } else if ( sss.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI) + && endpoint == null ) + endpoint = sss; + + } + + if (endpoint == null) { + Logger.warn("Building AuthnRequest FAILED: > Requested IDP " + idpEntity.getEntityID() + + " does not support POST or Redirect Binding."); + throw new AuthnRequestBuildException("sp.pvp2.00", new Object[]{idpEntity.getEntityID()}); + + } else + authReq.setDestination(endpoint.getLocation()); + + + //set basic AuthnRequest information + SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator(); + authReq.setID(gen.generateIdentifier()); + authReq.setIssueInstant(new DateTime()); + + //set isPassive flag + if (config.isPassivRequest() == null) + authReq.setIsPassive(false); + else + authReq.setIsPassive(config.isPassivRequest()); + + //set EntityID of the service provider + Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); + issuer.setFormat(NameIDType.ENTITY); + issuer.setValue(config.getSPEntityID()); + authReq.setIssuer(issuer); + + //set AssertionConsumerService ID + if (config.getAssertionConsumerServiceId() != null) + authReq.setAssertionConsumerServiceIndex(config.getAssertionConsumerServiceId()); + + //set NameIDPolicy + if (config.getNameIDPolicyFormat() != null) { + NameIDPolicy policy = SAML2Utils.createSAMLObject(NameIDPolicy.class); + policy.setAllowCreate(config.getNameIDPolicyAllowCreation()); + policy.setFormat(config.getNameIDPolicyFormat()); + authReq.setNameIDPolicy(policy); + } + + //set requested QAA level + if (config.getAuthnContextClassRef() != null) { + RequestedAuthnContext reqAuthContext = SAML2Utils.createSAMLObject(RequestedAuthnContext.class); + AuthnContextClassRef authnClassRef = SAML2Utils.createSAMLObject(AuthnContextClassRef.class); + + authnClassRef.setAuthnContextClassRef(config.getAuthnContextClassRef()); + + if (config.getAuthnContextComparison() == null) + reqAuthContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM); + else + reqAuthContext.setComparison(config.getAuthnContextComparison()); + + reqAuthContext.getAuthnContextClassRefs().add(authnClassRef); + authReq.setRequestedAuthnContext(reqAuthContext); + } + + //TODO: implement requested attributes + //maybe: config.getRequestedAttributes(); + + //select message encoder + IEncoder binding = null; + if (endpoint.getBinding().equals( + SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { + binding = new RedirectBinding(); + + } else if (endpoint.getBinding().equals( + SAMLConstants.SAML2_POST_BINDING_URI)) { + binding = new PostBinding(); + + } + + //encode message + binding.encodeRequest(null, httpResp, authReq, + endpoint.getLocation(), pendingReq.getRequestID(), config.getAuthnRequestSigningCredential()); + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/PVPMetadataBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/PVPMetadataBuilder.java new file mode 100644 index 000000000..3418ffb69 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/PVPMetadataBuilder.java @@ -0,0 +1,460 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.protocols.pvp2x.builder; + +import java.io.IOException; +import java.io.StringWriter; +import java.security.PrivateKey; +import java.security.interfaces.RSAPrivateKey; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.joda.time.DateTime; +import org.opensaml.Configuration; +import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.saml2.metadata.AssertionConsumerService; +import org.opensaml.saml2.metadata.AttributeConsumingService; +import org.opensaml.saml2.metadata.ContactPerson; +import org.opensaml.saml2.metadata.EntitiesDescriptor; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.IDPSSODescriptor; +import org.opensaml.saml2.metadata.KeyDescriptor; +import org.opensaml.saml2.metadata.LocalizedString; +import org.opensaml.saml2.metadata.NameIDFormat; +import org.opensaml.saml2.metadata.Organization; +import org.opensaml.saml2.metadata.RequestedAttribute; +import org.opensaml.saml2.metadata.RoleDescriptor; +import org.opensaml.saml2.metadata.SPSSODescriptor; +import org.opensaml.saml2.metadata.ServiceName; +import org.opensaml.saml2.metadata.SingleLogoutService; +import org.opensaml.saml2.metadata.SingleSignOnService; +import org.opensaml.xml.io.Marshaller; +import org.opensaml.xml.io.MarshallingException; +import org.opensaml.xml.security.SecurityException; +import org.opensaml.xml.security.SecurityHelper; +import org.opensaml.xml.security.credential.Credential; +import org.opensaml.xml.security.credential.UsageType; +import org.opensaml.xml.security.keyinfo.KeyInfoGenerator; +import org.opensaml.xml.security.x509.X509KeyInfoGeneratorFactory; +import org.opensaml.xml.signature.Signature; +import org.opensaml.xml.signature.SignatureConstants; +import org.opensaml.xml.signature.SignatureException; +import org.opensaml.xml.signature.Signer; +import org.springframework.stereotype.Service; +import org.w3c.dom.Document; + +import at.gv.egovernment.moa.id.config.ConfigurationException; +import at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPMetadataBuilderConfiguration; +import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialsNotAvailableException; +import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; + +/** + * @author tlenz + * + */ + +@Service("PVPMetadataBuilder") +public class PVPMetadataBuilder { + + X509KeyInfoGeneratorFactory keyInfoFactory = null; + + /** + * + */ + public PVPMetadataBuilder() { + keyInfoFactory = new X509KeyInfoGeneratorFactory(); + keyInfoFactory.setEmitEntityIDAsKeyName(true); + keyInfoFactory.setEmitEntityCertificate(true); + + } + + + /** + * + * Build PVP 2.1 conform SAML2 metadata + * + * @param config + * PVPMetadataBuilder configuration + * + * @return PVP metadata as XML String + * @throws SecurityException + * @throws ConfigurationException + * @throws CredentialsNotAvailableException + * @throws TransformerFactoryConfigurationError + * @throws MarshallingException + * @throws TransformerException + * @throws ParserConfigurationException + * @throws IOException + * @throws SignatureException + */ + public String buildPVPMetadata(IPVPMetadataBuilderConfiguration config) throws CredentialsNotAvailableException, ConfigurationException, SecurityException, TransformerFactoryConfigurationError, MarshallingException, TransformerException, ParserConfigurationException, IOException, SignatureException { + DateTime date = new DateTime(); + EntityDescriptor entityDescriptor = SAML2Utils + .createSAMLObject(EntityDescriptor.class); + + //set entityID + entityDescriptor.setEntityID(config.getEntityID()); + + //set contact and organisation information + List<ContactPerson> contactPersons = config.getContactPersonInformation(); + if (contactPersons != null) + entityDescriptor.getContactPersons().addAll(contactPersons); + + Organization organisation = config.getOrgansiationInformation(); + if (organisation != null) + entityDescriptor.setOrganization(organisation); + + //set IDP metadata + if (config.buildIDPSSODescriptor()) { + RoleDescriptor idpSSODesc = generateIDPMetadata(config); + if (idpSSODesc != null) + entityDescriptor.getRoleDescriptors().add(idpSSODesc); + + } + + //set SP metadata for interfederation + if (config.buildSPSSODescriptor()) { + RoleDescriptor spSSODesc = generateSPMetadata(config); + if (spSSODesc != null) + entityDescriptor.getRoleDescriptors().add(spSSODesc); + + } + + //set metadata signature parameters + Credential metadataSignCred = config.getMetadataSigningCredentials(); + Signature signature = getIDPSignature(metadataSignCred); + SecurityHelper.prepareSignatureParams(signature, metadataSignCred, null, null); + + + //initialize XML document builder + DocumentBuilder builder; + DocumentBuilderFactory factory = DocumentBuilderFactory + .newInstance(); + + builder = factory.newDocumentBuilder(); + Document document = builder.newDocument(); + + + //build entities descriptor + if (config.buildEntitiesDescriptorAsRootElement()) { + EntitiesDescriptor entitiesDescriptor = + SAML2Utils.createSAMLObject(EntitiesDescriptor.class); + entitiesDescriptor.setName(config.getEntityFriendlyName()); + entitiesDescriptor.setID(SAML2Utils.getSecureIdentifier()); + entitiesDescriptor.setValidUntil(date.plusHours(config.getMetadataValidUntil())); + entitiesDescriptor.getEntityDescriptors().add(entityDescriptor); + + entitiesDescriptor.setSignature(signature); + + //marshall document + Marshaller out = Configuration.getMarshallerFactory() + .getMarshaller(entitiesDescriptor); + out.marshall(entitiesDescriptor, document); + + } else { + entityDescriptor.setValidUntil(date.plusHours(config.getMetadataValidUntil())); + + entityDescriptor.setSignature(signature); + + //marshall document + Marshaller out = Configuration.getMarshallerFactory() + .getMarshaller(entityDescriptor); + out.marshall(entityDescriptor, document); + + } + + //sign metadata + Signer.signObject(signature); + + //transform metadata object to XML string + Transformer transformer = TransformerFactory.newInstance() + .newTransformer(); + + StringWriter sw = new StringWriter(); + StreamResult sr = new StreamResult(sw); + DOMSource source = new DOMSource(document); + transformer.transform(source, sr); + sw.close(); + + return sw.toString(); + } + + + private RoleDescriptor generateSPMetadata(IPVPMetadataBuilderConfiguration config) throws CredentialsNotAvailableException, SecurityException, ConfigurationException { + SPSSODescriptor spSSODescriptor = SAML2Utils.createSAMLObject(SPSSODescriptor.class); + spSSODescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS); + spSSODescriptor.setAuthnRequestsSigned(true); + spSSODescriptor.setWantAssertionsSigned(false); + + KeyInfoGenerator keyInfoGenerator = keyInfoFactory.newInstance(); + + //Set AuthRequest Signing certificate + Credential authcredential = config.getRequestorResponseSigningCredentials(); + if (authcredential == null) { + Logger.warn("SP Metadata generation FAILED! --> Builder has NO request signing-credential. "); + return null; + + } else { + KeyDescriptor signKeyDescriptor = SAML2Utils + .createSAMLObject(KeyDescriptor.class); + signKeyDescriptor.setUse(UsageType.SIGNING); + signKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(authcredential)); + spSSODescriptor.getKeyDescriptors().add(signKeyDescriptor); + + } + + //Set assertion encryption credentials + Credential authEncCredential = config.getEncryptionCredentials(); + + if (authEncCredential != null) { + KeyDescriptor encryKeyDescriptor = SAML2Utils + .createSAMLObject(KeyDescriptor.class); + encryKeyDescriptor.setUse(UsageType.ENCRYPTION); + encryKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(authEncCredential)); + spSSODescriptor.getKeyDescriptors().add(encryKeyDescriptor); + + } else { + Logger.warn("No Assertion Encryption-Key defined. This setting is not recommended!"); + + } + + //check nameID formates + if (config.getSPAllowedNameITTypes() == null || config.getSPAllowedNameITTypes().size() == 0) { + Logger.warn("SP Metadata generation FAILED! --> Builder has NO provideable SAML2 nameIDFormats. "); + return null; + + } else { + for (String format : config.getSPAllowedNameITTypes()) { + NameIDFormat nameIDFormat = SAML2Utils.createSAMLObject(NameIDFormat.class); + nameIDFormat.setFormat(format); + spSSODescriptor.getNameIDFormats().add(nameIDFormat); + + } + } + + + //add POST-Binding assertion consumer services + if (MiscUtil.isNotEmpty(config.getSPAssertionConsumerServicePostBindingURL())) { + AssertionConsumerService postassertionConsumerService = SAML2Utils.createSAMLObject(AssertionConsumerService.class); + postassertionConsumerService.setIndex(0); + postassertionConsumerService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI); + postassertionConsumerService.setLocation(config.getSPAssertionConsumerServicePostBindingURL()); + postassertionConsumerService.setIsDefault(true); + spSSODescriptor.getAssertionConsumerServices().add(postassertionConsumerService); + + } + + //add POST-Binding assertion consumer services + if (MiscUtil.isNotEmpty(config.getSPAssertionConsumerServiceRedirectBindingURL())) { + AssertionConsumerService redirectassertionConsumerService = SAML2Utils.createSAMLObject(AssertionConsumerService.class); + redirectassertionConsumerService.setIndex(1); + redirectassertionConsumerService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); + redirectassertionConsumerService.setLocation(config.getSPAssertionConsumerServiceRedirectBindingURL()); + spSSODescriptor.getAssertionConsumerServices().add(redirectassertionConsumerService); + + } + + //validate WebSSO endpoints + if (spSSODescriptor.getAssertionConsumerServices().size() == 0) { + Logger.warn("SP Metadata generation FAILED! --> NO SAML2 AssertionConsumerService endpoint found. "); + return null; + + } + + //add POST-Binding SLO descriptor + if (MiscUtil.isNotEmpty(config.getSPSLOPostBindingURL())) { + SingleLogoutService postSLOService = SAML2Utils.createSAMLObject(SingleLogoutService.class); + postSLOService.setLocation(config.getSPSLOPostBindingURL()); + postSLOService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI); + spSSODescriptor.getSingleLogoutServices().add(postSLOService); + + } + + //add POST-Binding SLO descriptor + if (MiscUtil.isNotEmpty(config.getSPSLORedirectBindingURL())) { + SingleLogoutService redirectSLOService = SAML2Utils.createSAMLObject(SingleLogoutService.class); + redirectSLOService.setLocation(config.getSPSLORedirectBindingURL()); + redirectSLOService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); + spSSODescriptor.getSingleLogoutServices().add(redirectSLOService); + + } + + //add POST-Binding SLO descriptor + if (MiscUtil.isNotEmpty(config.getSPSLOSOAPBindingURL())) { + SingleLogoutService soapSLOService = SAML2Utils.createSAMLObject(SingleLogoutService.class); + soapSLOService.setLocation(config.getSPSLOSOAPBindingURL()); + soapSLOService.setBinding(SAMLConstants.SAML2_SOAP11_BINDING_URI); + spSSODescriptor.getSingleLogoutServices().add(soapSLOService); + + } + + + //add required attributes + List<RequestedAttribute> reqSPAttr = config.getSPRequiredAttributes(); + AttributeConsumingService attributeService = SAML2Utils.createSAMLObject(AttributeConsumingService.class); + + attributeService.setIndex(0); + attributeService.setIsDefault(true); + ServiceName serviceName = SAML2Utils.createSAMLObject(ServiceName.class); + serviceName.setName(new LocalizedString("Default Service", "en")); + attributeService.getNames().add(serviceName); + + if (reqSPAttr != null && reqSPAttr.size() > 0) { + Logger.debug("Add " + reqSPAttr.size() + " attributes to SP metadata"); + attributeService.getRequestAttributes().addAll(reqSPAttr); + + } else { + Logger.debug("SP metadata contains NO requested attributes."); + + } + + spSSODescriptor.getAttributeConsumingServices().add(attributeService); + + return spSSODescriptor; + } + + private IDPSSODescriptor generateIDPMetadata(IPVPMetadataBuilderConfiguration config) throws ConfigurationException, CredentialsNotAvailableException, SecurityException { + //check response signing credential + Credential responseSignCred = config.getRequestorResponseSigningCredentials(); + if (responseSignCred == null) { + Logger.warn("IDP Metadata generation FAILED! --> Builder has NO Response signing credential. "); + return null; + + } + + //check nameID formates + if (config.getIDPPossibleNameITTypes() == null || config.getIDPPossibleNameITTypes().size() == 0) { + Logger.warn("IDP Metadata generation FAILED! --> Builder has NO provideable SAML2 nameIDFormats. "); + return null; + + } + + // build SAML2 IDP-SSO descriptor element + IDPSSODescriptor idpSSODescriptor = SAML2Utils + .createSAMLObject(IDPSSODescriptor.class); + + idpSSODescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS); + + //set ass default value, because PVP 2.x specification defines this feature as MUST + idpSSODescriptor.setWantAuthnRequestsSigned(true); + + // add WebSSO descriptor for POST-Binding + if (MiscUtil.isNotEmpty(config.getIDPWebSSOPostBindingURL())) { + SingleSignOnService postSingleSignOnService = SAML2Utils.createSAMLObject(SingleSignOnService.class); + postSingleSignOnService.setLocation(config.getIDPWebSSOPostBindingURL()); + postSingleSignOnService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI); + idpSSODescriptor.getSingleSignOnServices().add(postSingleSignOnService); + + } + + // add WebSSO descriptor for Redirect-Binding + if (MiscUtil.isNotEmpty(config.getIDPWebSSORedirectBindingURL())) { + SingleSignOnService postSingleSignOnService = SAML2Utils.createSAMLObject(SingleSignOnService.class); + postSingleSignOnService.setLocation(config.getIDPWebSSORedirectBindingURL()); + postSingleSignOnService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); + idpSSODescriptor.getSingleSignOnServices().add(postSingleSignOnService); + + } + + //add Single LogOut POST-Binding endpoing + if (MiscUtil.isNotEmpty(config.getIDPSLOPostBindingURL())) { + SingleLogoutService postSLOService = SAML2Utils.createSAMLObject(SingleLogoutService.class); + postSLOService.setLocation(config.getIDPSLOPostBindingURL()); + postSLOService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI); + idpSSODescriptor.getSingleLogoutServices().add(postSLOService); + + } + + //add Single LogOut Redirect-Binding endpoing + if (MiscUtil.isNotEmpty(config.getIDPSLORedirectBindingURL())) { + SingleLogoutService redirectSLOService = SAML2Utils.createSAMLObject(SingleLogoutService.class); + redirectSLOService.setLocation(config.getIDPSLORedirectBindingURL()); + redirectSLOService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); + idpSSODescriptor.getSingleLogoutServices().add(redirectSLOService); + + } + + //validate WebSSO endpoints + if (idpSSODescriptor.getSingleSignOnServices().size() == 0) { + Logger.warn("IDP Metadata generation FAILED! --> NO SAML2 SingleSignOnService endpoint found. "); + return null; + + } + + //set assertion signing key + KeyDescriptor signKeyDescriptor = SAML2Utils + .createSAMLObject(KeyDescriptor.class); + signKeyDescriptor.setUse(UsageType.SIGNING); + KeyInfoGenerator keyInfoGenerator = keyInfoFactory.newInstance(); + signKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(config.getRequestorResponseSigningCredentials())); + idpSSODescriptor.getKeyDescriptors().add(signKeyDescriptor); + + //set IDP attribute set + idpSSODescriptor.getAttributes().addAll(config.getIDPPossibleAttributes()); + + //set providable nameID formats + for (String format : config.getIDPPossibleNameITTypes()) { + NameIDFormat nameIDFormat = SAML2Utils.createSAMLObject(NameIDFormat.class); + nameIDFormat.setFormat(format); + idpSSODescriptor.getNameIDFormats().add(nameIDFormat); + + } + + return idpSSODescriptor; + + } + + private Signature getIDPSignature(Credential credentials) { + PrivateKey privatekey = credentials.getPrivateKey(); + Signature signer = SAML2Utils.createSAMLObject(Signature.class); + + if (privatekey instanceof RSAPrivateKey) { + signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256); + + } else if (privatekey instanceof iaik.security.ecc.ecdsa.ECPrivateKey) { + signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA1); + + } else { + Logger.warn("Could NOT evaluate the Private-Key type from " + credentials.getEntityId() + " credential."); + + + } + + signer.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); + signer.setSigningCredential(credentials); + return signer; + + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java index 50f42d928..a7fc8295a 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java @@ -23,12 +23,16 @@ package at.gv.egovernment.moa.id.protocols.pvp2x.builder; import java.security.NoSuchAlgorithmException; +import java.util.LinkedHashMap; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; import org.joda.time.DateTime; +import org.opensaml.Configuration; import org.opensaml.common.SAMLObject; import org.opensaml.common.binding.BasicSAMLMessageContext; import org.opensaml.common.impl.SecureRandomIdentifierGenerator; @@ -43,33 +47,41 @@ import org.opensaml.saml2.core.StatusCode; import org.opensaml.saml2.core.StatusMessage; import org.opensaml.saml2.core.StatusResponseType; import org.opensaml.saml2.metadata.EntityDescriptor; -import org.opensaml.saml2.metadata.IDPSSODescriptor; -import org.opensaml.saml2.metadata.SPSSODescriptor; import org.opensaml.saml2.metadata.SSODescriptor; import org.opensaml.saml2.metadata.SingleLogoutService; import org.opensaml.saml2.metadata.impl.SingleLogoutServiceBuilder; import org.opensaml.saml2.metadata.provider.MetadataProviderException; import org.opensaml.ws.message.encoder.MessageEncodingException; +import org.opensaml.xml.io.Marshaller; import org.opensaml.xml.security.SecurityException; import org.opensaml.xml.security.x509.X509Credential; +import org.opensaml.xml.signature.Signature; +import org.opensaml.xml.signature.SignatureConstants; +import org.opensaml.xml.signature.Signer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.w3c.dom.Document; import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore; +import at.gv.egovernment.moa.id.commons.db.dao.session.OASessionStore; import at.gv.egovernment.moa.id.config.ConfigurationException; +import at.gv.egovernment.moa.id.data.ISLOInformationContainer; import at.gv.egovernment.moa.id.data.SLOInformationContainer; import at.gv.egovernment.moa.id.data.SLOInformationImpl; import at.gv.egovernment.moa.id.opemsaml.MOAStringRedirectDeflateEncoder; +import at.gv.egovernment.moa.id.protocols.pvp2x.PVP2XProtocol; import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration; import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder; import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding; import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding; -import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.BindingNotSupportedException; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NOSLOServiceDescriptorException; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NoMetadataInformationException; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider; -import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialProvider; +import at.gv.egovernment.moa.id.protocols.pvp2x.signer.IDPCredentialProvider; import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; import at.gv.egovernment.moa.logging.Logger; @@ -78,9 +90,12 @@ import at.gv.egovernment.moa.logging.Logger; * @author tlenz * */ +@Service("PVP_SingleLogOutBuilder") public class SingleLogOutBuilder { - public static void checkStatusCode(SLOInformationContainer sloContainer, LogoutResponse logOutResp) { + @Autowired private IDPCredentialProvider credentialProvider; + + public void checkStatusCode(ISLOInformationContainer sloContainer, LogoutResponse logOutResp) { Status status = logOutResp.getStatus(); if (!status.getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) { String message = " Message: "; @@ -106,12 +121,12 @@ public class SingleLogOutBuilder { * @param relayState * @return */ - public static String getFrontChannelSLOMessageURL(String serviceURL, String bindingType, + public String getFrontChannelSLOMessageURL(String serviceURL, String bindingType, RequestAbstractType sloReq, HttpServletRequest httpReq, HttpServletResponse httpResp, String relayState) throws MOAIDException { try { - X509Credential credentials = CredentialProvider + X509Credential credentials = credentialProvider .getIDPAssertionSigningCredential(); Logger.debug("create SAML RedirectBinding response"); @@ -138,12 +153,12 @@ public class SingleLogOutBuilder { } } - public static String getFrontChannelSLOMessageURL(SingleLogoutService service, + public String getFrontChannelSLOMessageURL(SingleLogoutService service, StatusResponseType sloResp, HttpServletRequest httpReq, HttpServletResponse httpResp, String relayState) throws MOAIDException { try { - X509Credential credentials = CredentialProvider + X509Credential credentials = credentialProvider .getIDPAssertionSigningCredential(); Logger.debug("create SAML RedirectBinding response"); @@ -166,7 +181,7 @@ public class SingleLogOutBuilder { } } - public static void sendFrontChannelSLOMessage(SingleLogoutService consumerService, + public void sendFrontChannelSLOMessage(SingleLogoutService consumerService, LogoutResponse sloResp, HttpServletRequest req, HttpServletResponse resp, String relayState) throws MOAIDException { IEncoder binding = null; @@ -186,7 +201,8 @@ public class SingleLogOutBuilder { try { binding.encodeRespone(req, resp, sloResp, - consumerService.getLocation(), relayState); + consumerService.getLocation(), relayState, + credentialProvider.getIDPAssertionSigningCredential()); } catch (MessageEncodingException e) { Logger.error("Message Encoding exception", e); @@ -200,7 +216,7 @@ public class SingleLogOutBuilder { } - public static LogoutRequest buildSLORequestMessage(SLOInformationImpl sloInfo) throws ConfigurationException, MOAIDException { + public LogoutRequest buildSLORequestMessage(SLOInformationImpl sloInfo) throws ConfigurationException, MOAIDException { LogoutRequest sloReq = SAML2Utils.createSAMLObject(LogoutRequest.class); SecureRandomIdentifierGenerator gen; @@ -215,8 +231,8 @@ public class SingleLogOutBuilder { } DateTime now = new DateTime(); - Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); - issuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath()); + Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); + issuer.setValue(sloInfo.getAuthURL()); issuer.setFormat(NameID.ENTITY); sloReq.setIssuer(issuer); sloReq.setIssueInstant(now); @@ -228,11 +244,39 @@ public class SingleLogOutBuilder { nameID.setFormat(sloInfo.getUserNameIDFormat()); nameID.setValue(sloInfo.getUserNameIdentifier()); sloReq.setNameID(nameID ); - + + //sign message + try { + X509Credential idpSigningCredential = credentialProvider.getIDPAssertionSigningCredential(); + + Signature signer = SAML2Utils.createSAMLObject(Signature.class); + signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256); + signer.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); + signer.setSigningCredential(idpSigningCredential); + sloReq.setSignature(signer); + + DocumentBuilder builder; + DocumentBuilderFactory factory = DocumentBuilderFactory + .newInstance(); + + builder = factory.newDocumentBuilder(); + Document document = builder.newDocument(); + Marshaller out = Configuration.getMarshallerFactory() + .getMarshaller(sloReq); + out.marshall(sloReq, document); + + Signer.signObject(signer); + + } catch (Exception e) { + Logger.error("Single LogOut request signing FAILED!", e); + throw new MOAIDException("pvp2.19", null); + + } + return sloReq; } - public static LogoutResponse buildSLOErrorResponse(SingleLogoutService sloService, PVPTargetConfiguration spRequest, String firstLevelStatusCode) throws ConfigurationException, MOAIDException { + public LogoutResponse buildSLOErrorResponse(SingleLogoutService sloService, PVPTargetConfiguration spRequest, String firstLevelStatusCode) throws ConfigurationException, MOAIDException { LogoutResponse sloResp = buildBasicResponse(sloService, spRequest); Status status = SAML2Utils.createSAMLObject(Status.class); @@ -249,7 +293,7 @@ public class SingleLogOutBuilder { return sloResp; } - public static LogoutResponse buildSLOResponseMessage(SingleLogoutService sloService, PVPTargetConfiguration spRequest, List<String> failedOAs) throws MOAIDException { + public LogoutResponse buildSLOResponseMessage(SingleLogoutService sloService, PVPTargetConfiguration spRequest, List<String> failedOAs) throws MOAIDException { LogoutResponse sloResp = buildBasicResponse(sloService, spRequest); Status status; @@ -274,10 +318,10 @@ public class SingleLogOutBuilder { } - private static LogoutResponse buildBasicResponse(SingleLogoutService sloService, PVPTargetConfiguration spRequest) throws ConfigurationException, MOAIDException { + private LogoutResponse buildBasicResponse(SingleLogoutService sloService, PVPTargetConfiguration spRequest) throws ConfigurationException, MOAIDException { LogoutResponse sloResp = SAML2Utils.createSAMLObject(LogoutResponse.class); Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); - issuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath()); + issuer.setValue(spRequest.getAuthURLWithOutSlash()); issuer.setFormat(NameID.ENTITY); sloResp.setIssuer(issuer); sloResp.setIssueInstant(new DateTime()); @@ -305,7 +349,7 @@ public class SingleLogOutBuilder { } - public static SingleLogoutService getRequestSLODescriptor(String entityID) throws NOSLOServiceDescriptorException { + public SingleLogoutService getRequestSLODescriptor(String entityID) throws NOSLOServiceDescriptorException { try { EntityDescriptor entity = MOAMetadataProvider.getInstance().getEntityDescriptor(entityID); SSODescriptor spsso = entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS); @@ -346,7 +390,7 @@ public class SingleLogOutBuilder { } - public static SingleLogoutService getResponseSLODescriptor(PVPTargetConfiguration spRequest) throws NoMetadataInformationException, NOSLOServiceDescriptorException { + public SingleLogoutService getResponseSLODescriptor(PVPTargetConfiguration spRequest) throws NoMetadataInformationException, NOSLOServiceDescriptorException { MOARequest moaReq = (MOARequest) spRequest.getRequest(); EntityDescriptor metadata = moaReq.getEntityMetadata(); SSODescriptor ssodesc = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS); @@ -382,4 +426,91 @@ public class SingleLogOutBuilder { return sloService; } + public void parseActiveOAs(SLOInformationContainer container, + List<OASessionStore> dbOAs, String removeOAID) { + if (container.getActiveBackChannelOAs() == null) + container.setActiveBackChannelOAs(new LinkedHashMap<String, SLOInformationImpl>()); + if (container.getActiveFrontChannalOAs() == null) + container.setActiveFrontChannalOAs(new LinkedHashMap<String, SLOInformationImpl>()); + + + if (dbOAs != null) { + for (OASessionStore oa : dbOAs) { + if (!oa.getOaurlprefix().equals(removeOAID)) { + + //Actually only PVP 2.1 support Single LogOut + if (PVP2XProtocol.PATH.equals(oa.getProtocolType())) { + SingleLogoutService sloDesc; + try { + sloDesc = getRequestSLODescriptor(oa.getOaurlprefix()); + + if (sloDesc.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI)) + container.getActiveBackChannelOAs().put(oa.getOaurlprefix(), + new SLOInformationImpl( + oa.getAuthURL(), + oa.getAssertionSessionID(), + oa.getUserNameID(), + oa.getUserNameIDFormat(), + oa.getProtocolType(), + sloDesc)); + + else + container.getActiveFrontChannalOAs().put(oa.getOaurlprefix(), + new SLOInformationImpl( + oa.getAuthURL(), + oa.getAssertionSessionID(), + oa.getUserNameID(), + oa.getUserNameIDFormat(), + oa.getProtocolType(), + sloDesc)); + + } catch (NOSLOServiceDescriptorException e) { + container.putFailedOA(oa.getOaurlprefix()); + + } + + } else + container.putFailedOA(oa.getOaurlprefix()); + } + } + } + } + + /** + * @param dbIDPs + * @param value + */ + public void parseActiveIDPs(SLOInformationContainer container, + List<InterfederationSessionStore> dbIDPs, String removeIDP) { + if (container.getActiveBackChannelOAs() == null) + container.setActiveBackChannelOAs(new LinkedHashMap<String, SLOInformationImpl>()); + if (container.getActiveFrontChannalOAs() == null) + container.setActiveFrontChannalOAs(new LinkedHashMap<String, SLOInformationImpl>()); + + if (dbIDPs != null) { + for (InterfederationSessionStore el : dbIDPs) { + if (!el.getIdpurlprefix().equals(removeIDP)) { + + SingleLogoutService sloDesc; + try { + sloDesc = getRequestSLODescriptor(el.getIdpurlprefix()); + + container.getActiveFrontChannalOAs().put(el.getIdpurlprefix(), + new SLOInformationImpl( + el.getAuthURL(), + el.getSessionIndex(), + el.getUserNameID(), + NameID.TRANSIENT, + PVP2XProtocol.PATH, + sloDesc)); + + } catch (NOSLOServiceDescriptorException e) { + container.putFailedOA(el.getIdpurlprefix()); + + } + } + } + } + } + } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/assertion/PVP2AssertionBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/assertion/PVP2AssertionBuilder.java index d80ddba25..94e30238a 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/assertion/PVP2AssertionBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/assertion/PVP2AssertionBuilder.java @@ -55,7 +55,6 @@ import org.opensaml.saml2.metadata.RequestedAttribute; import org.opensaml.saml2.metadata.SPSSODescriptor; import org.w3c.dom.Element; - import at.gv.e_government.reference.namespace.mandates._20040701_.Mandate; import at.gv.e_government.reference.namespace.persondata._20020228_.CorporateBodyType; import at.gv.e_government.reference.namespace.persondata._20020228_.IdentificationType; @@ -64,21 +63,18 @@ import at.gv.egovernment.moa.id.auth.builder.BPKBuilder; import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; import at.gv.egovernment.moa.id.config.ConfigurationException; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; -import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; import at.gv.egovernment.moa.id.data.IAuthData; import at.gv.egovernment.moa.id.data.SLOInformationImpl; +import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; +import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration; import at.gv.egovernment.moa.id.protocols.pvp2x.builder.PVPAttributeBuilder; -import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.exceptions.AttributeException; import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.exceptions.UnavailableAttributeException; -import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration; -import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.MandateAttributesNotHandleAbleException; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NoMandateDataAvailableException; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.PVP2Exception; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.QAANotSupportedException; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.UnprovideableAttributeException; -import at.gv.egovernment.moa.id.protocols.pvp2x.utils.CheckMandateAttributes; import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; import at.gv.egovernment.moa.id.util.MandateBuilder; import at.gv.egovernment.moa.id.util.QAALevelVerifier; @@ -90,7 +86,7 @@ import at.gv.egovernment.moa.util.MiscUtil; public class PVP2AssertionBuilder implements PVPConstants { - public static Assertion buildAssertion(AttributeQuery attrQuery, + public static Assertion buildAssertion(IRequest pendingReq, AttributeQuery attrQuery, List<String> reqAttributes, IAuthData authData, DateTime date, String sessionIndex) throws ConfigurationException { @@ -136,12 +132,12 @@ public class PVP2AssertionBuilder implements PVPConstants { SubjectConfirmationData subjectConfirmationData = null; - return buildGenericAssertion(attrQuery.getIssuer().getValue(), date, + return buildGenericAssertion(pendingReq, attrQuery.getIssuer().getValue(), date, authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex, new DateTime(authData.getSsoSessionValidTo().getTime())); } - public static Assertion buildAssertion(AuthnRequest authnRequest, + public static Assertion buildAssertion(PVPTargetConfiguration pendingReq, AuthnRequest authnRequest, IAuthData authData, EntityDescriptor peerEntity, DateTime date, AssertionConsumerService assertionConsumerService, SLOInformationImpl sloInformation) throws MOAIDException { @@ -153,9 +149,7 @@ public class PVP2AssertionBuilder implements PVPConstants { AuthnContextClassRef authnContextClassRef = SAML2Utils .createSAMLObject(AuthnContextClassRef.class); - OAAuthParameter oaParam = AuthConfigurationProviderFactory.getInstance() - .getOnlineApplicationParameter( - peerEntity.getEntityID()); + IOAAuthParameters oaParam = pendingReq.getOnlineApplicationConfiguration(); if (reqAuthnContext == null) { authnContextClassRef.setAuthnContextClassRef(authData.getQAALevel()); @@ -416,10 +410,25 @@ public class PVP2AssertionBuilder implements PVPConstants { sloInformation.setNameIDFormat(subjectNameID.getFormat()); sloInformation.setSessionIndex(sessionIndex); - return buildGenericAssertion(peerEntity.getEntityID(), date, authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex, subjectConfirmationData.getNotOnOrAfter()); + return buildGenericAssertion(pendingReq, peerEntity.getEntityID(), date, authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex, subjectConfirmationData.getNotOnOrAfter()); } - public static Assertion buildGenericAssertion(String entityID, DateTime date, + /** + * + * @param pendingReq IDP PublicURL PreFix + * @param entityID Service Provider EntityID + * @param date + * @param authnContextClassRef + * @param attrList + * @param subjectNameID + * @param subjectConfirmationData + * @param sessionIndex + * @param isValidTo + * @return + * @throws ConfigurationException + */ + + public static Assertion buildGenericAssertion(IRequest pendingReq, String entityID, DateTime date, AuthnContextClassRef authnContextClassRef, List<Attribute> attrList, NameID subjectNameID, SubjectConfirmationData subjectConfirmationData, String sessionIndex, DateTime isValidTo) throws ConfigurationException { @@ -471,7 +480,10 @@ public class PVP2AssertionBuilder implements PVPConstants { Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); - issuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath()); + String authURL = pendingReq.getAuthURL(); + if (authURL.endsWith("/")) + authURL = authURL.substring(0, authURL.length()-1); + issuer.setValue(authURL); issuer.setFormat(NameID.ENTITY); assertion.setIssuer(issuer); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/IDPPVPMetadataConfiguration.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/IDPPVPMetadataConfiguration.java new file mode 100644 index 000000000..e0994ff19 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/IDPPVPMetadataConfiguration.java @@ -0,0 +1,288 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.protocols.pvp2x.config; + +import java.util.Arrays; +import java.util.List; + +import org.opensaml.saml2.core.Attribute; +import org.opensaml.saml2.core.NameIDType; +import org.opensaml.saml2.metadata.ContactPerson; +import org.opensaml.saml2.metadata.Organization; +import org.opensaml.saml2.metadata.RequestedAttribute; +import org.opensaml.xml.security.credential.Credential; + +import at.gv.egovernment.moa.id.config.ConfigurationException; +import at.gv.egovernment.moa.id.protocols.pvp2x.PVP2XProtocol; +import at.gv.egovernment.moa.id.protocols.pvp2x.builder.PVPAttributeBuilder; +import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialsNotAvailableException; +import at.gv.egovernment.moa.id.protocols.pvp2x.signer.IDPCredentialProvider; +import at.gv.egovernment.moa.logging.Logger; + +/** + * @author tlenz + * + */ +public class IDPPVPMetadataConfiguration implements IPVPMetadataBuilderConfiguration { + + private static final int VALIDUNTIL_IN_HOURS = 24; + + private String authURL; + private IDPCredentialProvider credentialProvider; + + public IDPPVPMetadataConfiguration(String authURL, IDPCredentialProvider credentialProvider) { + this.authURL = authURL; + this.credentialProvider = credentialProvider; + + } + + public String getDefaultActionName() { + return (PVP2XProtocol.METADATA); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getMetadataValidUntil() + */ + @Override + public int getMetadataValidUntil() { + return VALIDUNTIL_IN_HOURS; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#buildEntitiesDescriptorAsRootElement() + */ + @Override + public boolean buildEntitiesDescriptorAsRootElement() { + return true; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#buildIDPSSODescriptor() + */ + @Override + public boolean buildIDPSSODescriptor() { + return true; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#buildSPSSODescriptor() + */ + @Override + public boolean buildSPSSODescriptor() { + return false; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getEntityID() + */ + @Override + public String getEntityID() { + return authURL; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getEntityFriendlyName() + */ + @Override + public String getEntityFriendlyName() { + try { + return PVPConfiguration.getInstance().getIDPIssuerName(); + + } catch (ConfigurationException e) { + Logger.error("Can not load Metadata entry: EntityID friendlyName.", e); + return null; + + } + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getContactPersonInformation() + */ + @Override + public List<ContactPerson> getContactPersonInformation() { + try { + return PVPConfiguration.getInstance().getIDPContacts(); + + } catch (ConfigurationException e) { + Logger.warn("Can not load Metadata entry: Contect Person", e); + return null; + + } + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getOrgansiationInformation() + */ + @Override + public Organization getOrgansiationInformation() { + try { + return PVPConfiguration.getInstance().getIDPOrganisation(); + + } catch (ConfigurationException e) { + Logger.warn("Can not load Metadata entry: Organisation", e); + return null; + + } + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getMetadataSigningCredentials() + */ + @Override + public Credential getMetadataSigningCredentials() throws CredentialsNotAvailableException { + return credentialProvider.getIDPMetaDataSigningCredential(); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getRequestorResponseSigningCredentials() + */ + @Override + public Credential getRequestorResponseSigningCredentials() throws CredentialsNotAvailableException { + return credentialProvider.getIDPAssertionSigningCredential(); + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getEncryptionCredentials() + */ + @Override + public Credential getEncryptionCredentials() throws CredentialsNotAvailableException { + return credentialProvider.getIDPAssertionEncryptionCredential(); + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getIDPWebSSOPostBindingURL() + */ + @Override + public String getIDPWebSSOPostBindingURL() { + return authURL + PVPConfiguration.PVP2_IDP_POST; + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getIDPWebSSORedirectBindingURL() + */ + @Override + public String getIDPWebSSORedirectBindingURL() { + return authURL + PVPConfiguration.PVP2_IDP_REDIRECT; + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getIDPSLOPostBindingURL() + */ + @Override + public String getIDPSLOPostBindingURL() { + return authURL + PVPConfiguration.PVP2_IDP_POST; + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getIDPSLORedirectBindingURL() + */ + @Override + public String getIDPSLORedirectBindingURL() { + return authURL + PVPConfiguration.PVP2_IDP_REDIRECT; + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getSPAssertionConsumerServicePostBindingURL() + */ + @Override + public String getSPAssertionConsumerServicePostBindingURL() { + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getSPAssertionConsumerServiceRedirectBindingURL() + */ + @Override + public String getSPAssertionConsumerServiceRedirectBindingURL() { + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getSPSLOPostBindingURL() + */ + @Override + public String getSPSLOPostBindingURL() { + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getSPSLORedirectBindingURL() + */ + @Override + public String getSPSLORedirectBindingURL() { + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getSPSLOSOAPBindingURL() + */ + @Override + public String getSPSLOSOAPBindingURL() { + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getIDPPossibleAttributes() + */ + @Override + public List<Attribute> getIDPPossibleAttributes() { + return PVPAttributeBuilder.buildSupportedEmptyAttributes(); + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getIDPPossibleNameITTypes() + */ + @Override + public List<String> getIDPPossibleNameITTypes() { + return Arrays.asList(NameIDType.PERSISTENT, + NameIDType.TRANSIENT, + NameIDType.UNSPECIFIED); + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getSPRequiredAttributes() + */ + @Override + public List<RequestedAttribute> getSPRequiredAttributes() { + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.builder.AbstractPVPMetadataBuilder#getSPAllowedNameITTypes() + */ + @Override + public List<String> getSPAllowedNameITTypes() { + return null; + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/IPVPAuthnRequestBuilderConfiguruation.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/IPVPAuthnRequestBuilderConfiguruation.java new file mode 100644 index 000000000..d51231044 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/IPVPAuthnRequestBuilderConfiguruation.java @@ -0,0 +1,114 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.protocols.pvp2x.config; + +import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.xml.security.credential.Credential; + +/** + * @author tlenz + * + */ +public interface IPVPAuthnRequestBuilderConfiguruation { + + /** + * If true, the SAML2 isPassive flag is set in the AuthnRequest + * + * @return + */ + public Boolean isPassivRequest(); + + /** + * Define the ID of the AssertionConsumerService, + * which defines the required attributes in service-provider metadata. + * + * @return + */ + public Integer getAssertionConsumerServiceId(); + + /** + * Define the SAML2 EntityID of the service provider. + * + * @return + */ + public String getSPEntityID(); + + /** + * Define the SAML2 NameIDPolicy + * + * @return Service-Provider EntityID, but never null + */ + public String getNameIDPolicyFormat(); + + /** + * Define the AuthnContextClassRefernece of this request + * + * Example: + * http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-3 + * http://www.stork.gov.eu/1.0/citizenQAALevel/4 + * + * + * @return + */ + public String getAuthnContextClassRef(); + + /** + * Define the AuthnContextComparison model, which should be used + * + * @return + */ + public AuthnContextComparisonTypeEnumeration getAuthnContextComparison(); + + + /** + * Define the credential, which should be used to sign the AuthnRequest + * + * @return + */ + public Credential getAuthnRequestSigningCredential(); + + + /** + * Define the SAML2 EntityDescriptor of the IDP, which should receive the AuthnRequest + * + * @return Credential, but never null. + */ + public EntityDescriptor getIDPEntityDescriptor(); + + /** + * Set the SAML2 NameIDPolicy allow-creation flag + * + * @return EntityDescriptor, but never null. + */ + public boolean getNameIDPolicyAllowCreation(); + + + /** + * Set the requested SubjectNameID + * + * @return SubjectNameID, or null if no SubjectNameID should be used + */ + public String getSubjectNameID(); + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/IPVPMetadataBuilderConfiguration.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/IPVPMetadataBuilderConfiguration.java new file mode 100644 index 000000000..52096fd19 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/IPVPMetadataBuilderConfiguration.java @@ -0,0 +1,217 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.protocols.pvp2x.config; + +import java.util.List; + +import org.opensaml.saml2.core.Attribute; +import org.opensaml.saml2.metadata.ContactPerson; +import org.opensaml.saml2.metadata.Organization; +import org.opensaml.saml2.metadata.RequestedAttribute; +import org.opensaml.xml.security.credential.Credential; + +import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialsNotAvailableException; + +/** + * @author tlenz + * + */ +public interface IPVPMetadataBuilderConfiguration { + + + /** + * Set metadata valid area + * + * @return valid until in hours [h] + */ + public int getMetadataValidUntil(); + + /** + * Build a SAML2 Entities element as metadata root element + * + * @return true, if the metadata should start with entities element + */ + public boolean buildEntitiesDescriptorAsRootElement(); + + /** + * + * + * @return true, if an IDP SSO-descriptor element should be generated + */ + public boolean buildIDPSSODescriptor(); + + /** + * + * + * @return true, if an SP SSO-descriptor element should be generated + */ + public boolean buildSPSSODescriptor(); + + /** + * Set the PVP entityID for this SAML2 metadata. + * The entityID must be an URL and must be start with the public-URL prefix of the server + * + * @return PVP entityID postfix as String + */ + public String getEntityID(); + + /** + * Set a friendlyName for this PVP entity + * + * @return + */ + public String getEntityFriendlyName(); + + /** + * Set the contact information for this metadata entity + * + * @return + */ + public List<ContactPerson> getContactPersonInformation(); + + /** + * Set organisation information for this metadata entity + * + * @return + */ + public Organization getOrgansiationInformation(); + + + /** + * Set the credential for metadata signing + * + * @return + * @throws CredentialsNotAvailableException + */ + public Credential getMetadataSigningCredentials() throws CredentialsNotAvailableException; + + /** + * Set the credential for request/response signing + * IDP metadata: this credential is used for SAML2 response signing + * SP metadata: this credential is used for SAML2 response signing + * + * @return + * @throws CredentialsNotAvailableException + */ + public Credential getRequestorResponseSigningCredentials() throws CredentialsNotAvailableException; + + /** + * Set the credential for response encryption + * + * @return + * @throws CredentialsNotAvailableException + */ + public Credential getEncryptionCredentials() throws CredentialsNotAvailableException; + + /** + * Set the IDP Post-Binding URL for WebSSO + * + * @return + */ + public String getIDPWebSSOPostBindingURL(); + + /** + * Set the IDP Redirect-Binding URL for WebSSO + * + * @return + */ + public String getIDPWebSSORedirectBindingURL(); + + /** + * Set the IDP Post-Binding URL for Single LogOut + * + * @return + */ + public String getIDPSLOPostBindingURL(); + + /** + * Set the IDP Redirect-Binding URL for Single LogOut + * + * @return + */ + public String getIDPSLORedirectBindingURL(); + + /** + * Set the SP Post-Binding URL for for the Assertion-Consumer Service + * + * @return + */ + public String getSPAssertionConsumerServicePostBindingURL(); + + /** + * Set the SP Redirect-Binding URL for the Assertion-Consumer Service + * + * @return + */ + public String getSPAssertionConsumerServiceRedirectBindingURL(); + + /** + * Set the SP Post-Binding URL for Single LogOut + * + * @return + */ + public String getSPSLOPostBindingURL(); + + /** + * Set the SP Redirect-Binding URL for Single LogOut + * + * @return + */ + public String getSPSLORedirectBindingURL(); + + /** + * Set the SP SOAP-Binding URL for Single LogOut + * + * @return + */ + public String getSPSLOSOAPBindingURL(); + + + /** + * Set all SAML2 attributes which could be provided by this IDP + * + * @return + */ + public List<Attribute> getIDPPossibleAttributes(); + + /** + * Set all nameID types which could be provided by this IDP + * + * @return a List of SAML2 nameID types + */ + public List<String> getIDPPossibleNameITTypes(); + + /** + * Set all SAML2 attributes which are required by the SP + * + * @return + */ + public List<RequestedAttribute> getSPRequiredAttributes(); + + /** + * Set all nameID types which allowed from the SP + * + * @return a List of SAML2 nameID types + */ + public List<String> getSPAllowedNameITTypes(); +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/PVPConfiguration.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/PVPConfiguration.java index dc3b787e4..bbf395a6f 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/PVPConfiguration.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/PVPConfiguration.java @@ -22,8 +22,6 @@ *******************************************************************************/ package at.gv.egovernment.moa.id.protocols.pvp2x.config; -import iaik.x509.X509Certificate; - import java.io.IOException; import java.net.URL; import java.security.cert.CertificateException; @@ -51,12 +49,11 @@ import at.gv.egovernment.moa.id.commons.config.MOAIDConfigurationConstants; import at.gv.egovernment.moa.id.config.ConfigurationException; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; -import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider; import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.Base64Utils; -import at.gv.egovernment.moa.util.FileUtils; import at.gv.egovernment.moa.util.MiscUtil; +import iaik.x509.X509Certificate; public class PVPConfiguration { @@ -79,18 +76,6 @@ public class PVPConfiguration { public static final String PVP_CONFIG_FILE = "pvp2config.properties"; - public static final String IDP_JAVAKEYSTORE = "idp.ks.file"; - public static final String IDP_KS_PASS = "idp.ks.kspassword"; - - public static final String IDP_KEYALIASMETADATA = "idp.ks.metadata.alias"; - public static final String IDP_KEY_PASSMETADATA = "idp.ks.metadata.keypassword"; - - public static final String IDP_KEYALIASASSERTION = "idp.ks.assertion.sign.alias"; - public static final String IDP_KEY_PASSASSERTION = "idp.ks.assertion.sign.keypassword"; - - public static final String IDP_KEYALIASENCRYTPION = "sp.ks.assertion.encryption.alias"; - public static final String IDP_KEY_PASSENCRYTPION = "sp.ks.assertion.encryption.keypassword"; - public static final String IDP_ISSUER_NAME = "servicename"; public static final String IDP_ORG_NAME = "name.short"; @@ -121,75 +106,46 @@ public class PVPConfiguration { } } - public String getIDPPublicPath() throws ConfigurationException { - String publicPath = AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix(); - if(publicPath != null) { - if(publicPath.endsWith("/")) { - int length = publicPath.length(); - publicPath = publicPath.substring(0, length-1); - } + public List<String> getIDPPublicPath() throws ConfigurationException { + List<String> publicPath = AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix(); + List<String> returnvalue = new ArrayList<String>(); + for (String el : publicPath) { + if(el.endsWith("/")) { + int length = el.length(); + returnvalue.add(el.substring(0, length-1)); + + } else + returnvalue.add(el); } - return publicPath; + return returnvalue; } - public String getSPSSOPostService() throws ConfigurationException { - return getIDPPublicPath() + PVP2_SP_POST; + public String getSPSSOPostService(String publicURLPrefix) throws ConfigurationException { + return publicURLPrefix + PVP2_SP_POST; } - public String getSPSSORedirectService() throws ConfigurationException { - return getIDPPublicPath() + PVP2_SP_REDIRECT; + public String getSPSSORedirectService(String publicURLPrefix) throws ConfigurationException { + return publicURLPrefix + PVP2_SP_REDIRECT; } - public String getIDPSSOPostService() throws ConfigurationException { - return getIDPPublicPath() + PVP2_IDP_POST; + public String getIDPSSOPostService(String publicURLPrefix) throws ConfigurationException { + return publicURLPrefix + PVP2_IDP_POST; } - public String getIDPSSORedirectService() throws ConfigurationException { - return getIDPPublicPath() + PVP2_IDP_REDIRECT; + public String getIDPSSORedirectService(String publicURLPrefix) throws ConfigurationException { + return publicURLPrefix + PVP2_IDP_REDIRECT; } - public String getIDPSSOSOAPService() throws ConfigurationException { - return getIDPPublicPath() + PVP2_IDP_SOAP; + public String getIDPSSOSOAPService(String publicURLPrefix) throws ConfigurationException { + return publicURLPrefix + PVP2_IDP_SOAP; } - public String getIDPAttributeQueryService() throws ConfigurationException { - return getIDPPublicPath() + PVP2_IDP_ATTRIBUTEQUERY; + public String getIDPAttributeQueryService(String publicURLPrefix) throws ConfigurationException { + return publicURLPrefix + PVP2_IDP_ATTRIBUTEQUERY; } - public String getIDPSSOMetadataService() throws ConfigurationException { - return getIDPPublicPath() + PVP2_METADATA; - } - - public String getIDPKeyStoreFilename() { - return FileUtils.makeAbsoluteURL(props.getProperty(IDP_JAVAKEYSTORE), rootDir); - } - - public String getIDPKeyStorePassword() { - return props.getProperty(IDP_KS_PASS).trim(); - } - - public String getIDPKeyAliasMetadata() { - return props.getProperty(IDP_KEYALIASMETADATA).trim(); - } - - public String getIDPKeyPasswordMetadata() { - return props.getProperty(IDP_KEY_PASSMETADATA).trim(); - } - - public String getIDPKeyAliasAssertionSign() { - return props.getProperty(IDP_KEYALIASASSERTION).trim(); - } - - public String getIDPKeyPasswordAssertionSign() { - return props.getProperty(IDP_KEY_PASSASSERTION).trim(); - } - - public String getIDPKeyAliasAssertionEncryption() { - return props.getProperty(IDP_KEYALIASASSERTION).trim(); - } - - public String getIDPKeyPasswordAssertionEncryption() { - return props.getProperty(IDP_KEY_PASSASSERTION).trim(); + public String getIDPSSOMetadataService(String publicURLPrefix) throws ConfigurationException { + return publicURLPrefix + PVP2_METADATA; } public String getIDPIssuerName() throws ConfigurationException { diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/IExceptionStore.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/AuthnRequestBuildException.java index 4c76a49a4..eebaf6c9e 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/IExceptionStore.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/AuthnRequestBuildException.java @@ -1,4 +1,4 @@ -/******************************************************************************* +/* * Copyright 2014 Federal Chancellery Austria * MOA-ID has been developed in a cooperation between BRZ, the Federal * Chancellery Austria - ICT staff unit, and Graz University of Technology. @@ -19,11 +19,29 @@ * 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.egovernment.moa.id.storage; + */ +package at.gv.egovernment.moa.id.protocols.pvp2x.exceptions; -public interface IExceptionStore { - public String storeException(Throwable e); - public Throwable fetchException(String id); - public void removeException(String id); +/** + * @author tlenz + * + */ +public class AuthnRequestBuildException extends PVP2Exception { + + /** + * + */ + private static final long serialVersionUID = -1375451065455859354L; + + /** + * @param messageId + * @param parameters + */ + public AuthnRequestBuildException(String messageId, Object[] parameters) { + super(messageId, parameters); + } + + public AuthnRequestBuildException(String messageId, Object[] parameters, Throwable e) { + super(messageId, parameters, e); + } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/ServletInfo.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/AuthnResponseValidationException.java index 807f789ce..957f9af1d 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/ServletInfo.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/AuthnResponseValidationException.java @@ -1,4 +1,4 @@ -/******************************************************************************* +/* * Copyright 2014 Federal Chancellery Austria * MOA-ID has been developed in a cooperation between BRZ, the Federal * Chancellery Austria - ICT staff unit, and Graz University of Technology. @@ -19,35 +19,30 @@ * 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.egovernment.moa.id.moduls; - -import javax.servlet.http.HttpServlet; + */ +package at.gv.egovernment.moa.id.protocols.pvp2x.exceptions; +/** + * @author tlenz + * + */ +public class AuthnResponseValidationException extends PVP2Exception { -public class ServletInfo { - Class<? extends HttpServlet> servletClass; - String servletTarget; - ServletType type; - - public ServletInfo(Class<? extends HttpServlet> servletClass, - String servletTarget, ServletType type) { - super(); - this.servletClass = servletClass; - this.servletTarget = servletTarget; - this.type = type; - } + /** + * + */ + private static final long serialVersionUID = 8023812861029406575L; - public HttpServlet getServletInstance() - throws InstantiationException, IllegalAccessException { - return servletClass.newInstance(); + /** + * @param messageId + * @param parameters + */ + public AuthnResponseValidationException(String messageId, Object[] parameters) { + super(messageId, parameters); } - public String getTarget() { - return servletTarget; - } - - public ServletType getType() { - return type; + public AuthnResponseValidationException(String messageId, Object[] parameters, Throwable e) { + super(messageId, parameters, e); } + } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/InvalidAssertionConsumerServiceException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/InvalidAssertionConsumerServiceException.java index 94a4e8226..392569366 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/InvalidAssertionConsumerServiceException.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/InvalidAssertionConsumerServiceException.java @@ -34,6 +34,15 @@ public class InvalidAssertionConsumerServiceException extends PVP2Exception { /** * */ + public InvalidAssertionConsumerServiceException(String wrongURL) { + super("pvp2.23", new Object[]{wrongURL}); + this.statusCodeValue = StatusCode.REQUESTER_URI; + + } + + /** + * + */ private static final long serialVersionUID = 7861790149343943091L; } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/requestHandler/ArtifactResolution.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/requestHandler/ArtifactResolution.java deleted file mode 100644 index 7f6054f2d..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/requestHandler/ArtifactResolution.java +++ /dev/null @@ -1,82 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 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: - * http://www.osor.eu/eupl/ - * - * 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.egovernment.moa.id.protocols.pvp2x.requestHandler; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.joda.time.DateTime; -import org.opensaml.common.binding.artifact.SAMLArtifactMap.SAMLArtifactMapEntry; -import org.opensaml.saml2.core.ArtifactResolve; -import org.opensaml.saml2.core.ArtifactResponse; - -import at.gv.egovernment.moa.id.auth.exception.MOAIDException; -import at.gv.egovernment.moa.id.data.IAuthData; -import at.gv.egovernment.moa.id.data.SLOInformationInterface; -import at.gv.egovernment.moa.id.protocols.pvp2x.PVPAssertionStorage; -import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration; -import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessage; -import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; -import at.gv.egovernment.moa.id.protocols.pvp2x.binding.SoapBinding; -import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.RequestDeniedException; -import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; -import at.gv.egovernment.moa.logging.Logger; - -public class ArtifactResolution implements IRequestHandler { - - public boolean handleObject(InboundMessage obj) { - return (obj instanceof MOARequest && - ((MOARequest)obj).getSamlRequest() instanceof ArtifactResolve); - } - - public SLOInformationInterface process(PVPTargetConfiguration obj, HttpServletRequest req, - HttpServletResponse resp, IAuthData authData) throws MOAIDException { - if (!handleObject(obj.getRequest())) { - throw new MOAIDException("pvp2.13", null); - } - - ArtifactResolve artifactResolve = (ArtifactResolve) ((MOARequest)obj.getRequest()).getSamlRequest(); - String artifactID = artifactResolve.getArtifact().getArtifact(); - - PVPAssertionStorage pvpAssertion = PVPAssertionStorage.getInstance(); - - if (!pvpAssertion.contains(artifactID)) { - throw new RequestDeniedException(); - } else { - try { - SAMLArtifactMapEntry assertion = pvpAssertion.get(artifactID); - ArtifactResponse response = SAML2Utils - .createSAMLObject(ArtifactResponse.class); - response.setMessage(assertion.getSamlMessage()); - response.setIssueInstant(new DateTime()); - SoapBinding encoder = new SoapBinding(); - encoder.encodeRespone(req, resp, response, null, null); - } catch (Exception e) { - Logger.error("Failed to resolve artifact", e); - } - } - - return null; - } - -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/requestHandler/AuthnRequestHandler.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/requestHandler/AuthnRequestHandler.java deleted file mode 100644 index a31258784..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/requestHandler/AuthnRequestHandler.java +++ /dev/null @@ -1,127 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 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: - * http://www.osor.eu/eupl/ - * - * 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.egovernment.moa.id.protocols.pvp2x.requestHandler; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.joda.time.DateTime; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.core.Assertion; -import org.opensaml.saml2.core.AuthnRequest; -import org.opensaml.saml2.core.Response; -import org.opensaml.saml2.metadata.AssertionConsumerService; -import org.opensaml.saml2.metadata.EntityDescriptor; -import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.opensaml.xml.security.SecurityException; - -import at.gv.egovernment.moa.id.auth.exception.MOAIDException; -import at.gv.egovernment.moa.id.data.IAuthData; -import at.gv.egovernment.moa.id.data.SLOInformationImpl; -import at.gv.egovernment.moa.id.data.SLOInformationInterface; -import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; -import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration; -import at.gv.egovernment.moa.id.protocols.pvp2x.binding.ArtifactBinding; -import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder; -import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessage; -import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; -import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding; -import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding; -import at.gv.egovernment.moa.id.protocols.pvp2x.builder.AuthResponseBuilder; -import at.gv.egovernment.moa.id.protocols.pvp2x.builder.assertion.PVP2AssertionBuilder; -import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.BindingNotSupportedException; -import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; -import at.gv.egovernment.moa.logging.Logger; - -public class AuthnRequestHandler implements IRequestHandler, PVPConstants { - - public boolean handleObject(InboundMessage obj) { - - return (obj instanceof MOARequest && - ((MOARequest)obj).getSamlRequest() instanceof AuthnRequest); - } - - public SLOInformationInterface process(PVPTargetConfiguration obj, HttpServletRequest req, - HttpServletResponse resp, IAuthData authData) throws MOAIDException { - if (!handleObject(obj.getRequest())) { - throw new MOAIDException("pvp2.13", null); - } - - //get basic information - MOARequest moaRequest = (MOARequest) obj.getRequest(); - AuthnRequest authnRequest = (AuthnRequest) moaRequest.getSamlRequest(); - EntityDescriptor peerEntity = moaRequest.getEntityMetadata(); - - AssertionConsumerService consumerService = - SAML2Utils.createSAMLObject(AssertionConsumerService.class); - consumerService.setBinding(obj.getBinding()); - consumerService.setLocation(obj.getConsumerURL()); - - DateTime date = new DateTime(); - - SLOInformationImpl sloInformation = new SLOInformationImpl(); - - //build Assertion - Assertion assertion = PVP2AssertionBuilder.buildAssertion(authnRequest, authData, - peerEntity, date, consumerService, sloInformation); - - Response authResponse = AuthResponseBuilder.buildResponse(authnRequest, date, assertion); - - IEncoder binding = null; - - if (consumerService.getBinding().equals( - SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { - binding = new RedirectBinding(); - - } else if (consumerService.getBinding().equals( - SAMLConstants.SAML2_ARTIFACT_BINDING_URI)) { - // TODO: not supported YET!! - binding = new ArtifactBinding(); - - } else if (consumerService.getBinding().equals( - SAMLConstants.SAML2_POST_BINDING_URI)) { - binding = new PostBinding(); - - } - - if (binding == null) { - throw new BindingNotSupportedException(consumerService.getBinding()); - } - - try { - binding.encodeRespone(req, resp, authResponse, - consumerService.getLocation(), moaRequest.getRelayState()); - - return sloInformation; - - } catch (MessageEncodingException e) { - Logger.error("Message Encoding exception", e); - throw new MOAIDException("pvp2.01", null, e); - - } catch (SecurityException e) { - Logger.error("Security exception", e); - throw new MOAIDException("pvp2.01", null, e); - - } - } -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/requestHandler/RequestManager.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/requestHandler/RequestManager.java deleted file mode 100644 index b58b09f12..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/requestHandler/RequestManager.java +++ /dev/null @@ -1,73 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 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: - * http://www.osor.eu/eupl/ - * - * 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.egovernment.moa.id.protocols.pvp2x.requestHandler; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import at.gv.egovernment.moa.id.auth.exception.MOAIDException; -import at.gv.egovernment.moa.id.data.AuthenticationData; -import at.gv.egovernment.moa.id.data.IAuthData; -import at.gv.egovernment.moa.id.data.SLOInformationInterface; -import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration; -import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessage; -import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; -import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.SAMLRequestNotSupported; - -public class RequestManager { - - private static RequestManager instance = null; - - private List<IRequestHandler> handler; - - public static synchronized RequestManager getInstance() { - if(instance == null) { - instance = new RequestManager(); - } - return instance; - } - - private RequestManager() { - handler = new ArrayList<IRequestHandler>(); - handler.add(new AuthnRequestHandler()); - handler.add(new ArtifactResolution()); - } - - public SLOInformationInterface handle(PVPTargetConfiguration pvpRequest, HttpServletRequest req, HttpServletResponse resp, IAuthData authData) - throws SAMLRequestNotSupported, MOAIDException { - Iterator<IRequestHandler> it = handler.iterator(); - while(it.hasNext()) { - IRequestHandler handler = it.next(); - if(handler.handleObject(pvpRequest.getRequest())) { - return handler.process(pvpRequest, req, resp, authData); - } - } - - // not handled - throw new SAMLRequestNotSupported(); - } -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/signer/AbstractCredentialProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/signer/AbstractCredentialProvider.java new file mode 100644 index 000000000..e7df23d61 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/signer/AbstractCredentialProvider.java @@ -0,0 +1,186 @@ +/******************************************************************************* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.protocols.pvp2x.signer; + +import java.security.KeyStore; + +import org.opensaml.xml.security.credential.UsageType; +import org.opensaml.xml.security.x509.X509Credential; + +import at.gv.egovernment.moa.id.opemsaml.MOAKeyStoreX509CredentialAdapter; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.KeyStoreUtils; +import at.gv.egovernment.moa.util.MiscUtil; + +public abstract class AbstractCredentialProvider { + + private static KeyStore keyStore = null; + + /** + * Get a friendlyName for this keyStore implementation + * This friendlyName is used for logging + * + * @return keyStore friendlyName + */ + public abstract String getFriendlyName(); + + /** + * Get KeyStore + * + * @return URL to the keyStore + */ + public abstract String getKeyStoreFilePath(); + + /** + * Get keyStore password + * + * @return Password of the keyStore + */ + public abstract String getKeyStorePassword(); + + /** + * Get alias of key for metadata signing + * + * @return key alias + */ + public abstract String getMetadataKeyAlias(); + + /** + * Get password of key for metadata signing + * + * @return key password + */ + public abstract String getMetadataKeyPassword(); + + /** + * Get alias of key for request/response signing + * + * @return key alias + */ + public abstract String getSignatureKeyAlias(); + + /** + * Get password of key for request/response signing + * + * @return key password + */ + public abstract String getSignatureKeyPassword(); + + /** + * Get alias of key for IDP response encryption + * + * @return key alias + */ + public abstract String getEncryptionKeyAlias(); + + /** + * Get password of key for IDP response encryption + * + * @return key password + */ + public abstract String getEncryptionKeyPassword(); + + + public X509Credential getIDPMetaDataSigningCredential() + throws CredentialsNotAvailableException { + try { + + if (keyStore == null) + keyStore = KeyStoreUtils.loadKeyStore(getKeyStoreFilePath(), + getKeyStorePassword()); + + MOAKeyStoreX509CredentialAdapter credentials = new MOAKeyStoreX509CredentialAdapter( + keyStore, getMetadataKeyAlias(), getMetadataKeyPassword().toCharArray()); + + credentials.setUsageType(UsageType.SIGNING); + if (credentials.getPrivateKey() == null && credentials.getSecretKey() == null) { + Logger.error(getFriendlyName() + " Metadata Signing credentials is not found or contains no PrivateKey."); + throw new CredentialsNotAvailableException(getFriendlyName() + " Assertion Signing credentials (Alias: " + + getMetadataKeyAlias() + ") is not found or contains no PrivateKey.", null); + + } + return credentials; + } catch (Exception e) { + Logger.error("Failed to generate " + getFriendlyName() + " Metadata Signing credentials"); + e.printStackTrace(); + throw new CredentialsNotAvailableException(e.getMessage(), null); + } + } + + public X509Credential getIDPAssertionSigningCredential() + throws CredentialsNotAvailableException { + try { + if (keyStore == null) + keyStore = KeyStoreUtils.loadKeyStore(getKeyStoreFilePath(), + getKeyStorePassword()); + + MOAKeyStoreX509CredentialAdapter credentials = new MOAKeyStoreX509CredentialAdapter( + keyStore, getSignatureKeyAlias(), getSignatureKeyPassword().toCharArray()); + + credentials.setUsageType(UsageType.SIGNING); + if (credentials.getPrivateKey() == null && credentials.getSecretKey() == null) { + Logger.error(getFriendlyName() + " Assertion Signing credentials is not found or contains no PrivateKey."); + throw new CredentialsNotAvailableException(getFriendlyName() + " Assertion Signing credentials (Alias: " + + getSignatureKeyAlias() + ") is not found or contains no PrivateKey.", null); + + } + + return (X509Credential) credentials; + } catch (Exception e) { + Logger.error("Failed to generate " + getFriendlyName() + " Assertion Signing credentials"); + e.printStackTrace(); + throw new CredentialsNotAvailableException(e.getMessage(), null); + } + } + + public X509Credential getIDPAssertionEncryptionCredential() + throws CredentialsNotAvailableException { + try { + if (keyStore == null) + keyStore = KeyStoreUtils.loadKeyStore(getKeyStoreFilePath(), + getKeyStorePassword()); + + //if no encryption key is configured return null + if (MiscUtil.isEmpty(getEncryptionKeyAlias())) + return null; + + MOAKeyStoreX509CredentialAdapter credentials = new MOAKeyStoreX509CredentialAdapter( + keyStore, getEncryptionKeyAlias(), getEncryptionKeyPassword().toCharArray()); + + credentials.setUsageType(UsageType.ENCRYPTION); + + if (credentials.getPrivateKey() == null && credentials.getSecretKey() == null) { + Logger.error(getFriendlyName() + " Assertion Encryption credentials is not found or contains no PrivateKey."); + throw new CredentialsNotAvailableException(getFriendlyName() + " Assertion Encryption credentials (Alias: " + + getEncryptionKeyAlias() + ") is not found or contains no PrivateKey.", null); + + } + + return (X509Credential) credentials; + } catch (Exception e) { + Logger.error("Failed to generate " + getFriendlyName() + " Assertion Encryption credentials"); + e.printStackTrace(); + throw new CredentialsNotAvailableException(e.getMessage(), null); + } + } +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/signer/CredentialProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/signer/CredentialProvider.java deleted file mode 100644 index d76e6c2f1..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/signer/CredentialProvider.java +++ /dev/null @@ -1,198 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 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: - * http://www.osor.eu/eupl/ - * - * 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.egovernment.moa.id.protocols.pvp2x.signer; - -import java.security.KeyStore; -import java.security.PrivateKey; -import java.security.interfaces.RSAPrivateKey; - -import org.opensaml.xml.security.credential.Credential; -import org.opensaml.xml.security.credential.UsageType; -import org.opensaml.xml.security.x509.BasicX509Credential; -import org.opensaml.xml.security.x509.KeyStoreX509CredentialAdapter; -import org.opensaml.xml.security.x509.X509Credential; -import org.opensaml.xml.signature.Signature; -import org.opensaml.xml.signature.SignatureConstants; - -import at.gv.egovernment.moa.id.opemsaml.MOAKeyStoreX509CredentialAdapter; -import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration; -import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; -import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.KeyStoreUtils; -import at.gv.egovernment.moa.util.MiscUtil; - -public class CredentialProvider { - - private static KeyStore keyStore = null; - - public static X509Credential getIDPMetaDataSigningCredential() - throws CredentialsNotAvailableException { - PVPConfiguration config = PVPConfiguration.getInstance(); - try { - - if (keyStore == null) - keyStore = KeyStoreUtils.loadKeyStore(config.getIDPKeyStoreFilename(), - config.getIDPKeyStorePassword()); - - MOAKeyStoreX509CredentialAdapter credentials = new MOAKeyStoreX509CredentialAdapter( - keyStore, config.getIDPKeyAliasMetadata(), config - .getIDPKeyPasswordMetadata().toCharArray()); - - credentials.setUsageType(UsageType.SIGNING); - if (credentials.getPrivateKey() == null && credentials.getSecretKey() == null) { - Logger.error("IDP Metadata Signing credentials is not found or contains no PrivateKey."); - throw new CredentialsNotAvailableException("IDP Assertion Signing credentials (Alias: " - + config.getIDPKeyAliasMetadata() + ") is not found or contains no PrivateKey.", null); - - } - return credentials; - } catch (Exception e) { - Logger.error("Failed to generate IDP Metadata Signing credentials"); - e.printStackTrace(); - throw new CredentialsNotAvailableException(e.getMessage(), null); - } - } - - public static X509Credential getIDPAssertionSigningCredential() - throws CredentialsNotAvailableException { - PVPConfiguration config = PVPConfiguration.getInstance(); - try { - if (keyStore == null) - keyStore = KeyStoreUtils.loadKeyStore(config.getIDPKeyStoreFilename(), - config.getIDPKeyStorePassword()); - - MOAKeyStoreX509CredentialAdapter credentials = new MOAKeyStoreX509CredentialAdapter( - keyStore, config.getIDPKeyAliasAssertionSign(), config - .getIDPKeyPasswordAssertionSign().toCharArray()); - - credentials.setUsageType(UsageType.SIGNING); - if (credentials.getPrivateKey() == null && credentials.getSecretKey() == null) { - Logger.error("IDP Assertion Signing credentials is not found or contains no PrivateKey."); - throw new CredentialsNotAvailableException("IDP Assertion Signing credentials (Alias: " - + config.getIDPKeyAliasAssertionSign() + ") is not found or contains no PrivateKey.", null); - - } - - return (X509Credential) credentials; - } catch (Exception e) { - Logger.error("Failed to generate IDP Assertion Signing credentials"); - e.printStackTrace(); - throw new CredentialsNotAvailableException(e.getMessage(), null); - } - } - - public static X509Credential getIDPAssertionEncryptionCredential() - throws CredentialsNotAvailableException { - PVPConfiguration config = PVPConfiguration.getInstance(); - try { - if (keyStore == null) - keyStore = KeyStoreUtils.loadKeyStore(config.getIDPKeyStoreFilename(), - config.getIDPKeyStorePassword()); - - //if no encryption key is configured return null - if (MiscUtil.isEmpty(config.getIDPKeyAliasAssertionEncryption())) - return null; - - MOAKeyStoreX509CredentialAdapter credentials = new MOAKeyStoreX509CredentialAdapter( - keyStore, config.getIDPKeyAliasAssertionEncryption(), config - .getIDPKeyPasswordAssertionEncryption().toCharArray()); - - credentials.setUsageType(UsageType.ENCRYPTION); - - if (credentials.getPrivateKey() == null && credentials.getSecretKey() == null) { - Logger.error("IDP Assertion Encryption credentials is not found or contains no PrivateKey."); - throw new CredentialsNotAvailableException("IDP Assertion Encryption credentials (Alias: " - + config.getIDPKeyAliasAssertionEncryption() + ") is not found or contains no PrivateKey.", null); - - } - - return (X509Credential) credentials; - } catch (Exception e) { - Logger.error("Failed to generate IDP Assertion Encryption credentials"); - e.printStackTrace(); - throw new CredentialsNotAvailableException(e.getMessage(), null); - } - } - - public static Signature getIDPSignature(Credential credentials) { - - PrivateKey privatekey = credentials.getPrivateKey(); - - Signature signer = SAML2Utils.createSAMLObject(Signature.class); - - if (privatekey instanceof RSAPrivateKey) { - signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256); - - } else if (privatekey instanceof iaik.security.ecc.ecdsa.ECPrivateKey) { - signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA1); - - } else { - Logger.warn("Could NOT evaluate the Private-Key type from PVP credential."); - - } - - signer.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); - signer.setSigningCredential(credentials); - return signer; - - } - - public static Credential getSPTrustedCredential(String entityID) - throws CredentialsNotAvailableException { - - iaik.x509.X509Certificate cert = PVPConfiguration.getInstance() - .getTrustEntityCertificate(entityID); - - if (cert == null) { - throw new CredentialsNotAvailableException("ServiceProvider Certificate can not be loaded from Database", null); - } - - BasicX509Credential credential = new BasicX509Credential(); - credential.setEntityId(entityID); - credential.setUsageType(UsageType.SIGNING); - credential.setPublicKey(cert.getPublicKey()); - - return credential; - } - /* - * public static Credential getTrustedCredential() throws - * CredentialsNotAvailableException { String filename = - * PVPConfiguration.getInstance().getTrustEntityCertificate("sp.crt"); - * - * iaik.x509.X509Certificate cert; try { cert = new X509Certificate(new - * FileInputStream(new File(filename))); } catch (CertificateException e) { - * e.printStackTrace(); throw new - * CredentialsNotAvailableException(e.getMessage(), null); } catch - * (FileNotFoundException e) { e.printStackTrace(); throw new - * CredentialsNotAvailableException(e.getMessage(), null); } catch - * (IOException e) { e.printStackTrace(); throw new - * CredentialsNotAvailableException(e.getMessage(), null); } - * - * BasicX509Credential credential = new BasicX509Credential(); - * credential.setEntityId("sp.crt"); - * credential.setUsageType(UsageType.SIGNING); - * credential.setPublicKey(cert.getPublicKey()); - * - * return credential; } - */ -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/signer/IDPCredentialProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/signer/IDPCredentialProvider.java new file mode 100644 index 000000000..8fb4ec3cf --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/signer/IDPCredentialProvider.java @@ -0,0 +1,150 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.protocols.pvp2x.signer; + +import java.util.Properties; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; +import at.gv.egovernment.moa.util.FileUtils; + +@Service("IDPCredentialProvider") +public class IDPCredentialProvider extends AbstractCredentialProvider { + public static final String IDP_JAVAKEYSTORE = "idp.ks.file"; + public static final String IDP_KS_PASS = "idp.ks.kspassword"; + + public static final String IDP_KEYALIASMETADATA = "idp.ks.metadata.alias"; + public static final String IDP_KEY_PASSMETADATA = "idp.ks.metadata.keypassword"; + + public static final String IDP_KEYALIASASSERTION = "idp.ks.assertion.sign.alias"; + public static final String IDP_KEY_PASSASSERTION = "idp.ks.assertion.sign.keypassword"; + + public static final String IDP_KEYALIASENCRYTPION = "sp.ks.assertion.encryption.alias"; + public static final String IDP_KEY_PASSENCRYTPION = "sp.ks.assertion.encryption.keypassword"; + + + private @Autowired AuthConfiguration authConfig; + private Properties props = null; + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#getKeyStoreFilePath() + */ + @Override + public String getKeyStoreFilePath() { + if (props == null) + props = authConfig.getGeneralPVP2ProperiesConfig(); + + return FileUtils.makeAbsoluteURL( + props.getProperty(IDP_JAVAKEYSTORE), + authConfig.getRootConfigFileDir()); + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#getKeyStorePassword() + */ + @Override + public String getKeyStorePassword() { + if (props == null) + props = authConfig.getGeneralPVP2ProperiesConfig(); + + return props.getProperty(IDP_KS_PASS).trim(); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#getMetadataKeyAlias() + */ + @Override + public String getMetadataKeyAlias() { + if (props == null) + props = authConfig.getGeneralPVP2ProperiesConfig(); + + return props.getProperty(IDP_KEYALIASMETADATA).trim(); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#getMetadataKeyPassword() + */ + @Override + public String getMetadataKeyPassword() { + if (props == null) + props = authConfig.getGeneralPVP2ProperiesConfig(); + + return props.getProperty(IDP_KEY_PASSMETADATA).trim(); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#getSignatureKeyAlias() + */ + @Override + public String getSignatureKeyAlias() { + if (props == null) + props = authConfig.getGeneralPVP2ProperiesConfig(); + + return props.getProperty(IDP_KEYALIASASSERTION).trim(); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#getSignatureKeyPassword() + */ + @Override + public String getSignatureKeyPassword() { + if (props == null) + props = authConfig.getGeneralPVP2ProperiesConfig(); + + return props.getProperty(IDP_KEY_PASSASSERTION).trim(); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#getEncryptionKeyAlias() + */ + @Override + public String getEncryptionKeyAlias() { + if (props == null) + props = authConfig.getGeneralPVP2ProperiesConfig(); + + return props.getProperty(IDP_KEYALIASENCRYTPION).trim(); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#getEncryptionKeyPassword() + */ + @Override + public String getEncryptionKeyPassword() { + if (props == null) + props = authConfig.getGeneralPVP2ProperiesConfig(); + + return props.getProperty(IDP_KEYALIASENCRYTPION).trim(); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.signer.AbstractCredentialProvider#getCredentialName() + */ + @Override + public String getFriendlyName() { + return "IDP"; + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/MOASAMLSOAPClient.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/MOASAMLSOAPClient.java index 4d12c38da..75ef7e5a1 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/MOASAMLSOAPClient.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/MOASAMLSOAPClient.java @@ -57,6 +57,15 @@ public class MOASAMLSOAPClient { BasicSOAPMessageContext soapContext = new BasicSOAPMessageContext(); soapContext.setOutboundMessage(soapRequest); + + //set security policy context +// BasicSecurityPolicy policy = new BasicSecurityPolicy(); +// policy.getPolicyRules().add( +// new MOAPVPSignedRequestPolicyRule( +// TrustEngineFactory.getSignatureKnownKeysTrustEngine(), +// SPSSODescriptor.DEFAULT_ELEMENT_NAME)); +// SecurityPolicyResolver secResolver = new StaticSecurityPolicyResolver(policy); +// soapContext.setSecurityPolicyResolver(secResolver); HttpClientBuilder clientBuilder = new HttpClientBuilder(); if (destination.startsWith("https")) { diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/validation/AbstractRequestSignedSecurityPolicyRule.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/validation/AbstractRequestSignedSecurityPolicyRule.java new file mode 100644 index 000000000..f62410656 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/validation/AbstractRequestSignedSecurityPolicyRule.java @@ -0,0 +1,187 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.protocols.pvp2x.validation; + +import javax.xml.namespace.QName; +import javax.xml.transform.dom.DOMSource; +import javax.xml.validation.Schema; +import javax.xml.validation.Validator; + +import org.opensaml.common.SignableSAMLObject; +import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.common.xml.SAMLSchemaBuilder; +import org.opensaml.security.MetadataCriteria; +import org.opensaml.security.SAMLSignatureProfileValidator; +import org.opensaml.ws.message.MessageContext; +import org.opensaml.ws.security.SecurityPolicyException; +import org.opensaml.ws.security.SecurityPolicyRule; +import org.opensaml.xml.XMLObject; +import org.opensaml.xml.security.CriteriaSet; +import org.opensaml.xml.security.credential.UsageType; +import org.opensaml.xml.security.criteria.EntityIDCriteria; +import org.opensaml.xml.security.criteria.UsageCriteria; +import org.opensaml.xml.signature.SignatureTrustEngine; +import org.opensaml.xml.validation.ValidationException; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.SchemaValidationException; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; + +/** + * @author tlenz + * + */ +public abstract class AbstractRequestSignedSecurityPolicyRule implements SecurityPolicyRule { + + private SignatureTrustEngine trustEngine = null; + private QName peerEntityRole = null; + /** + * @param peerEntityRole + * + */ + public AbstractRequestSignedSecurityPolicyRule(SignatureTrustEngine trustEngine, QName peerEntityRole) { + this.trustEngine = trustEngine; + this.peerEntityRole = peerEntityRole; + + } + + + /** + * Reload the PVP metadata for a given entity + * + * @param entityID for which the metadata should be refreshed. + * @return true if the refresh was successful, otherwise false + */ + protected abstract boolean refreshMetadataProvider(String entityID); + + + protected abstract SignableSAMLObject getSignedSAMLObject(XMLObject inboundData); + + /* (non-Javadoc) + * @see org.opensaml.ws.security.SecurityPolicyRule#evaluate(org.opensaml.ws.message.MessageContext) + */ + @Override + public void evaluate(MessageContext context) throws SecurityPolicyException { + try { + verifySignature(context); + + } catch (SecurityPolicyException e) { + if (MiscUtil.isEmpty(context.getInboundMessageIssuer())) { + throw e; + + } + Logger.debug("PVP2X message validation FAILED. Reload metadata for entityID: " + context.getInboundMessageIssuer()); + if (!refreshMetadataProvider(context.getInboundMessageIssuer())) + throw e; + + else { + Logger.trace("PVP2X metadata reload finished. Check validate message again."); + verifySignature(context); + + } + Logger.trace("Second PVP2X message validation finished"); + + } + + + } + + private void verifySignature(MessageContext context) throws SecurityPolicyException { + SignableSAMLObject samlObj = getSignedSAMLObject(context.getInboundMessage()); + if (samlObj != null && samlObj.getSignature() != null) { + + SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator(); + try { + profileValidator.validate(samlObj.getSignature()); + performSchemaValidation(samlObj.getDOM()); + + } catch (ValidationException e) { + Logger.warn("Signature is not conform to SAML signature profile", e); + throw new SecurityPolicyException("Signature is not conform to SAML signature profile"); + + } catch (SchemaValidationException e) { + Logger.warn("Signature is not conform to SAML signature profile", e); + throw new SecurityPolicyException("Signature is not conform to SAML signature profile"); + + } + + + + CriteriaSet criteriaSet = new CriteriaSet(); + criteriaSet.add( new EntityIDCriteria(context.getInboundMessageIssuer()) ); + criteriaSet.add( new MetadataCriteria(peerEntityRole, SAMLConstants.SAML20P_NS) ); + criteriaSet.add( new UsageCriteria(UsageType.SIGNING) ); + + try { + if (!trustEngine.validate(samlObj.getSignature(), criteriaSet)) { + throw new SecurityPolicyException("Signature validation FAILED."); + + } + Logger.debug("PVP AuthnRequest signature valid."); + + } catch (org.opensaml.xml.security.SecurityException e) { + Logger.info("PVP2x message signature validation FAILED. Message:" + e.getMessage()); + throw new SecurityPolicyException("Signature validation FAILED."); + + } + + } else { + throw new SecurityPolicyException("Request is not signed."); + + } + + } + + private void performSchemaValidation(Element source) throws SchemaValidationException { + + String err = null; + try { + Schema test = SAMLSchemaBuilder.getSAML11Schema(); + Validator val = test.newValidator(); + val.validate(new DOMSource(source)); + Logger.debug("Schema validation check done OK"); + return; + + } catch (SAXException e) { + err = e.getMessage(); + if (Logger.isDebugEnabled() || Logger.isTraceEnabled()) + Logger.warn("Schema validation FAILED with exception:", e); + else + Logger.warn("Schema validation FAILED with message: "+ e.getMessage()); + + } catch (Exception e) { + err = e.getMessage(); + if (Logger.isDebugEnabled() || Logger.isTraceEnabled()) + Logger.warn("Schema validation FAILED with exception:", e); + else + Logger.warn("Schema validation FAILED with message: "+ e.getMessage()); + + } + + throw new SchemaValidationException("pvp2.22", new Object[]{err}); + + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/validation/MOAPVPSignedRequestPolicyRule.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/validation/MOAPVPSignedRequestPolicyRule.java new file mode 100644 index 000000000..932f3b818 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/validation/MOAPVPSignedRequestPolicyRule.java @@ -0,0 +1,70 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.protocols.pvp2x.validation; + +import javax.xml.namespace.QName; + +import org.opensaml.common.SignableSAMLObject; +import org.opensaml.xml.XMLObject; +import org.opensaml.xml.signature.SignatureTrustEngine; + +import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider; + +/** + * @author tlenz + * + */ +public class MOAPVPSignedRequestPolicyRule extends + AbstractRequestSignedSecurityPolicyRule { + + /** + * @param trustEngine + * @param peerEntityRole + */ + public MOAPVPSignedRequestPolicyRule(SignatureTrustEngine trustEngine, + QName peerEntityRole) { + super(trustEngine, peerEntityRole); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.validation.AbstractRequestSignedSecurityPolicyRule#refreshMetadataProvider(java.lang.String) + */ + @Override + protected boolean refreshMetadataProvider(String entityID) { + return MOAMetadataProvider.getInstance().refreshMetadataProvider(entityID); + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.validation.AbstractRequestSignedSecurityPolicyRule#getSignedSAMLObject(org.opensaml.xml.XMLObject) + */ + @Override + protected SignableSAMLObject getSignedSAMLObject(XMLObject inboundData) { + if (inboundData instanceof SignableSAMLObject) + return (SignableSAMLObject) inboundData; + + else + return null; + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/EntityVerifier.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/EntityVerifier.java index 69c760f19..4650327b4 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/EntityVerifier.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/EntityVerifier.java @@ -29,6 +29,8 @@ import org.opensaml.saml2.metadata.EntitiesDescriptor; import org.opensaml.saml2.metadata.EntityDescriptor; import org.opensaml.security.SAMLSignatureProfileValidator; import org.opensaml.xml.security.credential.Credential; +import org.opensaml.xml.security.credential.UsageType; +import org.opensaml.xml.security.x509.BasicX509Credential; import org.opensaml.xml.signature.SignatureValidator; import org.opensaml.xml.validation.ValidationException; @@ -37,9 +39,10 @@ import at.gv.egovernment.moa.id.commons.config.MOAIDConfigurationConstants; import at.gv.egovernment.moa.id.config.ConfigurationException; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NoCredentialsException; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.SAMLRequestNotSignedException; -import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialProvider; +import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialsNotAvailableException; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.Base64Utils; import at.gv.egovernment.moa.util.MiscUtil; @@ -83,8 +86,7 @@ public class EntityVerifier { throw new SAMLRequestNotSignedException(e); } - Credential credential = CredentialProvider - .getSPTrustedCredential(entityDescriptor.getEntityID()); + Credential credential = getSPTrustedCredential(entityDescriptor.getEntityID()); if (credential == null) { throw new NoCredentialsException(entityDescriptor.getEntityID()); } @@ -171,8 +173,7 @@ public class EntityVerifier { + " entryID is used to select the certificate to perform Metadata verification."); } - Credential credential = CredentialProvider - .getSPTrustedCredential(entities.get(0).getEntityID()); + Credential credential = getSPTrustedCredential(entities.get(0).getEntityID()); if (credential == null) { throw new NoCredentialsException("moaID IDP"); @@ -188,5 +189,23 @@ public class EntityVerifier { } } } + + public static Credential getSPTrustedCredential(String entityID) + throws CredentialsNotAvailableException { + + iaik.x509.X509Certificate cert = PVPConfiguration.getInstance() + .getTrustEntityCertificate(entityID); + + if (cert == null) { + throw new CredentialsNotAvailableException("ServiceProvider Certificate can not be loaded from Database", null); + } + + BasicX509Credential credential = new BasicX509Credential(); + credential.setEntityId(entityID); + credential.setUsageType(UsageType.SIGNING); + credential.setPublicKey(cert.getPublicKey()); + + return credential; + } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java index 70b778c49..5e44c9057 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java @@ -25,6 +25,7 @@ package at.gv.egovernment.moa.id.protocols.pvp2x.verification; import java.util.ArrayList; import java.util.List; +import javax.xml.namespace.QName; import javax.xml.transform.dom.DOMSource; import javax.xml.validation.Schema; import javax.xml.validation.Validator; @@ -49,32 +50,34 @@ import org.opensaml.xml.encryption.DecryptionException; import org.opensaml.xml.encryption.InlineEncryptedKeyResolver; import org.opensaml.xml.encryption.SimpleRetrievalMethodEncryptedKeyResolver; import org.opensaml.xml.security.CriteriaSet; +import org.opensaml.xml.security.credential.Credential; import org.opensaml.xml.security.credential.UsageType; import org.opensaml.xml.security.criteria.EntityIDCriteria; import org.opensaml.xml.security.criteria.UsageCriteria; import org.opensaml.xml.security.keyinfo.StaticKeyInfoCredentialResolver; -import org.opensaml.xml.security.x509.X509Credential; import org.opensaml.xml.signature.SignatureTrustEngine; import org.opensaml.xml.validation.ValidationException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import org.w3c.dom.Element; import org.xml.sax.SAXException; import at.gv.egovernment.moa.id.auth.exception.InvalidProtocolRequestException; import at.gv.egovernment.moa.id.config.ConfigurationException; -import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration; +import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AssertionValidationExeption; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.SchemaValidationException; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessage; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOAResponse; import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider; -import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialProvider; -import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialsNotAvailableException; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; +@Service("SAMLVerificationEngine") public class SAMLVerificationEngine { - + + @Autowired AuthConfiguration authConfig; public void verify(InboundMessage msg, SignatureTrustEngine sigTrustEngine ) throws org.opensaml.xml.security.SecurityException, Exception { try { @@ -83,7 +86,7 @@ public class SAMLVerificationEngine { verifyRequest(((RequestAbstractType)((MOARequest)msg).getSamlRequest()), sigTrustEngine); else - verifyResponse(((MOAResponse)msg).getResponse(), sigTrustEngine); + verifyIDPResponse(((MOAResponse)msg).getResponse(), sigTrustEngine); } catch (InvalidProtocolRequestException e) { if (MiscUtil.isEmpty(msg.getEntityID())) { @@ -102,15 +105,24 @@ public class SAMLVerificationEngine { verifyRequest(((RequestAbstractType)((MOARequest)msg).getSamlRequest()), sigTrustEngine); else - verifyResponse(((MOAResponse)msg).getResponse(), sigTrustEngine); + verifyIDPResponse(((MOAResponse)msg).getResponse(), sigTrustEngine); } Logger.trace("Second PVP2X message validation finished"); } } + public void verifyIDPResponse(StatusResponseType samlObj, SignatureTrustEngine sigTrustEngine) throws InvalidProtocolRequestException{ + verifyResponse(samlObj, sigTrustEngine, IDPSSODescriptor.DEFAULT_ELEMENT_NAME); + + } - public void verifyResponse(StatusResponseType samlObj, SignatureTrustEngine sigTrustEngine ) throws InvalidProtocolRequestException{ + public void verifySLOResponse(StatusResponseType samlObj, SignatureTrustEngine sigTrustEngine ) throws InvalidProtocolRequestException { + verifyResponse(samlObj, sigTrustEngine, SPSSODescriptor.DEFAULT_ELEMENT_NAME); + + } + + private void verifyResponse(StatusResponseType samlObj, SignatureTrustEngine sigTrustEngine, QName defaultElementName) throws InvalidProtocolRequestException{ SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator(); try { profileValidator.validate(samlObj.getSignature()); @@ -127,7 +139,7 @@ public class SAMLVerificationEngine { CriteriaSet criteriaSet = new CriteriaSet(); criteriaSet.add( new EntityIDCriteria(samlObj.getIssuer().getValue()) ); - criteriaSet.add( new MetadataCriteria(IDPSSODescriptor.DEFAULT_ELEMENT_NAME, SAMLConstants.SAML20P_NS) ); + criteriaSet.add( new MetadataCriteria(defaultElementName, SAMLConstants.SAML20P_NS) ); criteriaSet.add( new UsageCriteria(UsageType.SIGNING) ); try { @@ -170,15 +182,25 @@ public class SAMLVerificationEngine { } } - public static void validateAssertion(Response samlResp, boolean validateDestination) throws AssertionValidationExeption { + public void validateAssertion(Response samlResp, boolean validateDestination, Credential assertionDecryption) throws AssertionValidationExeption { try { if (samlResp.getStatus().getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) { List<org.opensaml.saml2.core.Assertion> saml2assertions = new ArrayList<org.opensaml.saml2.core.Assertion>(); - if (validateDestination && !samlResp.getDestination().startsWith( - PVPConfiguration.getInstance().getIDPPublicPath())) { + //validate destination URL + List<String> allowedPublicURLPrefix = authConfig.getPublicURLPrefix(); + boolean isValidDestination = false; + for (String allowedPreFix : allowedPublicURLPrefix) { + if (validateDestination && samlResp.getDestination().startsWith( + allowedPreFix)) { + isValidDestination = true; + break; + + } + } + if (!isValidDestination && validateDestination) { Logger.warn("PVP 2.1 assertion destination does not match to IDP URL"); - throw new AssertionValidationExeption("PVP 2.1 assertion destination does not match to IDP URL", null); + throw new AssertionValidationExeption("PVP 2.1 assertion destination does not match to IDP URL", null); } @@ -188,11 +210,9 @@ public class SAMLVerificationEngine { //decrypt assertions Logger.debug("Found encryped assertion. Start decryption ..."); - - X509Credential authDecCredential = CredentialProvider.getIDPAssertionEncryptionCredential(); - + StaticKeyInfoCredentialResolver skicr = - new StaticKeyInfoCredentialResolver(authDecCredential); + new StaticKeyInfoCredentialResolver(assertionDecryption); ChainingEncryptedKeyResolver encryptedKeyResolver = new ChainingEncryptedKeyResolver(); encryptedKeyResolver.getResolverChain().add( new InlineEncryptedKeyResolver() ); @@ -256,10 +276,6 @@ public class SAMLVerificationEngine { + samlResp.getStatus().getStatusCode().getValue(), null); } - } catch (CredentialsNotAvailableException e) { - Logger.warn("Assertion decrypt FAILED - No Credentials", e); - throw new AssertionValidationExeption("Assertion decrypt FAILED - No Credentials", null, e); - } catch (DecryptionException e) { Logger.warn("Assertion decrypt FAILED.", e); throw new AssertionValidationExeption("Assertion decrypt FAILED.", null, e); @@ -269,7 +285,7 @@ public class SAMLVerificationEngine { } } - private static void performSchemaValidation(Element source) throws SchemaValidationException { + private void performSchemaValidation(Element source) throws SchemaValidationException { String err = null; try { diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/DBAuthenticationSessionStoreage.java index d1582b883..cfdb4426b 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/DBAuthenticationSessionStoreage.java @@ -32,6 +32,8 @@ import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import com.fasterxml.jackson.core.JsonProcessingException; @@ -46,27 +48,29 @@ import at.gv.egovernment.moa.id.commons.db.dao.session.OASessionStore; import at.gv.egovernment.moa.id.commons.db.dao.session.OldSSOSessionIDStore; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; import at.gv.egovernment.moa.id.commons.utils.JsonMapper; -import at.gv.egovernment.moa.id.config.ConfigurationException; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; +import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; import at.gv.egovernment.moa.id.data.EncryptedData; import at.gv.egovernment.moa.id.data.SLOInformationInterface; import at.gv.egovernment.moa.id.moduls.IRequest; -import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStoreDAOImpl; +import at.gv.egovernment.moa.id.moduls.RequestImpl; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AssertionAttributeExtractorExeption; +import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOAResponse; import at.gv.egovernment.moa.id.protocols.pvp2x.utils.AssertionAttributeExtractor; import at.gv.egovernment.moa.id.util.Random; import at.gv.egovernment.moa.id.util.SessionEncrytionUtil; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; -public class AuthenticationSessionStoreage { - - //private static HashMap<String, AuthenticationSession> sessionStore = new HashMap<String, AuthenticationSession>(); +@Service("AuthenticationSessionStoreage") +public class DBAuthenticationSessionStoreage implements IAuthenticationSessionStoreage{ + @Autowired AuthConfiguration authConfig; + private static JsonMapper mapper = new JsonMapper(); - public static boolean isAuthenticated(String moaSessionID) { + @Override + public boolean isAuthenticated(String moaSessionID) { AuthenticatedSessionStore session; @@ -79,7 +83,8 @@ public class AuthenticationSessionStoreage { } } - public static AuthenticationSession createSession(IRequest target) throws MOADatabaseException, BuildException { + @Override + public AuthenticationSession createSession(IRequest target) throws MOADatabaseException, BuildException { String id = Random.nextRandom(); try { AuthenticatedSessionStore dbsession = new AuthenticatedSessionStore(); @@ -95,7 +100,7 @@ public class AuthenticationSessionStoreage { //set additional session informations AuthenticationSessionExtensions sessionExt = new AuthenticationSessionExtensions(); - sessionExt.setUniqueSessionId(target.getSessionIdentifier()); + sessionExt.setUniqueSessionId(target.getUniqueSessionIdentifier()); dbsession.setAdditionalInformation(mapper.serialize(sessionExt)); AuthenticationSession session = new AuthenticationSession(id, now); @@ -119,7 +124,11 @@ public class AuthenticationSessionStoreage { } - public static AuthenticationSession getSession(String sessionID) throws MOADatabaseException { + @Override + public AuthenticationSession getSession(String sessionID) throws MOADatabaseException { + + if (MiscUtil.isEmpty(sessionID)) + return null; try { AuthenticatedSessionStore dbsession = searchInDatabase(sessionID, true); @@ -127,7 +136,7 @@ public class AuthenticationSessionStoreage { } catch (MOADatabaseException e) { Logger.info("No MOA Session with id: " + sessionID); - throw new MOADatabaseException("No MOA Session with id: " + sessionID); + return null; } catch (Throwable e) { Logger.warn("MOASession deserialization-exception by using MOASessionID=" + sessionID, e); @@ -135,7 +144,8 @@ public class AuthenticationSessionStoreage { } } - public static AuthenticationSessionExtensions getAuthenticationSessionExtensions(String sessionID) throws MOADatabaseException { + @Override + public AuthenticationSessionExtensions getAuthenticationSessionExtensions(String sessionID) throws MOADatabaseException { AuthenticatedSessionStore dbsession = searchInDatabase(sessionID, true); if (MiscUtil.isNotEmpty(dbsession.getAdditionalInformation())) { @@ -151,7 +161,8 @@ public class AuthenticationSessionStoreage { } - public static void setAuthenticationSessionExtensions(String sessionID, AuthenticationSessionExtensions sessionExtensions) throws MOADatabaseException { + @Override + public void setAuthenticationSessionExtensions(String sessionID, AuthenticationSessionExtensions sessionExtensions) throws MOADatabaseException { try { AuthenticatedSessionStore dbsession = searchInDatabase(sessionID, true); @@ -174,18 +185,11 @@ public class AuthenticationSessionStoreage { } - public static void storeSession(AuthenticationSession session) throws MOADatabaseException, BuildException { - storeSession(session, null); - } - - public static void storeSession(AuthenticationSession session, String pendingRequestID) throws MOADatabaseException, BuildException { - + @Override + public void storeSession(AuthenticationSession session) throws MOADatabaseException, BuildException { try { AuthenticatedSessionStore dbsession = searchInDatabase(session.getSessionID(), true); - - if (MiscUtil.isNotEmpty(pendingRequestID)) - dbsession.setPendingRequestID(pendingRequestID); - + encryptSession(session, dbsession); //set Timestamp in this state, because automated timestamp generation is buggy in Hibernate 4.2.1 @@ -198,10 +202,11 @@ public class AuthenticationSessionStoreage { } catch (MOADatabaseException e) { Logger.warn("MOASession could not be stored."); throw new MOADatabaseException(e); - } + } } - public static void destroySession(String moaSessionID) throws MOADatabaseException { + @Override + public void destroySession(String moaSessionID) throws MOADatabaseException { Session session = MOASessionDBUtils.getCurrentSession(); @@ -238,52 +243,47 @@ public class AuthenticationSessionStoreage { } - public static String changeSessionID(AuthenticationSession session, String newSessionID) throws BuildException, AuthenticationException { - try { - AuthenticatedSessionStore dbsession = searchInDatabase(session.getSessionID(), true); + @Override + public String changeSessionID(AuthenticationSession session, String newSessionID) throws BuildException, MOADatabaseException { - - - Logger.debug("Change SessionID from " + session.getSessionID() - + "to " + newSessionID); - - session.setSessionID(newSessionID); - encryptSession(session, dbsession); - - dbsession.setSessionid(newSessionID); - dbsession.setAuthenticated(session.isAuthenticated()); - - //set Timestamp in this state, because automated timestamp generation is buggy in Hibernate 4.2.1 - dbsession.setUpdated(new Date()); - - MOASessionDBUtils.saveOrUpdate(dbsession); - - Logger.trace("Change SessionID complete."); - - return newSessionID; - - } catch (MOADatabaseException e) { - throw new AuthenticationException("TODO!", null); - } + AuthenticatedSessionStore dbsession = searchInDatabase(session.getSessionID(), true); + + Logger.debug("Change SessionID from " + session.getSessionID() + + "to " + newSessionID); + + session.setSessionID(newSessionID); + encryptSession(session, dbsession); + + dbsession.setSessionid(newSessionID); + dbsession.setAuthenticated(session.isAuthenticated()); + + //set Timestamp in this state, because automated timestamp generation is buggy in Hibernate 4.2.1 + dbsession.setUpdated(new Date()); + MOASessionDBUtils.saveOrUpdate(dbsession); + Logger.trace("Change SessionID complete."); + return newSessionID; + } - public static String changeSessionID(AuthenticationSession session) - throws AuthenticationException, BuildException { + @Override + public String changeSessionID(AuthenticationSession session) + throws BuildException, MOADatabaseException { String id = Random.nextRandom(); return changeSessionID(session, id); } - - public static void setAuthenticated(String moaSessionID, boolean value) { + + @Override + public void setAuthenticated(String moaSessionID, boolean isAuthenticated) { AuthenticatedSessionStore session; try { session = searchInDatabase(moaSessionID, true); - session.setAuthenticated(value); + session.setAuthenticated(isAuthenticated); MOASessionDBUtils.saveOrUpdate(session); @@ -292,7 +292,8 @@ public class AuthenticationSessionStoreage { } } - public static String getMOASessionSSOID(String SSOSessionID) { + @Override + public String getMOASessionSSOID(String SSOSessionID) { MiscUtil.assertNotNull(SSOSessionID, "SSOsessionID"); Logger.trace("Get authenticated session with SSOID " + SSOSessionID + " from database."); Session session = MOASessionDBUtils.getCurrentSession(); @@ -330,7 +331,8 @@ public class AuthenticationSessionStoreage { } } - public static boolean isSSOSession(String sessionID) throws MOADatabaseException { + @Override + public boolean isSSOSession(String sessionID) throws MOADatabaseException { try { AuthenticatedSessionStore dbsession = searchInDatabase(sessionID, true); return dbsession.isSSOSession(); @@ -341,7 +343,10 @@ public class AuthenticationSessionStoreage { } } - public static AuthenticatedSessionStore isValidSessionWithSSOID(String SSOId, String moaSessionId) { + @Override + public AuthenticatedSessionStore isValidSessionWithSSOID(String SSOId) { + + //TODO: is this method really needed?? MiscUtil.assertNotNull(SSOId, "SSOSessionID"); Logger.trace("Get authenticated session with SSOID " + SSOId + " from database."); Session session = MOASessionDBUtils.getCurrentSession(); @@ -376,8 +381,9 @@ public class AuthenticationSessionStoreage { } } - public static void addSSOInformation(String moaSessionID, String SSOSessionID, - SLOInformationInterface SLOInfo, String OAUrl) throws AuthenticationException { + @Override + public void addSSOInformation(String moaSessionID, String SSOSessionID, + SLOInformationInterface SLOInfo, IRequest protocolRequest) throws AuthenticationException { AuthenticatedSessionStore dbsession; Transaction tx = null; @@ -412,7 +418,7 @@ public class AuthenticationSessionStoreage { //check if OA already has an active OA session if (dbsession.getActiveOAsessions() != null) { for (OASessionStore el : dbsession.getActiveOAsessions()) { - if (el.getOaurlprefix().equals(OAUrl)) + if (el.getOaurlprefix().equals(protocolRequest.getOAURL())) activeOA = el; } } @@ -421,7 +427,7 @@ public class AuthenticationSessionStoreage { activeOA = new OASessionStore(); //set active OA applications - activeOA.setOaurlprefix(OAUrl); + activeOA.setOaurlprefix(protocolRequest.getOAURL()); activeOA.setMoasession(dbsession); activeOA.setCreated(new Date()); @@ -432,6 +438,7 @@ public class AuthenticationSessionStoreage { activeOA.setUserNameIDFormat(SLOInfo.getUserNameIDFormat()); activeOA.setProtocolType(SLOInfo.getProtocolType()); activeOA.setAttributeQueryUsed(false); + activeOA.setAuthURL(protocolRequest.getAuthURL()); } @@ -463,10 +470,10 @@ public class AuthenticationSessionStoreage { tx.commit(); if (SLOInfo != null) - Logger.info("Add SSO-Session login information for OA: " + OAUrl + Logger.info("Add SSO-Session login information for OA: " + protocolRequest.getOAURL() + " and AssertionID: " + SLOInfo.getSessionIndex()); else - Logger.info("Add SSO-Session login information for OA: " + OAUrl); + Logger.info("Add SSO-Session login information for OA: " + protocolRequest.getOAURL()); } @@ -481,7 +488,8 @@ public class AuthenticationSessionStoreage { } } - public static List<OASessionStore> getAllActiveOAFromMOASession(AuthenticationSession moaSession) { + @Override + public List<OASessionStore> getAllActiveOAFromMOASession(AuthenticationSession moaSession) { MiscUtil.assertNotNull(moaSession, "MOASession"); Session session = null; @@ -512,7 +520,8 @@ public class AuthenticationSessionStoreage { return null; } - public static List<InterfederationSessionStore> getAllActiveIDPsFromMOASession(AuthenticationSession moaSession) { + @Override + public List<InterfederationSessionStore> getAllActiveIDPsFromMOASession(AuthenticationSession moaSession) { MiscUtil.assertNotNull(moaSession, "MOASession"); Session session = null; try { @@ -541,7 +550,8 @@ public class AuthenticationSessionStoreage { return null; } - public static AuthenticationSession searchMOASessionWithNameIDandOAID(String oaID, String userNameID) { + @Override + public AuthenticationSession searchMOASessionWithNameIDandOAID(String oaID, String userNameID) { MiscUtil.assertNotNull(oaID, "OnlineApplicationIdentifier"); MiscUtil.assertNotNull(userNameID, "userNameID"); Logger.trace("Get moaSession for userNameID " + userNameID + " and OA " @@ -585,7 +595,8 @@ public class AuthenticationSessionStoreage { } - public static OASessionStore searchActiveOASSOSession(AuthenticationSession moaSession, String oaID, String protocolType) { + @Override + public OASessionStore searchActiveOASSOSession(AuthenticationSession moaSession, String oaID, String protocolType) { MiscUtil.assertNotNull(moaSession, "MOASession"); MiscUtil.assertNotNull(oaID, "OnlineApplicationIdentifier"); MiscUtil.assertNotNull(protocolType, "usedProtocol"); @@ -626,95 +637,8 @@ public class AuthenticationSessionStoreage { } } - public static String getPendingRequestID(String sessionID) { - try { - AuthenticatedSessionStore dbsession = searchInDatabase(sessionID, true); - return dbsession.getPendingRequestID(); - - } catch (MOADatabaseException e) { - Logger.warn("MOASession with ID " + sessionID + " not found"); - return ""; - } - } - - public static AuthenticationSession getSessionWithPendingRequestID(String pedingRequestID) { - Transaction tx = null; - try { - MiscUtil.assertNotNull(pedingRequestID, "pedingRequestID"); - Logger.trace("Get authenticated session with pedingRequestID " + pedingRequestID + " from database."); - Session session = MOASessionDBUtils.getCurrentSession(); - - List<AuthenticatedSessionStore> result; - - synchronized (session) { - tx = session.beginTransaction(); - Query query = session.getNamedQuery("getSessionWithPendingRequestID"); - query.setParameter("sessionid", pedingRequestID); - result = query.list(); - - //send transaction - tx.commit(); - } - - Logger.trace("Found entries: " + result.size()); - - //Assertion requires an unique artifact - if (result.size() != 1) { - Logger.trace("No entries found."); - return null; - } - - return decryptSession(result.get(0)); - - } catch (Throwable e) { - Logger.warn("MOASession deserialization-exception by using MOASessionID=" + pedingRequestID); - - if (tx != null && !tx.wasCommitted()) - tx.rollback(); - - return null; - - } - } - - public static boolean deleteSessionWithPendingRequestID(String id) { - MiscUtil.assertNotNull(id, "PendingRequestID"); - Logger.trace("Delete MOAsession with PendingRequestID " + id + " from database."); - Session session = MOASessionDBUtils.getCurrentSession(); - - List<AuthenticatedSessionStore> result; - Transaction tx = null; - try { - synchronized (session) { - tx = session.beginTransaction(); - Query query = session.getNamedQuery("getSessionWithPendingRequestID"); - query.setParameter("sessionid", id); - result = query.list(); - - //send transaction - tx.commit(); - - Logger.trace("Found entries: " + result.size()); - - //Assertion requires an unique artifact - if (result.size() != 1) { - Logger.trace("No entries found."); - return false; - - } else { - cleanDelete(result.get(0)); - return true; - } - } - - } catch (Exception e) { - if (tx != null && !tx.wasCommitted()) - tx.rollback(); - throw e; - } - } - - public static AuthenticationSession getSessionWithUserNameID(String nameID) { + @Override + public AuthenticationSession getSessionWithUserNameID(String nameID) { Transaction tx = null; try { @@ -752,8 +676,9 @@ public class AuthenticationSessionStoreage { } } - - public static InterfederationSessionStore searchInterfederatedIDPFORSSOWithMOASession(String sessionID) { + + @Override + public InterfederationSessionStore searchInterfederatedIDPFORSSOWithMOASession(String sessionID) { MiscUtil.assertNotNull(sessionID, "MOASession"); Logger.trace("Get interfederated IDP for SSO with sessionID " + sessionID + " from database."); Session session = MOASessionDBUtils.getCurrentSession(); @@ -788,7 +713,8 @@ public class AuthenticationSessionStoreage { } } - public static InterfederationSessionStore searchInterfederatedIDPFORSSOWithMOASessionIDPID(String sessionID, String idpID) { + @Override + public InterfederationSessionStore searchInterfederatedIDPFORSSOWithMOASessionIDPID(String sessionID, String idpID) { MiscUtil.assertNotNull(sessionID, "MOASession"); MiscUtil.assertNotNull(idpID, "Interfederated IDP ID"); Logger.trace("Get interfederated IDP "+ idpID + " for SSO with sessionID " + sessionID + " from database."); @@ -825,49 +751,38 @@ public class AuthenticationSessionStoreage { } } - public static String createInterfederatedSession(IRequest req, boolean isAuthenticated, String ssoID) throws MOADatabaseException, AssertionAttributeExtractorExeption, BuildException { + public void createInterfederatedSession(IRequest req, boolean isAuthenticated) throws MOADatabaseException, AssertionAttributeExtractorExeption, BuildException { AuthenticatedSessionStore dbsession = null; + Date now = new Date(); - //search for active SSO session - if (MiscUtil.isNotEmpty(ssoID)) { - String moaSession = getMOASessionSSOID(ssoID); - if (MiscUtil.isNotEmpty(moaSession)) { - try { - dbsession = searchInDatabase(moaSession, true); - - }catch (MOADatabaseException e) { + //search for active session + String moaSession = getMOASessionSSOID(req.getMOASessionIdentifier()); + if (MiscUtil.isNotEmpty(moaSession)) { + try { + dbsession = searchInDatabase(moaSession, true); - } - } - } + }catch (MOADatabaseException e) { + Logger.error("NO MOASession found but MOASession MUST already exist!"); + throw e; + } + } - String id = null; - Date now = new Date(); - //create new MOASession if any exists - AuthenticationSession session = null; - if (dbsession == null) { - id = Random.nextRandom(); - dbsession = new AuthenticatedSessionStore(); - dbsession.setSessionid(id); - dbsession.setCreated(now); - dbsession.setPendingRequestID(req.getRequestID()); - session = new AuthenticationSession(id, now); + AuthenticationSession session = decryptSession(dbsession); - } else { - id = dbsession.getSessionid(); - session = decryptSession(dbsession); - - } - - dbsession.setInterfederatedSSOSession(true); + //set Session parameters + session.setAuthenticated(isAuthenticated); dbsession.setAuthenticated(isAuthenticated); + dbsession.setInterfederatedSSOSession(true); dbsession.setUpdated(now); - session.setAuthenticated(true); - session.setAuthenticatedUsed(false); + encryptSession(session, dbsession); //add interfederation information List<InterfederationSessionStore> idpList = dbsession.getInderfederation(); + + MOAResponse interfederationResp = req.getGenericData(RequestImpl.DATAID_INTERFEDERATIOIDP_RESPONSE, MOAResponse.class); + String interFedEntityID = interfederationResp.getEntityID(); + InterfederationSessionStore idp = null; if (idpList == null) { idpList = new ArrayList<InterfederationSessionStore>(); @@ -876,7 +791,7 @@ public class AuthenticationSessionStoreage { } else { for (InterfederationSessionStore el : idpList) { //resue old entry if interfederation IDP is reused for authentication - if (el.getIdpurlprefix().equals(req.getInterfederationResponse().getEntityID())) + if (el.getIdpurlprefix().equals(interFedEntityID)) idp = el; } @@ -886,23 +801,16 @@ public class AuthenticationSessionStoreage { if (idp == null) { idp = new InterfederationSessionStore(); idp.setCreated(now); - idp.setIdpurlprefix(req.getInterfederationResponse().getEntityID()); + idp.setIdpurlprefix(interFedEntityID); + idp.setAuthURL(req.getAuthURL()); - try { - OAAuthParameter oa = AuthConfigurationProviderFactory.getInstance(). - getOnlineApplicationParameter(idp.getIdpurlprefix()); - idp.setStoreSSOInformation(oa.isInterfederationSSOStorageAllowed()); - - } catch (ConfigurationException e) { - Logger.warn("MOASession could not be created."); - throw new MOADatabaseException(e); - - } + OAAuthParameter oa = authConfig.getOnlineApplicationParameter(idp.getIdpurlprefix()); + idp.setStoreSSOInformation(oa.isInterfederationSSOStorageAllowed()); idp.setMoasession(dbsession); idpList.add(idp); } - AssertionAttributeExtractor extract = new AssertionAttributeExtractor(req.getInterfederationResponse().getResponse()); + AssertionAttributeExtractor extract = new AssertionAttributeExtractor(interfederationResp.getResponse()); idp.setSessionIndex(extract.getSessionIndex()); idp.setUserNameID(extract.getNameID()); idp.setAttributesRequested(false); @@ -911,17 +819,16 @@ public class AuthenticationSessionStoreage { //store AssertionStore element to Database try { MOASessionDBUtils.saveOrUpdate(dbsession); - Logger.debug("MOASession with sessionID=" + id + " is stored in Database"); } catch (MOADatabaseException e) { Logger.warn("MOASession could not be created."); throw new MOADatabaseException(e); } - return id; } - public static InterfederationSessionStore searchInterfederatedIDPFORAttributeQueryWithSessionID(AuthenticationSession moaSession) { + @Override + public InterfederationSessionStore searchInterfederatedIDPFORAttributeQueryWithSessionID(AuthenticationSession moaSession) { MiscUtil.assertNotNull(moaSession, "MOASession"); Logger.trace("Get interfederated IDP for AttributeQuery with sessionID " + moaSession.getSessionID() + " from database."); Session session = MOASessionDBUtils.getCurrentSession(); @@ -956,11 +863,8 @@ public class AuthenticationSessionStoreage { } } - /** - * @param entityID - * @param requestID - */ - public static boolean removeInterfederetedSession(String entityID, + @Override + public boolean removeInterfederetedSession(String entityID, String pedingRequestID) { try { @@ -972,6 +876,8 @@ public class AuthenticationSessionStoreage { List<AuthenticatedSessionStore> result; + //TODO: !!!!!!!!!!! PendingRequestID does not work + synchronized (session) { session.beginTransaction(); Query query = session.getNamedQuery("getSessionWithPendingRequestID"); @@ -1010,9 +916,10 @@ public class AuthenticationSessionStoreage { } } - public static void clean(long now, long authDataTimeOutCreated, long authDataTimeOutUpdated) { - Date expioredatecreate = new Date(now - authDataTimeOutCreated); - Date expioredateupdate = new Date(now - authDataTimeOutUpdated); + @Override + public void clean(Date now, long authDataTimeOutCreated, long authDataTimeOutUpdated) { + Date expioredatecreate = new Date(now.getTime() - authDataTimeOutCreated); + Date expioredateupdate = new Date(now.getTime() - authDataTimeOutUpdated); List<AuthenticatedSessionStore> results; Session session = MOASessionDBUtils.getCurrentSession(); @@ -1068,16 +975,6 @@ public class AuthenticationSessionStoreage { private static void cleanDelete(AuthenticatedSessionStore result) { try { - AuthenticationSession session = getSession(result.getSessionid()); - if (session.getProcessInstanceId() != null) { - ProcessInstanceStoreDAOImpl.getInstance().remove(session.getProcessInstanceId()); - } - - } catch (MOADatabaseException e) { - Logger.warn("Removing process associated with moa session " + result.getSessionid() + " FAILED.", e); - } - - try { result.setSession("blank".getBytes()); MOASessionDBUtils.saveOrUpdate(result); @@ -1115,10 +1012,12 @@ public class AuthenticationSessionStoreage { //Assertion requires an unique artifact if (result.size() != 1) { Logger.trace("No entries found."); - throw new MOADatabaseException("No session found with this sessionID"); + throw new MOADatabaseException("No session found with this sessionID"); + } return (AuthenticatedSessionStore) result.get(0); + } catch (Exception e) { if (tx != null && !tx.wasCommitted() && commit) tx.rollback(); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/DBExceptionStoreImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/DBExceptionStoreImpl.java deleted file mode 100644 index 4cddd141b..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/DBExceptionStoreImpl.java +++ /dev/null @@ -1,175 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 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: - * http://www.osor.eu/eupl/ - * - * 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.egovernment.moa.id.storage; - -import java.util.Date; -import java.util.List; - -import org.apache.commons.lang.SerializationUtils; -import org.hibernate.HibernateException; -import org.hibernate.Query; -import org.hibernate.Session; - -import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils; -import at.gv.egovernment.moa.id.commons.db.dao.session.ExceptionStore; -import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; -import at.gv.egovernment.moa.id.util.Random; -import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.MiscUtil; - -public class DBExceptionStoreImpl implements IExceptionStore { - - private static DBExceptionStoreImpl store; - - public static DBExceptionStoreImpl getStore() { - if(store == null) { - store = new DBExceptionStoreImpl(); - } - return store; - } - - public String storeException(Throwable e) { - String id = Random.nextRandom(); - - Logger.debug("Store Exception with ID " + id); - - ExceptionStore dbexception = new ExceptionStore(); - dbexception.setExid(id); - - byte[] data = SerializationUtils.serialize(e); - dbexception.setException(data); - - dbexception.setTimestamp(new Date()); - - try { - MOASessionDBUtils.saveOrUpdate(dbexception); - - } catch (MOADatabaseException e1) { - Logger.warn("Exception can not be stored in Database.", e); - return null; - } - - return id; - } - - public Throwable fetchException(String id) { - - try { - Logger.debug("Fetch Exception with ID " + id); - - ExceptionStore ex = searchInDatabase(id); - - Object data = SerializationUtils.deserialize(ex.getException()); - if (data instanceof Throwable) - return (Throwable) data; - - else { - Logger.warn("Exeption is not of classtype Throwable"); - return null; - } - - - } catch (MOADatabaseException e) { - Logger.info("No Exception found with ID=" + id); - return null; - - } catch (Exception e) { - Logger.warn("Exception can not deserialized from Database.",e); - return null; - } - - } - - public void removeException(String id) { - try { - ExceptionStore ex = searchInDatabase(id); - MOASessionDBUtils.delete(ex); - - Logger.debug("Delete Execption with ID " + id); - - } catch (MOADatabaseException e) { - Logger.info("No Exception found with ID=" + id); - } - - - } - - public void clean(long now, long exceptionTimeOut) { - Date expioredate = new Date(now - exceptionTimeOut); - - List<ExceptionStore> results; - Session session = MOASessionDBUtils.getCurrentSession(); - - synchronized (session) { - session.beginTransaction(); - Query query = session.getNamedQuery("getExceptionWithTimeOut"); - query.setTimestamp("timeout", expioredate); - results = query.list(); - session.getTransaction().commit(); - - if (results.size() != 0) { - for(ExceptionStore result : results) { - try { - MOASessionDBUtils.delete(result); - Logger.info("Remove Exception with ID=" + result.getExid() - + " after timeout."); - - } catch (HibernateException e){ - Logger.warn("Exception with ID=" + result.getExid() - + " not removed after timeout! (Error during Database communication)", e); - } - - } - } - } - } - - @SuppressWarnings("rawtypes") - private ExceptionStore searchInDatabase(String id) throws MOADatabaseException { - MiscUtil.assertNotNull(id, "exceptionID"); - Logger.trace("Getting Exception with ID " + id + " from database."); - Session session = MOASessionDBUtils.getCurrentSession(); - List result; - - synchronized (session) { - session.beginTransaction(); - Query query = session.getNamedQuery("getExceptionWithID"); - query.setParameter("id", id); - result = query.list(); - - //send transaction - session.getTransaction().commit(); - } - - Logger.trace("Found entries: " + result.size()); - - //Assertion requires an unique artifact - if (result.size() != 1) { - Logger.trace("No entries found."); - throw new MOADatabaseException("No Exception found with ID " + id); - } - - return (ExceptionStore) result.get(0); - } - -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AssertionStorage.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/DBTransactionStorage.java index 3b97f3b08..ff631a720 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AssertionStorage.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/DBTransactionStorage.java @@ -30,29 +30,21 @@ import org.apache.commons.lang.SerializationUtils; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; +import org.springframework.stereotype.Service; import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils; import at.gv.egovernment.moa.id.commons.db.dao.session.AssertionStore; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; -import at.gv.egovernment.moa.id.data.AuthenticationData; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; -public class AssertionStorage { - - private static AssertionStorage instance = null; - - public static AssertionStorage getInstance() { - if(instance == null) { - instance = new AssertionStorage(); - } - return instance; - } - - public boolean containsKey(String artifact) { +@Service("TransactionStorage") +public class DBTransactionStorage implements ITransactionStorage { + + public boolean containsKey(String key) { try { - searchInDatabase(artifact); + searchInDatabase(key); return true; } catch (MOADatabaseException e) { @@ -61,60 +53,68 @@ public class AssertionStorage { } - public void put(String artifact, Object assertion) throws MOADatabaseException { - //setup AssertionStore element - AssertionStore element = new AssertionStore(); - element.setArtifact(artifact); - element.setType(assertion.getClass().getName()); - element.setDatatime(new Date()); - - //serialize the Assertion for Database storage - byte[] data = SerializationUtils.serialize((Serializable) assertion); - element.setAssertion(data); - - //store AssertionStore element to Database - try { - MOASessionDBUtils.saveOrUpdate(element); - Logger.info(assertion.getClass().getName() + " with ID: " + artifact + " is stored in Database"); - } catch (MOADatabaseException e) { - Logger.warn("Sessioninformation could not be stored."); - throw new MOADatabaseException(e); + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.storage.ITransactionStorage#changeKey(java.lang.String, java.lang.String, java.lang.Object) + */ + @Override + public void changeKey(String oldKey, String newKey, Object value) throws MOADatabaseException { + //search if key already exists + AssertionStore element = searchInDatabase(oldKey); + if (element == null) { + Logger.info("No transaction-data with oldKey:" + oldKey + + " found. Process gets stopped."); + throw new MOADatabaseException("No transaction-data with oldKey:" + oldKey + + " found. Process gets stopped."); + } + put(element, newKey, value); + } - - /** - * @param samlArtifact - * @param class1 - * @param authdatatimeout - * @return - * @throws MOADatabaseException - * @throws AuthenticationException - */ - public <T> T get(String samlArtifact, + public void put(String key, Object value) throws MOADatabaseException { + //search if key already exists + AssertionStore element = searchInDatabase(key); + + //create a new entry if key does not exists already + if (element == null) { + element = new AssertionStore(); + + } + + put(element, key, value); + } + + public <T> T get(String key, final Class<T> clazz) throws MOADatabaseException { try { - return get(samlArtifact, clazz, -1); + return get(key, clazz, -1); } catch (AuthenticationException e) { //this execption only occurs if an additional timeOut is used Logger.error("This exeption should not occur!!!!", e); return null; + } } - public <T> T get(String artifact, final Class<T> clazz, long authdatatimeout) throws MOADatabaseException, AuthenticationException { + public <T> T get(String key, final Class<T> clazz, long dataTimeOut) throws MOADatabaseException, AuthenticationException { - AssertionStore element = searchInDatabase(artifact); + AssertionStore element = searchInDatabase(key); - if (authdatatimeout > -1) { + if (element == null) + return null; + + if (dataTimeOut > -1) { //check timeout long now = new Date().getTime(); - if (now - element.getDatatime().getTime() > authdatatimeout) - throw new AuthenticationException("1207", new Object[] { artifact }); + if (now - element.getDatatime().getTime() > dataTimeOut) { + Logger.info("Transaction-Data with key: " + key + " is out of time."); + throw new AuthenticationException("1207", new Object[] { key }); + + } } @@ -128,13 +128,14 @@ public class AssertionStorage { return test; } catch (Exception e) { - Logger.warn("Sessioninformation Cast-Exception by using Artifact=" + artifact); + Logger.warn("Sessioninformation Cast-Exception by using Artifact=" + key); throw new MOADatabaseException("Sessioninformation Cast-Exception"); + } } - public void clean(long now, long authDataTimeOut) { - Date expioredate = new Date(now - authDataTimeOut); + public void clean(Date now, long dataTimeOut) { + Date expioredate = new Date(now.getTime() - dataTimeOut); List<AssertionStore> results; Session session = MOASessionDBUtils.getCurrentSession(); @@ -163,17 +164,22 @@ public class AssertionStorage { } } - public void remove(String artifact) { + public void remove(String key) { try { - AssertionStore element = searchInDatabase(artifact); + AssertionStore element = searchInDatabase(key); + if (element == null) { + Logger.debug("Sessioninformation not removed! (Sessioninformation with ID=" + key + + "not found)"); + return; + } + cleanDelete(element); - Logger.info("Remove stored information with ID: " + artifact); + Logger.debug("Remove stored information with ID: " + key); } catch (MOADatabaseException e) { - Logger.info("Sessioninformation not removed! (Sessioninformation with ID=" + artifact - + "not found)"); + Logger.info("Sessioninformation not removed! (Message:"+ e.getMessage() + ")"); } catch (HibernateException e) { Logger.warn("Sessioninformation not removed! (Error during Database communication)", e); @@ -218,10 +224,34 @@ public class AssertionStorage { //Assertion requires an unique artifact if (result.size() != 1) { - Logger.trace("No entries found."); - throw new MOADatabaseException("No sessioninformation found with this ID"); + Logger.debug("No transaction information with ID:" + artifact + " found."); + return null; + } return (AssertionStore) result.get(0); } + + private void put(AssertionStore element, String key, Object value) throws MOADatabaseException { + element.setArtifact(key); + element.setType(value.getClass().getName()); + element.setDatatime(new Date()); + + //serialize the Assertion for Database storage + byte[] data = SerializationUtils.serialize((Serializable) value); + element.setAssertion(data); + + //store AssertionStore element to Database + try { + MOASessionDBUtils.saveOrUpdate(element); + Logger.debug(value.getClass().getName() + " with ID: " + key + " is stored in Database"); + + } catch (MOADatabaseException e) { + Logger.warn("Sessioninformation could not be stored."); + throw new MOADatabaseException(e); + + } + + } + } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/ExceptionStoreImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/ExceptionStoreImpl.java deleted file mode 100644 index ce974c531..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/ExceptionStoreImpl.java +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 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: - * http://www.osor.eu/eupl/ - * - * 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.egovernment.moa.id.storage; - -import java.util.HashMap; -import java.util.Map; - -import at.gv.egovernment.moa.id.util.Random; - -public class ExceptionStoreImpl implements IExceptionStore { - - // Just a quick implementation - private static IExceptionStore store; - - public static IExceptionStore getStore() { - if(store == null) { - store = new ExceptionStoreImpl(); - } - return store; - } - - private Map<String, Throwable> exceptionStore = new HashMap<String, Throwable>(); - - public String storeException(Throwable e) { - String id = Random.nextRandom(); - exceptionStore.put(id, e); - return id; - } - - public Throwable fetchException(String id) { - return exceptionStore.get(id); - } - - public void removeException(String id) { - exceptionStore.remove(id); - } - -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/IAuthenticationSessionStoreage.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/IAuthenticationSessionStoreage.java new file mode 100644 index 000000000..2fd540a67 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/IAuthenticationSessionStoreage.java @@ -0,0 +1,279 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.storage; + +import java.util.Date; +import java.util.List; + +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionExtensions; +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; +import at.gv.egovernment.moa.id.auth.exception.BuildException; +import at.gv.egovernment.moa.id.commons.db.dao.session.AuthenticatedSessionStore; +import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore; +import at.gv.egovernment.moa.id.commons.db.dao.session.OASessionStore; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.data.SLOInformationInterface; +import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AssertionAttributeExtractorExeption; + +/** + * @author tlenz + * + */ +public interface IAuthenticationSessionStoreage { + + /** + * Check if the stored MOASession is already authenticated + * + * @param moaSessionID MOASession identifier + * @return true if the MOASession is authenticated, otherwise false + */ + public boolean isAuthenticated(String moaSessionID); + + /** + * Create a new MOASession + * + * @param target Pending Request which is associated with this MOASession + * @return MOASession object + * @throws MOADatabaseException MOASession storage operation FAILED + * @throws BuildException MOASession encryption FAILED + */ + public AuthenticationSession createSession(IRequest target) throws MOADatabaseException, BuildException; + + /** + * Get a MOASession with sessionID + * + * @param sessionID SessionID which corresponds to a MOASession + * @return MOASession, or null if no session exists with this ID + * @throws MOADatabaseException MOASession load operation FAILED + */ + public AuthenticationSession getSession(String sessionID) throws MOADatabaseException; + + /** + * Get the session-data extension-object for a MOASession + * + * @param sessionID SessionID which corresponds to a MOASession + * @return AuthenticationSessionExtensions, or null if no session exists with this ID or extensionobject is null + * @throws MOADatabaseException MOASession load operation FAILED + */ + public AuthenticationSessionExtensions getAuthenticationSessionExtensions(String sessionID) throws MOADatabaseException; + + /** + * Store a session-data extension-object to MOASession + * + * @param sessionID SessionID which corresponds to a MOASession + * @param sessionExtensions AuthenticationSessionExtensions object + * @throws MOADatabaseException MOASession storage operation FAILED + */ + public void setAuthenticationSessionExtensions(String sessionID, AuthenticationSessionExtensions sessionExtensions) throws MOADatabaseException; + + + /** + * Store a MOASession + * + * @param session MOASession which should be stored + * @throws MOADatabaseException MOASession storage operation FAILED + * @throws BuildException MOASession encryption FAILED + */ + public void storeSession(AuthenticationSession session) throws MOADatabaseException, BuildException; + + /** + * Delete a MOASession + * + * @param moaSessionID SessionID which corresponds to a MOASession + * @throws MOADatabaseException MOASession delete operation FAILED + */ + public void destroySession(String moaSessionID) throws MOADatabaseException; + + + /** + * Change the sessionID of a MOASession + * + * @param session MOASession for which the sessionID should be changed + * @param newSessionID new MOASessionID which should be used + * @return new MOASessionID + * @throws MOADatabaseException MOASession storage operation FAILED + * @throws BuildException MOASession encryption/decryption FAILED + */ + public String changeSessionID(AuthenticationSession session, String newSessionID) throws BuildException, MOADatabaseException; + + /** + * Change the sessionID of a MOASession + * + * @param session MOASession for which the sessionID should be changed + * @return new MOASessionID + * @throws MOADatabaseException MOASession storage operation FAILED + * @throws BuildException MOASession encryption/decryption FAILED + */ + public String changeSessionID(AuthenticationSession session) throws BuildException, MOADatabaseException; + + /** + * Set the isAuthenticated flag to MOASession + * + * @param moaSessionID SessionID which corresponds to a MOASession + * @param isAuthenticated Is authenticated flag (true/false) + */ + public void setAuthenticated(String moaSessionID, boolean isAuthenticated); + + /** + * Find the MOASessionId of an active Single Sign-On session + * + * @param SSOSessionID Single Sign-On sessionID + * @return MOASessionID of the associated MOASession + */ + public String getMOASessionSSOID(String SSOSessionID); + + /** + * Check if a MOASession is an active Single Sign-On session + * + * @param sessionID SessionID which corresponds to a MOASession + * @return true, if the MOASession is a SSO session, otherwise false + * @throws MOADatabaseException MOASession load operation FAILED + */ + public boolean isSSOSession(String sessionID) throws MOADatabaseException; + + + /** + * @param SSOId + * @return + */ + public AuthenticatedSessionStore isValidSessionWithSSOID(String SSOId); + + /** + * Add Single Sign-On processing information to a MOASession. + * This processing information is required to execute a Single Log-Out process + * + * @param moaSessionID SessionID which corresponds to a MOASession + * @param SSOSessionID Single Sign-On sessionID + * @param SLOInfo Data object with Single LogOut information + * @param protocolRequest Protocol-request object of the authentication request + * @throws AuthenticationException Single Sign-On information store operation FAILED + */ + public void addSSOInformation(String moaSessionID, String SSOSessionID, + SLOInformationInterface SLOInfo, IRequest protocolRequest) throws AuthenticationException; + + + /** + * Get all Single Sign-On authenticated Service-Provider of a MOASession + * + * @param moaSession MOASession data object + * @return List of Service-Provider information + */ + public List<OASessionStore> getAllActiveOAFromMOASession(AuthenticationSession moaSession); + + + /** + * Get all active interfederation connections for a MOASession + * + * @param moaSession MOASession data object + * @return List of Interfederation-IDP information + */ + public List<InterfederationSessionStore> getAllActiveIDPsFromMOASession(AuthenticationSession moaSession); + + /** + * Search a MOASession by using already transfered authentication information + * + * @param oaID Service-Provider identifier, which has received the authentication information + * @param userNameID UserId (bPK), which was send to this Service-Provider + * @return MOASession, or null if no corresponding MOASession is found + */ + public AuthenticationSession searchMOASessionWithNameIDandOAID(String oaID, String userNameID); + + /** + * Search a active Single Sign-On session for a specific Service-Provider + * + * @param moaSession MOASession data object + * @param oaID Service-Provider identifier, which has received the authentication information + * @param protocolType Authentication protocol, which was used for SSO from this Service-Provider + * @return Internal Single Sign-On information for this Service-Provider + */ + public OASessionStore searchActiveOASSOSession(AuthenticationSession moaSession, String oaID, String protocolType); + + + /** + * Search a active MOASession with a userID + * + * @param nameID UserID (bPK) + * @return MOASession, or null if no corresponding MOASession is found + */ + public AuthenticationSession getSessionWithUserNameID(String nameID); + + /** + * Search an active federation IDP which could be used for federated Single Sign-On + * + * @param sessionID SessionID which corresponds to a MOASession + * @return Information of the federated IDP, or null if no active federated IDP is found + */ + public InterfederationSessionStore searchInterfederatedIDPFORSSOWithMOASession(String sessionID); + + /** + * Get information to an active federated IDP of MOASession + * + * @param sessionID SessionID which corresponds to a MOASession + * @param idpID Unique identifier of the federated IDP + * @return Information of the federated IDP, or null if no active federated IDP is found + */ + public InterfederationSessionStore searchInterfederatedIDPFORSSOWithMOASessionIDPID(String sessionID, String idpID); + + + /** + * Create a MOASession from interfederation information + * + * @param req Pending request + * @param isAuthenticated true if the session should be marked as authenticated, otherwise false + * @throws MOADatabaseException + * @throws AssertionAttributeExtractorExeption + * @throws BuildException + */ + @Deprecated + public void createInterfederatedSession(IRequest req, boolean isAuthenticated) throws MOADatabaseException, AssertionAttributeExtractorExeption, BuildException; + + /** + * Search an active federation IDP which could be used for federated Single Sign-On by using an AttributeQuery + * + * @param moaSession MOASession data object + * @return Information of the federated IDP, or null if no active federated IDP is found + */ + public InterfederationSessionStore searchInterfederatedIDPFORAttributeQueryWithSessionID(AuthenticationSession moaSession); + + /** + * Remove an active federation IDP from MOASession + * + * @param entityID Unique identifier of the federated IDP + * @param pedingRequestID + * @return true if the federated IDP could be remove, otherwise false + */ + @Deprecated + public boolean removeInterfederetedSession(String entityID, String pedingRequestID); + + /** + * Clean all MOASessions which has a timeOut + * + * @param now Current Time + * @param authDataTimeOutCreated timeOut after MOASession is created [ms] + * @param authDataTimeOutUpdated timeOut after MOASession is updated last time [ms] + */ + public void clean(Date now, long authDataTimeOutCreated, long authDataTimeOutUpdated); +} + diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/ITransactionStorage.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/ITransactionStorage.java new file mode 100644 index 000000000..48283d2b6 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/ITransactionStorage.java @@ -0,0 +1,101 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.storage; + +import java.util.Date; + +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; + +/** + * @author tlenz + * + */ +public interface ITransactionStorage { + + /** + * Check if transaction storage contains a data object with a specific key + * + * @param key Key, which identifies a data object + * @return true if key is found, otherwise false + */ + public boolean containsKey(String key); + + /** + * Store a data object with a key to transaction storage + * + * @param key Id which identifiers the data object + * @param value Data object which should be stored + * @throws MOADatabaseException In case of store operation failed + */ + public void put(String key, Object value) throws MOADatabaseException; + + /** + * Get a data object from transaction storage + * + * @param key Id which identifiers the data object + * @param clazz The class type which is stored with this key + * @return The transaction-data object from type class, or null + * @throws MOADatabaseException In case of load operation failed + */ + public <T> T get(String key, final Class<T> clazz) throws MOADatabaseException; + + /** + * Get a data object from transaction storage + * + * @param key Id which identifiers the data object + * @param clazz The class type which is stored with this key + * @param Data-object timeout in [ms] + * @return The transaction-data object from type class, or null + * @throws MOADatabaseException In case of load operation failed + * @throws AuthenticationException In case of data-object timeout occurs + */ + public <T> T get(String key, final Class<T> clazz, long dataTimeOut) throws MOADatabaseException, AuthenticationException; + + + /** + * Change the key of a data object and store it under the new key + * + * @param oldKey Old key of the data object + * @param newKey New key, which should be used to store the data object + * @param value Data object which should be stored + * @throws MOADatabaseException In case of store operation failed + */ + public void changeKey(String oldKey, String newKey, Object value) throws MOADatabaseException; + + /** + * Remove a data object from transaction storage + * + * @param key Id which identifiers the data object + */ + public void remove(String key); + + /** + * Clean-up the transaction storage + * + * @param now Current time + * @param dataTimeOut Data-object timeout in [ms] + */ + public void clean(Date now, long dataTimeOut); + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ErrorResponseUtils.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ErrorResponseUtils.java index 99ac6ba4c..8bd682421 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ErrorResponseUtils.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ErrorResponseUtils.java @@ -27,6 +27,7 @@ import java.util.Locale; import at.gv.egovernment.moa.id.auth.exception.BKUException; import at.gv.egovernment.moa.id.auth.exception.MISSimpleClientException; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.process.ProcessExecutionException; import at.gv.egovernment.moa.util.Messages; import at.gv.egovernment.moa.util.MiscUtil; @@ -78,7 +79,10 @@ public class ErrorResponseUtils { } else if (throwable instanceof MOAIDException) { MOAIDException error = (MOAIDException) throwable; errorCode = mapInternalErrorToExternalError(error.getMessageId()); - + + } else if (throwable instanceof ProcessExecutionException) { + errorCode = "1100"; + } else { errorCode = INTERNALERRORCODE; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/HTTPUtils.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/HTTPUtils.java index 1f08d9019..d2499af9d 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/HTTPUtils.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/HTTPUtils.java @@ -156,5 +156,30 @@ public class HTTPUtils { return buffer.toString(); } + + /** + * Extract the IDP PublicURLPrefix from authrequest + * + * @param req HttpServletRequest + * @return PublicURLPrefix <String> which ends always without / + */ + public static String extractAuthURLFromRequest(HttpServletRequest req) { + String authURL = req.getScheme() + "://" + req.getServerName(); + if ((req.getScheme().equalsIgnoreCase("https") && req.getServerPort()!=443) || (req.getScheme().equalsIgnoreCase("http") && req.getServerPort()!=80)) { + authURL = authURL.concat(":" + req.getServerPort()); + } + authURL = authURL.concat(req.getContextPath()); + return authURL; + + } + + public static String addURLParameter(String url, String paramname, + String paramvalue) { + String param = paramname + "=" + paramvalue; + if (url.indexOf("?") < 0) + return url + "?" + param; + else + return url + "&" + param; + } } |