diff options
Diffstat (limited to 'id/server/modules/moa-id-modules-federated_authentication')
5 files changed, 231 insertions, 15 deletions
diff --git a/id/server/modules/moa-id-modules-federated_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/federatedauth/FederatedAuthConstants.java b/id/server/modules/moa-id-modules-federated_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/federatedauth/FederatedAuthConstants.java index e2f851132..1f7f27617 100644 --- a/id/server/modules/moa-id-modules-federated_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/federatedauth/FederatedAuthConstants.java +++ b/id/server/modules/moa-id-modules-federated_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/federatedauth/FederatedAuthConstants.java @@ -28,6 +28,8 @@ package at.gv.egovernment.moa.id.auth.modules.federatedauth; */ public class FederatedAuthConstants { + public static final String MODULE_NAME_FOR_LOGGING = "federated IDP"; + public static final int METADATA_VALIDUNTIL_IN_HOURS = 24; public static final String ENDPOINT_POST = "/sp/federated/post"; diff --git a/id/server/modules/moa-id-modules-federated_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/federatedauth/config/FederatedAuthMetadataConfiguration.java b/id/server/modules/moa-id-modules-federated_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/federatedauth/config/FederatedAuthMetadataConfiguration.java index 29b6ea18b..0f2c85350 100644 --- a/id/server/modules/moa-id-modules-federated_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/federatedauth/config/FederatedAuthMetadataConfiguration.java +++ b/id/server/modules/moa-id-modules-federated_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/federatedauth/config/FederatedAuthMetadataConfiguration.java @@ -278,4 +278,13 @@ public class FederatedAuthMetadataConfiguration implements IPVPMetadataBuilderCo } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPMetadataBuilderConfiguration#getSPNameForLogging() + */ + @Override + public String getSPNameForLogging() { + return FederatedAuthConstants.MODULE_NAME_FOR_LOGGING; + } + } diff --git a/id/server/modules/moa-id-modules-federated_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/federatedauth/config/FederatedAuthnRequestBuilderConfiguration.java b/id/server/modules/moa-id-modules-federated_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/federatedauth/config/FederatedAuthnRequestBuilderConfiguration.java index eca5c7649..4ae162f5a 100644 --- a/id/server/modules/moa-id-modules-federated_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/federatedauth/config/FederatedAuthnRequestBuilderConfiguration.java +++ b/id/server/modules/moa-id-modules-federated_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/federatedauth/config/FederatedAuthnRequestBuilderConfiguration.java @@ -27,6 +27,7 @@ import org.opensaml.saml2.core.NameID; import org.opensaml.saml2.metadata.EntityDescriptor; import org.opensaml.xml.security.credential.Credential; +import at.gv.egovernment.moa.id.auth.modules.federatedauth.FederatedAuthConstants; import at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPAuthnRequestBuilderConfiguruation; /** @@ -157,5 +158,22 @@ public class FederatedAuthnRequestBuilderConfiguration implements IPVPAuthnReque return null; } + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPAuthnRequestBuilderConfiguruation#getSPNameForLogging() + */ + @Override + public String getSPNameForLogging() { + return FederatedAuthConstants.MODULE_NAME_FOR_LOGGING; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.pvp2x.config.IPVPAuthnRequestBuilderConfiguruation#getSubjectNameIDFormat() + */ + @Override + public String getSubjectNameIDFormat() { + // TODO Auto-generated method stub + return null; + } + } diff --git a/id/server/modules/moa-id-modules-federated_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/federatedauth/tasks/CreateAuthnRequestTask.java b/id/server/modules/moa-id-modules-federated_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/federatedauth/tasks/CreateAuthnRequestTask.java index 2e134713b..06664af45 100644 --- a/id/server/modules/moa-id-modules-federated_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/federatedauth/tasks/CreateAuthnRequestTask.java +++ b/id/server/modules/moa-id-modules-federated_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/federatedauth/tasks/CreateAuthnRequestTask.java @@ -89,7 +89,7 @@ public class CreateAuthnRequestTask extends AbstractAuthServletTask { Logger.debug("isInderfederationIDP:" + String.valueOf(idpConfig.isInderfederationIDP()) + " isInboundSSOAllowed:" + String.valueOf(idpConfig.isInboundSSOInterfederationAllowed())); - handleAuthnRequestBuildProblem(executionContext, idpConfig, "sp.pvp2.01", new Object[]{idpEntityID}); + handleAuthnRequestBuildProblem(executionContext, idpConfig, "sp.pvp2.01", new Object[]{FederatedAuthConstants.MODULE_NAME_FOR_LOGGING, idpEntityID}); return; @@ -102,7 +102,7 @@ public class CreateAuthnRequestTask extends AbstractAuthServletTask { Logger.warn("Requested IDP " + idpEntityID + " has no valid metadata or metadata is not found"); - handleAuthnRequestBuildProblem(executionContext, idpConfig, "sp.pvp2.02", new Object[]{idpEntityID}); + handleAuthnRequestBuildProblem(executionContext, idpConfig, "sp.pvp2.02", new Object[]{FederatedAuthConstants.MODULE_NAME_FOR_LOGGING, idpEntityID}); return; } diff --git a/id/server/modules/moa-id-modules-federated_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/federatedauth/tasks/ReceiveAuthnResponseTask.java b/id/server/modules/moa-id-modules-federated_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/federatedauth/tasks/ReceiveAuthnResponseTask.java index 49f9782ae..d87109244 100644 --- a/id/server/modules/moa-id-modules-federated_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/federatedauth/tasks/ReceiveAuthnResponseTask.java +++ b/id/server/modules/moa-id-modules-federated_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/federatedauth/tasks/ReceiveAuthnResponseTask.java @@ -23,14 +23,21 @@ package at.gv.egovernment.moa.id.auth.modules.federatedauth.tasks; import java.io.IOException; +import java.util.Collection; +import java.util.List; +import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.transform.TransformerException; +import org.opensaml.saml2.core.Attribute; +import org.opensaml.saml2.core.AttributeQuery; import org.opensaml.saml2.core.Response; import org.opensaml.saml2.core.StatusCode; import org.opensaml.ws.message.decoder.MessageDecodingException; +import org.opensaml.ws.soap.common.SOAPException; +import org.opensaml.xml.XMLObject; import org.opensaml.xml.io.MarshallingException; import org.opensaml.xml.security.SecurityException; import org.springframework.beans.factory.annotation.Autowired; @@ -38,25 +45,39 @@ import org.springframework.stereotype.Component; import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; +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.SessionDataStorageException; import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.auth.modules.federatedauth.FederatedAuthConstants; import at.gv.egovernment.moa.id.auth.modules.federatedauth.utils.FederatedAuthCredentialProvider; +import at.gv.egovernment.moa.id.config.ConfigurationException; +import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.data.FederatedAuthenticatenContainer; import at.gv.egovernment.moa.id.moduls.RequestImpl; import at.gv.egovernment.moa.id.moduls.SSOManager; import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration; import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IDecoder; 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.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.exceptions.AuthnResponseValidationException; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessage; 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.CredentialsNotAvailableException; +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.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.ITransactionStorage; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; @@ -67,9 +88,12 @@ import at.gv.egovernment.moa.util.MiscUtil; @Component("ReceiveFederatedAuthnResponseTask") public class ReceiveAuthnResponseTask extends AbstractAuthServletTask { - @Autowired SAMLVerificationEngine samlVerificationEngine; - @Autowired FederatedAuthCredentialProvider credentialProvider; - @Autowired SSOManager ssoManager; + @Autowired private SAMLVerificationEngine samlVerificationEngine; + @Autowired private FederatedAuthCredentialProvider credentialProvider; + @Autowired private SSOManager ssoManager; + @Autowired private AttributQueryBuilder attributQueryBuilder; + @Autowired private ITransactionStorage transactionStorage; + /* (non-Javadoc) * @see at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) @@ -94,21 +118,21 @@ public class ReceiveAuthnResponseTask extends AbstractAuthServletTask { } else { Logger.warn("Receive PVP Response, but Binding (" + request.getMethod() + ") is not supported."); - throw new AuthnResponseValidationException("sp.pvp2.03", null); + throw new AuthnResponseValidationException("sp.pvp2.03", new Object[] {FederatedAuthConstants.MODULE_NAME_FOR_LOGGING}); } //decode PVP response object - msg = (InboundMessage) decoder.decode(request, response, true); + msg = (InboundMessage) decoder.decode(request, response, MOAMetadataProvider.getInstance(), true); if (MiscUtil.isEmpty(msg.getEntityID())) { - throw new InvalidProtocolRequestException("sp.pvp2.04", new Object[] {}); + throw new InvalidProtocolRequestException("sp.pvp2.04", new Object[] {FederatedAuthConstants.MODULE_NAME_FOR_LOGGING}); } //validate response signature if(!msg.isVerified()) { - samlVerificationEngine.verify(msg, TrustEngineFactory.getSignatureKnownKeysTrustEngine()); + samlVerificationEngine.verify(msg, TrustEngineFactory.getSignatureKnownKeysTrustEngine(MOAMetadataProvider.getInstance())); msg.setVerified(true); } @@ -118,12 +142,77 @@ public class ReceiveAuthnResponseTask extends AbstractAuthServletTask { //validate assertion MOAResponse processedMsg = preProcessAuthResponse((MOAResponse) msg); - //store valid assertion into pending-request - pendingReq.setGenericDataToSession(RequestImpl.DATAID_INTERFEDERATIOIDP_RESPONSE, processedMsg); + //load IDP and SP configuration + IOAAuthParameters idpConfig = authConfig.getOnlineApplicationParameter(msg.getEntityID()); + IOAAuthParameters spConfig = pendingReq.getOnlineApplicationConfiguration(); + + //check if response Entity is valid + if (!idpConfig.isInderfederationIDP()) { + Logger.warn("Response Issuer is not a federated IDP. Stopping federated authentication ..."); + throw new AuthnResponseValidationException("sp.pvp2.08", + new Object[] {FederatedAuthConstants.MODULE_NAME_FOR_LOGGING, + msg.getEntityID()}); + + } - //update MOASession with federation information - authenticatedSessionStorage.createInterfederatedSession(pendingReq, true); + //load MOASession from database + defaultTaskInitialization(request, executionContext); + //initialize Attribute extractor + AssertionAttributeExtractor extractor = + new AssertionAttributeExtractor((Response) processedMsg.getResponse()); + + //check if SP is also a federated IDP + if (spConfig.isInderfederationIDP()) { + //SP is a federated IDP --> answer only with nameID and wait for attribute-Query + pendingReq.setGenericDataToSession( + PVPTargetConfiguration.DATAID_INTERFEDERATION_MINIMAL_FRONTCHANNEL_RESP, true); + pendingReq.setGenericDataToSession( + PVPTargetConfiguration.DATAID_INTERFEDERATION_NAMEID, extractor.getNameID()); + pendingReq.setGenericDataToSession( + PVPTargetConfiguration.DATAID_INTERFEDERATION_QAALEVEL, extractor.getQAALevel()); + + //build data-container for AttributeQuery + FederatedAuthenticatenContainer container = new FederatedAuthenticatenContainer(); + container.setIdpEntityID(idpConfig.getPublicURLPrefix()); + container.setUserNameID(extractor.getNameID()); + container.setUserQAALevel(extractor.getQAALevel()); + + if (idpConfig.isInterfederationSSOStorageAllowed()) { + //open SSO session and store IDP as federated IDP + container.setMoaSessionID(moasession.getSessionID()); + + //store federatedIDP to MOASession + authenticatedSessionStorage. + addFederatedSessionInformation(pendingReq, + idpConfig.getPublicURLPrefix(), extractor); + + } + + //store container into transaction storage + transactionStorage.put(container.getId(), container); + + //store container ID to pending-request + pendingReq.setGenericDataToSession( + PVPTargetConfiguration.DATAID_INTERFEDERATION_ATTRQUERYCONTAINERID, + container.getId()); + + } else { + //SP is real Service-Provider --> check attributes in response + // and start Attribute-Query if required + + //get authenticationData and store it into MOASession + getAuthDataFromInterfederation(extractor, pendingReq.getOnlineApplicationConfiguration(), + idpConfig); + + //update MOASession + authenticatedSessionStorage.storeSession(moasession); + + } + + //store valid assertion into pending-request + pendingReq.setGenericDataToSession(RequestImpl.DATAID_INTERFEDERATIOIDP_RESPONSE, processedMsg); + //store pending-request requestStoreage.storePendingRequest(pendingReq); @@ -165,6 +254,104 @@ public class ReceiveAuthnResponseTask extends AbstractAuthServletTask { } + private void getAuthDataFromInterfederation(AssertionAttributeExtractor extractor, IOAAuthParameters spConfig, + IOAAuthParameters idpConfig) throws BuildException, ConfigurationException{ + + try { + Logger.debug("Service Provider is no federated IDP --> start Attribute validation or requesting ... "); + Collection<String> requestedAttr = pendingReq.getRequestedAttributes(); + + //check if SAML2 Assertion contains a minimal set of 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 = idpConfig.getIDPAttributQueryServiceURL(); + if (MiscUtil.isEmpty(endpoint)) { + Logger.error("No AttributeQueryURL for interfederationIDP " + idpConfig.getPublicURLPrefix()); + throw new ConfigurationException("No AttributeQueryURL for interfederationIDP " + idpConfig.getPublicURLPrefix(), null); + + } + + //build attributQuery request + List<Attribute> attributs = + attributQueryBuilder.buildSAML2AttributeList(spConfig, requestedAttr.iterator()); + AttributeQuery query = + attributQueryBuilder.buildAttributQueryRequest(extractor.getNameID(), endpoint, attributs); + + //build SOAP request + List<XMLObject> xmlObjects = MOASAMLSOAPClient.send(endpoint, query); + + if (xmlObjects.size() == 0) { + Logger.error("Receive emptry AttributeQuery response-body."); + throw new AttributQueryException("Receive emptry AttributeQuery response-body.", null); + + } + + if (xmlObjects.get(0) instanceof Response) { + Response intfResp = (Response) xmlObjects.get(0); + + //validate PVP 2.1 response + try { + samlVerificationEngine.verifyIDPResponse(intfResp, + TrustEngineFactory.getSignatureKnownKeysTrustEngine( + MOAMetadataProvider.getInstance())); + + //create assertion attribute extractor from AttributeQuery response + extractor = new AssertionAttributeExtractor(intfResp); + + } catch (Exception e) { + Logger.warn("PVP 2.1 assertion validation FAILED.", e); + throw new AssertionValidationExeption("PVP 2.1 assertion validation FAILED.", null, e); + } + + } 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); + + } + + } else { + Logger.info("Interfedation response include a minimal set of attributes with are required. Skip AttributQuery request step. "); + + } + + //check if all attributes are include + if (!extractor.containsAllRequiredAttributes( + pendingReq.getRequestedAttributes())) { + Logger.warn("PVP Response from federated IDP contains not all requested attributes."); + throw new AssertionValidationExeption("sp.pvp2.06", new Object[]{FederatedAuthConstants.MODULE_NAME_FOR_LOGGING}); + + } + + //copy attributes into MOASession + Set<String> includedAttrNames = extractor.getAllIncludeAttributeNames(); + for (String el : includedAttrNames) { + moasession.setGenericDataToSession(el, extractor.getSingleAttributeValue(el)); + Logger.debug("Add PVP-attribute " + el + " into MOASession"); + + } + + } 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 (SessionDataStorageException 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); + + } + } + /** * @param executionContext * @param idpConfig @@ -215,8 +402,8 @@ public class ReceiveAuthnResponseTask extends AbstractAuthServletTask { } else { Logger.info("Receive StatusCode " + samlResp.getStatus().getStatusCode().getValue() + " from federated IDP."); - throw new AuthnResponseValidationException("sp.pvp2.04", - new Object[]{samlResp.getIssuer().getValue(), samlResp.getStatus().getStatusCode().getValue()}); + throw new AuthnResponseValidationException("sp.pvp2.05", + new Object[]{FederatedAuthConstants.MODULE_NAME_FOR_LOGGING, samlResp.getIssuer().getValue(), samlResp.getStatus().getStatusCode().getValue()}); } |