diff options
author | Thomas Lenz <tlenz@iaik.tugraz.at> | 2016-08-12 11:48:05 +0200 |
---|---|---|
committer | Thomas Lenz <tlenz@iaik.tugraz.at> | 2016-08-12 11:48:05 +0200 |
commit | d71a87f12afb08371a3f50030f183a89d9e319ca (patch) | |
tree | 1db7c016e9dd81aaa38c839bfd724e4c40135262 /id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas | |
parent | 404dae436be7d6e7d381ae183745e4edaac2a866 (diff) | |
download | moa-id-spss-d71a87f12afb08371a3f50030f183a89d9e319ca.tar.gz moa-id-spss-d71a87f12afb08371a3f50030f183a89d9e319ca.tar.bz2 moa-id-spss-d71a87f12afb08371a3f50030f183a89d9e319ca.zip |
fix a lot of problems which occur with new eIDAS SAML Engine v1.1.0
Diffstat (limited to 'id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas')
3 files changed, 138 insertions, 62 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()); diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java index a93dff3b3..dcce442a0 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java @@ -31,7 +31,9 @@ import org.springframework.stereotype.Service; import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAeIDASChainingMetadataProvider; import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineException; +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.MOAeIDASMetadataGenerator; import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils; +import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; import at.gv.egovernment.moa.id.commons.api.IRequest; import at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException; import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; @@ -43,7 +45,6 @@ import at.gv.egovernment.moa.logging.Logger; import eu.eidas.auth.engine.ProtocolEngineI; import eu.eidas.auth.engine.metadata.Contact; import eu.eidas.auth.engine.metadata.MetadataConfigParams; -import eu.eidas.auth.engine.metadata.MetadataGenerator; import eu.eidas.engine.exceptions.EIDASSAMLEngineException; @@ -54,6 +55,7 @@ import eu.eidas.engine.exceptions.EIDASSAMLEngineException; public class EidasMetaDataRequest implements IAction { @Autowired(required=true) MOAeIDASChainingMetadataProvider eIDASMetadataProvider; + @Autowired(required=true) AuthConfiguration authConfig; /* (non-Javadoc) * @see at.gv.egovernment.moa.id.moduls.IAction#processRequest(at.gv.egovernment.moa.id.moduls.IRequest, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, at.gv.egovernment.moa.id.data.IAuthData) @@ -110,7 +112,7 @@ public class EidasMetaDataRequest implements IAction { ProtocolEngineI engine = SAMLEngineUtils.createSAMLEngine(eIDASMetadataProvider); - MetadataGenerator generator = new MetadataGenerator(); + MOAeIDASMetadataGenerator generator = new MOAeIDASMetadataGenerator(); MetadataConfigParams mcp=new MetadataConfigParams(); generator.setConfigParams(mcp); generator.initialize(engine); @@ -158,7 +160,7 @@ public class EidasMetaDataRequest implements IAction { if (pvpOrganisation != null) { mcp.setNodeUrl(pvpOrganisation.getURLs().get(0).getURL().getLocalString()); - mcp.setCountryName("Austria"); + mcp.setCountryName(authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRY, "Austria")); technicalContact.setCompany(pvpOrganisation.getDisplayNames().get(0).getName().getLocalString()); } diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/eIDASAuthenticationRequest.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/eIDASAuthenticationRequest.java index 9e29c01f3..168cb42d9 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/eIDASAuthenticationRequest.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/eIDASAuthenticationRequest.java @@ -31,6 +31,7 @@ import javax.servlet.http.HttpServletResponse; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; +import org.opensaml.saml2.core.StatusCode; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.stereotype.Service; @@ -50,6 +51,7 @@ import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; import eu.eidas.auth.commons.EidasStringUtil; import eu.eidas.auth.commons.attribute.AttributeDefinition; +import eu.eidas.auth.commons.attribute.AttributeDefinition.Builder; import eu.eidas.auth.commons.attribute.AttributeValue; import eu.eidas.auth.commons.attribute.AttributeValueMarshaller; import eu.eidas.auth.commons.attribute.AttributeValueMarshallingException; @@ -89,36 +91,48 @@ public class eIDASAuthenticationRequest implements IAction { for(AttributeDefinition<?> attr : reqAttributeList.getDefinitions()) { String newValue = ""; - + boolean isUniqueID = false; // TODO make use of proper builder + switch(attr.getFriendlyName()) { - case Constants.eIDAS_ATTR_DATEOFBIRTH: newValue = new SimpleDateFormat("YYYY-MM-dd").format(authData.getDateOfBirth()); break; - case Constants.eIDAS_ATTR_CURRENTFAMILYNAME: newValue = authData.getFamilyName();break; - case Constants.eIDAS_ATTR_CURRENTGIVENNAME: newValue = authData.getGivenName();break; - case Constants.eIDAS_ATTR_PERSONALIDENTIFIER: newValue = authData.getBPK(); break; + case Constants.eIDAS_ATTR_DATEOFBIRTH: + newValue = new SimpleDateFormat("YYYY-MM-dd").format(authData.getDateOfBirth()); + break; + case Constants.eIDAS_ATTR_CURRENTFAMILYNAME: + newValue = authData.getFamilyName(); + break; + case Constants.eIDAS_ATTR_CURRENTGIVENNAME: + newValue = authData.getGivenName(); + break; + case Constants.eIDAS_ATTR_PERSONALIDENTIFIER: + newValue = authData.getBPK(); + isUniqueID = true; + break; } - + if(MiscUtil.isEmpty(newValue)) { -// current.getValue().setStatus(EIDASStatusCode.STATUS_NOT_AVAILABLE.toString()); Logger.info("eIDAS Attr:" + attr.getNameUri() + " is not available."); } else { - AttributeValueMarshaller<?> attributeValueMarshaller = attr.getAttributeValueMarshaller(); - ImmutableSet.Builder<AttributeValue<?>> builder = ImmutableSet.builder(); + Builder<?> attrBuilder = AttributeDefinition.builder(attr); + attrBuilder.uniqueIdentifier(isUniqueID); + AttributeDefinition<?> returnAttr = attrBuilder.build(); + AttributeValueMarshaller<?> attributeValueMarshaller = returnAttr.getAttributeValueMarshaller(); + ImmutableSet.Builder<AttributeValue<?>> builder = ImmutableSet.builder(); + AttributeValue<?> attributeValue = null; try { attributeValue = attributeValueMarshaller.unmarshal(newValue, false); + builder.add(attributeValue); } catch (AttributeValueMarshallingException e) { throw new IllegalStateException(e); } - - //TODO: check for 'isAvailable flag'! - attrMapBuilder.put((AttributeDefinition)attr, (ImmutableSet) builder.build()); + attrMapBuilder.put((AttributeDefinition)returnAttr, (ImmutableSet) builder.build()); } @@ -141,10 +155,16 @@ public class eIDASAuthenticationRequest implements IAction { //add attributes responseBuilder.attributes(attrMapBuilder.build()); + //set success statuscode + responseBuilder.statusCode(StatusCode.SUCCESS_URI); + + + //build response AuthenticationResponse response = responseBuilder.build(); String token = null; + IResponseMessage eIDASRespMsg = null; try { ProtocolEngineI engine = at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils.createSAMLEngine(eIDASMetadataProvider); @@ -152,9 +172,9 @@ public class eIDASAuthenticationRequest implements IAction { // but we need to set the appropriate request issuer //engine.setRequestIssuer(eidasRequest.getEidasRequest().getIssuer()); - IResponseMessage eIDASRespMsg = engine.generateResponseMessage(eidasRequest.getEidasRequest(), + eIDASRespMsg = engine.generateResponseMessage(eidasRequest.getEidasRequest(), response, true, eidasRequest.getRemoteAddress()); - + // if(null == eidasRequest.getEidasRequest().getAssertionConsumerServiceURL()) { // String assertionConsumerUrl = MetadataUtil.getAssertionUrlFromMetadata( // new MOAeIDASMetadataProviderDecorator(eIDASMetadataProvider), @@ -169,8 +189,9 @@ public class eIDASAuthenticationRequest implements IAction { token = EidasStringUtil.encodeToBase64(eIDASRespMsg.getMessageBytes()); - } catch(Exception e) { - e.printStackTrace(); + } catch(Exception e) { + Logger.error("eIDAS Response encoding error." , e); + throw new MOAIDException("eIDAS.13", new Object[]{e.getMessage()}, e); } @@ -202,7 +223,9 @@ public class eIDASAuthenticationRequest implements IAction { httpResp.setContentType(MediaType.TEXT_HTML.getType()); } catch (Exception e) { - Logger.error("Velocity error: " + e.getMessage()); + Logger.error("Velocity error: " + e.getMessage()); + throw new MOAIDException("eIDAS.13", new Object[]{e.getMessage()}, e); + } return null; |