From 45b0a790ad412e6b7118f1c937b620c66a32fd64 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Fri, 14 May 2021 11:50:01 +0200 Subject: add some TODO's for eIDAS Proxy-Service with mandates and fix some rebase errors --- .../protocol/EidasProxyServiceController.java | 184 +++++++++++---------- 1 file changed, 98 insertions(+), 86 deletions(-) (limited to 'eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol') diff --git a/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/EidasProxyServiceController.java b/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/EidasProxyServiceController.java index 8e417c36..fda1652e 100644 --- a/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/EidasProxyServiceController.java +++ b/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/EidasProxyServiceController.java @@ -41,44 +41,46 @@ import eu.eidas.specificcommunication.protocol.SpecificCommunicationService; import lombok.extern.slf4j.Slf4j; /** - * End-point implementation for authentication requests from eIDAS Proxy-Service + * End-point implementation for authentication requests from eIDAS Proxy-Service * to MS-specific eIDAS Proxy-Service. - * + * * @author tlenz * */ @Slf4j @Controller public class EidasProxyServiceController extends AbstractController implements IModulInfo { - + private static final String ERROR_01 = "eidas.proxyservice.01"; private static final String ERROR_02 = "eidas.proxyservice.02"; private static final String ERROR_03 = "eidas.proxyservice.03"; private static final String ERROR_04 = "eidas.proxyservice.04"; private static final String ERROR_05 = "eidas.proxyservice.05"; - + public static final String PROTOCOL_ID = "eidasProxy"; - - @Autowired private EidasAttributeRegistry attrRegistry; - + + @Autowired + private EidasAttributeRegistry attrRegistry; + /** - * End-point that receives authentication requests from eIDAS Node. - * - * @param httpReq Http request + * End-point that receives authentication requests from eIDAS Node. + * + * @param httpReq Http request * @param httpResp Http response - * @throws IOException In case of general error + * @throws IOException In case of general error * @throws EaafException In case of a validation or processing error */ - @RequestMapping(value = { - MsProxyServiceConstants.EIDAS_HTTP_ENDPOINT_IDP_POST, - MsProxyServiceConstants.EIDAS_HTTP_ENDPOINT_IDP_REDIRECT + @RequestMapping(value = { + MsProxyServiceConstants.EIDAS_HTTP_ENDPOINT_IDP_POST, + MsProxyServiceConstants.EIDAS_HTTP_ENDPOINT_IDP_REDIRECT }, method = { RequestMethod.POST, RequestMethod.GET }) - public void receiveEidasAuthnRequest(HttpServletRequest httpReq, HttpServletResponse httpResp) throws IOException, + public void receiveEidasAuthnRequest(HttpServletRequest httpReq, HttpServletResponse httpResp) + throws IOException, EaafException { log.trace("Receive request on eidas proxy-service end-points"); - ProxyServicePendingRequest pendingReq = null; - try { + ProxyServicePendingRequest pendingReq = null; + try { // get token from Request final String tokenBase64 = httpReq.getParameter(EidasParameterKeys.TOKEN.toString()); if (StringUtils.isEmpty(tokenBase64)) { @@ -89,57 +91,58 @@ public class EidasProxyServiceController extends AbstractController implements I log.trace("Receive eIDAS-node token: {}. Searching authentication request from eIDAS Proxy-Service ...", tokenBase64); - //read authentication request from shared cache + // read authentication request from shared cache final SpecificCommunicationService specificProxyCommunicationService = (SpecificCommunicationService) applicationContext.getBean( - SpecificCommunicationDefinitionBeanNames.SPECIFIC_PROXYSERVICE_COMMUNICATION_SERVICE.toString()); + SpecificCommunicationDefinitionBeanNames.SPECIFIC_PROXYSERVICE_COMMUNICATION_SERVICE + .toString()); final ILightRequest eidasRequest = specificProxyCommunicationService.getAndRemoveRequest( tokenBase64, ImmutableSortedSet.copyOf(attrRegistry.getCoreAttributeRegistry().getAttributes())); - log.debug("Received eIDAS auth. request from: {}, Initializing authentication environment ... ", + log.debug("Received eIDAS auth. request from: {}, Initializing authentication environment ... ", eidasRequest.getSpCountryCode() != null ? eidasRequest.getSpCountryCode() : "'missing SP-country'"); - + // create pendingRequest object pendingReq = applicationContext.getBean(ProxyServicePendingRequest.class); pendingReq.initialize(httpReq, authConfig); pendingReq.setModule(getName()); - + // log 'transaction created' event revisionsLogger.logEvent(EventConstants.TRANSACTION_CREATED, pendingReq.getUniqueTransactionIdentifier()); revisionsLogger.logEvent(pendingReq.getUniqueSessionIdentifier(), pendingReq.getUniqueTransactionIdentifier(), EventConstants.TRANSACTION_IP, httpReq.getRemoteAddr()); - - //validate eIDAS Authn. request and set into pending-request + + // validate eIDAS Authn. request and set into pending-request validateEidasAuthnRequest(eidasRequest); pendingReq.setEidasRequest(eidasRequest); - - //generate Service-Provider configuration from eIDAS request - ISpConfiguration spConfig = generateSpConfigurationFromEidasRequest(eidasRequest); - - // populate pendingRequest with parameters + + // generate Service-Provider configuration from eIDAS request + final ISpConfiguration spConfig = generateSpConfigurationFromEidasRequest(eidasRequest); + + // populate pendingRequest with parameters pendingReq.setOnlineApplicationConfiguration(spConfig); pendingReq.setSpEntityId(spConfig.getUniqueIdentifier()); pendingReq.setPassiv(false); pendingReq.setForce(true); - + // AuthnRequest needs authentication pendingReq.setNeedAuthentication(true); - + // set protocol action, which should be executed after authentication pendingReq.setAction(ProxyServiceAuthenticationAction.class.getName()); - + // switch to session authentication protAuthService.performAuthentication(httpReq, httpResp, pendingReq); - - } catch (EidasProxyServiceException e) { + + } catch (final EidasProxyServiceException e) { throw e; - + } catch (final SpecificCommunicationException e) { log.error("Can not read eIDAS Authn request from shared cache. Reason: {}", e.getMessage()); - throw new EidasProxyServiceException(ERROR_03, new Object[] {e.getMessage()}, e); - + throw new EidasProxyServiceException(ERROR_03, new Object[] { e.getMessage() }, e); + } catch (final Throwable e) { // write revision log entries if (pendingReq != null) { @@ -149,115 +152,124 @@ public class EidasProxyServiceController extends AbstractController implements I throw new EidasProxyServiceException(ERROR_01, new Object[] { e.getMessage() }, e); } - + } @Override public boolean generateErrorMessage(Throwable e, HttpServletRequest request, HttpServletResponse response, IRequest protocolRequest) throws Throwable { - - //TODO: implement error handling for eIDAS Node communication + + // TODO: implement error handling for eIDAS Node communication return false; - + } - + @Override public String getName() { return EidasProxyServiceController.class.getName(); - + } @Override public String getAuthProtocolIdentifier() { return PROTOCOL_ID; - + } @Override public boolean validate(HttpServletRequest request, HttpServletResponse response, IRequest pending) { return true; - + } - + /** * Validate incoming eIDAS request. - * + * * @param eidasRequest Incoming eIDAS authentication request * @throws EidasProxyServiceException In case of a validation error */ private void validateEidasAuthnRequest(ILightRequest eidasRequest) throws EidasProxyServiceException { if (StringUtils.isEmpty(eidasRequest.getSpCountryCode())) { throw new EidasProxyServiceException(ERROR_05, null); - + } - - //TODO: validate requested attributes - - //TODO: validate some other stuff - + + /* + * TODO: validate requested attributes --> check if natural-person and + * legal-person attributes requested in parallel + */ + + // TODO: validate some other stuff + } /** * Generate a dummy Service-Provider configuration for processing. - * + * * @param eidasRequest Incoming eIDAS authentication request * @return Service-Provider configuration that can be used for authentication * @throws EidasProxyServiceException In case of a configuration error */ - private ISpConfiguration generateSpConfigurationFromEidasRequest(ILightRequest eidasRequest) - throws EidasProxyServiceException { + private ISpConfiguration generateSpConfigurationFromEidasRequest(ILightRequest eidasRequest) + throws EidasProxyServiceException { try { - String spCountry = eidasRequest.getSpCountryCode(); - Map spConfigMap = new HashMap<>(); + final String spCountry = eidasRequest.getSpCountryCode(); + final Map spConfigMap = new HashMap<>(); - //TODO: how we get the EntityId from eIDAS connector? + // TODO: how we get the EntityId from eIDAS connector? spConfigMap.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, - MessageFormat.format(MsProxyServiceConstants.TEMPLATE_SP_UNIQUE_ID, + MessageFormat.format(MsProxyServiceConstants.TEMPLATE_SP_UNIQUE_ID, spCountry, eidasRequest.getSpType())); - - ServiceProviderConfiguration spConfig = new ServiceProviderConfiguration(spConfigMap, authConfig); - + + final ServiceProviderConfiguration spConfig = new ServiceProviderConfiguration(spConfigMap, authConfig); + final String ccCountry = authConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRYCODE, Constants.DEFAULT_MS_NODE_COUNTRY_CODE); - + spConfig.setBpkTargetIdentifier( - EaafConstants.URN_PREFIX_EIDAS + ccCountry + "+" + spCountry); + EaafConstants.URN_PREFIX_EIDAS + ccCountry + "+" + spCountry); spConfig.setRequiredLoA( eidasRequest.getLevelsOfAssurance().stream().map(el -> el.getValue()).collect(Collectors.toList())); - + + // TODO: check if only mandates are allowed in case of legal person requested + // --> set force-mandate flag spConfig.setMandateProfiles(buildMandateProfileConfiguration(eidasRequest)); - - + return spConfig; - - } catch (EaafException e) { - throw new EidasProxyServiceException(ERROR_04, new Object[] {e.getMessage()}, e); - - } + + } catch (final EaafException e) { + throw new EidasProxyServiceException(ERROR_04, new Object[] { e.getMessage() }, e); + + } } private List buildMandateProfileConfiguration(ILightRequest eidasRequest) { if (authConfig.getBasicConfigurationBoolean( MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED, false)) { - log.trace("eIDAS Proxy-Service allows mandates. Selecting profiles ... "); - List spMandateProfiles = authConfig.getBasicConfigurationWithPrefix( + log.trace("eIDAS Proxy-Service allows mandates. Selecting profiles ... "); + + /* + * TODO: split profiles in natural-person and legal-person profiles and select + * correct one based on requested attributes + */ + final List spMandateProfiles = authConfig.getBasicConfigurationWithPrefix( MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_SPECIFIC) - .entrySet().stream() - .filter(el -> el.getKey().endsWith(eidasRequest.getSpCountryCode().toLowerCase())) - .findFirst() - .map(el -> KeyValueUtils.getListOfCsvValues(el.getValue())) - .orElse(KeyValueUtils.getListOfCsvValues( - authConfig.getBasicConfiguration( - MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT))); - + .entrySet().stream() + .filter(el -> el.getKey().endsWith(eidasRequest.getSpCountryCode().toLowerCase())) + .findFirst() + .map(el -> KeyValueUtils.getListOfCsvValues(el.getValue())) + .orElse(KeyValueUtils.getListOfCsvValues( + authConfig.getBasicConfiguration( + MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT))); + log.debug("Set mandate-profiles: {} to request from country: {}", spMandateProfiles, eidasRequest.getSpCountryCode()); return spMandateProfiles; - + } - + return Collections.emptyList(); - + } } -- cgit v1.2.3