From 8663c9f02683dbacd081c379f12dacf8bc289ff3 Mon Sep 17 00:00:00 2001 From: Stian Thorgersen Date: Fri, 27 Sep 2013 13:09:52 +0100 Subject: [PATCH] Added social login test using a dummy social provider --- .../org/keycloak/testsuite/DummySocial.java | 57 +++++++++++++ .../testsuite/DummySocialServlet.java | 51 +++++++++++ .../keycloak/testsuite/pages/LoginPage.java | 5 ++ .../keycloak/testsuite/rule/KeycloakRule.java | 11 ++- .../testsuite/social/SocialLoginTest.java | 85 +++++++++++++++++++ .../org.keycloak.social.SocialProvider | 1 + 6 files changed, 207 insertions(+), 3 deletions(-) create mode 100644 testsuite/src/test/java/org/keycloak/testsuite/DummySocial.java create mode 100644 testsuite/src/test/java/org/keycloak/testsuite/DummySocialServlet.java create mode 100644 testsuite/src/test/java/org/keycloak/testsuite/social/SocialLoginTest.java create mode 100644 testsuite/src/test/resources/META-INF/services/org.keycloak.social.SocialProvider diff --git a/testsuite/src/test/java/org/keycloak/testsuite/DummySocial.java b/testsuite/src/test/java/org/keycloak/testsuite/DummySocial.java new file mode 100644 index 0000000000..056e651773 --- /dev/null +++ b/testsuite/src/test/java/org/keycloak/testsuite/DummySocial.java @@ -0,0 +1,57 @@ +package org.keycloak.testsuite; + +import java.util.UUID; + +import org.keycloak.social.AuthCallback; +import org.keycloak.social.AuthRequest; +import org.keycloak.social.AuthRequestBuilder; +import org.keycloak.social.SocialProvider; +import org.keycloak.social.SocialProviderConfig; +import org.keycloak.social.SocialProviderException; +import org.keycloak.social.SocialUser; + +public class DummySocial implements SocialProvider { + + private static final String AUTH_PATH = "http://localhost:8081/dummy-social/auth"; + + @Override + public String getId() { + return "dummy"; + } + + @Override + public AuthRequest getAuthUrl(SocialProviderConfig config) throws SocialProviderException { + String state = UUID.randomUUID().toString(); + + AuthRequestBuilder b = AuthRequestBuilder.create(state, AUTH_PATH).setQueryParam("response_type", "token") + .setQueryParam("redirect_uri", config.getCallbackUrl()).setQueryParam("state", state); + + b.setAttribute("state", state); + + return b.build(); + } + + @Override + public String getRequestIdParamName() { + return "state"; + } + + @Override + public String getName() { + return "Dummy Provider"; + } + + @Override + public SocialUser processCallback(SocialProviderConfig config, AuthCallback callback) throws SocialProviderException { + if (!callback.getQueryParam("state").equals(callback.getAttribute("state"))) { + throw new SocialProviderException("Invalid state"); + } + + String username = callback.getQueryParam("access_token"); + SocialUser user = new SocialUser(username); + user.setEmail(username + "@dummy-social"); + user.setUsername(username); + return user; + } + +} diff --git a/testsuite/src/test/java/org/keycloak/testsuite/DummySocialServlet.java b/testsuite/src/test/java/org/keycloak/testsuite/DummySocialServlet.java new file mode 100644 index 0000000000..d7b1e37b07 --- /dev/null +++ b/testsuite/src/test/java/org/keycloak/testsuite/DummySocialServlet.java @@ -0,0 +1,51 @@ +package org.keycloak.testsuite; + +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.charset.Charset; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.http.NameValuePair; +import org.apache.http.client.utils.URLEncodedUtils; + +public class DummySocialServlet extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + PrintWriter pw = resp.getWriter(); + pw.print(""); + pw.print(""); + pw.print("
"); + pw.print(""); + pw.print(""); + pw.print("
"); + pw.print(""); + pw.print(""); + pw.flush(); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + String accessToken = req.getParameter("username"); + String state = null; + String redirectUri = null; + + List query = URLEncodedUtils.parse(req.getQueryString(), Charset.forName("UTF-8")); + for (NameValuePair p : query) { + if ("state".equals(p.getName())) { + state = p.getValue(); + } else if ("redirect_uri".equals(p.getName())) { + redirectUri = p.getValue(); + } + } + + String redirect = redirectUri + "?access_token=" + accessToken + "&token_type=bearer&state=" + state; + resp.sendRedirect(redirect); + } + +} diff --git a/testsuite/src/test/java/org/keycloak/testsuite/pages/LoginPage.java b/testsuite/src/test/java/org/keycloak/testsuite/pages/LoginPage.java index b23dd2bb02..7abbbdb129 100644 --- a/testsuite/src/test/java/org/keycloak/testsuite/pages/LoginPage.java +++ b/testsuite/src/test/java/org/keycloak/testsuite/pages/LoginPage.java @@ -23,6 +23,7 @@ package org.keycloak.testsuite.pages; import org.keycloak.testsuite.OAuthClient; import org.keycloak.testsuite.rule.WebResource; +import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; @@ -74,6 +75,10 @@ public class LoginPage extends Page { registerLink.click(); } + public void clickSocial(String id) { + driver.findElement(By.className(id)).click(); + } + public void resetPassword() { resetPasswordLink.click(); } diff --git a/testsuite/src/test/java/org/keycloak/testsuite/rule/KeycloakRule.java b/testsuite/src/test/java/org/keycloak/testsuite/rule/KeycloakRule.java index 6ff7d2b7c2..e62c955f07 100644 --- a/testsuite/src/test/java/org/keycloak/testsuite/rule/KeycloakRule.java +++ b/testsuite/src/test/java/org/keycloak/testsuite/rule/KeycloakRule.java @@ -32,6 +32,7 @@ import java.io.IOException; import java.io.InputStream; import javax.servlet.DispatcherType; +import javax.servlet.Servlet; import org.jboss.resteasy.jwt.JsonSerialization; import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer; @@ -100,12 +101,16 @@ public class KeycloakRule extends ExternalResource { configure(setup); } + deployServlet("app", "/app", ApplicationServlet.class); + } + + public void deployServlet(String name, String contextPath, Class servletClass) { DeploymentInfo deploymentInfo = new DeploymentInfo(); deploymentInfo.setClassLoader(getClass().getClassLoader()); - deploymentInfo.setDeploymentName("app"); - deploymentInfo.setContextPath("/app"); + deploymentInfo.setDeploymentName(name); + deploymentInfo.setContextPath(contextPath); - ServletInfo servlet = new ServletInfo(ApplicationServlet.class.getSimpleName(), ApplicationServlet.class); + ServletInfo servlet = new ServletInfo(servletClass.getSimpleName(), servletClass); servlet.addMapping("/*"); deploymentInfo.addServlet(servlet); diff --git a/testsuite/src/test/java/org/keycloak/testsuite/social/SocialLoginTest.java b/testsuite/src/test/java/org/keycloak/testsuite/social/SocialLoginTest.java new file mode 100644 index 0000000000..278e45c46a --- /dev/null +++ b/testsuite/src/test/java/org/keycloak/testsuite/social/SocialLoginTest.java @@ -0,0 +1,85 @@ +/* + * JBoss, Home of Professional Open Source. + * Copyright 2012, Red Hat, Inc., and individual contributors + * as indicated by the @author tags. See the copyright.txt file in the + * distribution for a full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.keycloak.testsuite.social; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.keycloak.services.managers.RealmManager; +import org.keycloak.services.models.RealmModel; +import org.keycloak.testsuite.DummySocialServlet; +import org.keycloak.testsuite.pages.AppPage; +import org.keycloak.testsuite.pages.LoginPage; +import org.keycloak.testsuite.pages.AppPage.RequestType; +import org.keycloak.testsuite.rule.KeycloakRule; +import org.keycloak.testsuite.rule.KeycloakRule.KeycloakSetup; +import org.keycloak.testsuite.rule.WebResource; +import org.keycloak.testsuite.rule.WebRule; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; + +/** + * @author Stian Thorgersen + */ +public class SocialLoginTest { + + @ClassRule + public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakSetup() { + @Override + public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) { + appRealm.setSocial(true); + appRealm.setAutomaticRegistrationAfterSocialLogin(true); + } + }); + + @Rule + public WebRule webRule = new WebRule(this); + + @WebResource + protected WebDriver driver; + + @WebResource + protected AppPage appPage; + + @WebResource + protected LoginPage loginPage; + + @BeforeClass + public static void before() { + keycloakRule.deployServlet("dummy-social", "/dummy-social", DummySocialServlet.class); + } + + @Test + public void loginSuccess() { + loginPage.open(); + + loginPage.clickSocial("dummy"); + + driver.findElement(By.id("username")).sendKeys("dummy-user"); + driver.findElement(By.id("submit")).click(); + + Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType()); + } + +} diff --git a/testsuite/src/test/resources/META-INF/services/org.keycloak.social.SocialProvider b/testsuite/src/test/resources/META-INF/services/org.keycloak.social.SocialProvider new file mode 100644 index 0000000000..1fea90f4d5 --- /dev/null +++ b/testsuite/src/test/resources/META-INF/services/org.keycloak.social.SocialProvider @@ -0,0 +1 @@ +org.keycloak.testsuite.DummySocial \ No newline at end of file