diff options
Diffstat (limited to 'id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/eIDASAuthenticationRequest.java')
-rw-r--r-- | id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/eIDASAuthenticationRequest.java | 229 |
1 files changed, 175 insertions, 54 deletions
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 9943cc5fb..0f17eccab 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 @@ -23,8 +23,8 @@ package at.gv.egovernment.moa.id.protocols.eidas; import java.io.StringWriter; +import java.security.MessageDigest; import java.text.SimpleDateFormat; -import java.util.Map.Entry; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -32,29 +32,44 @@ 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; +import com.google.common.collect.ImmutableSet; + import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger; import at.gv.egovernment.moa.id.auth.frontend.velocity.VelocityProvider; 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.engine.MOAeIDASMetadataProviderDecorator; -import at.gv.egovernment.moa.id.auth.modules.eidas.utils.MOAPersonalAttributeList; -import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils; +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SimpleEidasAttributeGenerator; import at.gv.egovernment.moa.id.commons.api.IRequest; import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; import at.gv.egovernment.moa.id.data.IAuthData; +import at.gv.egovernment.moa.id.data.SLOInformationImpl; import at.gv.egovernment.moa.id.data.SLOInformationInterface; import at.gv.egovernment.moa.id.moduls.IAction; +import at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator; +import at.gv.egovernment.moa.id.protocols.builder.attributes.MandateLegalPersonFullNameAttributeBuilder; +import at.gv.egovernment.moa.id.protocols.builder.attributes.MandateLegalPersonSourcePinAttributeBuilder; +import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.exceptions.AttributeException; +import at.gv.egovernment.moa.id.util.Random; import at.gv.egovernment.moa.logging.Logger; -import eu.eidas.auth.commons.EIDASAuthnResponse; -import eu.eidas.auth.commons.EIDASStatusCode; -import eu.eidas.auth.commons.EIDASUtil; -import eu.eidas.auth.commons.PersonalAttribute; -import eu.eidas.auth.engine.EIDASSAMLEngine; -import eu.eidas.auth.engine.metadata.MetadataUtil; +import at.gv.egovernment.moa.util.Base64Utils; +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; +import eu.eidas.auth.commons.attribute.ImmutableAttributeMap; +import eu.eidas.auth.commons.protocol.IResponseMessage; +import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse; +import eu.eidas.auth.commons.protocol.impl.SamlNameIdFormat; +import eu.eidas.auth.engine.ProtocolEngineI; +import eu.eidas.auth.engine.xml.opensaml.SAMLEngineUtils; /** @@ -67,7 +82,10 @@ import eu.eidas.auth.engine.metadata.MetadataUtil; @Service("eIDASAuthenticationRequest") public class eIDASAuthenticationRequest implements IAction { + private static IAttributeGenerator<String> generator = new SimpleEidasAttributeGenerator(); + @Autowired protected MOAReversionLogger revisionsLogger; + @Autowired(required=true) MOAeIDASChainingMetadataProvider eIDASMetadataProvider; @Override public SLOInformationInterface processRequest(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp, IAuthData authData) throws MOAIDException { @@ -78,67 +96,136 @@ public class eIDASAuthenticationRequest implements IAction { throw new MOAIDException("got wrong IRequest type. is: {}, should be: {}", new String[] {req.getClass().toString(), EIDASData.class.toString()}); - // gather attributes - MOAPersonalAttributeList resultingAttributeList = (MOAPersonalAttributeList) eidasRequest.getEidasRequestedAttributes().clone(); + String subjectNameID = null; - for(Entry<String, PersonalAttribute> current : resultingAttributeList.entrySet()) { + //gather attributes + ImmutableAttributeMap reqAttributeList = (ImmutableAttributeMap) eidasRequest.getEidasRequestedAttributes(); + ImmutableAttributeMap.Builder attrMapBuilder = ImmutableAttributeMap.builder(); + + //TODO: if we support more then this minimum required attributes -> redesign to a smoother attribute builder selector + for(AttributeDefinition<?> attr : reqAttributeList.getDefinitions()) { String newValue = ""; - - // TODO make use of proper builder - switch(current.getKey()) { - 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; - - //TODO: change bPK builder !!!!!! - case Constants.eIDAS_ATTR_PERSONALIDENTIFIER: newValue = authData.getBPK(); break; + boolean isUniqueID = false; + try { + 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(); + isUniqueID = true; + + //generate a transient unique identifier if it is requested + String reqNameIDFormat = eidasRequest.getEidasRequest().getNameIdFormat(); + if (MiscUtil.isNotEmpty(reqNameIDFormat) + && reqNameIDFormat.equals(SamlNameIdFormat.TRANSIENT.getNameIdFormat())) + newValue = generateTransientNameID(newValue); + + subjectNameID = newValue; + break; + case Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER: + newValue = new MandateLegalPersonSourcePinAttributeBuilder().build( + req.getOnlineApplicationConfiguration(), authData, generator); + break; + case Constants.eIDAS_ATTR_LEGALNAME: + newValue = new MandateLegalPersonFullNameAttributeBuilder().build( + req.getOnlineApplicationConfiguration(), authData, generator); + break; + + } + + } catch (AttributeException e) { + Logger.debug("Attribute can not generate requested attribute:" + attr.getFriendlyName() + " Reason:" + e.getMessage()); + } - - if("".equals(newValue)) - current.getValue().setStatus(EIDASStatusCode.STATUS_NOT_AVAILABLE.toString()); - else { - current.getValue().getValue().clear(); - current.getValue().getValue().add(newValue); - current.getValue().setStatus(EIDASStatusCode.STATUS_AVAILABLE.toString()); + + if(MiscUtil.isEmpty(newValue)) { + Logger.info("eIDAS Attr:" + attr.getNameUri() + " is not available."); + + } else { + //set uniqueIdentifier attribute, because eIDAS SAMLEngine use this flag to select the + // Subject->NameID value from this attribute + Builder<?> attrBuilder = AttributeDefinition.builder(attr); + attrBuilder.uniqueIdentifier(isUniqueID); + AttributeDefinition<?> returnAttr = attrBuilder.build(); + + //unmarshal attribute value into eIDAS attribute + 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); + + } + + //add attribute to Map + attrMapBuilder.put((AttributeDefinition)returnAttr, (ImmutableSet) builder.build()); + } } // construct eIDaS response - EIDASAuthnResponse response = new EIDASAuthnResponse(); - response.setPersonalAttributeList(resultingAttributeList); + AuthenticationResponse.Builder responseBuilder = new AuthenticationResponse.Builder(); + + responseBuilder.id(SAMLEngineUtils.generateNCName()); + responseBuilder.inResponseTo(eidasRequest.getEidasRequest().getId()); - // - create metadata url - String pubURLPrefix = req.getAuthURL(); + String pubURLPrefix = req.getAuthURL(); String metadata_url = pubURLPrefix + Constants.eIDAS_HTTP_ENDPOINT_METADATA; - response.setIssuer(metadata_url); - - response.setAssuranceLevel(authData.getEIDASQAALevel()); + responseBuilder.issuer(metadata_url); + + responseBuilder.levelOfAssurance(authData.getEIDASQAALevel()); + + //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 { - EIDASSAMLEngine engine = SAMLEngineUtils.createSAMLEngine(); + ProtocolEngineI engine = at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils.createSAMLEngine(eIDASMetadataProvider); // encryption is done by the SamlEngine, i.e. by the module we provide in the config // but we need to set the appropriate request issuer - engine.setRequestIssuer(eidasRequest.getEidasRequest().getIssuer()); - + //engine.setRequestIssuer(eidasRequest.getEidasRequest().getIssuer()); - if(null == eidasRequest.getEidasRequest().getAssertionConsumerServiceURL()) { - String assertionConsumerUrl = MetadataUtil.getAssertionUrlFromMetadata( - new MOAeIDASMetadataProviderDecorator(MOAeIDASChainingMetadataProvider.getInstance()), - engine, - eidasRequest.getEidasRequest()); - eidasRequest.getEidasRequest().setAssertionConsumerServiceURL(assertionConsumerUrl); - - } + eIDASRespMsg = engine.generateResponseMessage(eidasRequest.getEidasRequest(), + response, true, eidasRequest.getRemoteAddress()); + +// if(null == eidasRequest.getEidasRequest().getAssertionConsumerServiceURL()) { +// String assertionConsumerUrl = MetadataUtil.getAssertionUrlFromMetadata( +// new MOAeIDASMetadataProviderDecorator(eIDASMetadataProvider), +// engine, +// eidasRequest.getEidasRequest()); +// eidasRequest.getEidasRequest().setAssertionConsumerServiceURL(assertionConsumerUrl); +// +// } - response = engine.generateEIDASAuthnResponse(eidasRequest.getEidasRequest(), response, eidasRequest.getRemoteAddress(), true); +// response = engine.generateEIDASAuthnResponse(eidasRequest.getEidasRequest(), response, eidasRequest.getRemoteAddress(), true); - token = EIDASUtil.encodeSAMLToken(response.getTokenSaml()); + token = EidasStringUtil.encodeToBase64(eIDASRespMsg.getMessageBytes()); + + } catch(Exception e) { + Logger.error("eIDAS Response encoding error." , e); + throw new MOAIDException("eIDAS.13", new Object[]{e.getMessage()}, e); - } catch(Exception e) { - e.printStackTrace(); } revisionsLogger.logEvent(req, Constants.eIDAS_REVERSIONSLOG_IDP_AUTHREQUEST); @@ -169,10 +256,28 @@ 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; + + SLOInformationInterface ssoContainer = null; + try { + ssoContainer = new SLOInformationImpl( + req.getAuthURL(), + eidasRequest.getEidasRequest().getIssuer(), + null, + subjectNameID, + eidasRequest.getEidasRequest().getNameIdFormat(), + EIDASProtocol.NAME); + + } catch (Exception e) { + Logger.error("Can not generate container with SSO information!", e); + + } + + return ssoContainer; + } @Override @@ -186,4 +291,20 @@ public class eIDASAuthenticationRequest implements IAction { } + private String generateTransientNameID(String nameID) { + String random = Random.nextLongRandom(); + + try { + MessageDigest md = MessageDigest.getInstance("SHA-1"); + byte[] hash = md.digest((nameID + random).getBytes("ISO-8859-1")); + return Base64Utils.encode(hash); + + } catch (Exception e) { + Logger.error("Can not generate transient personal identifier!", e); + return null; + + } + + } + } |