package at.gv.egovernment.moa.id.protocols.stork2; import java.util.ArrayList; import java.util.List; import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; 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.moduls.IAction; import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.id.storage.AssertionStorage; import at.gv.egovernment.moa.logging.Logger; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.opensaml.common.impl.SecureRandomIdentifierGenerator; import eu.stork.peps.auth.commons.IPersonalAttributeList; import eu.stork.peps.auth.commons.PersonalAttribute; /** * 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"; private ArrayList attributeProviders; /** The return url. */ // TODO find correct return URL private String returnUrl = "findCorrectReturnURL"; public AttributeCollector() { // TODO generate from config attributeProviders = new ArrayList(); attributeProviders.add(new DemoRedirectAttributeProvider()); attributeProviders.add(new DemoNoRedirectAttributeProvider()); } /* (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 String processRequest(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp, AuthenticationSession moasession) throws MOAIDException { // check if we have a STORKAttributeResponse in the request // - no, how did we get here? // yes, we got a recent requested attribute // - find the attribute provider plugin that can handle the response PersonalAttribute newAttribute = null; for (AttributeProvider current : attributeProviders) try { newAttribute = current.parse(httpReq); } catch (UnsupportedAttributeException e1) { // the current provider cannot find anything familiar within the // provided httpreq. Try the next one. } if (null == newAttribute) { // we do not have a provider which is capable of fetching something // from the received httpreq. // TODO should we continue with the next attribute? Logger.error("No attribute could be retrieved from the response the attribute provider gave us."); throw new MOAIDException("stork.11", null); } // - fetch the container String artifactId = (String) httpReq.getAttribute(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); } // - insert the embedded attribute(s) into the container container.getResponse().getPersonalAttributeList().add(newAttribute); // see if we need some more attributes return processRequest(container, httpResp); } /** * 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 String processRequest(DataContainer container, HttpServletResponse response) throws MOAIDException { // check if there are attributes we need to fetch IPersonalAttributeList requestAttributeList = container.getRequest().getPersonalAttributeList(); IPersonalAttributeList responseAttributeList = container.getResponse().getPersonalAttributeList(); List missingAttributes = new ArrayList(); for(PersonalAttribute current : requestAttributeList) if(!responseAttributeList.containsKey(current)) missingAttributes.add(current.getName()); try { // for each attribute still missing for(String currentAttribute : missingAttributes) { // - check if we can find a suitable AttributeProvider Plugin for(AttributeProvider currentProvider : attributeProviders) { try { // - hand over control to the suitable plugin PersonalAttribute aquiredAttribute = currentProvider.acquire(currentAttribute); // - add the aquired attribute to the container container.getResponse().getPersonalAttributeList().add(aquiredAttribute); } catch(UnsupportedAttributeException e) { // ok, try the next attributeprovider } } } } catch (ExternalAttributeRequestRequiredException e) { // the attribute request is ongoing and requires an external service. try { // memorize the container again // - generate new key String newArtifactId = new SecureRandomIdentifierGenerator() .generateIdentifier(); // - put container in temporary store. AssertionStorage.getInstance().put(newArtifactId, container); // add container-key to redirect embedded within the return URL e.getAp().performRedirect(returnUrl + "?" + ARTIFACT_ID + "=" + newArtifactId, response); } catch (Exception e1) { // TODO should we return the response as is to the PEPS? Logger.error("Error putting incomplete Stork response into temporary storage", e); throw new MOAIDException("stork.11", null); } return "12345"; // TODO what to do here? } // build response // done return "12345"; // AssertionId } /* (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; } }