diff options
Diffstat (limited to 'id/server/idserverlib/src/main/java')
41 files changed, 935 insertions, 283 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..7ac026888 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,11 +23,10 @@ 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 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; @@ -47,7 +46,7 @@ public class MOAReversionLogger { private static MOAReversionLogger instance = null; - private static final List<Integer> defaultEventCodes = Ints.asList( + private static final List<Integer> defaultEventCodes = Arrays.asList( MOAIDEventConstants.SESSION_CREATED, MOAIDEventConstants.SESSION_DESTROYED, MOAIDEventConstants.SESSION_ERROR, @@ -69,8 +68,9 @@ public class MOAReversionLogger { MOAIDEventConstants.AUTHPROCESS_INTERFEDERATION, MOAIDEventConstants.AUTHPROCESS_STORK_REQUESTED, MOAIDEventConstants.AUTHPROCESS_SERVICEPROVIDER - ); - + ); + + public static synchronized MOAReversionLogger getInstance() { if (instance == null) { instance = new MOAReversionLogger(); 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..038a35d42 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 @@ -12,10 +12,8 @@ import java.security.GeneralSecurityException; import javax.activation.CommandMap; import javax.activation.MailcapCommandMap; -import javax.net.ssl.SSLSocketFactory; 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; @@ -136,50 +134,27 @@ 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(); + + //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(); 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..fe29dd2b7 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 @@ -139,10 +139,12 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { AuthenticationData authdata = null; 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>()); @@ -314,7 +316,7 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { //validate PVP 2.1 response try { SAMLVerificationEngine engine = new SAMLVerificationEngine(); - engine.verifyResponse(intfResp, TrustEngineFactory.getSignatureKnownKeysTrustEngine()); + engine.verifyIDPResponse(intfResp, TrustEngineFactory.getSignatureKnownKeysTrustEngine()); SAMLVerificationEngine.validateAssertion(intfResp, false); 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..d4350f97b 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 @@ -95,6 +95,9 @@ public class DataURLBuilder { // dataURL = individualDataURLPrefix + authServletName; // } else + if (!authBaseURL.endsWith("/")) + authBaseURL += "/"; + dataURL = authBaseURL + authServletName; dataURL = addParameter(dataURL, MOAIDAuthConstants.PARAM_SESSIONID, sessionID); 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..d14910319 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 @@ -147,6 +147,9 @@ public class SendAssertionFormBuilder { value = value.replace(ACTION, action); value = value.replace(ID, id); 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/modules/internal/tasks/CreateInterfedeartionRequestTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CreateInterfedeartionRequestTask.java index 8429baf23..4a6ecd56a 100644 --- 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 @@ -152,8 +152,7 @@ public class CreateInterfedeartionRequestTask extends AbstractAuthServletTask { authReq.setAssertionConsumerServiceIndex(0); authReq.setIssueInstant(new DateTime()); Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); - String serviceURL = PVPConfiguration.getInstance().getIDPPublicPath(); - issuer.setValue(serviceURL); + issuer.setValue(pendingReq.getAuthURLWithOutSlash()); issuer.setFormat(NameIDType.ENTITY); authReq.setIssuer(issuer); 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..e659c9447 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 @@ -56,7 +56,8 @@ public class StartAuthentificationParameterParser extends MOAIDAuthConstants{ String ccc, String module, String action, - HttpServletRequest req) throws WrongParametersException, MOAIDException { + HttpServletRequest req, + IRequest protocolReq) throws WrongParametersException, MOAIDException { String targetFriendlyName = null; @@ -223,20 +224,15 @@ public class StartAuthentificationParameterParser extends MOAIDAuthConstants{ 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() + "/"); - + String authURL = protocolReq.getAuthURL(); 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() + "/"); + moasession.setAuthURL(authURL); //check and set SourceID if (oaParam.getSAML1Parameter() != null) { @@ -318,7 +314,7 @@ public class StartAuthentificationParameterParser extends MOAIDAuthConstants{ oaURL = request.getOAURL(); target = request.getTarget(); - parse(moasession, target, oaURL, bkuURL, templateURL, useMandate, ccc, modul, action, req); + parse(moasession, target, oaURL, bkuURL, templateURL, useMandate, ccc, modul, action, req, request); } 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 index 2a63968dd..15d596049 100644 --- 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 @@ -24,8 +24,6 @@ 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; @@ -33,28 +31,18 @@ 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.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.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.ProcessExecutionException; 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 { @@ -139,6 +127,25 @@ public class GenerateIFrameTemplateServlet extends AuthServlet { catch (MOAIDException ex) { handleError(null, ex, req, resp, pendingRequestID); + + } catch (ProcessExecutionException e) { + Throwable cause = e.getCause(); + if (cause != null && cause instanceof TaskExecutionException) { + Throwable taskCause = cause.getCause(); + if (taskCause != null && taskCause instanceof WrongParametersException) { + WrongParametersException internalEx = (WrongParametersException) taskCause; + handleWrongParameters(internalEx, req, resp); + return; + + } else if (taskCause != null && taskCause instanceof MOAIDException) { + MOAIDException moaTaskCause = (MOAIDException) taskCause; + handleError(null, moaTaskCause, req, resp, pendingRequestID); + return; + + } + } + + Logger.error("BKUSelectionServlet has an interal Error.", e); } catch (Exception e) { Logger.error("BKUSelectionServlet has an interal Error.", e); 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..fe5cd1ac0 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 @@ -45,6 +45,7 @@ import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NOSLOServiceDescripto 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.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; @@ -62,6 +63,23 @@ public class IDPSingleLogOutServlet extends AuthServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Logger.debug("receive IDP SingleLogOut Request"); + + 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; + + } + SSOManager ssomanager = SSOManager.getInstance(); String ssoid = ssomanager.getSSOSessionID(req); @@ -109,7 +127,7 @@ public class IDPSingleLogOutServlet extends AuthServlet { AuthenticationSession authSession = AuthenticationSessionStoreage .getSession(moaSessionID); if(authSession != null) { - authmanager.performSingleLogOut(req, resp, authSession, null); + authmanager.performSingleLogOut(req, resp, authSession, authURL); return; } @@ -142,7 +160,7 @@ public class IDPSingleLogOutServlet extends AuthServlet { } else { //print SLO information directly - redirectURL = AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix() + "/idpSingleLogout"; + redirectURL = HTTPUtils.extractAuthURLFromRequest(req) + "/idpSingleLogout"; String artifact = Random.nextRandom(); 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..53187088e 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 @@ -60,6 +60,7 @@ 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.util.HTTPUtils; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; @@ -85,14 +86,14 @@ public class LogOutServlet extends AuthServlet { if (MiscUtil.isEmpty(redirectUrl)) { //set default redirect Target Logger.debug("Set default RedirectURL back to MOA-ID-Auth"); - redirectUrl = AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix(); + 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 = AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix(); + redirectUrl = HTTPUtils.extractAuthURLFromRequest(req); } 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..a914659b0 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 @@ -36,6 +36,7 @@ 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; @@ -64,8 +65,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; 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..9812f346d 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 @@ -65,7 +65,7 @@ public class AuthConfigurationProviderFactory { instance = new PropertyBasedAuthConfigurationProvider(fileURI); } catch (URISyntaxException e){ - Logger.error("MOA-ID-Auth configuration file does not starts with file:/ as prefix."); + 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, fileName}); } 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..18926046c 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,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; +import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -21,8 +22,15 @@ 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.ConfigurationProviderImpl; import at.gv.egovernment.moa.id.config.ConfigurationUtils; @@ -48,6 +56,8 @@ public class PropertyBasedAuthConfigurationProvider extends ConfigurationProvide private final Properties properties = new Properties(); private ApplicationContext context = null; + private boolean requireJDBCBackupImplementation = false; + public PropertyBasedAuthConfigurationProvider() { } @@ -84,6 +94,20 @@ public class PropertyBasedAuthConfigurationProvider extends ConfigurationProvide 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); @@ -796,20 +820,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 +1039,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 +1178,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/data/SLOInformationContainer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationContainer.java index d1e04e107..a4bba8b19 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 @@ -75,6 +75,7 @@ public class SLOInformationContainer implements Serializable { if (sloDesc.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI)) activeBackChannelOAs.put(oa.getOaurlprefix(), new SLOInformationImpl( + oa.getAuthURL(), oa.getAssertionSessionID(), oa.getUserNameID(), oa.getUserNameIDFormat(), @@ -84,6 +85,7 @@ public class SLOInformationContainer implements Serializable { else activeFrontChannalOAs.put(oa.getOaurlprefix(), new SLOInformationImpl( + oa.getAuthURL(), oa.getAssertionSessionID(), oa.getUserNameID(), oa.getUserNameIDFormat(), @@ -123,6 +125,7 @@ public class SLOInformationContainer implements Serializable { activeFrontChannalOAs.put(el.getIdpurlprefix(), new SLOInformationImpl( + el.getAuthURL(), el.getSessionIndex(), el.getUserNameID(), NameID.TRANSIENT, 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 index 771c9a35e..ce44db215 100644 --- 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 @@ -33,7 +33,6 @@ 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; @@ -45,7 +44,7 @@ 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.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.data.IAuthData; @@ -86,13 +85,18 @@ public class DispatcherServlet extends AuthServlet{ MOAIDAuthInitializer.initialize(); Logger.info(MOAIDMessageProvider.getInstance().getMessage( "init.00", null)); + + Logger.info("Dispatcher Servlet initialization finished."); + } catch (Exception ex) { Logger.fatal( MOAIDMessageProvider.getInstance().getMessage("init.02", null), ex); - throw new ServletException(ex); + + //throw new ServletException(ex); + } - Logger.info("Dispatcher Servlet initialization finished."); + } protected void processRequest(HttpServletRequest req, @@ -364,7 +368,10 @@ public class DispatcherServlet extends AuthServlet{ } catch (AuthnRequestValidatorException e) { //log Error Message StatisticLogger logger = StatisticLogger.getInstance(); - logger.logErrorOperation(e, e.getErrorRequest()); + logger.logErrorOperation(e, e.getErrorRequest()); + + //TODO: maybe add some error message handling??? + return; }catch (InvalidProtocolRequestException e) { @@ -377,6 +384,13 @@ public class DispatcherServlet extends AuthServlet{ "(Errorcode=" + code + " | Description=" + descr + ")"); return; + } catch (ConfigurationException e) { + resp.setContentType("text/html;charset=UTF-8"); + resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "NO valid protocol request received!" + + "(Errorcode=9199" + +" | Description="+ e.getMessage() + ")"); + return; + } catch (MOAIDException e) { Logger.error("Failed to generate a valid protocol request!"); resp.setContentType("text/html;charset=UTF-8"); @@ -544,7 +558,7 @@ public class DispatcherServlet extends AuthServlet{ try { //Store OA specific SSO session information AuthenticationSessionStoreage.addSSOInformation(moasessionID, - newSSOSessionId, assertionID, protocolRequest.getOAURL()); + newSSOSessionId, assertionID, protocolRequest); } catch (AuthenticationException e) { Logger.warn("SSO Session information can not be stored -> SSO is not enabled!"); 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..c38bbc68f 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 @@ -52,7 +52,6 @@ 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; @@ -72,9 +71,10 @@ 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.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; @@ -82,12 +82,11 @@ 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.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.PVPConstants; 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; @@ -98,6 +97,8 @@ 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.protocols.pvp2x.verification.SAMLVerificationEngine; +import at.gv.egovernment.moa.id.protocols.pvp2x.verification.TrustEngineFactory; import at.gv.egovernment.moa.id.storage.AssertionStorage; import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; @@ -167,7 +168,20 @@ public class AuthenticationManager extends MOAIDAuthConstants { } public void performSingleLogOut(HttpServletRequest httpReq, - HttpServletResponse httpResp, AuthenticationSession session, PVPTargetConfiguration pvpReq) throws MOAIDException { + HttpServletResponse httpResp, AuthenticationSession session, PVPTargetConfiguration pvpReq) throws MOAIDException { + performSingleLogOut(httpReq, httpResp, session, pvpReq, null); + + } + + public void performSingleLogOut(HttpServletRequest httpReq, + HttpServletResponse httpResp, AuthenticationSession session, String authURL) throws MOAIDException { + performSingleLogOut(httpReq, httpResp, session, null, authURL); + + } + + + private void performSingleLogOut(HttpServletRequest httpReq, + HttpServletResponse httpResp, AuthenticationSession session, PVPTargetConfiguration pvpReq, String authURL) throws MOAIDException { String pvpSLOIssuer = null; String inboundRelayState = null; @@ -176,6 +190,7 @@ public class AuthenticationManager extends MOAIDAuthConstants { LogoutRequest logOutReq = (LogoutRequest) samlReq.getSamlRequest(); pvpSLOIssuer = logOutReq.getIssuer().getValue(); inboundRelayState = samlReq.getRelayState(); + } SSOManager ssomanager = SSOManager.getInstance(); @@ -195,7 +210,7 @@ public class AuthenticationManager extends MOAIDAuthConstants { } catch (MOADatabaseException e) { Logger.warn("Delete MOASession FAILED."); - sloContainer.putFailedOA(AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix()); + sloContainer.putFailedOA(pvpReq.getAuthURL()); } @@ -219,8 +234,13 @@ public class AuthenticationManager extends MOAIDAuthConstants { + " FAILED. NO LogOut response received."); sloContainer.putFailedOA(sloReq.getIssuer().getValue()); + } else { + SAMLVerificationEngine engine = new SAMLVerificationEngine(); + engine.verifySLOResponse(sloResp, + TrustEngineFactory.getSignatureKnownKeysTrustEngine()); + } - + SingleLogOutBuilder.checkStatusCode(sloContainer, sloResp); } catch (SOAPException e) { @@ -228,7 +248,7 @@ public class AuthenticationManager extends MOAIDAuthConstants { + " 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()); @@ -258,7 +278,10 @@ public class AuthenticationManager extends MOAIDAuthConstants { AssertionStorage.getInstance().put(relayState, sloContainer); - String timeOutURL = AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix() + if (MiscUtil.isEmpty(authURL)) + authURL = pvpReq.getAuthURL(); + + String timeOutURL = authURL + "/idpSingleLogout" + "?restart=" + relayState; @@ -381,7 +404,7 @@ public class AuthenticationManager extends MOAIDAuthConstants { String form = SendAssertionFormBuilder.buildForm(target.requestedModule(), target.requestedAction(), target.getRequestID(), oaParam, - AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix()); + target.getAuthURL()); MOAReversionLogger.getInstance().logEvent(target.getOnlineApplicationConfiguration(), target, MOAIDEventConstants.AUTHPROCESS_SSO_ASK_USER_START); @@ -450,7 +473,7 @@ public class AuthenticationManager extends MOAIDAuthConstants { authReq.setAssertionConsumerServiceIndex(0); authReq.setIssueInstant(new DateTime()); Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); - String serviceURL = PVPConfiguration.getInstance().getIDPPublicPath(); + String serviceURL = PVPConfiguration.getInstance().getIDPPublicPath().get(0); issuer.setValue(serviceURL); issuer.setFormat(NameIDType.ENTITY); @@ -470,28 +493,27 @@ public class AuthenticationManager extends MOAIDAuthConstants { SAML2Utils.createSAMLObject(AuthnContextClassRef.class); //check if STORK protocol module is in ClassPath - Object storkRequst = null; + Class<?> storkRequstTemplate = null; Integer storkSecClass = null; try { - storkRequst = Class.forName("at.gv.egovernment.moa.id.protocols.stork2.MOASTORKRequest").newInstance(); - if (storkRequst != null && - target.getClass().isInstance(storkRequst)) { + storkRequstTemplate = Class.forName("at.gv.egovernment.moa.id.protocols.stork2.MOASTORKRequest"); + if (storkRequstTemplate != null && + storkRequstTemplate.isInstance(target)) { 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) { + } catch (ClassNotFoundException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | java.lang.SecurityException ex) { } - - - if (sp != null && sp.isSTORKPVPGateway()){ + + if (sp != null && sp.isSTORKPVPGateway()) { //use PVP SecClass instead of STORK QAA level String secClass = null; - if (storkRequst != null && - target.getClass().isInstance(storkRequst)) { + if (storkRequstTemplate != null && + storkRequstTemplate.isInstance(target)) { try { secClass = PVPtoSTORKMapper.getInstance().mapToSecClass( @@ -509,8 +531,8 @@ public class AuthenticationManager extends MOAIDAuthConstants { authnClassRef.setAuthnContextClassRef("http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-3"); } else { - if (storkRequst != null && - target.getClass().isInstance(storkRequst)) { + if (storkRequstTemplate != null && + storkRequstTemplate.isInstance(target)) { //use requested QAA level from STORK request try { authnClassRef.setAuthnContextClassRef( @@ -525,7 +547,8 @@ public class AuthenticationManager extends MOAIDAuthConstants { } - if (MiscUtil.isEmpty(authnClassRef.getAuthnContextClassRef())) + if (MiscUtil.isEmpty(authnClassRef.getAuthnContextClassRef())) + //TODO: switch to eIDAS QAA-levels authnClassRef.setAuthnContextClassRef("http://www.stork.gov.eu/1.0/citizenQAALevel/4"); } @@ -692,7 +715,9 @@ public class AuthenticationManager extends MOAIDAuthConstants { //Build authentication form - String publicURLPreFix = AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix(); + String publicURLPreFix = target.getAuthURL(); + if (publicURLPreFix.endsWith("/")) + publicURLPreFix = publicURLPreFix.substring(0, publicURLPreFix.length() - 1); String loginForm = LoginFormBuilder.buildLoginForm(target.requestedModule(), target.requestedAction(), oaParam, publicURLPreFix, moasession.getSessionID()); @@ -714,6 +739,17 @@ public class AuthenticationManager extends MOAIDAuthConstants { out.flush(); } } 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[] { moasession.getProcessInstanceId(), moasession }, e); } } 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..4ae271bbc 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 @@ -49,5 +49,13 @@ public interface IRequest { public List<Attribute> getRequestedAttributes(); public IOAAuthParameters getOnlineApplicationConfiguration(); + /** + * 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(); + //public void setTarget(); } 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..cdaade1bb 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,15 +23,24 @@ package at.gv.egovernment.moa.id.moduls; import java.io.Serializable; +import java.net.MalformedURLException; +import java.net.URL; import java.util.List; +import javax.servlet.http.HttpServletRequest; + import org.opensaml.saml2.core.Attribute; +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.logging.Logger; public abstract class RequestImpl implements IRequest, Serializable{ - + private static final long serialVersionUID = 1L; private String oaURL; @@ -44,12 +53,79 @@ public abstract class RequestImpl implements IRequest, Serializable{ private String requestID; private String sessionIdentifier; private IOAAuthParameters OAConfiguration = null; + private String authURL = null; //MOA-ID interfederation private String requestedIDP = null; private MOAResponse response = null; /** + * @throws ConfigurationException + * + */ + public RequestImpl(HttpServletRequest req) throws ConfigurationException { + 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(); + + } + } + } + + /** * 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 @@ -169,4 +245,27 @@ public abstract class RequestImpl implements IRequest, Serializable{ this.OAConfiguration = oaConfig; } + + /** + * @return the authURL + */ + public String getAuthURL() { + return authURL; + } + + public String getAuthURLWithOutSlash() { + if (authURL.endsWith("/")) + return authURL.substring(0, authURL.length()-1); + else + return authURL; + + } + +// /** +// * @param authURL the authURL to set +// */ +// public void setAuthURL(String authURL) { +// this.authURL = authURL; +// } + } 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..9327cabd7 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 @@ -102,10 +102,10 @@ public class AttributQueryAction implements IAction { 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.getAuthURL(), 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(); 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..50f91df44 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 @@ -110,7 +110,7 @@ public class MetadataAction implements IAction { // .setEntityID(PVPConfiguration.getInstance().getIDPSSOMetadataService()); idpEntityDescriptor - .setEntityID(PVPConfiguration.getInstance().getIDPPublicPath()); + .setEntityID(req.getAuthURLWithOutSlash()); idpEntityDescriptor.setValidUntil(date.plusDays(VALIDUNTIL_IN_HOURS)); @@ -139,10 +139,10 @@ public class MetadataAction implements IAction { idpEntitiesDescriptor.setSignature(signature); //set IDP metadata - idpEntityDescriptor.getRoleDescriptors().add(generateIDPMetadata(keyInfoGenerator)); + idpEntityDescriptor.getRoleDescriptors().add(generateIDPMetadata(req, keyInfoGenerator)); //set SP metadata for interfederation - idpEntityDescriptor.getRoleDescriptors().add(generateSPMetadata(keyInfoGenerator)); + idpEntityDescriptor.getRoleDescriptors().add(generateSPMetadata(req, keyInfoGenerator)); DocumentBuilder builder; DocumentBuilderFactory factory = DocumentBuilderFactory @@ -190,7 +190,7 @@ public class MetadataAction implements IAction { return (PVP2XProtocol.METADATA); } - private RoleDescriptor generateSPMetadata(KeyInfoGenerator keyInfoGenerator) throws CredentialsNotAvailableException, SecurityException, ConfigurationException { + private RoleDescriptor generateSPMetadata(IRequest req, KeyInfoGenerator keyInfoGenerator) throws CredentialsNotAvailableException, SecurityException, ConfigurationException { Logger.debug("Set SP Metadata key information"); @@ -248,7 +248,7 @@ public class MetadataAction implements IAction { postassertionConsumerService.setIndex(0); postassertionConsumerService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI); postassertionConsumerService.setLocation(PVPConfiguration - .getInstance().getSPSSOPostService()); + .getInstance().getSPSSOPostService(req.getAuthURL())); postassertionConsumerService.setIsDefault(true); spSSODescriptor.getAssertionConsumerServices().add(postassertionConsumerService); @@ -257,7 +257,7 @@ public class MetadataAction implements IAction { redirectassertionConsumerService.setIndex(1); redirectassertionConsumerService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); redirectassertionConsumerService.setLocation(PVPConfiguration - .getInstance().getSPSSORedirectService()); + .getInstance().getSPSSORedirectService(req.getAuthURL())); spSSODescriptor.getAssertionConsumerServices().add(redirectassertionConsumerService); @@ -273,7 +273,7 @@ public class MetadataAction implements IAction { SingleLogoutService redirectSLOService = SAML2Utils.createSAMLObject(SingleLogoutService.class); redirectSLOService.setLocation(PVPConfiguration - .getInstance().getSPSSORedirectService()); + .getInstance().getSPSSORedirectService(req.getAuthURL())); redirectSLOService .setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); spSSODescriptor.getSingleLogoutServices().add(redirectSLOService); @@ -293,7 +293,7 @@ public class MetadataAction implements IAction { return spSSODescriptor; } - private IDPSSODescriptor generateIDPMetadata(KeyInfoGenerator keyInfoGenerator) throws ConfigurationException, CredentialsNotAvailableException, SecurityException { + private IDPSSODescriptor generateIDPMetadata(IRequest req, KeyInfoGenerator keyInfoGenerator) throws ConfigurationException, CredentialsNotAvailableException, SecurityException { // //set SignatureMethode @@ -325,12 +325,12 @@ public class MetadataAction implements IAction { idpSSODescriptor.setWantAuthnRequestsSigned(true); - if (PVPConfiguration.getInstance().getIDPSSOPostService() != null) { + if (PVPConfiguration.getInstance().getIDPSSOPostService(req.getAuthURL()) != null) { //add SSO descriptor SingleSignOnService postSingleSignOnService = SAML2Utils .createSAMLObject(SingleSignOnService.class); postSingleSignOnService.setLocation(PVPConfiguration - .getInstance().getIDPSSOPostService()); + .getInstance().getIDPSSOPostService(req.getAuthURL())); postSingleSignOnService .setBinding(SAMLConstants.SAML2_POST_BINDING_URI); idpSSODescriptor.getSingleSignOnServices().add( @@ -347,12 +347,12 @@ public class MetadataAction implements IAction { } - if (PVPConfiguration.getInstance().getIDPSSORedirectService() != null) { + if (PVPConfiguration.getInstance().getIDPSSORedirectService(req.getAuthURL()) != null) { //add SSO descriptor SingleSignOnService redirectSingleSignOnService = SAML2Utils .createSAMLObject(SingleSignOnService.class); redirectSingleSignOnService.setLocation(PVPConfiguration - .getInstance().getIDPSSORedirectService()); + .getInstance().getIDPSSORedirectService(req.getAuthURL())); redirectSingleSignOnService .setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); idpSSODescriptor.getSingleSignOnServices().add( @@ -362,7 +362,7 @@ public class MetadataAction implements IAction { SingleLogoutService redirectSLOService = SAML2Utils.createSAMLObject(SingleLogoutService.class); redirectSLOService.setLocation(PVPConfiguration - .getInstance().getIDPSSORedirectService()); + .getInstance().getIDPSSORedirectService(req.getAuthURL())); redirectSLOService .setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); idpSSODescriptor.getSingleLogoutServices().add(redirectSLOService); 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..ee5685e5f 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 @@ -24,6 +24,7 @@ package at.gv.egovernment.moa.id.protocols.pvp2x; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -55,8 +56,6 @@ import org.opensaml.xml.io.MarshallingException; import org.opensaml.xml.security.SecurityException; import org.opensaml.xml.signature.SignableXMLObject; -import java.util.Arrays; - import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger; import at.gv.egovernment.moa.id.advancedlogging.TransactionIDUtils; @@ -76,12 +75,9 @@ 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.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,12 +88,16 @@ 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.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; @@ -210,7 +210,7 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { if(METADATA.equals(action)) { - return new PVPTargetConfiguration(); + return new PVPTargetConfiguration(request); } @@ -231,7 +231,7 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { SAMLVerificationEngine engine = new SAMLVerificationEngine(); engine.verify(msg, TrustEngineFactory.getSignatureKnownKeysTrustEngine()); msg.setVerified(true); - + } if (msg instanceof MOARequest && @@ -387,7 +387,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); @@ -460,7 +460,7 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { HttpServletResponse response, InboundMessage inMsg, String sessionId, String transactionId) throws MOAIDException { - PVPTargetConfiguration config = new PVPTargetConfiguration(); + PVPTargetConfiguration config = new PVPTargetConfiguration(request); MOARequest msg; if (inMsg instanceof MOARequest && @@ -496,13 +496,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(); @@ -533,7 +544,7 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { //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,7 +569,7 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { } - PVPTargetConfiguration config = new PVPTargetConfiguration(); + PVPTargetConfiguration config = new PVPTargetConfiguration(request); config.setRequest(moaRequest); config.setOAURL(moaRequest.getEntityID()); config.setOnlineApplicationConfiguration(oa); @@ -586,7 +597,7 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { if(!(samlReq instanceof AuthnRequest)) { throw new MOAIDException("Unsupported request", new Object[] {}); } - + EntityDescriptor metadata = moaRequest.getEntityMetadata(); if(metadata == null) { throw new NoMetadataInformationException(); @@ -607,14 +618,30 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { } + //parse AssertionConsumerService 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 +660,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,7 +697,7 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo { Logger.info("Dispatch PVP2 AuthnRequest: OAURL=" + oaURL + " Binding=" + consumerService.getBinding()); - PVPTargetConfiguration config = new PVPTargetConfiguration(); + PVPTargetConfiguration config = new PVPTargetConfiguration(request); config.setOAURL(oaURL); config.setOnlineApplicationConfiguration(oa); config.setBinding(consumerService.getBinding()); 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..0b402a0fd 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 @@ -26,6 +26,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.servlet.http.HttpServletRequest; + import org.opensaml.common.xml.SAMLConstants; import org.opensaml.saml2.core.Attribute; import org.opensaml.saml2.core.impl.AuthnRequestImpl; @@ -46,6 +48,16 @@ import at.gv.egovernment.moa.logging.Logger; public class PVPTargetConfiguration extends RequestImpl { + /** + * @param req + * @throws ConfigurationException + */ + public PVPTargetConfiguration(HttpServletRequest req) + throws ConfigurationException { + super(req); + + } + private static final long serialVersionUID = 4889919265919638188L; InboundMessage request; 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..582f5939d 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,20 @@ 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 at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; @@ -67,35 +45,22 @@ 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.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.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; @@ -134,7 +99,7 @@ public class SingleLogOutAction implements IAction { SSOManager ssomanager = SSOManager.getInstance(); String ssoID = ssomanager.getSSOSessionID(httpReq); if (MiscUtil.isEmpty(ssoID)) { - Logger.warn("Can not find active Session. Single LogOut not possible!"); + Logger.info("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); @@ -148,7 +113,7 @@ public class SingleLogOutAction implements IAction { session = AuthenticationSessionStoreage.getSession(moasession); } catch (MOADatabaseException e) { - Logger.warn("Can not find active Session. Single LogOut not possible!"); + Logger.info("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); @@ -259,7 +224,7 @@ public class SingleLogOutAction implements IAction { } else { //print SLO information directly - redirectURL = AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix() + "/idpSingleLogout"; + redirectURL = req.getAuthURL() + "/idpSingleLogout"; String artifact = Random.nextRandom(); @@ -275,7 +240,7 @@ public class SingleLogOutAction implements IAction { } //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/PostBinding.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/PostBinding.java index 65400444d..b8f7e6d80 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 @@ -33,28 +33,26 @@ 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; @@ -62,6 +60,9 @@ 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; @@ -159,11 +160,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 +172,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 +207,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..f48d216dd 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 @@ -62,6 +62,7 @@ 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; @@ -149,11 +150,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..c1e94ff36 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 @@ -37,7 +37,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; @@ -51,7 +50,6 @@ import org.opensaml.xml.signature.SignableXMLObject; 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; @@ -72,9 +70,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 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..ebbafd4e3 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 @@ -127,7 +127,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); 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/SingleLogOutBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java index 50f42d928..dbbc21ec9 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 @@ -27,8 +27,11 @@ 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,15 +46,18 @@ 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.w3c.dom.Document; import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; @@ -63,7 +69,6 @@ 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; @@ -215,8 +220,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,7 +233,35 @@ 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; } @@ -277,7 +310,7 @@ public class SingleLogOutBuilder { private static 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()); 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..065118e2b 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 @@ -90,7 +90,7 @@ import at.gv.egovernment.moa.util.MiscUtil; public class PVP2AssertionBuilder implements PVPConstants { - public static Assertion buildAssertion(AttributeQuery attrQuery, + public static Assertion buildAssertion(String authURL, AttributeQuery attrQuery, List<String> reqAttributes, IAuthData authData, DateTime date, String sessionIndex) throws ConfigurationException { @@ -136,12 +136,12 @@ public class PVP2AssertionBuilder implements PVPConstants { SubjectConfirmationData subjectConfirmationData = null; - return buildGenericAssertion(attrQuery.getIssuer().getValue(), date, + return buildGenericAssertion(authURL, attrQuery.getIssuer().getValue(), date, authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex, new DateTime(authData.getSsoSessionValidTo().getTime())); } - public static Assertion buildAssertion(AuthnRequest authnRequest, + public static Assertion buildAssertion(String authURL, AuthnRequest authnRequest, IAuthData authData, EntityDescriptor peerEntity, DateTime date, AssertionConsumerService assertionConsumerService, SLOInformationImpl sloInformation) throws MOAIDException { @@ -416,10 +416,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(authURL, peerEntity.getEntityID(), date, authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex, subjectConfirmationData.getNotOnOrAfter()); } - public static Assertion buildGenericAssertion(String entityID, DateTime date, + /** + * + * @param authURL 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 + */ + + private static Assertion buildGenericAssertion(String authURL, String entityID, DateTime date, AuthnContextClassRef authnContextClassRef, List<Attribute> attrList, NameID subjectNameID, SubjectConfirmationData subjectConfirmationData, String sessionIndex, DateTime isValidTo) throws ConfigurationException { @@ -471,7 +486,9 @@ public class PVP2AssertionBuilder implements PVPConstants { Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); - issuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath()); + 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/PVPConfiguration.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/PVPConfiguration.java index dc3b787e4..47d7a29b3 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 @@ -121,43 +121,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 getIDPSSOMetadataService(String publicURLPrefix) throws ConfigurationException { + return publicURLPrefix + PVP2_METADATA; } public String getIDPKeyStoreFilename() { 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/AuthnRequestHandler.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/requestHandler/AuthnRequestHandler.java index a31258784..059e68865 100644 --- 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 @@ -82,10 +82,10 @@ public class AuthnRequestHandler implements IRequestHandler, PVPConstants { SLOInformationImpl sloInformation = new SLOInformationImpl(); //build Assertion - Assertion assertion = PVP2AssertionBuilder.buildAssertion(authnRequest, authData, + Assertion assertion = PVP2AssertionBuilder.buildAssertion(obj.getAuthURL(), authnRequest, authData, peerEntity, date, consumerService, sloInformation); - Response authResponse = AuthResponseBuilder.buildResponse(authnRequest, date, assertion); + Response authResponse = AuthResponseBuilder.buildResponse(obj.getAuthURL(), authnRequest, date, assertion); IEncoder binding = null; 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/SAMLVerificationEngine.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java index 70b778c49..812e27a36 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; @@ -61,7 +62,7 @@ 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.AuthConfigurationProviderFactory; 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; @@ -74,7 +75,6 @@ import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; public class SAMLVerificationEngine { - public void verify(InboundMessage msg, SignatureTrustEngine sigTrustEngine ) throws org.opensaml.xml.security.SecurityException, Exception { try { @@ -83,7 +83,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 +102,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 +136,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 { @@ -175,10 +184,20 @@ public class SAMLVerificationEngine { 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())) { + List<String> allowedPublicURLPrefix = + AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix(); + boolean isValidDestination = false; + for (String allowedPreFix : allowedPublicURLPrefix) { + if (validateDestination && samlResp.getDestination().startsWith( + allowedPreFix)) { + isValidDestination = true; + break; + + } + } + if (!isValidDestination) { 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); } 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/AuthenticationSessionStoreage.java index d1582b883..9dee39fe8 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/AuthenticationSessionStoreage.java @@ -377,7 +377,7 @@ public class AuthenticationSessionStoreage { } public static void addSSOInformation(String moaSessionID, String SSOSessionID, - SLOInformationInterface SLOInfo, String OAUrl) throws AuthenticationException { + SLOInformationInterface SLOInfo, IRequest protocolRequest) throws AuthenticationException { AuthenticatedSessionStore dbsession; Transaction tx = null; @@ -412,7 +412,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 +421,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 +432,7 @@ public class AuthenticationSessionStoreage { activeOA.setUserNameIDFormat(SLOInfo.getUserNameIDFormat()); activeOA.setProtocolType(SLOInfo.getProtocolType()); activeOA.setAttributeQueryUsed(false); + activeOA.setAuthURL(protocolRequest.getAuthURL()); } @@ -463,10 +464,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()); } @@ -887,6 +888,7 @@ public class AuthenticationSessionStoreage { idp = new InterfederationSessionStore(); idp.setCreated(now); idp.setIdpurlprefix(req.getInterfederationResponse().getEntityID()); + idp.setAuthURL(req.getAuthURL()); try { OAAuthParameter oa = AuthConfigurationProviderFactory.getInstance(). 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..2aceb833c 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,21 @@ 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; + + } } |