package at.gv.egovernment.moa.id.configuration.auth.pvp2; import java.io.IOException; import java.security.KeyStore; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.runtime.RuntimeConstants; import org.joda.time.DateTime; import org.opensaml.Configuration; import org.opensaml.common.SAMLObject; import org.opensaml.common.binding.BasicSAMLMessageContext; import org.opensaml.common.impl.SecureRandomIdentifierGenerator; import org.opensaml.common.xml.SAMLConstants; import org.opensaml.saml2.binding.encoding.HTTPPostEncoder; import org.opensaml.saml2.core.AuthnContextClassRef; import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration; import org.opensaml.saml2.core.AuthnRequest; import org.opensaml.saml2.core.Issuer; import org.opensaml.saml2.core.NameID; import org.opensaml.saml2.core.NameIDPolicy; import org.opensaml.saml2.core.NameIDType; import org.opensaml.saml2.core.RequestedAuthnContext; import org.opensaml.saml2.core.Subject; import org.opensaml.saml2.metadata.EntityDescriptor; import org.opensaml.saml2.metadata.SingleSignOnService; import org.opensaml.saml2.metadata.impl.SingleSignOnServiceBuilder; import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; import org.opensaml.ws.transport.http.HttpServletResponseAdapter; import org.opensaml.xml.XMLObject; import org.opensaml.xml.io.Marshaller; import org.opensaml.xml.io.MarshallingException; import org.opensaml.xml.security.x509.KeyStoreX509CredentialAdapter; import org.opensaml.xml.security.x509.X509Credential; import org.opensaml.xml.signature.Signature; import org.opensaml.xml.signature.SignatureConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import at.gv.egovernment.moa.id.configuration.Constants; import at.gv.egovernment.moa.id.configuration.config.ConfigurationProvider; import at.gv.egovernment.moa.id.configuration.exception.ConfigurationException; import at.gv.egovernment.moa.id.configuration.utils.SAML2Utils; import at.gv.egovernment.moa.util.MiscUtil; /** * Servlet implementation class Authenticate */ public class Authenticate extends HttpServlet { private static final long serialVersionUID = 1L; private static final Logger log = LoggerFactory .getLogger(Authenticate.class); /** * @see HttpServlet#HttpServlet() */ public Authenticate() { super(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); try { builder = factory.newDocumentBuilder(); } catch (ParserConfigurationException e) { log.warn("PVP2 AuthenticationServlet can not be initialized.", e); } } DocumentBuilder builder; public Document asDOMDocument(XMLObject object) throws IOException, MarshallingException, TransformerException { Document document = builder.newDocument(); Marshaller out = Configuration.getMarshallerFactory().getMarshaller( object); out.marshall(object, document); return document; } protected void process(HttpServletRequest request, HttpServletResponse response, Map legacyParameter) throws ServletException, IOException { try { ConfigurationProvider config = ConfigurationProvider.getInstance(); config.initializePVP2Login(); AuthnRequest authReq = SAML2Utils .createSAMLObject(AuthnRequest.class); SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator(); authReq.setID(gen.generateIdentifier()); HttpSession session = request.getSession(); if (session != null) { session.setAttribute(Constants.SESSION_PVP2REQUESTID, authReq.getID()); } authReq.setAssertionConsumerServiceIndex(0); authReq.setAttributeConsumingServiceIndex(0); authReq.setIssueInstant(new DateTime()); Subject subject = SAML2Utils.createSAMLObject(Subject.class); NameID name = SAML2Utils.createSAMLObject(NameID.class); Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); String serviceURL = config.getPublicUrlPreFix(request); if (!serviceURL.endsWith("/")) serviceURL = serviceURL + "/"; name.setValue(serviceURL); issuer.setValue(serviceURL); subject.setNameID(name); authReq.setSubject(subject); issuer.setFormat(NameIDType.ENTITY); authReq.setIssuer(issuer); NameIDPolicy policy = SAML2Utils .createSAMLObject(NameIDPolicy.class); policy.setAllowCreate(true); policy.setFormat(NameID.PERSISTENT); authReq.setNameIDPolicy(policy); String entityname = config.getPVP2IDPMetadataEntityName(); if (MiscUtil.isEmpty(entityname)) { log.info("No IDP EntityName configurated"); throw new ConfigurationException("No IDP EntityName configurated"); } HTTPMetadataProvider idpmetadata = config.getMetaDataProvier(); EntityDescriptor idpEntity = idpmetadata.getEntityDescriptor(entityname); if (idpEntity == null) { log.info("IDP EntityName is not found in IDP Metadata"); throw new ConfigurationException("IDP EntityName is not found in IDP Metadata"); } SingleSignOnService redirectEndpoint = null; for (SingleSignOnService sss : idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS).getSingleSignOnServices()) { if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { //Get the service address for the binding you wish to use redirectEndpoint = sss; } } authReq.setDestination(redirectEndpoint.getLocation()); RequestedAuthnContext reqAuthContext = SAML2Utils.createSAMLObject(RequestedAuthnContext.class); AuthnContextClassRef authnClassRef = SAML2Utils.createSAMLObject(AuthnContextClassRef.class); authnClassRef.setAuthnContextClassRef("http://www.stork.gov.eu/1.0/citizenQAALevel/4"); reqAuthContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM); reqAuthContext.getAuthnContextClassRefs().add(authnClassRef); authReq.setRequestedAuthnContext(reqAuthContext); KeyStore keyStore = config.getPVP2KeyStore(); X509Credential authcredential = new KeyStoreX509CredentialAdapter( keyStore, config.getPVP2KeystoreAuthRequestKeyAlias(), config.getPVP2KeystoreAuthRequestKeyPassword().toCharArray()); Signature signer = SAML2Utils.createSAMLObject(Signature.class); signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1); signer.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); signer.setSigningCredential(authcredential); authReq.setSignature(signer); VelocityEngine engine = new VelocityEngine(); engine.setProperty(RuntimeConstants.ENCODING_DEFAULT, "UTF-8"); engine.setProperty(RuntimeConstants.OUTPUT_ENCODING, "UTF-8"); engine.setProperty(RuntimeConstants.ENCODING_DEFAULT, "UTF-8"); engine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); engine.setProperty("classpath.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); engine.init(); HTTPPostEncoder encoder = new HTTPPostEncoder(engine, "templates/pvp_postbinding_template.html"); HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter( response, true); BasicSAMLMessageContext context = new BasicSAMLMessageContext(); SingleSignOnService service = new SingleSignOnServiceBuilder() .buildObject(); service.setBinding("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"); service.setLocation(redirectEndpoint.getLocation());; context.setOutboundSAMLMessageSigningCredential(authcredential); context.setPeerEntityEndpoint(service); context.setOutboundSAMLMessage(authReq); context.setOutboundMessageTransport(responseAdapter); encoder.encode(context); } catch (Exception e) { log.warn("Authentication Request can not be generated", e); throw new ServletException("Authentication Request can not be generated.", e); } } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse * response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { process(request, response, null); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse * response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { process(request, response, null); } }