diff options
Diffstat (limited to 'id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java')
-rw-r--r-- | id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java | 135 |
1 files changed, 93 insertions, 42 deletions
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java index cf9414a3b..cb91d5fa3 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java @@ -34,6 +34,7 @@ import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.opensaml.saml2.core.StatusCode; import org.opensaml.saml2.metadata.AssertionConsumerService; +import org.opensaml.saml2.metadata.EntityDescriptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; @@ -49,6 +50,7 @@ import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASAuthnRequestP import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASAuthnRequestValidationException; import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASException; import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils; +import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants; import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters; import at.gv.egovernment.moa.id.commons.api.IRequest; import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; @@ -59,6 +61,8 @@ import at.gv.egovernment.moa.util.MiscUtil; import eu.eidas.auth.commons.EidasStringUtil; import eu.eidas.auth.commons.protocol.IAuthenticationRequest; import eu.eidas.auth.commons.protocol.IResponseMessage; +import eu.eidas.auth.commons.protocol.eidas.IEidasAuthenticationRequest; +import eu.eidas.auth.commons.protocol.eidas.impl.EidasAuthenticationRequest; import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse; import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse.Builder; import eu.eidas.auth.engine.ProtocolEngineI; @@ -74,7 +78,7 @@ import eu.eidas.engine.exceptions.EIDASSAMLEngineException; public class EIDASProtocol extends AbstractAuthProtocolModulController { public static final String NAME = EIDASProtocol.class.getName(); - public static final String PATH = "eidas"; + public static final String PATH = "eidas"; @Autowired(required=true) MOAeIDASChainingMetadataProvider eIDASMetadataProvider; @@ -169,7 +173,7 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController { String base64SamlToken = request.getParameter("SAMLRequest"); if (MiscUtil.isEmpty(base64SamlToken)) { Logger.warn("No eIDAS SAMLRequest found in http request."); - throw new MOAIDException("HTTP request includes no eIDAS SAML-Request element.", null); + throw new MOAIDException("eIDAS.06", new Object[]{"HTTP request includes no eIDAS SAML-Request element."}); } try { @@ -178,34 +182,29 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController { //get eIDAS SAML-engine ProtocolEngineI engine = SAMLEngineUtils.createSAMLEngine(eIDASMetadataProvider); - - //TODO: change to configurable COUNTRY-CODE - String cititzenCountryCode = "AT"; - //validate SAML token - IAuthenticationRequest samlReq = engine.unmarshallRequestAndValidate(decSamlToken, cititzenCountryCode ); - - // - memorize remote ip - pendingReq.setRemoteAddress(request.getRemoteAddr()); - - // - memorize relaystate - String relayState = request.getParameter("RelayState"); - pendingReq.setRemoteRelayState(relayState); - - // - memorize country code of target country - pendingReq.setGenericDataToSession( - RequestImpl.eIDAS_GENERIC_REQ_DATA_COUNTRY, samlReq.getOriginCountryCode()); - //TODO: store level of assurance + String cititzenCountryCode = + authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRYCODE, + MOAIDAuthConstants.COUNTRYCODE_AUSTRIA); - // - memorize requested attributes - pendingReq.setEidasRequestedAttributes(samlReq.getRequestedAttributes()); + //**************************************** + //***** validate eIDAS request ********* + //**************************************** + //validate SAML token + IAuthenticationRequest samlReq = engine.unmarshallRequestAndValidate(decSamlToken, cititzenCountryCode ); - // - memorize whole request - pendingReq.setEidasRequest(samlReq); - + //validate internal JAVA class type + if (!(samlReq instanceof IEidasAuthenticationRequest)) { + Logger.error("eIDAS AuthnRequst from node:" + samlReq.getIssuer() + + " is NOT from Type:" + IEidasAuthenticationRequest.class.getName()); + throw new MOAIDException("eIDAS.06", new Object[]{"eIDAS AuthnRequest maps to an wrong internal Type."}); + + } + IEidasAuthenticationRequest eIDASSamlReq = (IEidasAuthenticationRequest) samlReq; + //validate Destination against MOA-ID-Auth configuration - String reqDestination = samlReq.getDestination(); + String reqDestination = eIDASSamlReq.getDestination(); if (MiscUtil.isEmpty(reqDestination) || !reqDestination.startsWith(pendingReq.getAuthURL())) { Logger.info("eIDAS AuthnRequest contains a not valid 'Destination' attribute"); @@ -213,13 +212,16 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController { new Object[]{"eIDAS AuthnRequest contains a not valid 'Destination' attribute"}); } - + //validate AssertionConsumerServiceURL against metadata - String reqAssertionConsumerServiceURL = samlReq.getAssertionConsumerServiceURL(); + EntityDescriptor eIDASNodeEntityDesc = new MOAeIDASMetadataProviderDecorator(eIDASMetadataProvider) + .getEntityDescriptor(eIDASSamlReq.getIssuer(), SAMLEngineUtils.getMetadataSigner()); + + String reqAssertionConsumerServiceURL = eIDASSamlReq.getAssertionConsumerServiceURL(); if (MiscUtil.isNotEmpty(reqAssertionConsumerServiceURL)) { - boolean isValid = false; - List<AssertionConsumerService> allowedAssertionConsumerUrl = new MOAeIDASMetadataProviderDecorator(eIDASMetadataProvider) - .getSPSSODescriptor(samlReq.getIssuer()).getAssertionConsumerServices(); + boolean isValid = false; + List<AssertionConsumerService> allowedAssertionConsumerUrl = + MetadataUtil.getSPSSODescriptor(eIDASNodeEntityDesc).getAssertionConsumerServices(); for (AssertionConsumerService el : allowedAssertionConsumerUrl) { if (reqAssertionConsumerServiceURL.equals(el.getLocation())) @@ -229,13 +231,59 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController { if (!isValid) { Logger.info("eIDAS AuthnRequest contains a not valid 'AssertionConsumerServiceURL' attribute"); - throw new EIDASAuthnRequestValidationException("stork.01", + throw new EIDASAuthnRequestValidationException("eIDAS.12", new Object[]{"eIDAS AuthnRequest contains a not valid 'AssertionConsumerServiceURL' attribute"}); } - } + } else { + /*TODO: eIDAS SAMLEngine 1.1.0 does not validate and set AssertionConsumerServiceURL in a correct form + * + * Actually, this step is required because EidasProtocolProcesser.class only use the AssertionConsumerServiceURL + * from AuthnRequest to set the 'Destination' attribute in eIDAS Response. However, the AssertionConsumerServiceURL + * could be empty in Request, which break the Response building process. + */ + String assertionConsumerServiceURL = MetadataUtil.getAssertionConsumerUrlFromMetadata( + SAMLEngineUtils.getMetadataFetcher(), SAMLEngineUtils.getMetadataSigner(), eIDASSamlReq); + if (MiscUtil.isEmpty(assertionConsumerServiceURL)) { + Logger.error("eIDAS metadata for node:" + eIDASSamlReq.getIssuer() + + " contains NO 'AssertionConsumerServiceURL' element!"); + throw new EIDASSAMLEngineException("eIDAS metadata for node:" + eIDASSamlReq.getIssuer() + + " contains NO 'AssertionConsumerServiceURL' element!"); + + } + + EidasAuthenticationRequest.Builder test = EidasAuthenticationRequest.builder(eIDASSamlReq); + test.assertionConsumerServiceURL(assertionConsumerServiceURL); + eIDASSamlReq = test.build(); + + } + + + + //************************************************* + //***** store eIDAS request information ********* + //************************************************* + // - memorize remote ip + pendingReq.setRemoteAddress(request.getRemoteAddr()); + + // - memorize relaystate + String relayState = request.getParameter("RelayState"); + pendingReq.setRemoteRelayState(relayState); + + // - memorize country code of target country + pendingReq.setGenericDataToSession( + RequestImpl.eIDAS_GENERIC_REQ_DATA_COUNTRY, samlReq.getOriginCountryCode()); + //store level of assurance + pendingReq.setGenericDataToSession(RequestImpl.eIDAS_GENERIC_REQ_DATA_LEVELOFASSURENCE, + eIDASSamlReq.getEidasLevelOfAssurance().stringValue()); + // - memorize requested attributes + pendingReq.setEidasRequestedAttributes(eIDASSamlReq.getRequestedAttributes()); + + // - memorize whole request + pendingReq.setEidasRequest(eIDASSamlReq); + // - memorize OA url pendingReq.setOAURL(samlReq.getIssuer()); @@ -245,16 +293,19 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController { throw new EIDASAuthnRequestProcessingException("eIDAS.08", new Object[]{pendingReq.getOAURL()}); pendingReq.setOnlineApplicationConfiguration(oaConfig); - - //TODO: is not supported any more ?!? -// String spType = samlReq.getSPType(); -// if (MiscUtil.isEmpty(spType)) { -// Logger.info("Load SPType from metadata ... IS NOT IMPLEMENTED YET!!!"); -// //TODO: maybe implement this if required -// -// } -// -// Logger.debug("eIDAS request has SPType:" + spType); + + // - memorize service-provider type from eIDAS request + String spType = null; + if (eIDASSamlReq.getSpType() != null) + spType = eIDASSamlReq.getSpType().getValue(); + + if (MiscUtil.isEmpty(spType)) + spType = MetadataUtil.getSPTypeFromMetadata(eIDASNodeEntityDesc); + + if (MiscUtil.isEmpty(spType)) + Logger.debug("eIDAS request has SPType:" + spType); + else + Logger.info("eIDAS request and eIDAS metadata contains NO 'SPType' element."); } catch (MOAIDException e) { Logger.info("eIDAS AuthnRequest preProcessing FAILED. Msg:" + e.getMessage()); |