diff options
| author | Thomas Lenz <tlenz@iaik.tugraz.at> | 2019-02-04 08:00:14 +0100 | 
|---|---|---|
| committer | Thomas Lenz <tlenz@iaik.tugraz.at> | 2019-02-04 08:00:14 +0100 | 
| commit | 9ddeacf32976d14c3f2f70ec446262998eb8a68e (patch) | |
| tree | b682599a1e31b027ec5f1d529b8bc09c7e7bf8cd /id/server | |
| parent | f33643667ae2daf3525be8744fff7e73ef4d7974 (diff) | |
| download | moa-id-spss-9ddeacf32976d14c3f2f70ec446262998eb8a68e.tar.gz moa-id-spss-9ddeacf32976d14c3f2f70ec446262998eb8a68e.tar.bz2 moa-id-spss-9ddeacf32976d14c3f2f70ec446262998eb8a68e.zip | |
add code for eID4U attribute collection
Diffstat (limited to 'id/server')
11 files changed, 530 insertions, 75 deletions
| diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GenericFrontChannelRedirectTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GenericFrontChannelRedirectTask.java new file mode 100644 index 000000000..e19d40773 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GenericFrontChannelRedirectTask.java @@ -0,0 +1,66 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * 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.gv.egovernment.moa.id.auth.modules.internal.tasks; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import at.gv.egiz.eaaf.core.api.gui.IGUIFormBuilder; +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.auth.servlet.GeneralProcessEngineSignalController; +import at.gv.egovernment.moa.logging.Logger; + +/** + * @author tlenz + * + */ +@Component("GenericFrontChannelRedirectTask") +public class GenericFrontChannelRedirectTask extends AbstractAuthServletTask { + +	@Autowired IGUIFormBuilder guiBuilder; +	  +	/* (non-Javadoc) +	 * @see at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) +	 */ +	@Override +	public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) +			throws TaskExecutionException { +		try { +			//perform redirect to itself to get out from BKU communication +			Logger.trace("Perform generic 'http Redirect' to MOA-ID ... "); +			performRedirectToItself(pendingReq, response, GeneralProcessEngineSignalController.ENDPOINT_GENERIC); +											 +		} catch (Exception e) { +			Logger.info("Generic redirect to MOA-ID: General Exception. Msg:" + e.getMessage()); +			throw new TaskExecutionException(pendingReq, "MOA-ID-Auth: General Exception.", e); +			 +		} + +	} +	 +} diff --git a/id/server/idserverlib/src/main/resources/moaid.authentication.beans.xml b/id/server/idserverlib/src/main/resources/moaid.authentication.beans.xml index 26fd1f986..02c683305 100644 --- a/id/server/idserverlib/src/main/resources/moaid.authentication.beans.xml +++ b/id/server/idserverlib/src/main/resources/moaid.authentication.beans.xml @@ -106,6 +106,10 @@  				class="at.gv.egovernment.moa.id.auth.modules.internal.tasks.UserRestrictionTask"  				scope="prototype"/>		 +	<bean id="GenericFrontChannelRedirectTask"  +				class="at.gv.egovernment.moa.id.auth.modules.internal.tasks.GenericFrontChannelRedirectTask" +				scope="prototype"/>				 +				  	<beans profile="advancedLogOn">  		<bean id="StatisticLogger"   				class="at.gv.egovernment.moa.id.advancedlogging.StatisticLogger"/> diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eID4UAPSignalServlet.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eID4UAPSignalServlet.java new file mode 100644 index 000000000..c8c65ce76 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eID4UAPSignalServlet.java @@ -0,0 +1,61 @@ +package at.gv.egovernment.moa.id.auth.modules.eidas; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import at.gv.egiz.eaaf.core.impl.idp.controller.AbstractProcessEngineSignalController; +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Constants; +import at.gv.egovernment.moa.id.util.CookieUtils; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; + +@Controller +public class eID4UAPSignalServlet extends AbstractProcessEngineSignalController { + +	public eID4UAPSignalServlet() { +		Logger.debug("Registering servlet " + getClass().getName() +  +				" with mappings '"+ eID4UConstants.HTTP_ENDPOINT_AP_CONSENT_RETURN + "'."); +		 +	} +	 +	@RequestMapping(value = {eID4UConstants.HTTP_ENDPOINT_AP_CONSENT_RETURN },  +					method = {RequestMethod.POST, RequestMethod.GET}) +	public void performCitizenCardAuthentication(HttpServletRequest req, HttpServletResponse resp) throws IOException { +		signalProcessManagement(req, resp); +	} + +	@Override +	/** +	 * Protocol specific implementation to get the pending-requestID  +	 * from http request object +	 *  +	 * @param request The http Servlet-Request object +	 * @return The Pending-request id  +	 * 	 +	 */ +	public String getPendingRequestId(HttpServletRequest request) { +		String pendigReqId = super.getPendingRequestId(request); +		 +		if (MiscUtil.isEmpty(pendigReqId)) { +			Logger.trace("No 'pendingReqID', seach for 'state' parameter in eID4U use-case ... ");			 +			pendigReqId = request.getParameter(OAuth20Constants.PARAM_STATE);			 +			if (MiscUtil.isEmpty(pendigReqId)) {						 +				Logger.trace("No 'pendingReqID', seach HTTP-Cookie in eID4U use-case ... "); +				pendigReqId = CookieUtils.getValueFromCookie(request, eID4UConstants.HTTP_TRANSACTION_COOKIE_NAME); +				if (MiscUtil.isEmpty(pendigReqId)) +					Logger.info("NO eID4U cookie or 'state' parameter with pendingReqId."); +				 +			} +		} +		 +		return pendigReqId; +		 +	} +	 +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eID4UConstants.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eID4UConstants.java new file mode 100644 index 000000000..45eb161d3 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eID4UConstants.java @@ -0,0 +1,25 @@ +package at.gv.egovernment.moa.id.auth.modules.eidas; + +public class eID4UConstants { +	 +	//configuration parameter +	public static final String CONFIG_PROPS_AP_CONSENT_ENTITYID = "moa.id.protocols.eIDAS.eID4U.AP.consent.entityID"; +	public static final String CONFIG_PROPS_AP_CONSENT_URL = "moa.id.protocols.eIDAS.eID4U.AP.consent.url";		 +	public static final String CONFIG_PROPS_AP_SCOPES = "moa.id.protocols.eIDAS.eID4U.AP.scopes.full";		 +	public static final String CONFIG_PROPS_AP_AUTHTOKENSERVICE_URL = "moa.id.protocols.eIDAS.eID4U.AP.authtokenservice.url"; +	public static final String CONFIG_PROPS_AP_AUTHTOKENSERVICE_PARAM_GRANTTYPE = "moa.id.protocols.eIDAS.eID4U.AP.authtokenservice.param.granttype"; +	public static final String CONFIG_PROPS_AP_AUTHTOKENSERVICE_USERNAME = "moa.id.protocols.eIDAS.eID4U.AP.authtokenservice.username"; +	public static final String CONFIG_PROPS_AP_AUTHTOKENSERVICE_PASSWORD = "moa.id.protocols.eIDAS.eID4U.AP.authtokenservice.password"; +	public static final String CONFIG_PROPS_AP_DATASERVICE_URL = "moa.id.protocols.eIDAS.eID4U.AP.dataservice.url"; +	 +	//session parameter +	public static final String HTTP_TRANSACTION_COOKIE_NAME = "eID4APTransactionId"; +	public static final String HTTP_ENDPOINT_AP_CONSENT_RETURN = "/eidas/eid4u/resume"; +	 +	//process context +	public static final String PROCESS_CONTEXT_FLAG_EID4U_AP_ACCESS = "collecteID4UAttr"; +	public static final String PROCESS_CONTEXT_USERS_BPK_EID4U_ATTRPROVIDER = "eID4UAttrProvbPK"; +	 +	 +	 +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/eID4UAPException.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/eID4UAPException.java new file mode 100644 index 000000000..b7a9fcba9 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/eID4UAPException.java @@ -0,0 +1,32 @@ +package at.gv.egovernment.moa.id.auth.modules.eidas.exceptions; + +import org.opensaml.saml2.core.StatusCode; + +public class eID4UAPException extends EIDASException { + +	/** +	 *  +	 */ +	private static final long serialVersionUID = 1L; + +	public eID4UAPException(String messageId, Object[] parameters) { +		super(messageId, parameters); +	} + +	public eID4UAPException(String messageId, Object[] parameters, Throwable e) { +		super(messageId, parameters, e); +	} +	 +	@Override +	public String getStatusCodeFirstLevel() { +		return StatusCode.RESPONDER_URI; +		 +	} + +	@Override +	public String getStatusCodeSecondLevel() { +		return StatusCode.AUTHN_FAILED_URI; +		 +	} + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/CollectAddtionalAttributesTask.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/CollectAddtionalAttributesTask.java index 7cd276043..9d9d44b34 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/CollectAddtionalAttributesTask.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/CollectAddtionalAttributesTask.java @@ -11,23 +11,26 @@ import org.springframework.stereotype.Component;  import at.gv.egiz.eaaf.core.api.idp.IAuthData;  import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;  import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; -import at.gv.egiz.eaaf.core.exceptions.EAAFStorageException;  import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;  import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; +import at.gv.egiz.eaaf.core.impl.idp.builder.attributes.BPKAttributeBuilder;  import at.gv.egiz.eaaf.core.impl.utils.Random;  import at.gv.egiz.eid4u.api.attributes.Definitions; -import at.gv.egiz.eid4u.api.attributes.natural.IdType; -import at.gv.egiz.eid4u.api.attributes.natural.MaritalState;  import at.gv.egovernment.moa.id.auth.builder.AuthenticationDataBuilder;  import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionWrapper; +import at.gv.egovernment.moa.id.auth.modules.eidas.eID4UConstants; +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SimpleEidasAttributeGenerator;  import at.gv.egovernment.moa.id.protocols.eidas.EIDASData; +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Constants;  import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20SessionObject;  import at.gv.egovernment.moa.id.protocols.oauth20.protocol.OAuth20AuthAction;  import at.gv.egovernment.moa.id.protocols.oauth20.protocol.OAuth20AuthRequest; +import at.gv.egovernment.moa.id.protocols.oauth20.protocol.OAuth20Protocol; +import at.gv.egovernment.moa.id.util.CookieUtils;  import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil;  import eu.eidas.auth.commons.attribute.ImmutableAttributeMap;  import eu.eidas.auth.commons.attribute.ImmutableAttributeMap.Builder; -import eu.eidas.auth.commons.protocol.eidas.impl.PostalAddress;  @Component("CollectAddtionalAttributesTask")  public class CollectAddtionalAttributesTask extends AbstractAuthServletTask { @@ -40,6 +43,8 @@ public class CollectAddtionalAttributesTask extends AbstractAuthServletTask {  	public void execute(ExecutionContext context, HttpServletRequest httpReq, HttpServletResponse httpResp)  			throws TaskExecutionException {  		try{ +			context.put(eID4UConstants.PROCESS_CONTEXT_FLAG_EID4U_AP_ACCESS, false); +			  			if (pendingReq instanceof EIDASData) {  				EIDASData eidasReq = (EIDASData) pendingReq;  				Logger.debug("Find eIDAS Auth. Req. Check if eID4U attributes are requested ..."); @@ -59,12 +64,26 @@ public class CollectAddtionalAttributesTask extends AbstractAuthServletTask {  				ImmutableAttributeMap reqEid4uAttrList = reqEid4uAttrListBuilder.build();  				if (reqEid4uAttrList != null && reqEid4uAttrList.size() > 0) {  					Logger.info("Starting eID4U attribute collection process ... "); - -					//generate scope from attributes - -										 +				 +					//mark execution context with eID4U AP flag +					context.put(eID4UConstants.PROCESS_CONTEXT_FLAG_EID4U_AP_ACCESS, true); +					  					//load connection parameters to TUG -					String uniqueID = null; +					String uniqueID = authConfig.getBasicConfiguration(eID4UConstants.CONFIG_PROPS_AP_CONSENT_ENTITYID); +					String redirectURI = authConfig.getBasicConfiguration(eID4UConstants.CONFIG_PROPS_AP_CONSENT_URL); +					String scopes = authConfig.getBasicConfiguration(eID4UConstants.CONFIG_PROPS_AP_SCOPES); +					 +					if (MiscUtil.isEmpty(scopes)) { +						//generate scope from attributes +						//TODO extract 'scopes' from requested attributes +						Logger.warn("Dynamic 'scope' generation is currently NOT supported"); +						 +					}					 +					 +					Logger.debug("Load eID4U AP-Config:" +							+ " EntityID: " + uniqueID +							+ " RedirectURL:" + redirectURI +							+ " Scopes: " + scopes);  					/* @@ -72,10 +91,13 @@ public class CollectAddtionalAttributesTask extends AbstractAuthServletTask {  					*/  					//generate fake OpenID_Connect request -					OAuth20AuthRequest fakeOpenIDReq = new OAuth20AuthRequest();					 +					OAuth20AuthRequest fakeOpenIDReq = new OAuth20AuthRequest(); +					fakeOpenIDReq.initialize(httpReq, authConfig); +					fakeOpenIDReq.setSPEntityId(uniqueID); +					fakeOpenIDReq.setModule(OAuth20Protocol.NAME);  					fakeOpenIDReq.setOnlineApplicationConfiguration(authConfig.getServiceProviderConfiguration(uniqueID));  					fakeOpenIDReq.setScope("openId profile"); -					 +										  					//populate with SessionData  					fakeOpenIDReq.setRawDataToTransaction(  							pendingReq.getSessionData(AuthenticationSessionWrapper.class) @@ -92,14 +114,33 @@ public class CollectAddtionalAttributesTask extends AbstractAuthServletTask {  					Map<String, Object> idToken = openIDAuthAction.generateIDToken(o, fakeOpenIDReq, authData, accessToken);  					o.setAuthDataSession(idToken);  					transactionStorage.put(accessToken, o, -1); -					 -					 +										  					//forward to TUG - -					 -					//TODO: implement collection process -					populateEid4uDummyAttributes(); +					httpResp.setStatus(HttpServletResponse.SC_FOUND);					 +					redirectURI = addURLParameter(redirectURI, OAuth20Constants.PARAM_OPENID_CODE, accessToken); +					redirectURI = addURLParameter(redirectURI, OAuth20Constants.PARAM_SCOPE, scopes); +					redirectURI = addURLParameter(redirectURI, OAuth20Constants.PARAM_STATE,  +							pendingReq.getPendingRequestId()); +					redirectURI = addURLParameter(redirectURI, OAuth20Constants.PARAM_REDIRECT_URI,  +							pendingReq.getAuthURL() + eID4UConstants.HTTP_ENDPOINT_AP_CONSENT_RETURN); +															 +					final String finalUrl = redirectURI; +					httpResp.addHeader("Location", finalUrl); +					Logger.debug("REDIRECT TO: " + finalUrl.toString()); +					//set session cookie, because eID4U AP from TUG maybe not support pendingReqIds on request level +					CookieUtils.setCookie(httpReq, httpResp,  +							eID4UConstants.HTTP_TRANSACTION_COOKIE_NAME,  +							pendingReq.getPendingRequestId(), -1); + +					//set user's bPK into pendingRequst because TUG AttributeProvider needs it +					pendingReq.setRawDataToTransaction( +							eID4UConstants.PROCESS_CONTEXT_USERS_BPK_EID4U_ATTRPROVIDER,  +							new BPKAttributeBuilder().build( +									fakeOpenIDReq.getServiceProviderConfiguration(),  +									authData,  +									new SimpleEidasAttributeGenerator())); +					requestStoreage.storePendingRequest(pendingReq);  				} else  					Logger.debug("No eID4U attributes found. Skip eID4U attribute collection"); @@ -108,54 +149,9 @@ public class CollectAddtionalAttributesTask extends AbstractAuthServletTask {  				Logger.debug("No eIDAS Request found. Skip eID4U attribute collection");  		} catch (Exception e) { -			Logger.error("IdentityLink generation for foreign person FAILED.", e); -			throw new TaskExecutionException(pendingReq, "IdentityLink generation for foreign person FAILED.", e); -			 -		} -		 -	} - -	private void populateEid4uDummyAttributes() { -		try { -			eu.eidas.auth.commons.protocol.eidas.impl.PostalAddress.Builder dummyAddr = PostalAddress.builder(); -			dummyAddr.postCode("8020"); -			dummyAddr.postName("Graz"); -			dummyAddr.addressId("25"); -			dummyAddr.cvAddressArea("Mustergasse"); -			dummyAddr.locatorDesignator("25"); -			dummyAddr.thoroughfare("Mustergasse");  - -			AuthenticationSessionWrapper session = pendingReq.getSessionData(AuthenticationSessionWrapper.class); -			session.setGenericDataToSession(Definitions.IDTYPE_NAME, IdType.PASSPORT); -			session.setGenericDataToSession(Definitions.IDNUMBER_NAME, "P0571414"); -			session.setGenericDataToSession(Definitions.IDISSUER_NAME, "Magistrat Nirgendwo"); -			session.setGenericDataToSession(Definitions.IDEXPIREDATE_NAME, "2020-01-01"); -			session.setGenericDataToSession(Definitions.EHICID_NAME, "80010000012345678990"); -			session.setGenericDataToSession(Definitions.NATIONALITY_NAME, "AT"); -			session.setGenericDataToSession(Definitions.CITIZENSHIP_FRIENDLYNAME, "AT"); -			session.setGenericDataToSession(Definitions.MARITALSTATE_NAME, MaritalState.SINGLE); -			session.setGenericDataToSession(Definitions.COUNTRYOFBIRTH_NAME, "AT"); -			session.setGenericDataToSession(Definitions.EMAIL_NAME, "max.mustermann@domain.at"); -			session.setGenericDataToSession(Definitions.PHONE_NAME, "+43666111222444"); -			session.setGenericDataToSession(Definitions.TEMPORARYADDRESS_NAME, dummyAddr.build()); -			session.setGenericDataToSession(Definitions.TAXIDENTIFICATIONNUMBER_NAME, "AT/1213454654718"); -			session.setGenericDataToSession(Definitions.HOMEINSTITUTIONNAME_NAME, "Graz Technical University"); -			session.setGenericDataToSession(Definitions.HOMEINSTITUTIONIDENTIFIER_NAME, "A GRAZ02"); -			session.setGenericDataToSession(Definitions.HOMEINSTITUTIONCOUNTRY_NAME, "AT"); -			session.setGenericDataToSession(Definitions.HOMEINSTITUTIONADDRESS_NAME, dummyAddr.build()); -			session.setGenericDataToSession(Definitions.CURRENTLEVELOFSTUDY_NAME, "7"); -			session.setGenericDataToSession(Definitions.FIELDOFSTUDY_NAME, "52"); -			session.setGenericDataToSession(Definitions.CURRENTDEGREE_NAME, "MsC"); -			session.setGenericDataToSession(Definitions.DEGREE_NAME, "6"); -			session.setGenericDataToSession(Definitions.DEGREEAWARDINGINSTITUTION_NAME, "Graz Technical University"); -			session.setGenericDataToSession(Definitions.GRADUATIONYEAR_NAME, "2016"); -			session.setGenericDataToSession(Definitions.DEGREECOUNTRY_NAME, "AT"); -			 -			//TODO: not all attributes are populated with dummy values +			Logger.error("eID4U AttributeProvider communication FAILED.", e); +			throw new TaskExecutionException(pendingReq, "eID4U AttributeProvider communication FAILED", e); -		} catch (EAAFStorageException e) { -			// TODO Auto-generated catch block -			e.printStackTrace();  		}  	} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveConsentForAddtionalAttributesTask.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveConsentForAddtionalAttributesTask.java new file mode 100644 index 000000000..3f1e999ca --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveConsentForAddtionalAttributesTask.java @@ -0,0 +1,255 @@ +package at.gv.egovernment.moa.id.auth.modules.eidas.tasks; + +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +import javax.net.ssl.SSLSocketFactory; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.http.Header; +import org.apache.http.HttpHeaders; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.impl.client.CloseableHttpClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; +import at.gv.egiz.eaaf.core.exceptions.EAAFStorageException; +import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; +import at.gv.egiz.eid4u.api.attributes.Definitions; +import at.gv.egiz.eid4u.api.attributes.natural.IdType; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionWrapper; +import at.gv.egovernment.moa.id.auth.modules.eidas.eID4UConstants; +import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.eID4UAPException; +import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; +import at.gv.egovernment.moa.id.commons.utils.HttpClientWithProxySupport; +import at.gv.egovernment.moa.id.protocols.eidas.EIDASData; +import at.gv.egovernment.moa.id.protocols.oauth20.OAuth20Constants; +import at.gv.egovernment.moa.id.util.CookieUtils; +import at.gv.egovernment.moa.id.util.SSLUtils; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; +import eu.eidas.auth.commons.protocol.eidas.impl.PostalAddress; + +@Component("ReceiveConsentForAddtionalAttributesTask") +public class ReceiveConsentForAddtionalAttributesTask extends AbstractAuthServletTask { + +	@Autowired private AuthConfiguration moaAuthConfig; +	 +	@Override +	public void execute(ExecutionContext context, HttpServletRequest httpReq, HttpServletResponse httpResp) +			throws TaskExecutionException { +		try{ +			if (pendingReq instanceof EIDASData) { +				EIDASData eidasReq = (EIDASData) pendingReq; +			 +				//delete eID4U http Cookie with pendingRequestId  +				CookieUtils.deleteCookie(httpReq, httpResp, eID4UConstants.HTTP_TRANSACTION_COOKIE_NAME); +				 +				String authCode = httpReq.getParameter(OAuth20Constants.RESPONSE_CODE);	 +				if (MiscUtil.isEmpty(authCode)) { +					Logger.info("Find NO OAuth2 authCode as http parameter 'code'. eID4U AP process stopping ... "); +					throw new eID4UAPException("NO OAuth2 'authCode' to access AP", null); +					 +				}				 +				Logger.trace("Find OAuth2 'code' with: " + authCode); +					 +				/* +				 * access backend service with authCode +				 *  +				 */ +				String tokenServiceURL = authConfig.getBasicConfiguration(eID4UConstants.CONFIG_PROPS_AP_AUTHTOKENSERVICE_URL); +				String tokenServiceUsername = authConfig.getBasicConfiguration(eID4UConstants.CONFIG_PROPS_AP_AUTHTOKENSERVICE_USERNAME); +				String tokenServicePassword = authConfig.getBasicConfiguration(eID4UConstants.CONFIG_PROPS_AP_AUTHTOKENSERVICE_PASSWORD); +				 +				if (MiscUtil.isEmpty(tokenServiceURL)) { +					Logger.info("NO TokenService URL in configuration for eID4U AP. "); +					throw new eID4UAPException("NO TokenService URL in configuration for eID4U AP.", null); +					 +				} +					 +				//open http client +				SSLSocketFactory sslFactory = SSLUtils.getSSLSocketFactory( +						moaAuthConfig, +						tokenServiceURL); +				CloseableHttpClient httpClient = HttpClientWithProxySupport.getHttpClient( +						sslFactory, +						authConfig.getBasicMOAIDConfigurationBoolean(AuthConfiguration.PROP_KEY_OVS_SSL_HOSTNAME_VALIDATION, true)); +								 +				//build request URL +				URIBuilder uriBuilderToken = new URIBuilder(tokenServiceURL); +				uriBuilderToken.addParameter(OAuth20Constants.PARAM_GRANT_TYPE,  +						authConfig.getBasicConfiguration( +								eID4UConstants.CONFIG_PROPS_AP_AUTHTOKENSERVICE_PARAM_GRANTTYPE,  +								OAuth20Constants.PARAM_GRANT_TYPE_VALUE_AUTHORIZATION_CODE)); +				uriBuilderToken.addParameter(OAuth20Constants.RESPONSE_CODE, authCode); +				Logger.trace("Full eID4U Token-Service request URL: " + uriBuilderToken.build()); +				 +				HttpGet httpGetToken = new HttpGet(uriBuilderToken.build()); +				 +				HttpClientContext localContext = HttpClientContext.create(); +				if (MiscUtil.isNotEmpty(tokenServiceUsername)) {										 +					Logger.debug("Find AuthCredentials for eID4U AP. Injecting credentials ... "); + +					//Raw work-around, because API solution does not work well +					String auth = tokenServiceUsername.trim() + ":" + tokenServicePassword.trim(); +					byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes(StandardCharsets.ISO_8859_1)); +					String authHeader = "Basic " + new String(encodedAuth); +					httpGetToken.setHeader(HttpHeaders.AUTHORIZATION, authHeader); +					 +					//API solutuion +//					HttpHost targetHost = new HttpHost(uriBuilderToken.build().toString());					 +//					AuthCache authCache = new BasicAuthCache(); +//					authCache.put(targetHost, new BasicScheme()); +//					 +//					CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); +//					credentialsProvider.setCredentials(AuthScope.ANY,  +//							new UsernamePasswordCredentials(tokenServiceUsername.trim(), tokenServicePassword.trim()));					 +//					localContext.setCredentialsProvider(credentialsProvider); +//					localContext.setAuthCache(authCache); +					 +				} +				 +				//request tokenService +				HttpResponse httpResultToken = httpClient.execute(httpGetToken, localContext); + +				Logger.trace("Receive http StatusCode: " + httpResultToken.getStatusLine().getStatusCode()  +						+ " from eID4U AP TokenService");								 +								 +				if (Logger.isTraceEnabled()) { +					for (Header el : httpResultToken.getAllHeaders()) +						Logger.trace("Headername:" + el.getName() + " Value:" + el.getValue()); +				} + +				if (httpResultToken.getStatusLine().getStatusCode() != 200) { +					Logger.info("eID4U AP TokenService anwser with StatusCode:" + httpResultToken.getStatusLine().getStatusCode() +							+ " eID4U AP process stopping ... "); +					throw new eID4UAPException("eID4U AP TokenService return statusCode: " + httpResultToken.getStatusLine().getStatusCode(), null); +					 +				} +				 +				//parse AccessToken from TokenService response +				JsonElement fullToken = new JsonParser().parse( +						new InputStreamReader(httpResultToken.getEntity().getContent())); +				Logger.trace("FullToken: " + fullToken.toString()); +				String accessToken = fullToken.getAsJsonObject().get(OAuth20Constants.RESPONSE_ACCESS_TOKEN).getAsString(); +				 +								 +				//call Attribute Provider to receice eID4U attributes from TUG +				String attrProviderServiceURL = authConfig.getBasicConfiguration(eID4UConstants.CONFIG_PROPS_AP_DATASERVICE_URL);				 +				if (MiscUtil.isEmpty(attrProviderServiceURL)) { +					Logger.info("NO Attr.Provider Service URL in configuration for eID4U AP. "); +					throw new eID4UAPException("NO Attr.Provider URL in configuration for eID4U AP.", null); +					 +				} +				 +				 +				URIBuilder uriBuilderAttrProv = new URIBuilder(attrProviderServiceURL); +				HttpGet httpGetData = new HttpGet(uriBuilderAttrProv.build()); +				 +				//encode and add token as header +				String authHeader = "Bearer " + accessToken; +				httpGetData.setHeader(HttpHeaders.AUTHORIZATION, authHeader); +				 +				//get and add bPK as header +				httpGetData.setHeader( +						"X-PVP-BPK",  +						pendingReq.getRawData(eID4UConstants.PROCESS_CONTEXT_USERS_BPK_EID4U_ATTRPROVIDER, String.class)); +				 +				//request Attribute Provider +				HttpResponse httpResultData = httpClient.execute(httpGetData); + +				//parse response +				Logger.trace("Receive http StatusCode: " + httpResultData.getStatusLine().getStatusCode()  +						+ " from eID4U Attr.Provider Service");								 +								 +				if (Logger.isTraceEnabled()) { +					for (Header el : httpResultData.getAllHeaders()) +						Logger.trace("Headername:" + el.getName() + " Value:" + el.getValue()); +				} + +				if (httpResultData.getStatusLine().getStatusCode() != 200) { +					Logger.info("eID4U Attr.Provider Service anwser with StatusCode:" + httpResultData.getStatusLine().getStatusCode() +							+ " eID4U AP process stopping ... "); +					throw new eID4UAPException("eID4U Attr.Provider Service return statusCode: " + httpResultData.getStatusLine().getStatusCode(), null); +					 +				} +				 +				 +				//parse eID4U attributes from Attr.Provider service response +				JsonElement fullAttrSet = new JsonParser().parse( +						new InputStreamReader(httpResultData.getEntity().getContent())); +				Logger.trace("FullAttrSet: " + fullAttrSet.toString()); +				 +				 +				//TODO: implement collection process +				populateEid4uDummyAttributes(fullAttrSet.getAsJsonObject()); +					 +								 +			} else +				Logger.debug("No eIDAS Request found. Skip eID4U attribute collection"); +			 +		} catch (Exception e) { +			Logger.error("IdentityLink generation for foreign person FAILED.", e); +			throw new TaskExecutionException(pendingReq, "IdentityLink generation for foreign person FAILED.", e); +			 +		} +		 +	} + +	private void populateEid4uDummyAttributes(JsonObject jsonObject) { +		try { +			eu.eidas.auth.commons.protocol.eidas.impl.PostalAddress.Builder dummyAddr = PostalAddress.builder(); +			dummyAddr.postCode("8020"); +			dummyAddr.postName("Graz"); +			dummyAddr.addressId("25"); +			dummyAddr.cvAddressArea("Mustergasse"); +			dummyAddr.locatorDesignator("25"); +			dummyAddr.thoroughfare("Mustergasse");  + +			AuthenticationSessionWrapper session = pendingReq.getSessionData(AuthenticationSessionWrapper.class); +			session.setGenericDataToSession(Definitions.IDTYPE_NAME, IdType.PASSPORT); +			session.setGenericDataToSession(Definitions.IDNUMBER_NAME, "P0571414"); +//			session.setGenericDataToSession(Definitions.IDISSUER_NAME, "Magistrat Nirgendwo"); +//			session.setGenericDataToSession(Definitions.IDEXPIREDATE_NAME, "2020-01-01"); +//			//session.setGenericDataToSession(Definitions.EHICID_NAME, "80010000012345678990"); +//			session.setGenericDataToSession(Definitions.NATIONALITY_NAME, "AT"); +//			session.setGenericDataToSession(Definitions.CITIZENSHIP_FRIENDLYNAME, "AT"); +//			session.setGenericDataToSession(Definitions.MARITALSTATE_NAME, MaritalState.SINGLE); +//			session.setGenericDataToSession(Definitions.COUNTRYOFBIRTH_NAME, "AT"); +			session.setGenericDataToSession(Definitions.EMAIL_NAME, jsonObject.get("email").getAsString()); +//			session.setGenericDataToSession(Definitions.PHONE_NAME, "+43666111222444"); +//			session.setGenericDataToSession(Definitions.TEMPORARYADDRESS_NAME, dummyAddr.build()); +			//session.setGenericDataToSession(Definitions.TAXIDENTIFICATIONNUMBER_NAME, "AT/1213454654718"); +//			session.setGenericDataToSession(Definitions.HOMEINSTITUTIONNAME_NAME, "Graz Technical University"); +//			session.setGenericDataToSession(Definitions.HOMEINSTITUTIONIDENTIFIER_NAME, "A GRAZ02"); +//			session.setGenericDataToSession(Definitions.HOMEINSTITUTIONCOUNTRY_NAME, "AT"); +//			session.setGenericDataToSession(Definitions.HOMEINSTITUTIONADDRESS_NAME, dummyAddr.build()); +//			session.setGenericDataToSession(Definitions.CURRENTLEVELOFSTUDY_NAME, "7"); +//			session.setGenericDataToSession(Definitions.FIELDOFSTUDY_NAME, "52"); +			//session.setGenericDataToSession(Definitions.CURRENTDEGREE_NAME, "MsC"); +//			session.setGenericDataToSession(Definitions.DEGREE_NAME, "6"); +//			session.setGenericDataToSession(Definitions.DEGREEAWARDINGINSTITUTION_NAME, "Graz Technical University"); +//			session.setGenericDataToSession(Definitions.GRADUATIONYEAR_NAME, "2016"); +//			session.setGenericDataToSession(Definitions.DEGREECOUNTRY_NAME, "AT"); +			 +			//TODO: not all attributes are populated with dummy values +			 +		} catch (EAAFStorageException e) { +			// TODO Auto-generated catch block +			e.printStackTrace(); +		} +		 +	} + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/resources/eid4u.Authentication.process.xml b/id/server/modules/moa-id-module-eIDAS/src/main/resources/eid4u.Authentication.process.xml index 56af3955e..4ab49641f 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/resources/eid4u.Authentication.process.xml +++ b/id/server/modules/moa-id-module-eIDAS/src/main/resources/eid4u.Authentication.process.xml @@ -17,9 +17,12 @@  	<pd:Task id="finalizeAuthentication" 	class="FinalizeAuthenticationTask" />  	<pd:Task id="getForeignID"              class="GetForeignIDTask"              async="true" />	  	<pd:Task id="userRestrictionTask" 		class="UserRestrictionTask" /> +	<pd:Task id="genericFrontChannelRedirectTask" class="GenericFrontChannelRedirectTask"/>  	<!-- eID4U extensions --> -	<pd:Task id="collectAddtionalAttributesTask" 		class="CollectAddtionalAttributesTask" /> +	<pd:Task id="collectAddtionalAttributesTask" 		class="CollectAddtionalAttributesTask" async="true"/> +	<pd:Task id="receiveConsentForAddtionalAttributesTask" 		class="ReceiveConsentForAddtionalAttributesTask" async="true"/> + @@ -53,11 +56,15 @@  	<pd:Transition from="getForeignID"              to="userRestrictionTask" /> -	<pd:Transition from="userRestrictionTask"           to="collectAddtionalAttributesTask" /> +	<pd:Transition from="userRestrictionTask"           to="genericFrontChannelRedirectTask" /> +	 +	<!-- eID4U tasks for attribute collection -->	 +	<pd:Transition from="genericFrontChannelRedirectTask"           to="collectAddtionalAttributesTask" /> -	<!-- eID4U tasks for attribute collection --> -	<pd:Transition from="collectAddtionalAttributesTask"           to="finalizeAuthentication" /> +	<pd:Transition from="collectAddtionalAttributesTask"           	to="receiveConsentForAddtionalAttributesTask" conditionExpression="ctx['collecteID4UAttr']" /> +	<pd:Transition from="collectAddtionalAttributesTask"           	to="finalizeAuthentication" conditionExpression="!ctx['collecteID4UAttr']" /> +	<pd:Transition from="receiveConsentForAddtionalAttributesTask"  to="finalizeAuthentication" />  	<pd:Transition from="finalizeAuthentication"    to="end" /> diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/resources/moaid_eidas_auth.beans.xml b/id/server/modules/moa-id-module-eIDAS/src/main/resources/moaid_eidas_auth.beans.xml index 836e6319b..da4a2a95b 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/resources/moaid_eidas_auth.beans.xml +++ b/id/server/modules/moa-id-module-eIDAS/src/main/resources/moaid_eidas_auth.beans.xml @@ -17,6 +17,9 @@  	<bean id="eIDASSignalServlet"  				class="at.gv.egovernment.moa.id.auth.modules.eidas.eIDASSignalServlet"/> +	<bean id="eID4UAPSignalServlet" +				class="at.gv.egovernment.moa.id.auth.modules.eidas.eID4UAPSignalServlet"/> +  	<bean id="EIDASProtocol"  				class="at.gv.egovernment.moa.id.protocols.eidas.EIDASProtocol"/> @@ -39,5 +42,10 @@  	<bean id="CollectAddtionalAttributesTask"   				class="at.gv.egovernment.moa.id.auth.modules.eidas.tasks.CollectAddtionalAttributesTask"  				scope="prototype"/> +	 +	<bean id="ReceiveConsentForAddtionalAttributesTask"  +				class="at.gv.egovernment.moa.id.auth.modules.eidas.tasks.ReceiveConsentForAddtionalAttributesTask" +				scope="prototype"/>			 +				  </beans>
\ No newline at end of file diff --git a/id/server/modules/moa-id-module-openID/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20Constants.java b/id/server/modules/moa-id-module-openID/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20Constants.java index b0736ff2e..cc987bfe7 100644 --- a/id/server/modules/moa-id-module-openID/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20Constants.java +++ b/id/server/modules/moa-id-module-openID/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/OAuth20Constants.java @@ -56,7 +56,8 @@ public final class OAuth20Constants {  	public static final String PARAM_SCOPE = "scope";  	public static final String PARAM_MOA_MOD = "mod";  	public static final String PARAM_MOA_ACTION = "action"; - +	public static final String PARAM_OPENID_CODE = "openid_code"; +	  	// reponse parameters  	public static final String RESPONSE_CODE = "code"; diff --git a/id/server/modules/moa-id-module-openID/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/protocol/OAuth20Protocol.java b/id/server/modules/moa-id-module-openID/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/protocol/OAuth20Protocol.java index e83353059..0952ba0a6 100644 --- a/id/server/modules/moa-id-module-openID/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/protocol/OAuth20Protocol.java +++ b/id/server/modules/moa-id-module-openID/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/protocol/OAuth20Protocol.java @@ -107,12 +107,12 @@ public class OAuth20Protocol extends AbstractAuthProtocolModulController impleme  	//openID Connect tokken request  	@RequestMapping(value = "/oauth2/token", method = {RequestMethod.POST, RequestMethod.GET}) -	public void OpenIDConnectTokkenRequest(HttpServletRequest req, HttpServletResponse resp) throws MOAIDException, IOException, InvalidProtocolRequestException { -//		if (!authConfig.getAllowedProtocols().isOAUTHActive()) { -//			Logger.info("OpenID-Connect is deaktivated!"); -//			throw new ProtocolNotActiveException("auth.22", new java.lang.Object[] { NAME }); -//			 -//		} +	public void OpenIDConnectTokkenRequest(HttpServletRequest req, HttpServletResponse resp) throws EAAFException, IOException, InvalidProtocolRequestException { +		if (!moaAuthConfig.getAllowedProtocols().isOAUTHActive()) { +			Logger.info("OpenID-Connect is deaktivated!"); +			throw new ProtocolNotActiveException("auth.22", new java.lang.Object[] { NAME }); +			 +		}  		OAuth20TokenRequest pendingReq = applicationContext.getBean(OAuth20TokenRequest.class);  		try {			 | 
