diff --git a/docbook/reference/en/en-US/master.xml b/docbook/reference/en/en-US/master.xml
index 37c07963f4..d87cb047a4 100755
--- a/docbook/reference/en/en-US/master.xml
+++ b/docbook/reference/en/en-US/master.xml
@@ -10,6 +10,7 @@
+
@@ -73,6 +74,7 @@
&SocialConfig;
&SocialFacebook;
+ &SocialGitHub;
&SocialGoogle;
&SocialTwitter;
&SocialProviderSPI;
diff --git a/docbook/reference/en/en-US/modules/social-github.xml b/docbook/reference/en/en-US/modules/social-github.xml
new file mode 100644
index 0000000000..4315f6db05
--- /dev/null
+++ b/docbook/reference/en/en-US/modules/social-github.xml
@@ -0,0 +1,27 @@
+
+ GitHub
+
+ To enable login with Google you first have to create an application in
+ GitHub Settings. Then you need to copy
+ the client id and secret into the Keycloak Admin Console.
+
+
+
+
+ Log in to GitHub Settings. Click the
+ Register new application button. Use any value for Application name,
+ Homepage URL and Application Description you want. In Authorization callback URL
+ enter the social callback url for your realm. Click the
+ Register application button.
+
+
+
+
+ Copy Client ID and Client secret from the
+ GitHub Settings into the settings
+ page in the Keycloak Admin Console as the Key and Secret. Then click
+ Save in the Keycloak Admin Console to enable login with Google.
+
+
+
+
\ No newline at end of file
diff --git a/services/src/main/java/org/keycloak/services/resources/SocialResource.java b/services/src/main/java/org/keycloak/services/resources/SocialResource.java
index a4efab29f7..4914c8a2bd 100755
--- a/services/src/main/java/org/keycloak/services/resources/SocialResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/SocialResource.java
@@ -106,10 +106,10 @@ public class SocialResource {
RequestDetails requestData = getRequestDetails(queryParams);
SocialProvider provider = SocialLoader.load(requestData.getProviderId());
- String realmId = requestData.getClientAttribute("realmId");
+ String realmName = requestData.getClientAttribute("realm");
RealmManager realmManager = new RealmManager(session);
- RealmModel realm = realmManager.getRealm(realmId);
+ RealmModel realm = realmManager.getRealmByName(realmName);
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
@@ -186,12 +186,12 @@ public class SocialResource {
@GET
@Path("{realm}/login")
- public Response redirectToProviderAuth(@PathParam("realm") final String realmId,
+ public Response redirectToProviderAuth(@PathParam("realm") final String realmName,
@QueryParam("provider_id") final String providerId, @QueryParam("client_id") final String clientId,
@QueryParam("scope") final String scope, @QueryParam("state") final String state,
@QueryParam("redirect_uri") String redirectUri) {
RealmManager realmManager = new RealmManager(session);
- RealmModel realm = realmManager.getRealm(realmId);
+ RealmModel realm = realmManager.getRealmByName(realmName);
SocialProvider provider = SocialLoader.load(providerId);
if (provider == null) {
@@ -223,7 +223,7 @@ public class SocialResource {
AuthRequest authRequest = provider.getAuthUrl(config);
RequestDetails socialRequest = RequestDetails.create(providerId)
- .putSocialAttributes(authRequest.getAttributes()).putClientAttribute("realmId", realmId)
+ .putSocialAttributes(authRequest.getAttributes()).putClientAttribute("realm", realmName)
.putClientAttribute("clientId", clientId).putClientAttribute("scope", scope)
.putClientAttribute("state", state).putClientAttribute("redirectUri", redirectUri).build();
diff --git a/social/core/src/main/java/org/keycloak/social/AbstractOAuth2Provider.java b/social/core/src/main/java/org/keycloak/social/AbstractOAuth2Provider.java
new file mode 100644
index 0000000000..ae8a0a5d49
--- /dev/null
+++ b/social/core/src/main/java/org/keycloak/social/AbstractOAuth2Provider.java
@@ -0,0 +1,90 @@
+package org.keycloak.social;
+
+import org.json.JSONObject;
+import org.keycloak.social.utils.SimpleHttp;
+
+import java.io.IOException;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author Stian Thorgersen
+ */
+public abstract class AbstractOAuth2Provider implements SocialProvider {
+
+ private static final String AUTHORIZATION_CODE = "authorization_code";
+ private static final String ACCESS_TOKEN = "access_token";
+ private static final String CLIENT_ID = "client_id";
+ private static final String CLIENT_SECRET = "client_secret";
+ private static final String CODE = "code";
+ private static final String GRANT_TYPE = "grant_type";
+ private static final String REDIRECT_URI = "redirect_uri";
+ private static final String RESPONSE_TYPE = "response_type";
+ private static final String SCOPE = "scope";
+ private static final String STATE = "state";
+
+ private static final String TOKEN_REGEX = "access_token=([^&]+)";
+
+ @Override
+ public abstract String getId();
+
+ @Override
+ public abstract String getName();
+
+ protected abstract String getScope();
+
+ protected abstract String getAuthUrl();
+
+ protected abstract String getTokenUrl();
+
+ protected abstract SocialUser getProfile(String accessToken) throws SocialProviderException;
+
+ @Override
+ public AuthRequest getAuthUrl(SocialProviderConfig config) throws SocialProviderException {
+ String state = UUID.randomUUID().toString();
+
+ return AuthRequest.create(state, getAuthUrl()).setQueryParam(CLIENT_ID, config.getKey())
+ .setQueryParam(RESPONSE_TYPE, CODE).setQueryParam(SCOPE, getScope())
+ .setQueryParam(REDIRECT_URI, config.getCallbackUrl()).setQueryParam(STATE, state).setAttribute(STATE, state).build();
+ }
+
+ @Override
+ public SocialUser processCallback(SocialProviderConfig config, AuthCallback callback) throws SocialProviderException {
+ try {
+ String code = callback.getQueryParam(CODE);
+
+ if (!callback.getQueryParam(STATE).equals(callback.getAttribute(STATE))) {
+ throw new SocialProviderException("Invalid state");
+ }
+
+ String response = SimpleHttp.doPost(getTokenUrl()).param(CODE, code).param(CLIENT_ID, config.getKey())
+ .param(CLIENT_SECRET, config.getSecret())
+ .param(REDIRECT_URI, config.getCallbackUrl())
+ .param(GRANT_TYPE, AUTHORIZATION_CODE).asString();
+
+ String accessToken;
+
+ if (response.startsWith("{")) {
+ accessToken = new JSONObject(response).getString(ACCESS_TOKEN);
+ } else {
+ Matcher matcher = Pattern.compile(TOKEN_REGEX).matcher(response);
+ if (matcher.find()) {
+ accessToken = matcher.group(1);
+ } else {
+ throw new SocialProviderException("Invalid response, could not find token");
+ }
+ }
+
+ return getProfile(accessToken);
+ } catch (IOException e) {
+ throw new SocialProviderException(e);
+ }
+ }
+
+ @Override
+ public String getRequestIdParamName() {
+ return STATE;
+ }
+
+}
diff --git a/social/facebook/pom.xml b/social/facebook/pom.xml
index fdfc7bf580..78527e09bb 100755
--- a/social/facebook/pom.xml
+++ b/social/facebook/pom.xml
@@ -18,17 +18,6 @@
org.keycloak
keycloak-social-core
${project.version}
- provided
-
-
- org.jboss.resteasy
- resteasy-client
- provided
-
-
- org.codehaus.jackson
- jackson-core-asl
- provided
diff --git a/social/facebook/src/main/java/org/keycloak/social/facebook/FacebookProvider.java b/social/facebook/src/main/java/org/keycloak/social/facebook/FacebookProvider.java
index 8b911b2360..dd2d7e3853 100755
--- a/social/facebook/src/main/java/org/keycloak/social/facebook/FacebookProvider.java
+++ b/social/facebook/src/main/java/org/keycloak/social/facebook/FacebookProvider.java
@@ -1,149 +1,81 @@
package org.keycloak.social.facebook;
-import org.jboss.resteasy.client.jaxrs.ResteasyClient;
-import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
-import org.keycloak.social.AuthCallback;
+import org.json.JSONObject;
+import org.keycloak.social.AbstractOAuth2Provider;
import org.keycloak.social.AuthRequest;
-import org.keycloak.social.SocialProvider;
import org.keycloak.social.SocialProviderConfig;
import org.keycloak.social.SocialProviderException;
import org.keycloak.social.SocialUser;
-
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import java.net.URI;
-import java.util.UUID;
+import org.keycloak.social.utils.SimpleHttp;
/**
- * Social provider for Facebook
- *
- * @author Marek Posolda
+ * @author Stian Thorgersen
*/
-public class FacebookProvider implements SocialProvider {
+public class FacebookProvider extends AbstractOAuth2Provider {
- private static final String AUTHENTICATION_ENDPOINT_URL = "https://graph.facebook.com/oauth/authorize";
+ private static final String ID = "facebook";
+ private static final String NAME = "Facebook";
- private static final String ACCESS_TOKEN_ENDPOINT_URL = "https://graph.facebook.com/oauth/access_token";
-
- private static final String PROFILE_ENDPOINT_URL = "https://graph.facebook.com/me";
-
- private static final String DEFAULT_RESPONSE_TYPE = "code";
+ private static final String AUTH_URL = "https://graph.facebook.com/oauth/authorize";
+ private static final String TOKEN_URL = "https://graph.facebook.com/oauth/access_token";
+ private static final String PROFILE_URL = "https://graph.facebook.com/me";
private static final String DEFAULT_SCOPE = "email";
@Override
public String getId() {
- return "facebook";
- }
-
- @Override
- public AuthRequest getAuthUrl(SocialProviderConfig config) throws SocialProviderException {
- String state = UUID.randomUUID().toString();
-
- String redirectUri = config.getCallbackUrl();
- redirectUri = redirectUri.replace("//localhost", "//127.0.0.1");
-
- return AuthRequest.create(state, AUTHENTICATION_ENDPOINT_URL).setQueryParam("client_id", config.getKey())
- .setQueryParam("response_type", DEFAULT_RESPONSE_TYPE).setQueryParam("scope", DEFAULT_SCOPE)
- .setQueryParam("redirect_uri", redirectUri).setQueryParam("state", state).setAttribute("state", state).build();
- }
-
- @Override
- public String getRequestIdParamName() {
- return "state";
+ return ID;
}
@Override
public String getName() {
- return "Facebook";
+ return NAME;
}
@Override
- public SocialUser processCallback(SocialProviderConfig config, AuthCallback callback) throws SocialProviderException {
- String code = callback.getQueryParam(DEFAULT_RESPONSE_TYPE);
+ protected String getScope() {
+ return DEFAULT_SCOPE;
+ }
+ @Override
+ protected String getAuthUrl() {
+ return AUTH_URL;
+ }
+
+ @Override
+ protected String getTokenUrl() {
+ return TOKEN_URL;
+ }
+
+ @Override
+ protected SocialUser getProfile(String accessToken) throws SocialProviderException {
try {
- if (!callback.getQueryParam("state").equals(callback.getAttribute("state"))) {
- throw new SocialProviderException("Invalid state");
+ JSONObject profile = SimpleHttp.doGet(PROFILE_URL).header("Authorization", "Bearer " + accessToken).asJson();
+
+ SocialUser user = new SocialUser(profile.getString("id"));
+
+ user.setUsername(profile.getString("username"));
+ if (user.getUsername() == null || user.getUsername().length() == 0) {
+ user.setUsername(profile.getString("id"));
}
- ResteasyClient client = new ResteasyClientBuilder()
- .hostnameVerification(ResteasyClientBuilder.HostnameVerificationPolicy.ANY).build();
+ user.setFirstName(profile.optString("first_name"));
+ user.setLastName(profile.optString("last_name"));
+ user.setEmail(profile.optString("email"));
- String accessToken = loadAccessToken(code, config, client);
-
- FacebookUser facebookUser = loadUser(accessToken, client);
-
- SocialUser socialUser = new SocialUser(facebookUser.getId());
- socialUser.setUsername(facebookUser.getUsername());
-
- // This could happen with Facebook testing users
- if (facebookUser.getUsername() == null || facebookUser.getUsername().length() == 0) {
- socialUser.setUsername(facebookUser.getId());
- }
-
- socialUser.setEmail(facebookUser.getEmail());
- socialUser.setLastName(facebookUser.getLastName());
- socialUser.setFirstName(facebookUser.getFirstName());
-
- return socialUser;
- } catch (SocialProviderException spe) {
- throw spe;
+ return user;
} catch (Exception e) {
throw new SocialProviderException(e);
}
}
- protected String loadAccessToken(String code, SocialProviderConfig config, ResteasyClient client) throws SocialProviderException {
- Form form = new Form();
- form.param("grant_type", "authorization_code")
- .param("code", code)
- .param("client_id", config.getKey())
- .param("client_secret", config.getSecret())
- .param("redirect_uri", config.getCallbackUrl());
-
- Response response = client.target(ACCESS_TOKEN_ENDPOINT_URL).request().post(Entity.form(form));
-
- if (response.getStatus() != 200) {
- String errorTokenResponse = response.readEntity(String.class);
- throw new SocialProviderException("Access token request to Facebook failed. Status: " + response.getStatus() + ", response: " + errorTokenResponse);
+ @Override
+ public AuthRequest getAuthUrl(SocialProviderConfig config) throws SocialProviderException {
+ if (config.getCallbackUrl().contains("//localhost")) {
+ String callbackUrl = config.getCallbackUrl().replace("//localhost", "//127.0.0.1");
+ config = new SocialProviderConfig(config.getKey(), config.getSecret(), callbackUrl);
}
-
- String accessTokenResponse = response.readEntity(String.class);
- return parseParameter(accessTokenResponse, "access_token");
+ return super.getAuthUrl(config);
}
- protected FacebookUser loadUser(String accessToken, ResteasyClient client) throws SocialProviderException {
- URI userDetailsUri = UriBuilder.fromUri(PROFILE_ENDPOINT_URL)
- .queryParam("access_token", accessToken)
- .queryParam("fields", "id,name,username,first_name,last_name,email")
- .build();
-
- Response response = client.target(userDetailsUri).request()
- .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON)
- .get();
- if (response.getStatus() != 200) {
- String errorTokenResponse = response.readEntity(String.class);
- throw new SocialProviderException("Request to Facebook for obtaining user failed. Status: " + response.getStatus() + ", response: " + errorTokenResponse);
- }
-
- return response.readEntity(FacebookUser.class);
- }
-
- // Parses value of given parameter from input string like "my_param=abcd&another_param=xyz"
- private String parseParameter(String input, String paramName) {
- int start = input.indexOf(paramName + "=");
- if (start != -1) {
- input = input.substring(start + paramName.length() + 1);
- int end = input.indexOf("&");
- return end==-1 ? input : input.substring(0, end);
- } else {
- throw new IllegalArgumentException("Parameter " + paramName + " not available in response " + input);
- }
-
- }
}
diff --git a/social/facebook/src/main/java/org/keycloak/social/facebook/FacebookUser.java b/social/facebook/src/main/java/org/keycloak/social/facebook/FacebookUser.java
deleted file mode 100644
index 8a30fc7a0d..0000000000
--- a/social/facebook/src/main/java/org/keycloak/social/facebook/FacebookUser.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package org.keycloak.social.facebook;
-
-import org.codehaus.jackson.annotate.JsonProperty;
-
-/**
- * Wrap info about user from Facebook
- *
- * @author Marek Posolda
- */
-public class FacebookUser {
-
- @JsonProperty("id")
- private String id;
-
- @JsonProperty("first_name")
- private String firstName;
-
- @JsonProperty("last_name")
- private String lastName;
-
- @JsonProperty("username")
- private String username;
-
- @JsonProperty("name")
- private String name;
-
- @JsonProperty("email")
- private String email;
-
- public String getId() {
- return id;
- }
-
- public void setId(String id) {
- this.id = id;
- }
-
- public String getFirstName() {
- return firstName;
- }
-
- public void setFirstName(String firstName) {
- this.firstName = firstName;
- }
-
- public String getLastName() {
- return lastName;
- }
-
- public void setLastName(String lastName) {
- this.lastName = lastName;
- }
-
- public String getUsername() {
- return username;
- }
-
- public void setUsername(String username) {
- this.username = username;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getEmail() {
- return email;
- }
-
- public void setEmail(String email) {
- this.email = email;
- }
-}
diff --git a/social/github/pom.xml b/social/github/pom.xml
new file mode 100755
index 0000000000..e75021dd7b
--- /dev/null
+++ b/social/github/pom.xml
@@ -0,0 +1,23 @@
+
+
+ keycloak-social-parent
+ org.keycloak
+ 1.0-alpha-2-SNAPSHOT
+ ../pom.xml
+
+ 4.0.0
+ jar
+
+ keycloak-social-github
+ Keycloak Social GitHub
+
+
+
+
+ org.keycloak
+ keycloak-social-core
+ ${project.version}
+
+
+
diff --git a/social/github/src/main/java/org/keycloak/social/github/GitHubProvider.java b/social/github/src/main/java/org/keycloak/social/github/GitHubProvider.java
new file mode 100755
index 0000000000..9ea009607b
--- /dev/null
+++ b/social/github/src/main/java/org/keycloak/social/github/GitHubProvider.java
@@ -0,0 +1,67 @@
+package org.keycloak.social.github;
+
+import org.json.JSONObject;
+import org.keycloak.social.AbstractOAuth2Provider;
+import org.keycloak.social.AuthRequest;
+import org.keycloak.social.SocialProviderConfig;
+import org.keycloak.social.SocialProviderException;
+import org.keycloak.social.SocialUser;
+import org.keycloak.social.utils.SimpleHttp;
+
+/**
+ * @author Stian Thorgersen
+ */
+public class GitHubProvider extends AbstractOAuth2Provider {
+
+ private static final String ID = "github";
+ private static final String NAME = "GitHub";
+
+ private static final String AUTH_URL = "https://github.com/login/oauth/authorize";
+ private static final String TOKEN_URL = "https://github.com/login/oauth/access_token";
+ private static final String PROFILE_URL = "https://api.github.com/user";
+
+ private static final String DEFAULT_SCOPE = "user:email";
+
+ @Override
+ public String getId() {
+ return ID;
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ protected String getScope() {
+ return DEFAULT_SCOPE;
+ }
+
+ @Override
+ protected String getAuthUrl() {
+ return AUTH_URL;
+ }
+
+ @Override
+ protected String getTokenUrl() {
+ return TOKEN_URL;
+ }
+
+ @Override
+ protected SocialUser getProfile(String accessToken) throws SocialProviderException {
+ try {
+ JSONObject profile = SimpleHttp.doGet(PROFILE_URL).header("Authorization", "Bearer " + accessToken).asJson();
+
+ SocialUser user = new SocialUser(profile.get("id").toString());
+
+ user.setUsername(profile.getString("login"));
+ user.setFirstName(profile.optString("name"));
+ user.setEmail(profile.optString("email"));
+
+ return user;
+ } catch (Exception e) {
+ throw new SocialProviderException(e);
+ }
+ }
+
+}
diff --git a/social/github/src/main/resources/META-INF/services/org.keycloak.social.SocialProvider b/social/github/src/main/resources/META-INF/services/org.keycloak.social.SocialProvider
new file mode 100644
index 0000000000..f9e6b0c0e7
--- /dev/null
+++ b/social/github/src/main/resources/META-INF/services/org.keycloak.social.SocialProvider
@@ -0,0 +1 @@
+org.keycloak.social.github.GitHubProvider
diff --git a/social/google/pom.xml b/social/google/pom.xml
index 12ecb81507..f5b5681b44 100755
--- a/social/google/pom.xml
+++ b/social/google/pom.xml
@@ -19,5 +19,4 @@
${project.version}
-
diff --git a/social/google/src/main/java/org/keycloak/social/google/GoogleProvider.java b/social/google/src/main/java/org/keycloak/social/google/GoogleProvider.java
index 87ea93f348..2db4a9c71e 100755
--- a/social/google/src/main/java/org/keycloak/social/google/GoogleProvider.java
+++ b/social/google/src/main/java/org/keycloak/social/google/GoogleProvider.java
@@ -22,67 +22,54 @@
package org.keycloak.social.google;
import org.json.JSONObject;
-import org.keycloak.social.AuthCallback;
-import org.keycloak.social.AuthRequest;
+import org.keycloak.social.AbstractOAuth2Provider;
import org.keycloak.social.utils.SimpleHttp;
-import org.keycloak.social.SocialProvider;
-import org.keycloak.social.SocialProviderConfig;
import org.keycloak.social.SocialProviderException;
import org.keycloak.social.SocialUser;
-import java.util.UUID;
-
/**
* @author Stian Thorgersen
*/
-public class GoogleProvider implements SocialProvider {
+public class GoogleProvider extends AbstractOAuth2Provider {
- private static final String DEFAULT_RESPONSE_TYPE = "code";
+ private static final String ID = "google";
+ private static final String NAME = "Google";
- private static final String AUTH_PATH = "https://accounts.google.com/o/oauth2/auth";
-
- private static final String TOKEN_PATH = "https://accounts.google.com/o/oauth2/token";
-
- private static final String PROFILE_PATH = "https://www.googleapis.com/plus/v1/people/me/openIdConnect";
+ private static final String AUTH_URL = "https://accounts.google.com/o/oauth2/auth";
+ private static final String TOKEN_URL = "https://accounts.google.com/o/oauth2/token";
+ private static final String PROFILE_URL = "https://www.googleapis.com/plus/v1/people/me/openIdConnect";
private static final String DEFAULT_SCOPE = "openid profile email";
@Override
public String getId() {
- return "google";
- }
-
- @Override
- public AuthRequest getAuthUrl(SocialProviderConfig config) throws SocialProviderException {
- String state = UUID.randomUUID().toString();
-
- return AuthRequest.create(state, AUTH_PATH).setQueryParam("client_id", config.getKey())
- .setQueryParam("response_type", DEFAULT_RESPONSE_TYPE).setQueryParam("scope", DEFAULT_SCOPE)
- .setQueryParam("redirect_uri", config.getCallbackUrl()).setQueryParam("state", state).setAttribute("state", state).build();
+ return ID;
}
@Override
public String getName() {
- return "Google";
+ return NAME;
}
@Override
- public SocialUser processCallback(SocialProviderConfig config, AuthCallback callback) throws SocialProviderException {
- String code = callback.getQueryParam(DEFAULT_RESPONSE_TYPE);
+ protected String getScope() {
+ return DEFAULT_SCOPE;
+ }
+ @Override
+ protected String getAuthUrl() {
+ return AUTH_URL;
+ }
+
+ @Override
+ protected String getTokenUrl() {
+ return TOKEN_URL;
+ }
+
+ @Override
+ protected SocialUser getProfile(String accessToken) throws SocialProviderException {
try {
- if (!callback.getQueryParam("state").equals(callback.getAttribute("state"))) {
- throw new SocialProviderException("Invalid state");
- }
-
- JSONObject token = SimpleHttp.doPost(TOKEN_PATH).param("code", code).param("client_id", config.getKey())
- .param("client_secret", config.getSecret())
- .param("redirect_uri", config.getCallbackUrl())
- .param("grant_type", "authorization_code").asJson();
-
- String accessToken = token.getString("access_token");
-
- JSONObject profile = SimpleHttp.doGet(PROFILE_PATH).header("Authorization", "Bearer " + accessToken).asJson();
+ JSONObject profile = SimpleHttp.doGet(PROFILE_URL).header("Authorization", "Bearer " + accessToken).asJson();
SocialUser user = new SocialUser(profile.getString("sub"));
@@ -98,9 +85,4 @@ public class GoogleProvider implements SocialProvider {
}
}
- @Override
- public String getRequestIdParamName() {
- return "state";
- }
-
}
diff --git a/social/pom.xml b/social/pom.xml
index 1061eda794..5d4edd7f2a 100755
--- a/social/pom.xml
+++ b/social/pom.xml
@@ -15,6 +15,7 @@
core
+ github
google
twitter
facebook
diff --git a/testsuite/integration/pom.xml b/testsuite/integration/pom.xml
index e228bbe91d..acd2316d48 100755
--- a/testsuite/integration/pom.xml
+++ b/testsuite/integration/pom.xml
@@ -73,6 +73,11 @@
keycloak-social-core
${project.version}
+
+ org.keycloak
+ keycloak-social-github
+ ${project.version}
+
org.keycloak
keycloak-social-google