package at.gv.egovernment.moa.id.auth.modules.eidas.tasks; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.opensaml.saml2.core.StatusCode; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants; import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionWrapper; 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.exceptions.EIDASResponseNotSuccessException; import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils; import at.gv.egovernment.moa.id.commons.api.data.AuthProzessDataConstants; import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; import at.gv.egovernment.moa.id.protocols.eidas.validator.eIDASResponseValidator; import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; 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.protocol.IAuthenticationResponse; import eu.eidas.auth.engine.ProtocolEngineI; import eu.eidas.engine.exceptions.EIDASSAMLEngineException; @Component("ReceiveAuthnResponseTask") public class ReceiveAuthnResponseTask extends AbstractAuthServletTask { @Autowired(required=true) MOAeIDASChainingMetadataProvider eIDASMetadataProvider; @Override public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) throws TaskExecutionException { try{ //get SAML Response String base64SamlToken = request.getParameter("SAMLResponse"); if (MiscUtil.isEmpty(base64SamlToken)) { Logger.warn("No eIDAS SAMLReponse found in http request."); throw new MOAIDException("HTTP request includes no eIDAS SAML-Response element.", null); } //get MOASession //defaultTaskInitialization(request, executionContext); //decode SAML response byte[] decSamlToken = EidasStringUtil.decodeBytesFromBase64(base64SamlToken); //get eIDAS SAML-engine ProtocolEngineI engine = SAMLEngineUtils.createSAMLEngine(eIDASMetadataProvider); //validate SAML token //TODO: maybe add whitelist IAuthenticationResponse samlResp = engine.unmarshallResponseAndValidate(decSamlToken, request.getRemoteHost(), Constants.CONFIG_PROPS_SKEWTIME_BEFORE, Constants.CONFIG_PROPS_SKEWTIME_AFTER, pendingReq.getAuthURL() + Constants.eIDAS_HTTP_ENDPOINT_METADATA, null, false); if (samlResp.isEncrypted()) { Logger.info("Received encrypted eIDAS SAML-Response."); //TODO: check if additional decryption operation is required } //check response StatusCode if (!samlResp.getStatusCode().equals(StatusCode.SUCCESS_URI)) { Logger.info("Receice eIDAS Response with StatusCode:" + samlResp.getStatusCode() + " Subcode:" + samlResp.getSubStatusCode() + " Msg:" + samlResp.getStatusMessage()); throw new EIDASResponseNotSuccessException("eIDAS.11", new Object[]{samlResp.getStatusMessage()}); } // ********************************************************** // ******* MOA-ID specific response validation ********** // ********************************************************** String spCountry = authConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRYCODE, "AT"); eIDASResponseValidator.validateResponse(pendingReq, samlResp, spCountry); // ********************************************************** // ******* Store resonse infos into session object ********** // ********************************************************** //update MOA-Session data with received information Logger.debug("Store eIDAS response information into MOA-session."); AuthenticationSessionWrapper session = pendingReq.getSessionData(AuthenticationSessionWrapper.class); session.setGenericDataToSession(AuthProzessDataConstants.VALUE_QAALEVEL, samlResp.getLevelOfAssurance()); session.setGenericDataToSession( AuthenticationSessionStorageConstants.eIDAS_ATTRIBUTELIST, samlResp.getAttributes()); session.setGenericDataToSession( AuthenticationSessionStorageConstants.eIDAS_RESPONSE, decSamlToken); //set issuer nation as PVP attribute into MOASession session.setGenericDataToSession(PVPConstants.EID_ISSUING_NATION_NAME, samlResp.getCountry()); //store MOA-session to database requestStoreage.storePendingRequest(pendingReq); revisionsLogger.logEvent(pendingReq, MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED, samlResp.getId()); } catch (MOAIDException e) { throw new TaskExecutionException(pendingReq, "eIDAS Response processing FAILED.", e); }catch (EIDASSAMLEngineException e) { Logger.warn("eIDAS Response validation FAILED.", e); Logger.debug("eIDAS response was: " + request.getParameter("SAMLResponse")); revisionsLogger.logEvent(pendingReq, MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED_ERROR); throw new TaskExecutionException(pendingReq, "eIDAS Response processing FAILED.", new EIDASEngineException("eIDAS.09", new Object[]{e.getMessage()}, e)); } catch (MOADatabaseException e) { revisionsLogger.logEvent(pendingReq, MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED_ERROR); throw new TaskExecutionException(pendingReq, "eIDAS Response processing FAILED.", new MOAIDException("init.04", new Object[]{""}, e)); } catch (Exception e) { Logger.warn("eIDAS Response processing FAILED.", e); revisionsLogger.logEvent(pendingReq, MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED_ERROR); throw new TaskExecutionException(pendingReq, e.getMessage(), new MOAIDException("eIDAS.10", new Object[]{e.getMessage()}, e)); } } }