/*
* Copyright 2021 A-SIT Plus GmbH
* AT-specific eIDAS Connector has been developed in a cooperation between EGIZ,
* A-SIT Plus GmbH, A-SIT, and Graz University of Technology.
*
* Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
* the European Commission - subsequent versions of the EUPL (the "License");
* You may not use this work except in compliance with the License.
* You may obtain a copy of the License at:
* https://joinup.ec.europa.eu/news/understanding-eupl-v12
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This product combines work with different licenses. See the "NOTICE" text
* file for details on the various modules and licenses.
* The "NOTICE" text file is part of the distribution. Any derivative works
* that you distribute must include a readable copy of the "NOTICE" text file.
*/
package at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks;
import java.util.Enumeration;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringEscapeUtils;
import org.springframework.stereotype.Component;
import com.google.common.collect.Sets;
import at.asitplus.eidas.specific.core.MsEidasNodeConstants.MatchingStates;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SelectedLoginMethod;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.MatchingTaskUtils;
import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
import at.gv.egiz.eaaf.core.exceptions.EaafException;
import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
import at.gv.egiz.eaaf.core.impl.idp.controller.tasks.AbstractLocaleAuthServletTask;
import lombok.extern.slf4j.Slf4j;
/**
* Handles user's selection from {@link GenerateOtherLoginMethodGuiTask}.
* This corresponds to Steps 10, 14, 16 in the eIDAS Matching Concept.
* Input:
*
* - {@link Constants#DATA_SIMPLE_EIDAS} initial login data from user
* - {@link Constants#DATA_INTERMEDIATE_RESULT} results from search in registers with personIdentifier
*
* Transitions:
*
* - {@link GenerateMobilePhoneSignatureRequestTask} if selected by user
* - {@link GenerateAustrianResidenceGuiTask} if selected by user
* - {@link GenerateAuthnRequestTask} if selected by user
* - {@link GenerateOtherLoginMethodGuiTask} if a user input error has happened
*
*
* @author amarsalek
* @author ckollmann
*/
@Slf4j
@Component("ReceiveOtherLoginMethodGuiResponseTask")
public class ReceiveOtherLoginMethodGuiResponseTask extends AbstractLocaleAuthServletTask {
public static final Set ALL_EXECUTIONCONTEXT_PARAMETERS = Sets.newHashSet(
Constants.REQ_SELECTED_LOGIN_METHOD_PARAMETER,
Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK,
Constants.TRANSITION_TO_GENERATE_EIDAS_LOGIN,
Constants.TRANSITION_TO_GENERATE_MOBILE_PHONE_SIGNATURE_REQUEST_TASK,
Constants.TRANSITION_TO_GENERATE_GUI_QUERY_AUSTRIAN_RESIDENCE_TASK,
Constants.TRANSITION_TO_CREATE_NEW_ERNP_ENTRY_TASK,
Constants.TRANSITION_TO_CREATE_NEW_ERNP_ENTRY_BY_USER_TASK);
@Override
public void executeWithLocale(ExecutionContext executionContext, HttpServletRequest request,
HttpServletResponse response) throws TaskExecutionException {
try {
SelectedLoginMethod selection = SelectedLoginMethod.valueOf(extractUserSelection(request));
executionContext.put(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, false);
executionContext.put(Constants.REQ_SELECTED_LOGIN_METHOD_PARAMETER, selection.name());
executionContext.remove(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED);
executionContext.remove(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON);
transitionToNextTask(executionContext, selection, request, response);
} catch (TaskExecutionException e) {
throw e;
} catch (final Exception e) {
log.error("Parsing selected login method FAILED.", e);
executionContext.put(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true);
executionContext.put(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true);
}
}
private String extractUserSelection(HttpServletRequest request) {
Enumeration paramNames = request.getParameterNames();
while (paramNames.hasMoreElements()) {
String paramName = paramNames.nextElement();
if (Constants.REQ_SELECTED_LOGIN_METHOD_PARAMETER.equalsIgnoreCase(paramName)) {
return StringEscapeUtils.escapeHtml(request.getParameter(paramName));
}
}
return null;
}
private void transitionToNextTask(ExecutionContext executionContext, SelectedLoginMethod selection,
HttpServletRequest request, HttpServletResponse response) throws TaskExecutionException {
switch (selection) {
case STOP_MATCHING_PROCESS:
log.info("Matching process WAS stopped by entity. Stopping auth. process ... ");
MatchingTaskUtils.setMatchingState(pendingReq, MatchingStates.CANCELED_BY_USER);
stopProcessFromUserDecision(executionContext, request, response);
return;
case EIDAS_LOGIN:
log.info("User selects alternative eIDAS authentication. Starting process ... ");
executionContext.put(Constants.TRANSITION_TO_GENERATE_EIDAS_LOGIN, true);
return;
case MOBILE_PHONE_SIGNATURE_LOGIN:
log.info("User selects ID Austria authentication. Starting process ... ");
executionContext.put(Constants.TRANSITION_TO_GENERATE_MOBILE_PHONE_SIGNATURE_REQUEST_TASK, true);
return;
case NO_OTHER_LOGIN:
if (!authConfig.getBasicConfigurationBoolean(Constants.CONFIG_PROP_MATCHING_BY_ADDRESS)) {
log.error("Matching by address was requested but it's disabled by configuration!");
throw new TaskExecutionException(pendingReq,
"Matching by address was requested but it's disabled by configuration!",
new EaafException("module.eidasauth.matching.98"));
}
log.info("User selects no alternative authentication-methode. Switching to residence search ... ");
executionContext.put(Constants.TRANSITION_TO_GENERATE_GUI_QUERY_AUSTRIAN_RESIDENCE_TASK, true);
return;
case REQUESTING_NEW_ENTRY:
executionContext.put(Constants.TRANSITION_TO_REQUESTING_NEW_ERNP_ENTRY_TASK, true);
return;
case ADD_ME_AS_NEW:
if (!MatchingTaskUtils.getIntermediateMatchingResult(pendingReq)
.getOperationStatus().isAllowErnpEntryByUser()) {
log.error("Create new ERnP entry by user was requested but it's not allowed!");
throw new TaskExecutionException(pendingReq,
"Create new ERnP entry by user was requested but it's not allowed!",
new EaafException("module.eidasauth.matching.98"));
}
log.info("User selects insert-into-ERnP option. Starting ERnP operation and complete prozess ... ");
executionContext.put(Constants.TRANSITION_TO_CREATE_NEW_ERNP_ENTRY_BY_USER_TASK, true);
executionContext.put(Constants.TRANSITION_TO_REQUESTING_NEW_ERNP_ENTRY_TASK, false);
return;
default:
executionContext.put(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true);
executionContext.put(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true);
return;
}
}
}