From da937437e46e06365072820aa555d4cb3f9f9110 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Wed, 2 Mar 2016 22:10:36 +0100 Subject: next parts of new federated authentication implementation --- .../id/auth/builder/AuthenticationDataBuilder.java | 226 ++++++++++++--------- .../builder/DynamicOAAuthParameterBuilder.java | 71 ++----- 2 files changed, 146 insertions(+), 151 deletions(-) (limited to 'id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder') 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 999f289e0..8b9918eab 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 @@ -32,6 +32,7 @@ import java.util.Arrays; import java.util.Date; import java.util.Iterator; import java.util.List; +import java.util.Set; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -45,6 +46,9 @@ import javax.xml.bind.Marshaller; import org.opensaml.saml2.core.Attribute; import org.opensaml.saml2.core.AttributeQuery; import org.opensaml.saml2.core.AuthnStatement; +import org.opensaml.saml2.core.Response; +import org.opensaml.ws.soap.common.SOAPException; +import org.opensaml.xml.XMLObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.w3c.dom.Element; @@ -77,7 +81,9 @@ import at.gv.egovernment.moa.id.commons.db.dao.session.OASessionStore; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; import at.gv.egovernment.moa.id.config.ConfigurationException; import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; import at.gv.egovernment.moa.id.data.AuthenticationData; import at.gv.egovernment.moa.id.data.AuthenticationRoleFactory; import at.gv.egovernment.moa.id.data.IAuthData; @@ -86,13 +92,16 @@ import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.id.moduls.RequestImpl; import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration; +import at.gv.egovernment.moa.id.protocols.pvp2x.builder.AttributQueryBuilder; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AssertionAttributeExtractorExeption; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AssertionValidationExeption; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AttributQueryException; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOAResponse; +import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider; import at.gv.egovernment.moa.id.protocols.pvp2x.utils.AssertionAttributeExtractor; import at.gv.egovernment.moa.id.protocols.pvp2x.utils.MOASAMLSOAPClient; +import at.gv.egovernment.moa.id.protocols.pvp2x.verification.SAMLVerificationEngine; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.TrustEngineFactory; import at.gv.egovernment.moa.id.storage.IAuthenticationSessionStoreage; import at.gv.egovernment.moa.id.util.IdentityLinkReSigner; @@ -118,9 +127,11 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { @Autowired private IAuthenticationSessionStoreage authenticatedSessionStorage; @Autowired protected AuthConfiguration authConfig; + @Autowired private AttributQueryBuilder attributQueryBuilder; + @Autowired private SAMLVerificationEngine samlVerificationEngine; public IAuthData buildAuthenticationDataForAttributQuery(IRequest pendingReq, - AuthenticationSession session, List reqAttributes) { + AuthenticationSession session, List reqAttributes, InterfederationSessionStore nextIDPInformation) throws MOAIDException { AuthenticationData authdata = new AuthenticationData(); try { @@ -146,134 +157,147 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants { } } } - - getAuthDataFromInterfederation(authdata, session, spConfig, pendingReq, interfIDP, idp, reqAttributes); - - - - + //build OnlineApplication dynamic from requested attributes (AttributeQuerry Request) and configuration + IOAAuthParameters spConfig = DynamicOAAuthParameterBuilder.buildFromAttributeQuery(reqAttributes); - //mark attribute request as used - try { - interfIDP.setAttributesRequested(true); - MOASessionDBUtils.saveOrUpdate(interfIDP); - - } catch (MOADatabaseException e) { - Logger.error("MOASession interfederation information can not stored to database.", e); + //search federated IDP information for this MOASession + if (nextIDPInformation != null) { + Logger.info("Find active federated IDP information." + + ". --> Request next IDP:" + nextIDPInformation.getIdpurlprefix() + + " for authentication information."); + + //load configuration of next IDP + OAAuthParameter idp = authConfig.getOnlineApplicationParameter(nextIDPInformation.getIdpurlprefix()); + if (idp == null) { + Logger.warn("Configuration for federated IDP:" + nextIDPInformation.getIdpurlprefix() + + "is not loadable."); + throw new MOAIDException("auth.32", new Object[]{nextIDPInformation.getIdpurlprefix()}); + + } + + //check if next IDP config allows inbound messages + if (!idp.isInboundSSOInterfederationAllowed()) { + Logger.warn("Configuration for federated IDP:" + nextIDPInformation.getIdpurlprefix() + + "disallow inbound authentication messages."); + throw new MOAIDException("auth.33", new Object[]{nextIDPInformation.getIdpurlprefix()}); + + } + + //check next IDP service area policy. BusinessService IDPs can only request wbPKs + if (!spConfig.getBusinessService() && !idp.isIDPPublicService()) { + Logger.error("Interfederated IDP " + idp.getPublicURLPrefix() + + " has a BusinessService-IDP but requests PublicService attributes."); + throw new MOAIDException("auth.34", new Object[]{nextIDPInformation.getIdpurlprefix()}); + + } + + //validation complete --> start AttributeQuery Request + getAuthDataFromInterfederation(authdata, reqAttributes, nextIDPInformation, idp); + + } else { + Logger.debug("Build authData for AttributQuery from local MOASession."); + buildAuthDataFormMOASession(authdata, session, spConfig, pendingReq); } - - + return authdata; - - } catch (DynamicOABuildException e) { - //TODO: - + + } catch (MOAIDException e) { + throw e; } } private void getAuthDataFromInterfederation( - AuthenticationData authdata, AuthenticationSession session, - IOAAuthParameters oaParam, IRequest req, - InterfederationSessionStore interfIDP, OAAuthParameter idp, List reqQueryAttr) throws BuildException, ConfigurationException{ + AuthenticationData authdata, List reqQueryAttr, + InterfederationSessionStore nextIDPInfo, OAAuthParameter nextIDPConfig ) throws MOAIDException{ + String idpEnityID = nextIDPConfig.getPublicURLPrefix(); + AssertionAttributeExtractor extractor; try { - List attributs = null; - - //IDP is a chained interfederated IDP and request is of type AttributQuery - if (oaParam.isInderfederationIDP() && req instanceof PVPTargetConfiguration && - (((PVPTargetConfiguration)req).getRequest() instanceof AttributeQuery) && - reqQueryAttr != null) { - attributs = reqQueryAttr; - - //IDP is a service provider IDP and request interfederated IDP to collect attributes - } else { - //get PVP 2.1 attributes from protocol specific requested attributes - attributs = (List) req.getGenericData(RequestImpl.DATAID_REQUESTED_ATTRIBUTES); + Logger.debug("Starting AttributeQuery process ..."); + //collect attributes by using BackChannel communication + String endpoint = nextIDPConfig.getIDPAttributQueryServiceURL(); + if (MiscUtil.isEmpty(endpoint)) { + Logger.error("No AttributeQueryURL for interfederationIDP " + idpEnityID); + throw new ConfigurationException("config.26", new Object[]{idpEnityID}); } - - //get SAML2 Response from federated IDP - Response intfResp = - (Response) req.getGenericData( - RequestImpl.DATAID_INTERFEDERATIOIDP_RESPONSE, MOAResponse.class).getResponse(); - - //initialize Attribute extractor - AssertionAttributeExtractor extractor = new AssertionAttributeExtractor(intfResp); - - //check if SAML2 Assertion contains already all required attributes - if (!extractor.containsAllRequiredAttributes()) { - Logger.info("Received assertion does no contain a minimum set of attributes. Starting AttributeQuery process ..."); - //collect attributes by using BackChannel communication - String endpoint = idp.getIDPAttributQueryServiceURL(); - if (MiscUtil.isEmpty(endpoint)) { - Logger.error("No AttributeQueryURL for interfederationIDP " + idp.getPublicURLPrefix()); - throw new ConfigurationException("No AttributeQueryURL for interfederationIDP " + idp.getPublicURLPrefix(), null); - } - //build attributQuery request - AttributeQuery query = - attributQueryBuilder.buildAttributQueryRequest(interfIDP.getUserNameID(), endpoint, attributs); + //build attributQuery request + AttributeQuery query = attributQueryBuilder.buildAttributQueryRequest(nextIDPInfo.getUserNameID(), endpoint, reqQueryAttr); - //build SOAP request - List xmlObjects = MOASAMLSOAPClient.send(endpoint, query); + //build SOAP request + List xmlObjects = MOASAMLSOAPClient.send(endpoint, query); + + if (xmlObjects.size() == 0) { + Logger.error("Receive emptry AttributeQuery response-body."); + throw new AttributQueryException("auth.27", + new Object[]{idpEnityID, "Receive emptry AttributeQuery response-body."}); - if (xmlObjects.size() == 0) { - Logger.error("Receive emptry AttributeQuery response-body."); - throw new AttributQueryException("Receive emptry AttributeQuery response-body.", null); - - } + } + + Response intfResp; + if (xmlObjects.get(0) instanceof Response) { + intfResp = (Response) xmlObjects.get(0); - if (xmlObjects.get(0) instanceof Response) { - intfResp = (Response) xmlObjects.get(0); - - //validate PVP 2.1 response - try { - samlVerificationEngine.verifyIDPResponse(intfResp, TrustEngineFactory.getSignatureKnownKeysTrustEngine()); - - //TODO: find better solution - //SAMLVerificationEngine.validateAssertion(intfResp, false); - - } catch (Exception e) { - Logger.warn("PVP 2.1 assertion validation FAILED.", e); - throw new AssertionValidationExeption("PVP 2.1 assertion validation FAILED.", null, e); + //validate PVP 2.1 response + try { + samlVerificationEngine.verifyIDPResponse(intfResp, + TrustEngineFactory.getSignatureKnownKeysTrustEngine( + MOAMetadataProvider.getInstance())); + + //create assertion attribute extractor from AttributeQuery response + extractor = new AssertionAttributeExtractor(intfResp); + + //copy attributes into authData object + Set includedAttrNames = extractor.getAllIncludeAttributeNames(); + for (String el : includedAttrNames) { + authdata.setGenericData(el, extractor.getSingleAttributeValue(el)); + Logger.debug("Add PVP-attribute " + el + " into authData objext"); + } - - } else { - Logger.error("Receive AttributeQuery response-body include no PVP 2.1 response"); - throw new AttributQueryException("Receive AttributeQuery response-body include no PVP 2.1 response.", null); - + + + } catch (Exception e) { + Logger.warn("PVP 2.1 assertion validation FAILED.", e); + throw new AssertionValidationExeption("auth.27", + new Object[]{idpEnityID, e.getMessage()}, e); } - - //create assertion attribute extractor from AttributeQuery response - extractor = new AssertionAttributeExtractor(intfResp); - + } else { - Logger.info("Interfedation response include all attributes with are required. Skip AttributQuery request step. "); + Logger.error("Receive AttributeQuery response-body include no PVP 2.1 response"); + throw new AttributQueryException("auth.27", + new Object[]{idpEnityID, "Receive AttributeQuery response-body include no PVP 2.1 response"}); + + } + + try { + //mark attribute request as used + if (nextIDPInfo.isStoreSSOInformation()) { + nextIDPInfo.setAttributesRequested(true); + MOASessionDBUtils.saveOrUpdate(nextIDPInfo); + + //delete federated IDP from Session + } else { + MOASessionDBUtils.delete(nextIDPInfo); + + } + + } catch (MOADatabaseException e) { + Logger.error("MOASession interfederation information can not stored to database.", e); } - //parse response information to authData - buildAuthDataFormInterfederationResponse(authdata, session, extractor, oaParam, req); - + } catch (SOAPException e) { throw new BuildException("builder.06", null, e); } catch (SecurityException e) { throw new BuildException("builder.06", null, e); - - } catch (AttributQueryException e) { - throw new BuildException("builder.06", null, e); - - } catch (BuildException e) { - throw new BuildException("builder.06", null, e); - - } catch (AssertionValidationExeption e) { - throw new BuildException("builder.06", null, e); - - } catch (AssertionAttributeExtractorExeption e) { - throw new BuildException("builder.06", null, e); + + } catch (org.opensaml.xml.security.SecurityException e1) { + throw new BuildException("builder.06", null, e1); } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/DynamicOAAuthParameterBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/DynamicOAAuthParameterBuilder.java index ab43f2f79..8c0de1121 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/DynamicOAAuthParameterBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/DynamicOAAuthParameterBuilder.java @@ -38,6 +38,7 @@ import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.Constants; +import at.gv.egovernment.moa.util.MiscUtil; /** * @author tlenz @@ -45,65 +46,35 @@ import at.gv.egovernment.moa.util.Constants; */ public class DynamicOAAuthParameterBuilder { - public static IOAAuthParameters buildFromAttributeQuery(OAAuthParameter oa, List reqAttributes, InterfederationSessionStore interfIDP) throws DynamicOABuildException { + public static IOAAuthParameters buildFromAttributeQuery(List reqAttributes) throws DynamicOABuildException { Logger.debug("Build dynamic OAConfiguration from AttributeQuery and interfederation information"); - try { - DynamicOAAuthParameters dynamicOA = new DynamicOAAuthParameters(); - - for (Attribute attr : reqAttributes) { - //get Target or BusinessService from request - if (attr.getName().equals(PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME)) { - String attrValue = attr.getAttributeValues().get(0).getDOM().getTextContent(); - if (attrValue.startsWith(Constants.URN_PREFIX_CDID)) { - dynamicOA.setBusinessService(false); - dynamicOA.setTarget(attrValue.substring((Constants.URN_PREFIX_CDID + "+").length())); - - } else if( attrValue.startsWith(Constants.URN_PREFIX_WBPK) || - attrValue.startsWith(Constants.URN_PREFIX_STORK) ) { - dynamicOA.setBusinessService(true); - dynamicOA.setTarget(attrValue); - - } else { - Logger.error("Sector identification " + attrValue + " is not a valid Target or BusinessServiceArea"); - throw new DynamicOABuildException("Sector identification " + attrValue + " is not a valid Target or BusinessServiceArea", null); - - } - - } + DynamicOAAuthParameters dynamicOA = new DynamicOAAuthParameters(); - } - - if (interfIDP != null) { - //load interfederated IDP informations - OAAuthParameter idp = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(interfIDP.getIdpurlprefix()); - if (idp == null) { - Logger.warn("Interfederated IDP configuration is not loadable."); - throw new DynamicOABuildException("Interfederated IDP configuration is not loadable.", null); + for (Attribute attr : reqAttributes) { + //get Target or BusinessService from request + if (attr.getName().equals(PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME)) { + String attrValue = attr.getAttributeValues().get(0).getDOM().getTextContent(); + if (attrValue.startsWith(Constants.URN_PREFIX_CDID)) { + dynamicOA.setBusinessService(false); + dynamicOA.setTarget(attrValue.substring((Constants.URN_PREFIX_CDID + "+").length())); + + } else if( attrValue.startsWith(Constants.URN_PREFIX_WBPK) || + attrValue.startsWith(Constants.URN_PREFIX_STORK) ) { + dynamicOA.setBusinessService(true); + dynamicOA.setTarget(attrValue); + + } else { + Logger.error("Sector identification " + attrValue + " is not a valid Target or BusinessServiceArea"); + throw new DynamicOABuildException("Sector identification " + attrValue + " is not a valid Target or BusinessServiceArea", null); } - - dynamicOA.setApplicationID(idp.getPublicURLPrefix()); - dynamicOA.setInderfederatedIDP(idp.isInderfederationIDP()); - dynamicOA.setIDPQueryURL(idp.getIDPAttributQueryServiceURL()); - //check if IDP service area policy. BusinessService IDPs can only request wbPKs - if (!dynamicOA.getBusinessService() && !idp.isIDPPublicService()) { - Logger.error("Interfederated IDP " + idp.getPublicURLPrefix() - + " has a BusinessService-IDP but requests PublicService attributes."); - throw new DynamicOABuildException("Interfederated IDP " + idp.getPublicURLPrefix() - + " has a BusinessService-IDP but requests PublicService attributes.", null); - - } } - return dynamicOA; - - } catch (ConfigurationException e) { - Logger.warn("Internel server errror. Basic configuration load failed.", e); - throw new DynamicOABuildException("Basic configuration load failed.", null); - } + } + return dynamicOA; -- cgit v1.2.3