aboutsummaryrefslogtreecommitdiff
path: root/eidas_modules/eidas_proxy-sevice/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'eidas_modules/eidas_proxy-sevice/src/main/java')
-rw-r--r--eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/EidasProxyMessageSource.java22
-rw-r--r--eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceConstants.java25
-rw-r--r--eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/exception/EidasProxyServiceException.java19
-rw-r--r--eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/EidasProxyServiceController.java232
-rw-r--r--eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java52
-rw-r--r--eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServicePendingRequest.java13
6 files changed, 363 insertions, 0 deletions
diff --git a/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/EidasProxyMessageSource.java b/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/EidasProxyMessageSource.java
new file mode 100644
index 00000000..23390da8
--- /dev/null
+++ b/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/EidasProxyMessageSource.java
@@ -0,0 +1,22 @@
+package at.asitplus.eidas.specific.modules.msproxyservice;
+
+import java.util.Arrays;
+import java.util.List;
+
+import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation;
+
+/**
+ * i18n Message-Source for eIDAS Proxy-Service messages.
+ *
+ * @author tlenz
+ *
+ */
+public class EidasProxyMessageSource implements IMessageSourceLocation {
+
+ @Override
+ public List<String> getMessageSourceLocation() {
+ return Arrays.asList("classpath:messages/eidasproxy_messages");
+
+ }
+
+}
diff --git a/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceConstants.java b/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceConstants.java
new file mode 100644
index 00000000..a7c3b8e2
--- /dev/null
+++ b/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceConstants.java
@@ -0,0 +1,25 @@
+package at.asitplus.eidas.specific.modules.msproxyservice;
+
+/**
+ * Constants for MS-specific eIDAS Proxy-Service.
+ *
+ * @author tlenz
+ *
+ */
+public class MsProxyServiceConstants {
+
+ //general constants
+ public static final String TEMPLATE_SP_UNIQUE_ID = "eidasProxyAuth_from_{0}_type_{1}";
+
+ //configuration constants
+
+ //http end-points
+ public static final String EIDAS_HTTP_ENDPOINT_IDP_POST = "/eidas/light/idp/post";
+ public static final String EIDAS_HTTP_ENDPOINT_IDP_REDIRECT = "/eidas/light/idp/redirect";
+
+ private MsProxyServiceConstants() {
+ //private constructor for class with only constant values
+
+ }
+
+}
diff --git a/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/exception/EidasProxyServiceException.java b/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/exception/EidasProxyServiceException.java
new file mode 100644
index 00000000..43592a28
--- /dev/null
+++ b/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/exception/EidasProxyServiceException.java
@@ -0,0 +1,19 @@
+package at.asitplus.eidas.specific.modules.msproxyservice.exception;
+
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+
+public class EidasProxyServiceException extends EaafException {
+
+ private static final long serialVersionUID = 1L;
+
+ public EidasProxyServiceException(String errorId, Object[] params) {
+ super(errorId, params);
+
+ }
+
+ public EidasProxyServiceException(String errorId, Object[] params, Throwable e) {
+ super(errorId, params, e);
+
+ }
+
+}
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
new file mode 100644
index 00000000..47cfd3a9
--- /dev/null
+++ b/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/EidasProxyServiceController.java
@@ -0,0 +1,232 @@
+package at.asitplus.eidas.specific.modules.msproxyservice.protocol;
+
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import com.google.common.collect.ImmutableSortedSet;
+
+import at.asitplus.eidas.specific.connector.config.ServiceProviderConfiguration;
+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.components.eventlog.api.EventConstants;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.idp.IModulInfo;
+import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.impl.idp.controller.AbstractController;
+import eu.eidas.auth.commons.EidasParameterKeys;
+import eu.eidas.auth.commons.light.ILightRequest;
+import eu.eidas.specificcommunication.SpecificCommunicationDefinitionBeanNames;
+import eu.eidas.specificcommunication.exception.SpecificCommunicationException;
+import eu.eidas.specificcommunication.protocol.SpecificCommunicationService;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 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;
+
+ /**
+ * 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 EaafException In case of a validation or processing error
+ */
+ @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,
+ EaafException {
+ log.trace("Receive request on eidas proxy-service end-points");
+ ProxyServicePendingRequest pendingReq = null;
+ try {
+ // get token from Request
+ final String tokenBase64 = httpReq.getParameter(EidasParameterKeys.TOKEN.toString());
+ if (StringUtils.isEmpty(tokenBase64)) {
+ log.warn("NO eIDAS message token found.");
+ throw new EidasProxyServiceException(ERROR_02, null);
+
+ }
+ log.trace("Receive eIDAS-node token: {}. Searching authentication request from eIDAS Proxy-Service ...",
+ tokenBase64);
+
+ //read authentication request from shared cache
+ final SpecificCommunicationService specificProxyCommunicationService =
+ (SpecificCommunicationService) applicationContext.getBean(
+ 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 ... ",
+ 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
+ validateEidasAuthnRequest(eidasRequest);
+ pendingReq.setEidasRequest(eidasRequest);
+
+ //generate Service-Provider configuration from eIDAS request
+ 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) {
+ 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);
+
+ } catch (final Throwable e) {
+ // write revision log entries
+ if (pendingReq != null) {
+ revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR,
+ pendingReq.getUniqueTransactionIdentifier());
+ }
+
+ throw new EidasProxyServiceException(ERROR_01, new Object[] { e.getMessage() }, e);
+ }
+
+ }
+
+
+ /**
+ * 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
+
+ }
+
+ /**
+ * 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 {
+ try {
+ String spCountry = eidasRequest.getSpCountryCode();
+ Map<String, String> spConfigMap = new HashMap<>();
+ spConfigMap.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER,
+ MessageFormat.format(MsProxyServiceConstants.TEMPLATE_SP_UNIQUE_ID,
+ spCountry, eidasRequest.getSpType()));
+ 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);
+ spConfig.setRequiredLoA(
+ eidasRequest.getLevelsOfAssurance().stream().map(el -> el.getValue()).collect(Collectors.toList()));
+
+ return spConfig;
+
+ } catch (EaafException e) {
+ throw new EidasProxyServiceException(ERROR_04, 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
+ 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;
+
+ }
+
+}
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
new file mode 100644
index 00000000..3ff35ac9
--- /dev/null
+++ b/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java
@@ -0,0 +1,52 @@
+package at.asitplus.eidas.specific.modules.msproxyservice.protocol;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import at.gv.egiz.eaaf.core.api.IRequest;
+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.slo.SloInformationInterface;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * Result action of a successfully performed eIDAS Proxy-Service authentication.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class ProxyServiceAuthenticationAction implements IAction {
+
+ private static final String PROXYSERVICE_AUTH_ACTION_NAME = "MS-specific eIDAS-Proxy action";
+
+ @Override
+ public SloInformationInterface processRequest(IRequest pendingReq, HttpServletRequest httpReq,
+ HttpServletResponse httpResp, IAuthData authData) throws EaafException {
+ if (pendingReq instanceof ProxyServicePendingRequest) {
+
+
+ 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) {
+ return true;
+
+ }
+
+ @Override
+ public String getDefaultActionName() {
+ return PROXYSERVICE_AUTH_ACTION_NAME;
+
+ }
+
+}
diff --git a/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServicePendingRequest.java b/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServicePendingRequest.java
index acd314c6..a3b5007a 100644
--- a/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServicePendingRequest.java
+++ b/eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServicePendingRequest.java
@@ -1,6 +1,13 @@
package at.asitplus.eidas.specific.modules.msproxyservice.protocol;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl;
+import eu.eidas.auth.commons.light.ILightRequest;
+import lombok.Getter;
+import lombok.Setter;
/**
* Pending-request of an authentication process from eIDAS Proxy-Service.
@@ -8,8 +15,14 @@ import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl;
* @author tlenz
*
*/
+@Component("ProxyServicePendingRequest")
+@Scope(value = BeanDefinition.SCOPE_PROTOTYPE)
public class ProxyServicePendingRequest extends RequestImpl {
private static final long serialVersionUID = 4227378344716277935L;
+ @Getter
+ @Setter
+ ILightRequest eidasRequest;
+
}