From fa2384985454568439dc286a6a9051fba47322ed Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Mon, 25 Jan 2021 16:30:07 +0100 Subject: add ID Austria communication-module and additional jUnit test It's first alpha-version of eIDAS MS-specific Proxy-Service with ID Austria authentication --- .../protocol/ProxyServiceAuthenticationAction.java | 200 +++++++++++++++++++-- 1 file changed, 190 insertions(+), 10 deletions(-) (limited to 'eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java') diff --git a/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java b/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java index 3ff35ac9..c51db460 100644 --- a/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java +++ b/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java @@ -1,18 +1,53 @@ package at.asitplus.eidas.specific.modules.msproxyservice.protocol; +import java.io.IOException; +import java.util.UUID; + +import javax.annotation.PostConstruct; +import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang3.StringUtils; +import org.opensaml.saml.saml2.core.NameIDType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.core.io.ResourceLoader; +import org.springframework.web.util.UriComponentsBuilder; + +import at.asitplus.eidas.specific.connector.gui.StaticGuiBuilderConfiguration; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry; +import at.asitplus.eidas.specific.modules.msproxyservice.MsProxyServiceConstants; +import at.asitplus.eidas.specific.modules.msproxyservice.exception.EidasProxyServiceException; import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.gui.ISpringMvcGuiFormBuilder; import at.gv.egiz.eaaf.core.api.idp.IAction; import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; import at.gv.egiz.eaaf.core.api.idp.slo.SloInformationInterface; +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.GuiBuildException; +import at.gv.egiz.eaaf.core.impl.data.SloInformationImpl; +import eu.eidas.auth.commons.EidasParameterKeys; +import eu.eidas.auth.commons.attribute.AttributeDefinition; +import eu.eidas.auth.commons.attribute.ImmutableAttributeMap; +import eu.eidas.auth.commons.light.ILightRequest; +import eu.eidas.auth.commons.light.ILightResponse; +import eu.eidas.auth.commons.light.impl.LightResponse; +import eu.eidas.auth.commons.light.impl.LightResponse.Builder; +import eu.eidas.auth.commons.light.impl.ResponseStatus; +import eu.eidas.auth.commons.tx.BinaryLightToken; +import eu.eidas.specificcommunication.BinaryLightTokenHelper; +import eu.eidas.specificcommunication.SpecificCommunicationDefinitionBeanNames; +import eu.eidas.specificcommunication.exception.SpecificCommunicationException; +import eu.eidas.specificcommunication.protocol.SpecificCommunicationService; import lombok.extern.slf4j.Slf4j; /** * Result action of a successfully performed eIDAS Proxy-Service authentication. - * + * * @author tlenz * */ @@ -20,33 +55,178 @@ import lombok.extern.slf4j.Slf4j; public class ProxyServiceAuthenticationAction implements IAction { private static final String PROXYSERVICE_AUTH_ACTION_NAME = "MS-specific eIDAS-Proxy action"; - + + @Autowired + ApplicationContext context; + @Autowired + IConfiguration basicConfig; + @Autowired + ResourceLoader resourceLoader; + @Autowired + ISpringMvcGuiFormBuilder guiBuilder; + @Autowired + EidasAttributeRegistry attrRegistry; + @Override public SloInformationInterface processRequest(IRequest pendingReq, HttpServletRequest httpReq, HttpServletResponse httpResp, IAuthData authData) throws EaafException { if (pendingReq instanceof ProxyServicePendingRequest) { + try { + ILightRequest eidasReq = ((ProxyServicePendingRequest) pendingReq).getEidasRequest(); + + //build eIDAS response + Builder lightRespBuilder = LightResponse.builder(); + lightRespBuilder.id(UUID.randomUUID().toString()); + lightRespBuilder.inResponseToId(eidasReq.getId()); + lightRespBuilder.relayState(eidasReq.getRelayState()); + + lightRespBuilder.status(ResponseStatus.builder() + .statusCode(Constants.SUCCESS_URI) + .build()); + + //TODO: check if we can use transient subjectNameIds + lightRespBuilder.subject(UUID.randomUUID().toString()); + lightRespBuilder.subjectNameIdFormat(NameIDType.TRANSIENT); + + //TODO: + lightRespBuilder.issuer(basicConfig.getBasicConfiguration( + MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_NODE_ENTITYID)); + lightRespBuilder.levelOfAssurance(authData.getEidasQaaLevel()); + lightRespBuilder.attributes(buildAttributesFromAuthData(authData)); + + // put request into shared cache + final BinaryLightToken token = putResponseInCommunicationCache(lightRespBuilder.build()); + final String tokenBase64 = BinaryLightTokenHelper.encodeBinaryLightTokenBase64(token); + + // set SLO response object of EAAF framework + final SloInformationImpl sloInformation = new SloInformationImpl(); + sloInformation.setProtocolType(pendingReq.requestedModule()); + sloInformation + .setSpEntityID(pendingReq.getServiceProviderConfiguration().getUniqueIdentifier()); + + // forward to eIDAS Proxy-Service + forwardToEidasProxy(pendingReq, httpReq, httpResp, tokenBase64); + + return sloInformation; + + } catch (ServletException | IOException | GuiBuildException e) { + throw new EidasProxyServiceException("eidas.proxyservice.06", null, e); + + } - - return null; - } else { log.error("eIDAS Proxy-Service authentication requires PendingRequest of Type: {}", ProxyServicePendingRequest.class.getName()); throw new EaafException("eidas.proxyservice.99"); - - } - } + } + } + @Override - public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp) { + public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp) { return true; - + } @Override public String getDefaultActionName() { return PROXYSERVICE_AUTH_ACTION_NAME; + + } + + + @PostConstruct + private void checkConfiguration() { + //TODO: validate configuration on start-up } + + + private ImmutableAttributeMap buildAttributesFromAuthData(IAuthData authData) { + final AttributeDefinition attrDefPersonalId = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( + Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first(); + final AttributeDefinition attrDefFamilyName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( + Constants.eIDAS_ATTR_CURRENTFAMILYNAME).first(); + final AttributeDefinition attrDefGivenName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( + Constants.eIDAS_ATTR_CURRENTGIVENNAME).first(); + final AttributeDefinition attrDefDateOfBirth = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( + Constants.eIDAS_ATTR_DATEOFBIRTH).first(); + + final ImmutableAttributeMap.Builder attributeMap = + ImmutableAttributeMap.builder().put(attrDefPersonalId, + authData.getGenericData(MsProxyServiceConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, String.class)) + .put(attrDefFamilyName, authData.getFamilyName()) + .put(attrDefGivenName, authData.getGivenName()) + .put(attrDefDateOfBirth, authData.getFormatedDateOfBirth()); + + return attributeMap.build(); + + } + + private BinaryLightToken putResponseInCommunicationCache(ILightResponse lightResponse) + throws ServletException { + final BinaryLightToken binaryLightToken; + try { + final SpecificCommunicationService springManagedSpecificConnectorCommunicationService = + (SpecificCommunicationService) context.getBean( + SpecificCommunicationDefinitionBeanNames.SPECIFIC_PROXYSERVICE_COMMUNICATION_SERVICE + .toString()); + + binaryLightToken = springManagedSpecificConnectorCommunicationService.putResponse(lightResponse); + + } catch (final SpecificCommunicationException e) { + log.error("Unable to process specific request"); + throw new ServletException(e); + + } + + return binaryLightToken; + } + + private void forwardToEidasProxy(IRequest pendingReq, HttpServletRequest httpReq, + HttpServletResponse httpResp, String tokenBase64) throws EaafConfigurationException, IOException, + GuiBuildException { + // select forward URL regarding the selected environment + final String forwardUrl = basicConfig.getBasicConfiguration( + MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_NODE_FORWARD_URL); + + if (StringUtils.isEmpty(forwardUrl)) { + log.warn("NO ForwardURL defined in configuration. Can NOT forward to eIDAS node! Process stops"); + throw new EaafConfigurationException("config.08", + new Object[] { MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_NODE_FORWARD_URL }); + + } + log.debug("ForwardURL: " + forwardUrl + " selected to forward eIDAS request"); + + if (basicConfig.getBasicConfiguration( + Constants.CONIG_PROPS_EIDAS_NODE_FORWARD_METHOD, + Constants.FORWARD_METHOD_GET).equals(Constants.FORWARD_METHOD_GET)) { + + log.debug("Use http-redirect for eIDAS node forwarding ... "); + // send redirect + final UriComponentsBuilder redirectUrl = UriComponentsBuilder.fromHttpUrl(forwardUrl); + redirectUrl.queryParam(EidasParameterKeys.TOKEN.toString(), tokenBase64); + httpResp.sendRedirect(redirectUrl.build().encode().toString()); + + } else { + log.debug("Use http-post for eIDAS node forwarding ... "); + final StaticGuiBuilderConfiguration config = new StaticGuiBuilderConfiguration( + basicConfig, + pendingReq, + Constants.TEMPLATE_POST_FORWARD_NAME, + null, + resourceLoader); + + config.putCustomParameter(null, Constants.TEMPLATE_POST_FORWARD_ENDPOINT, forwardUrl); + config.putCustomParameter(null, Constants.TEMPLATE_POST_FORWARD_TOKEN_NAME, + EidasParameterKeys.TOKEN.toString()); + config.putCustomParameter(null, Constants.TEMPLATE_POST_FORWARD_TOKEN_VALUE, + tokenBase64); + + guiBuilder.build(httpReq, httpResp, config, "Forward to eIDASNode form"); + + } + + } } -- cgit v1.2.3