diff options
Diffstat (limited to 'id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeCollector.java')
-rw-r--r-- | id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeCollector.java | 367 |
1 files changed, 0 insertions, 367 deletions
diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeCollector.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeCollector.java deleted file mode 100644 index 25cb952d7..000000000 --- a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeCollector.java +++ /dev/null @@ -1,367 +0,0 @@ -/******************************************************************************* - * 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.protocols.stork2; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; -import at.gv.egovernment.moa.id.auth.exception.MOAIDException; -import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; -import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; -import at.gv.egovernment.moa.id.data.IAuthData; -import at.gv.egovernment.moa.id.data.SLOInformationImpl; -import at.gv.egovernment.moa.id.data.SLOInformationInterface; -import at.gv.egovernment.moa.id.moduls.IAction; -import at.gv.egovernment.moa.id.moduls.IRequest; -import at.gv.egovernment.moa.id.protocols.stork2.attributeproviders.AttributeProvider; -import at.gv.egovernment.moa.id.storage.AssertionStorage; -import at.gv.egovernment.moa.logging.Logger; -import eu.stork.peps.auth.commons.*; -import eu.stork.peps.auth.engine.STORKSAMLEngine; -import eu.stork.peps.complex.attributes.eu.stork.names.tc.stork._1_0.assertion.AttributeStatusType; -import eu.stork.peps.exceptions.STORKSAMLEngineException; - -import org.opensaml.common.impl.SecureRandomIdentifierGenerator; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - * The AttributeCollector Action tries to get all requested attributes from a set of {@link AttributeProvider} Plugins. - * The class is called whenever the {@link AuthenticationRequest} Action is invoked and checks for missing attributes. - * Furthermore, the class can handle direct posts. That is when the class triggers an attribute query which needs user - * interaction, redirect to another portal, etc. The redirect will hit here and the class can continue to fetch attributes. - * - * TODO how do we treat mandatory and optional attributes? - */ -public class AttributeCollector implements IAction { - - /** - * The Constant ARTIFACT_ID. - */ - private static final String ARTIFACT_ID = "artifactId"; - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.moduls.IAction#processRequest(at.gv.egovernment.moa.id.moduls.IRequest, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, at.gv.egovernment.moa.id.auth.data.AuthenticationSession) - */ - public SLOInformationInterface processRequest(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp, IAuthData authData) throws MOAIDException { - - // - fetch the container - String artifactId = (String) httpReq.getParameter(ARTIFACT_ID); - DataContainer container; - try { - container = AssertionStorage.getInstance().get(artifactId, DataContainer.class); - } catch (MOADatabaseException e) { - Logger.error("Error fetching incomplete Stork response from temporary storage. Most likely a timeout occured.", e); - throw new MOAIDException("stork.11", null); - } - - - if (httpReq.getParameter("SAMLResponse") != null) { - Logger.info("Got SAML response from external attribute provider."); - - MOASTORKResponse STORK2Response = new MOASTORKResponse(); - - //extract STORK Response from HTTP Request - byte[] decSamlToken; - try { - decSamlToken = PEPSUtil.decodeSAMLToken(httpReq.getParameter("SAMLResponse")); - } catch (NullPointerException e) { - if (httpReq.getRemoteHost().contains("129.27.142")) { - Logger.warn("Availability check by " + httpReq.getRemoteHost() + " on URI: " + httpReq.getRequestURI()); - } else { - Logger.error("Unable to retrieve STORK Request for host: " + httpReq.getRemoteHost() + " and URI: " + httpReq.getRequestURI(), e); - } - throw new MOAIDException("stork.04", null); - } - - //Get SAMLEngine instance - STORKSAMLEngine engine = STORKSAMLEngine.getInstance("VIDP"); - - STORKAuthnResponse authnResponse = null; - - - // check if valid authn response is contained - try { - authnResponse = engine.validateSTORKAuthnResponse(decSamlToken, httpReq.getRemoteAddr()); - } catch (STORKSAMLEngineException ex) { - Logger.error("Unable to validate Stork AuthenticationResponse: " + ex.getMessage()); - } - - STORK2Response.setSTORKAuthnResponseToken(decSamlToken); - - // check if the attributes are provided for the same person from request - // requires presence of eIdentifier for unambigious correlation - Logger.debug("Checking if the attribute relates to the correct person.."); - try { - String remoteEIdentifier= authnResponse.getPersonalAttributeList().get("eIdentifier").getValue().get(0); - String localEidentifier= container.getResponse().getStorkAuthnResponse().getPersonalAttributeList().get("eIdentifier").getValue().get(0); - if (!remoteEIdentifier.equals(localEidentifier)) { - Logger.error("The attribute is not provided for the same person!"); - throw new MOAIDException("stork.25", null); - } - } catch (NullPointerException ex) { - Logger.warn("Could not check the correlation of attributes from external provider. Ignoring the check."); - //Logger.debug(ex); - //throw new MOAIDException("stork.04", null); // TODO revise message, raise exception when ehvd checked - } - - if (authnResponse.getPersonalAttributeList().size() > 0) { - Logger.info("Response from external attribute provider contains " + authnResponse.getPersonalAttributeList().size() + " attributes."); - container.getResponse().setPersonalAttributeList(addOrUpdateAll(container.getResponse().getPersonalAttributeList(), authnResponse.getPersonalAttributeList())); - } - - } - - // end addition - - - // read configuration parameters of OA - OAAuthParameter oaParam = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(container.getRequest().getAssertionConsumerServiceURL()); - if (oaParam == null) - throw new AuthenticationException("stork.12", new Object[]{container.getRequest().getAssertionConsumerServiceURL()}); - - // find the attribute provider plugin that can handle the response - IPersonalAttributeList newAttributes = null; - - Iterator<AttributeProvider> attibuteProvidersInterator = AttributeProviderFactory.getConfiguredPlugins(oaParam.getStorkAPs()); - while(attibuteProvidersInterator.hasNext()) - try { - newAttributes = attibuteProvidersInterator.next().parse(httpReq); - - // stop as soon as we hit a capable plugin - break; - } catch (UnsupportedAttributeException e1) { - // the current provider cannot find anything familiar within the - // provided httpreq. Try the next one. - } - - if (null == newAttributes) { - // we do not have a provider which is capable of fetching something - // from the received httpreq. - Logger.error("No attribute could be retrieved from the response the attribute provider gave us."); - } - - // - insert the embedded attribute(s) into the container - if (null != newAttributes) - container.getResponse().setPersonalAttributeList(addOrUpdateAll(container.getResponse().getPersonalAttributeList(), newAttributes)); - - // see if we need some more attributes - SLOInformationImpl sloInfo = (SLOInformationImpl) processRequest(container, httpReq, httpResp, authData, oaParam); - - if (sloInfo == null) { - sloInfo = new SLOInformationImpl(null, null, null, req.requestedModule()); - } - - return sloInfo; - - } - - /** - * Checks if there are missing attributes and tries to fetch them. If there are no more attribute to fetch, - * this very method creates and sends the protocol result to the asking S-PEPS. - * - * @param container the {@link DataContainer} representing the status of the overall query. - * @return the string - * @throws MOAIDException - */ - public SLOInformationInterface processRequest(DataContainer container, HttpServletRequest request, HttpServletResponse response, IAuthData authData, OAAuthParameter oaParam) throws MOAIDException { - // check if there are attributes we need to fetch - - IPersonalAttributeList requestAttributeList = container.getRequest().getPersonalAttributeList(); - IPersonalAttributeList responseAttributeList = container.getResponse().getPersonalAttributeList(); - List<PersonalAttribute> missingAttributes = new ArrayList<PersonalAttribute>(); - Logger.debug("aquire list of missing attributes"); - for (PersonalAttribute current : requestAttributeList) - if (!responseAttributeList.containsKey(current.getName())) { - if(null == current.getStatus() || (null != current.getStatus() && !current.getStatus().equals(AttributeStatusType.WITHHELD.value()))) { - // add the ones we need - missingAttributes.add(current); - Logger.debug("add " + current.getName() + " to the list of missing attributes"); - } - } else { - // remove the ones we do not want to share from the response list - if(null != current.getStatus() && current.getStatus().equals(AttributeStatusType.WITHHELD.value())) { - responseAttributeList.remove(current.getName()); - Logger.debug("remove " + current.getName() + " from the list of resulting attributes because the user does not want to disclose the data"); - } - } - - Logger.info("collecting attributes..."); - Logger.debug("found " + missingAttributes.size() + " missing attributes"); - - // Try to get all missing attributes - try { - // for each attribute still missing - for (PersonalAttribute currentAttribute : missingAttributes) { - - /* - * prefill attributes with "notAvailable". If we get them later, we override the value and status. - * This way, there is no error case in which an attribute is left unanswered. - */ - IPersonalAttributeList aquiredAttributes = new PersonalAttributeList(); - currentAttribute.setStatus(AttributeStatusType.NOT_AVAILABLE.value()); - aquiredAttributes.add((PersonalAttribute) currentAttribute.clone()); - container.getResponse().setPersonalAttributeList( - addOrUpdateAll(container.getResponse().getPersonalAttributeList(), aquiredAttributes)); - // - check if we can find a suitable AttributeProvider Plugin - - Iterator<AttributeProvider> attibuteProvidersInterator = AttributeProviderFactory.getConfiguredPlugins(oaParam.getStorkAPs()); - while(attibuteProvidersInterator.hasNext()) { - AttributeProvider currentProvider = attibuteProvidersInterator.next(); - - // build a section of attribute provider's predefined attributes and missing attributes - // only missing attributes that can be handled by attribute provider will be sent to it - List<PersonalAttribute> currentProviderConfiguredAttributes = new ArrayList<PersonalAttribute>(); - for (String attributeName : currentProvider.getSupportedAttributeNames()) { - for (PersonalAttribute missingAttribute : missingAttributes) { - if (missingAttribute.getName().equals(attributeName)) { - currentProviderConfiguredAttributes.add(missingAttribute); - break; - } - } - } - - try { - // - hand over control to the suitable plugin - Logger.info(currentProvider.getClass().getSimpleName() + " called to handle attribute '" + currentAttribute.getName() + "'"); - - //aquiredAttributes = currentProvider.acquire(currentAttribute, container.getRequest().getSpCountry(), moasession); - //aquiredAttributes = currentProvider.acquire(missingAttributes, container.getRequest().getSpCountry(), moasession); - aquiredAttributes = currentProvider.acquire(currentProviderConfiguredAttributes, container.getRequest(), authData); - - Logger.info(currentProvider.getClass().getSimpleName() + " can handle attribute '" + currentAttribute.getName() + "'"); - break; - } catch (UnsupportedAttributeException e) { - // ok, try the next attributeprovider - Logger.info(currentProvider.getClass().getSimpleName() + " could not handle attribute '" + currentAttribute.getName() + "'"); - } catch (MOAIDException e) { - // the current plugin had an error. Try the next one. - Logger.info(currentProvider.getClass().getSimpleName() + " could not handle attribute '" + currentAttribute.getName() + "' due to an error"); - } - } - - // check if we could fetch the attribute - if (null == aquiredAttributes) { - // if not - Logger.error("We have no suitable plugin for obtaining the attribute '" + currentAttribute.getName() + "'"); - } else - // else, update any existing attributes - container.getResponse().setPersonalAttributeList(addOrUpdateAll(container.getResponse().getPersonalAttributeList(), aquiredAttributes)); - } - Logger.info("collecting attributes done"); - - // ask for consent if necessary - new ConsentEvaluator().generateSTORKResponse(response, container); - - return null; // AssertionId - // TODO - - } catch (ExternalAttributeRequestRequiredException e) { - // the attribute request is ongoing and requires an external service. - try { - // memorize the container again - Logger.debug("prepare putting the container into temporary storage..."); - - // - generate new key - String newArtifactId = new SecureRandomIdentifierGenerator() - .generateIdentifier(); - // - put container in temporary store. - AssertionStorage.getInstance().put(newArtifactId, container); - - Logger.debug("...successful"); - - Logger.info(e.getAp().getClass().getSimpleName() + " is going to ask an external service provider for the requested attributes"); - - // add container-key to redirect embedded within the return URL - e.getAp().performRedirect(AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix() + "/stork2/ResumeAuthentication?" + ARTIFACT_ID + "=" + newArtifactId, request, response, oaParam); - - } catch (Exception e1) { - // TODO should we return the response as is to the PEPS? - Logger.error("Error putting incomplete Stork response into temporary storage", e1); - e1.printStackTrace(); - throw new MOAIDException("stork.11", null); - } - - //TODO: in case of Single LogOut -> SLO information has to be stored - return null; // TODO what to do here? - } - } - - /** - * Adds or updates all {@link PersonalAttribute} objects given in {@code source} to/in {@code target}. - * - * @param target the target - * @param source the source - * @return - * @throws MOAIDException - */ - private PersonalAttributeList addOrUpdateAll(IPersonalAttributeList target, IPersonalAttributeList source) throws MOAIDException { - - PersonalAttributeList updatedList = new PersonalAttributeList(); - for (PersonalAttribute el : target) - updatedList.add(el); - - Logger.debug("Updating " + source.size() + " attributes..."); - for (PersonalAttribute current : source) { - Logger.debug("treating " + current.getName()); - - // check if we need to update the current pa - if (updatedList.containsKey(current.getName())) { - PersonalAttribute existing = target.get(current.getName()); - if(!(existing.isEmptyValue() && existing.isEmptyComplexValue())) - if(!(existing.getValue().equals(current.getValue()) || existing.getComplexValue().equals(current.getComplexValue()))) { - Logger.error("Attribute Value does not match the value from first authentication!"); - throw new MOAIDException("stork.16", new Object[] {existing.getName()}); - } - - updatedList.get(current.getName()).setStatus(current.getStatus()); - updatedList.get(current.getName()).setValue(current.getValue()); - updatedList.get(current.getName()).setComplexValue(current.getComplexValue()); - } else - updatedList.add(current); - - Logger.debug("...successfully treated " + current.getName()); - } - - return updatedList; - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.moduls.IAction#needAuthentication(at.gv.egovernment.moa.id.moduls.IRequest, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) - */ - public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp) { - // this action does not need any authentication. The authentication is already done by the preceding AuthenticationRequest-Action. - return false; - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.moduls.IAction#getDefaultActionName() - */ - public String getDefaultActionName() { - return STORKProtocol.ATTRIBUTE_COLLECTOR; - } -} |