package at.gv.egovernment.moa.id.protocols.stork2; import java.io.StringWriter; import java.util.ArrayList; import java.util.HashMap; import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; import at.gv.egovernment.moa.id.auth.stork.VelocityProvider; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; 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 eu.stork.peps.auth.commons.PEPSUtil; import eu.stork.peps.auth.commons.PersonalAttribute; import eu.stork.peps.auth.commons.STORKAuthnResponse; import eu.stork.peps.auth.engine.STORKSAMLEngine; import eu.stork.peps.exceptions.STORKSAMLEngineException; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.joda.time.DateTime; import org.opensaml.common.impl.SecureRandomIdentifierGenerator; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * The ConsentEvaluator assists with fetching user consent on the list of attributes to be sent to the asking S-PEPS. */ public class ConsentEvaluator 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 String processRequest(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp, AuthenticationSession moasession) 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.17", null); } // evaluate response for(PersonalAttribute current : container.getResponse().getPersonalAttributeList()) { if(null == httpReq.getParameter(current.getName())) { current.setStatus("notAvailable"); current.setValue(new ArrayList()); current.setComplexValue(new HashMap()); } } // build and send response generateSTORKResponse(httpResp, container); return "12345"; // AssertionId } /** * Fills the given HttpResponse with the required web page. * * @param container the container * @param response the response * @param oaParam the oa param * @return the string * @throws MOAIDException the mOAID exception */ public String requestConsent(DataContainer container, HttpServletResponse response, OAAuthParameter oaParam) throws MOAIDException { // prepare redirect String newArtifactId; try { // memorize the container again Logger.debug("prepare putting the container into temporary storage..."); // - generate new key newArtifactId = new SecureRandomIdentifierGenerator().generateIdentifier(); // - put container in temporary store. AssertionStorage.getInstance().put(newArtifactId, container); Logger.debug("...successful"); } catch (Exception e1) { // TODO should we return the response as is to the PEPS? e1.printStackTrace(); Logger.error("Error putting incomplete Stork response into temporary storage", e1); throw new MOAIDException("stork.17", null); } // ask for consent try { VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine(); Template template = velocityEngine.getTemplate("/resources/templates/stork2_consent.html"); VelocityContext context = new VelocityContext(); context.put("action", AuthConfigurationProvider.getInstance().getPublicURLPrefix() + "/stork2/CompleteAuthentication?" + ARTIFACT_ID + "=" + newArtifactId); // assemble table String table = ""; for (PersonalAttribute current : container.getResponse().getPersonalAttributeList()) if ("Available".equals(current.getStatus())) table += "" + current.getName() + "\n"; context.put("tablecontent", table); StringWriter writer = new StringWriter(); template.merge(context, writer); response.getOutputStream().write(writer.getBuffer().toString().getBytes()); } catch (Exception e) { Logger.error("Velocity error: " + e.getMessage()); throw new MOAIDException("stork.17", null); } return "12345"; // AssertionId } /** * generates binary response from given response class and fill the given HttpResponse with a SAML Post Binding template. * * @param httpResp the http resp * @param container the container * @throws MOAIDException the mOAID exception */ public void generateSTORKResponse(HttpServletResponse httpResp, DataContainer container) throws MOAIDException { MOASTORKRequest request = container.getRequest(); MOASTORKResponse response = container.getResponse(); Logger.info("generating stork response..."); try { //Get SAMLEngine instance STORKSAMLEngine engine = STORKSAMLEngine.getInstance("VIDP"); Logger.debug("Starting generation of SAML response"); if(response.isAuthnResponse()) response.setSTORKAuthnResponse(engine.generateSTORKAuthnResponse(request.getStorkAuthnRequest(), response.getStorkAuthnResponse(), container.getRemoteAddress(), false)); else response.setSTORKAttrResponse(engine.generateSTORKAttrQueryResponse(request.getStorkAttrQueryRequest(), response.getStorkAttrQueryResponse(), container.getRemoteAddress(), "", false)); //generateSAML Token Logger.info("SAML response succesfully generated!"); } catch (STORKSAMLEngineException e) { Logger.error("Failed to generate STORK SAML Response", e); throw new MOAIDException("stork.05", null); } // preparing redirection for the client try { VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine(); Template template = velocityEngine.getTemplate("/resources/templates/stork2_postbinding_template.html"); VelocityContext context = new VelocityContext(); byte[] blob; if(request.isAttrRequest()) blob = response.getStorkAttrQueryResponse().getTokenSaml(); else blob = response.getStorkAuthnResponse().getTokenSaml(); context.put("SAMLResponse", PEPSUtil.encodeSAMLToken(blob)); Logger.debug("SAMLResponse original: " + new String(blob)); Logger.debug("Putting assertion consumer url as action: " + request.getAssertionConsumerServiceURL()); context.put("action", request.getAssertionConsumerServiceURL()); Logger.debug("Starting template merge"); StringWriter writer = new StringWriter(); Logger.debug("Doing template merge"); template.merge(context, writer); Logger.debug("Template merge done"); Logger.debug("Sending html content: " + writer.getBuffer().toString()); Logger.debug("Sending html content2 : " + new String(writer.getBuffer())); httpResp.getOutputStream().write(writer.getBuffer().toString().getBytes()); } catch (Exception e) { Logger.error("Velocity error: " + e.getMessage()); } } /* (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.CONSENT_EVALUATOR; } }