/* * JBoss, Home of Professional Open Source * * Copyright 2013 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.picketlink.test.identity.federation.bindings.wildfly; import com.meterware.httpunit.GetMethodWebRequest; import com.meterware.httpunit.HttpUnitOptions; import com.meterware.httpunit.SubmitButton; import com.meterware.httpunit.WebConversation; import com.meterware.httpunit.WebForm; import com.meterware.httpunit.WebRequest; import com.meterware.httpunit.WebResponse; import io.undertow.server.HttpHandler; import io.undertow.server.handlers.PathHandler; import io.undertow.server.handlers.resource.Resource; import io.undertow.server.handlers.resource.ResourceChangeListener; import io.undertow.server.handlers.resource.ResourceManager; import io.undertow.server.handlers.resource.URLResource; import io.undertow.servlet.api.DeploymentInfo; import io.undertow.servlet.api.DeploymentManager; import io.undertow.servlet.api.FilterInfo; import io.undertow.servlet.api.LoginConfig; import io.undertow.servlet.api.ServletContainer; import io.undertow.servlet.api.ServletInfo; import io.undertow.servlet.api.ServletSecurityInfo; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.junit.Before; import org.junit.Test; import org.picketlink.identity.federation.bindings.wildfly.sp.SPServletExtension; import org.picketlink.identity.federation.web.filters.IDPFilter; import javax.servlet.DispatcherType; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Writer; import java.net.URL; import java.security.Principal; import static junit.framework.Assert.assertNotNull; import static org.junit.Assert.assertTrue; /** * Simple Workflow for SAML SSO using Undertow * @author Anil Saldhana * @since November 14, 2013 */ public class SPInitiatedSSOWorkflowTestCase extends UndertowTestCase { protected final PathHandler path = new PathHandler(); private WebConversation webConversation = null; private WebResponse webResponse = null; private int responseCode = 0; @Override protected HttpHandler getHandler() { System.out.println("Inside SPInitiatedSSOWorkflowTestCase -> getHandler"); return path; } @Before public void setup() throws Exception{ super.setup(); assertNotNull(server); deployIDP(); deploySP(); } protected String getContextPathShortForm(){ return "sp"; } public void deployIDP() throws Exception{ final ServletContainer container = ServletContainer.Factory.newInstance(); FilterInfo idpFilterInfo = new FilterInfo("IDPFilter", IDPFilter.class); ServletInfo regularServletInfo = new ServletInfo("servlet", SendUsernameServlet.class) .setServletSecurityInfo(new ServletSecurityInfo() .addRoleAllowed("role1")) .addMapping("/*") ; ServletInfo formServletInfo = new ServletInfo("loginPage", FormLoginServlet.class) .setServletSecurityInfo(new ServletSecurityInfo() .addRoleAllowed("group1")) .addMapping("/FormLoginServlet"); TestIdentityManager identityManager = new TestIdentityManager(); identityManager.addUser("user1", "password1", "role1"); LoginConfig loginConfig = new LoginConfig("FORM", "Test Realm", "/FormLoginServlet","/error.html"); DeploymentInfo deploymentInfo = new DeploymentInfo() .setClassLoader(SPInitiatedSSOWorkflowTestCase.class.getClassLoader()) .setContextPath("/idp") .setDeploymentName("idp.war") .setClassIntrospecter(TestClassIntrospector.INSTANCE) .setIdentityManager(identityManager) .setLoginConfig(loginConfig) .setResourceManager(new TestResourceManager("idp")) .addServlets(regularServletInfo, formServletInfo) .addFilter(idpFilterInfo) .addFilterUrlMapping(idpFilterInfo.getName(), "/*", DispatcherType.REQUEST); DeploymentManager manager = container.addDeployment(deploymentInfo); manager.deploy(); try{ path.addPath(deploymentInfo.getContextPath(), manager.start()); }catch(ServletException se){ throw new RuntimeException(se); } System.out.println("Deployment success:" + deploymentInfo.getContextPath()); } public void deploySP() throws Exception{ final ServletContainer container = ServletContainer.Factory.newInstance(); ServletInfo welcomeServlet = new ServletInfo("/", WelcomeServlet.class) .addMapping("/WelcomeServlet"); ServletInfo regularServletInfo = new ServletInfo("servlet", SendUsernameServlet.class) .setServletSecurityInfo(new ServletSecurityInfo() .addRoleAllowed("role1")) .addMapping("/secured/*"); ServletInfo formServletInfo = new ServletInfo("loginPage", FormLoginServlet.class) .setServletSecurityInfo(new ServletSecurityInfo() .addRoleAllowed("group1")) .addMapping("/FormLoginServlet"); TestIdentityManager identityManager = new TestIdentityManager(); identityManager.addUser("user1", "password1", "role1"); LoginConfig loginConfig = new LoginConfig("FORM", "Test Realm", "/FormLoginServlet","/error.html"); ResourceManager resourceManager = new TestResourceManager(getContextPathShortForm()); DeploymentInfo deploymentInfo = new DeploymentInfo() .setClassLoader(SPInitiatedSSOWorkflowTestCase.class.getClassLoader()) .setContextPath("/"+getContextPathShortForm()) .setDeploymentName(getContextPathShortForm() + ".war") .setClassIntrospecter(TestClassIntrospector.INSTANCE) .setIdentityManager(identityManager) .setLoginConfig(loginConfig) .setResourceManager(resourceManager) .addServlets(regularServletInfo, formServletInfo) .addServletExtension(new SPServletExtension()); DeploymentManager manager = container.addDeployment(deploymentInfo); manager.deploy(); try{ path.addPath(deploymentInfo.getContextPath(), manager.start()); }catch(ServletException se){ throw new RuntimeException(se); } System.out.println("Deployment success:" + deploymentInfo.getContextPath()); } public static class WelcomeServlet extends HttpServlet { @Override protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { OutputStream stream = resp.getOutputStream(); stream.write("Welcome".getBytes()); } } /** * @author Stuart Douglas */ public static class SendUsernameServlet extends HttpServlet { @Override protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { OutputStream stream = resp.getOutputStream(); Principal principal = req.getUserPrincipal(); String name = principal.getName(); stream.write(name.getBytes()); } @Override protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { OutputStream stream = resp.getOutputStream(); Principal principal = req.getUserPrincipal(); String name = principal.getName(); stream.write(name.getBytes()); } } /* * @author Stuart Douglas */ public static class FormLoginServlet extends HttpServlet { @Override protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { writeLoginForm(resp); } @Override protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { writeLoginForm(resp); } private void writeLoginForm(HttpServletResponse resp) throws IOException { Writer writer = resp.getWriter(); writer.write("Login Page"); writer.write("<form id=\"login_form\" name=\"login_form\" method=\"post\"\n" + " action=\"j_security_check\" enctype=\"application/x-www-form-urlencoded\">\n" + " <div style=\"margin-left: 15px;\">\n" + " <p>\n" + " <label for=\"username\"> Username</label><br /> <input id=\"username\"\n" + " type=\"text\" name=\"j_username\" size=\"20\" />\n" + " </p>\n" + " <p>\n" + " <label for=\"password\"> Password</label><br /> <input id=\"password\"\n" + " type=\"password\" name=\"j_password\" value=\"\" size=\"20\" />\n" + " </p>\n" + " <center>\n" + " <input id=\"submit\" type=\"submit\" name=\"submit\" value=\"Login\"\n" + " class=\"buttonmed\" />\n" + " </center>\n" + " </div>\n" + " </form>"); } } @Test public void testServerUp() throws Exception{ } public class TestResourceManager implements ResourceManager{ private final String basePath; public TestResourceManager(String basePath){ this.basePath = basePath; } @Override public Resource getResource(String path) throws IOException { String temp = path; //Remove WEB-INF temp = temp.replace("/WEB-INF",""); URL url = getClass().getClassLoader().getResource(basePath+temp); return new URLResource(url, url.openConnection(), path); } @Override public boolean isResourceChangeListenerSupported() { throw new RuntimeException(); } @Override public void registerResourceChangeListener(ResourceChangeListener listener) { throw new RuntimeException(); } @Override public void removeResourceChangeListener(ResourceChangeListener listener) { throw new RuntimeException(); } @Override public void close() throws IOException { throw new RuntimeException(); } } @Test public void testSSO() throws Exception{ String spURI = "http://localhost:8080/"+ getContextPathShortForm() + "/secured/test"; WebRequest serviceRequest1 = new GetMethodWebRequest(spURI); webConversation = new WebConversation(); HttpUnitOptions.setLoggingHttpHeaders(true); webResponse = webConversation.getResponse(serviceRequest1); responseCode = webResponse.getResponseCode(); if (responseCode == HttpServletResponse.SC_SEE_OTHER) { String otherLocation = webResponse.getHeaderField("LOCATION"); webResponse = webConversation.getResponse(otherLocation); } WebForm loginForm = webResponse.getForms()[0]; loginForm.setParameter("j_username", "user1"); loginForm.setParameter("j_password", "password1"); SubmitButton submitButton = loginForm.getSubmitButtons()[0]; submitButton.click(); webResponse = webConversation.getCurrentPage(); responseCode = webResponse.getResponseCode(); while (responseCode == 303) { handle303(); } String text = webResponse.getText(); assertTrue(" Saw user1 ", text.contains("user1")); } private String readResponse(final HttpResponse response) throws IOException { HttpEntity entity = response.getEntity(); if(entity == null) { return ""; } return readResponse(entity.getContent()); } private String readResponse(InputStream stream) throws IOException { final StringBuilder builder = new StringBuilder(); byte[] data = new byte[100]; int read; while ((read = stream.read(data)) != -1) { builder.append(new String(data,0,read,"UTF-8")); } return builder.toString(); } private void handle303() throws Exception { String otherLocation = webResponse.getHeaderField("LOCATION"); webResponse = webConversation.getResponse(otherLocation); responseCode = webResponse.getResponseCode(); } }