aboutsummaryrefslogtreecommitdiff
path: root/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java
diff options
context:
space:
mode:
Diffstat (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java')
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java159
1 files changed, 77 insertions, 82 deletions
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java
index a6ff345d..fd469f49 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java
@@ -23,24 +23,45 @@
package at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks;
+import static at.asitplus.eidas.specific.modules.auth.eidas.v2.idaustriaclient.IdAustriaClientAuthConstants.MODULE_NAME_FOR_LOGGING;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.transform.TransformerException;
+
+import org.apache.commons.lang3.StringUtils;
+import org.jetbrains.annotations.NotNull;
+import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.messaging.decoder.MessageDecodingException;
+import org.opensaml.saml.saml2.core.Response;
+import org.opensaml.saml.saml2.core.StatusCode;
+import org.opensaml.saml.saml2.metadata.IDPSSODescriptor;
+import org.springframework.stereotype.Component;
+
import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
-import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MergedRegisterSearchResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleMobileSignatureData;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.InvalidUserInputException;
-import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.ManualFixNecessaryException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.WorkflowException;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.idaustriaclient.IdAustriaClientAuthConstants;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.idaustriaclient.IdAustriaClientAuthEventConstants;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.idaustriaclient.provider.IdAustriaClientAuthCredentialProvider;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.idaustriaclient.provider.IdAustriaClientAuthMetadataProvider;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.RegisterSearchService;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.RegisterSearchService.RegisterSearchResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.MatchingTaskUtils;
import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
import at.gv.egiz.eaaf.core.exceptions.EaafBuilderException;
-import at.gv.egiz.eaaf.core.exceptions.EaafStorageException;
import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
import at.gv.egiz.eaaf.core.impl.data.Pair;
-import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper;
import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask;
import at.gv.egiz.eaaf.modules.pvp2.api.binding.IDecoder;
import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException;
@@ -58,23 +79,6 @@ import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AssertionValidationExeption;
import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AuthnResponseValidationException;
import at.gv.egiz.eaaf.modules.pvp2.sp.impl.utils.AssertionAttributeExtractor;
import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-import org.jetbrains.annotations.NotNull;
-import org.opensaml.core.xml.io.MarshallingException;
-import org.opensaml.messaging.decoder.MessageDecodingException;
-import org.opensaml.saml.saml2.core.Response;
-import org.opensaml.saml.saml2.core.StatusCode;
-import org.opensaml.saml.saml2.metadata.IDPSSODescriptor;
-import org.springframework.stereotype.Component;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.transform.TransformerException;
-import java.io.IOException;
-import java.util.List;
-import java.util.Set;
-
-import static at.asitplus.eidas.specific.modules.auth.eidas.v2.idaustriaclient.IdAustriaClientAuthConstants.MODULE_NAME_FOR_LOGGING;
/**
* Task that receives the SAML2 response from ID Austria system.
@@ -144,95 +148,84 @@ public class ReceiveMobilePhoneSignatureResponseTask extends AbstractAuthServlet
InboundMessage inboundMessage = decodeAndVerifyMessage(request, response, decoder, comparator);
Pair<PvpSProfileResponse, Boolean> processedMsg = validateAssertion((PvpSProfileResponse) inboundMessage);
if (processedMsg.getSecond()) {
- stopProcessFromUserDecision(executionContext, request, response);
+ // forward to next matching step in case of ID Autria authentication was stopped by user
+ executionContext.put(Constants.TRANSITION_TO_GENERATE_GUI_QUERY_AUSTRIAN_RESIDENCE_TASK, true);
return;
+
}
+ // validate SAML2 response
validateEntityId(inboundMessage);
+ log.info("Receive a valid assertion from IDP " + inboundMessage.getEntityID());
+
+ // load already existing information from session
+ SimpleEidasData eidasData = MatchingTaskUtils.getInitialEidasData(pendingReq);
+ RegisterSearchResult initialSearchResult = MatchingTaskUtils.getInitialRegisterResult(pendingReq);
+
+ // extract user information from ID Austria authentication
AssertionAttributeExtractor extractor = new AssertionAttributeExtractor(processedMsg.getFirst().getResponse());
-
- /*
- * SAML2 response ist bereits vollständig validiert und die Attribute können aus dem
- * <AssertionAttributeExtractor extractor> ausgelesen werden.
- * Die AttributeNamen sind entsprechend PVP Spezifikation, z.B. PvpAttributeDefinitions.GIVEN_NAME_NAME
- *
- * ---------------------------------------------------------------------------------------------
- *
- * TODO: ab hier müssen wir wohl was anpassen
- *
- */
-
- MergedRegisterSearchResult initialSearchResult = getInitialRegisterResult();
- SimpleEidasData eidasData = getInitialEidasData();
- String bpkZp = extractBpkZp(extractor, eidasData);
-
- // TODO Hier ist wohl keine Register-Suche notwendig, denn das ergibt sicher einen Treffer
- // TODO Soll: In den Ergebnissen aus Step8 matchen! Über BPK matchen, und dann schauen, ob zumindest
- // Geburtsdatum passt
- MergedRegisterSearchResult registerResult = registerSearchService.searchWithBpkZp(bpkZp);
- if (registerResult.getResultCount() == 0) {
- executionContext.put(Constants.TRANSITION_TO_GENERATE_GUI_QUERY_AUSTRIAN_RESIDENCE_TASK, true);
- return;
- } else if (registerResult.getResultCount() == 1) {
- String bpk = registerSearchService
- .step7aKittProcess(initialSearchResult, registerResult, eidasData, pendingReq);
- storeMatchingBpk(bpk);
- return;
- } else if (registerResult.getResultCount() > 1) {
- throw new ManualFixNecessaryException(eidasData);
+ SimpleMobileSignatureData simpleMobileSignatureData = getAuthDataFromInterfederation(extractor);
+
+ // check if MDS from ID Austria authentication matchs to eIDAS authentication
+ if (!simpleMobileSignatureData.equalsSimpleEidasData(eidasData)) {
+ // user has cheated!?
+ throw new InvalidUserInputException("module.eidasauth.matching.05");
+
}
-
- // set NeedConsent to false, because user gives consent during authentication
- pendingReq.setNeedUserConsent(false);
- log.info("Receive a valid assertion from IDP " + inboundMessage.getEntityID());
+
+ // search entry in initial search result from steps before and build new RegisterSearchResult
+ RegisterSearchResult registerResult = new RegisterSearchResult(initialSearchResult.getOperationStatus(),
+ extractEntriesByBpk(initialSearchResult.getResultsZmr().stream(), simpleMobileSignatureData.getBpk()),
+ extractEntriesByBpk(initialSearchResult.getResultsErnp().stream(), simpleMobileSignatureData.getBpk()));
+
+ if (registerResult.getResultCount() != 1) {
+ throw new WorkflowException("matchWithIDAustriaAuthentication",
+ "Suspect state detected. MDS matches to eIDAS authentication "
+ + "but register search-result with MDS contains #" + registerResult.getResultCount()
+ + " entry with bPK from ID Austria authentication", false);
+
+ } else {
+ // perform kit operation
+ registerSearchService.step7aKittProcess(registerResult, eidasData);
+
+ // store search result to re-used in CreateIdentityLink step, because there we need bPK and MDS
+ registerResult.setMatchingFinished(true);
+ MatchingTaskUtils.storeInitialRegisterResult(pendingReq, registerResult);
+
+ }
+
} catch (final AuthnResponseValidationException e) {
throw new TaskExecutionException(pendingReq, ERROR_MSG_03, e);
+
} catch (MessageDecodingException | SecurityException | SamlSigningException e) {
//final String samlRequest = request.getParameter("SAMLRequest");
//log.debug("Receive INVALID PVP Response from 'ms-specific eIDAS node': {}",
// samlRequest, null, e);
throw new TaskExecutionException(pendingReq, ERROR_MSG_00,
new AuthnResponseValidationException(ERROR_PVP_11, new Object[]{MODULE_NAME_FOR_LOGGING}, e));
+
} catch (IOException | MarshallingException | TransformerException e) {
log.debug("Processing PVP response from 'ms-specific eIDAS node' FAILED.", e);
throw new TaskExecutionException(pendingReq, ERROR_MSG_01,
new AuthnResponseValidationException(ERROR_PVP_12, new Object[]{MODULE_NAME_FOR_LOGGING, e.getMessage()}, e));
+
} catch (final CredentialsNotAvailableException e) {
log.debug("PVP response decryption FAILED. No credential found.", e);
throw new TaskExecutionException(pendingReq, ERROR_MSG_02,
new AuthnResponseValidationException(ERROR_PVP_10, new Object[]{MODULE_NAME_FOR_LOGGING}, e));
+
} catch (final Exception e) {
// todo catch ManualFixNecessaryException in any other way?
log.debug("PVP response validation FAILED. Msg:" + e.getMessage(), e);
throw new TaskExecutionException(pendingReq, ERROR_MSG_03,
new AuthnResponseValidationException(ERROR_PVP_12, new Object[]{MODULE_NAME_FOR_LOGGING, e.getMessage()}, e));
+
}
}
- private String extractBpkZp(AssertionAttributeExtractor extractor,
- SimpleEidasData eidasData) throws EaafBuilderException, InvalidUserInputException {
- SimpleMobileSignatureData simpleMobileSignatureData = getAuthDataFromInterfederation(extractor);
- if (!simpleMobileSignatureData.equalsSimpleEidasData(eidasData)) {
- throw new InvalidUserInputException(); // user has cheated!?
- }
- return simpleMobileSignatureData.getBpk();
- }
+ private List<RegisterResult> extractEntriesByBpk(Stream<RegisterResult> stream, String bpk) {
+ return stream.filter(el -> bpk.equals(el.getBpk())).collect(Collectors.toList());
- private SimpleEidasData getInitialEidasData() {
- return getAuthProcessDataWrapper().getGenericDataFromSession(Constants.DATA_SIMPLE_EIDAS, SimpleEidasData.class);
- }
-
- private MergedRegisterSearchResult getInitialRegisterResult() {
- return getAuthProcessDataWrapper().getGenericDataFromSession(Constants.DATA_INITIAL_REGISTER_RESULT,
- MergedRegisterSearchResult.class);
- }
-
- private void storeMatchingBpk(String bpk) throws EaafStorageException {
- getAuthProcessDataWrapper().setGenericDataToSession(Constants.DATA_RESULT_MATCHING_BPK, bpk);
- }
-
- private AuthProcessDataWrapper getAuthProcessDataWrapper() {
- return pendingReq.getSessionData(AuthProcessDataWrapper.class);
}
@NotNull
@@ -359,13 +352,15 @@ public class ReceiveMobilePhoneSignatureResponseTask extends AbstractAuthServlet
}
if (PvpAttributeDefinitions.BIRTHDATE_NAME.equals(attrName)) {
builder.dateOfBirth(extractor.getSingleAttributeValue(attrName));
- }
+ }
if (PvpAttributeDefinitions.EID_CITIZEN_EIDAS_QAA_LEVEL_NAME.equals(attrName)) {
- getAuthProcessDataWrapper().setQaaLevel(extractor.getSingleAttributeValue(attrName));
+ MatchingTaskUtils.getAuthProcessDataWrapper(pendingReq).setQaaLevel(
+ extractor.getSingleAttributeValue(attrName));
}
}
- getAuthProcessDataWrapper().setIssueInstant(extractor.getAssertionIssuingDate());
+ MatchingTaskUtils.getAuthProcessDataWrapper(pendingReq).setIssueInstant(extractor.getAssertionIssuingDate());
return builder.build();
+
}