From 13261b52dbb99c9fe7fc0c0e2f3d105907288ed2 Mon Sep 17 00:00:00 2001 From: gregoirew Date: Sat, 11 Nov 2017 15:49:22 +0100 Subject: [PATCH] Use the github /user/emails api endpoint if the github user did not set any public email. Github can send a null email on the user info endpoint if there is no public email on the user profile. This commit look for email on the /user/emails endpoint, selecting the primary email. --- .../social/github/GitHubIdentityProvider.java | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/services/src/main/java/org/keycloak/social/github/GitHubIdentityProvider.java b/services/src/main/java/org/keycloak/social/github/GitHubIdentityProvider.java index 9b04b76aca..fff4a4093b 100755 --- a/services/src/main/java/org/keycloak/social/github/GitHubIdentityProvider.java +++ b/services/src/main/java/org/keycloak/social/github/GitHubIdentityProvider.java @@ -18,6 +18,8 @@ package org.keycloak.social.github; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import java.util.Iterator; import org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider; import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig; import org.keycloak.broker.oidc.mappers.AbstractJsonUserAttributeMapper; @@ -36,6 +38,7 @@ public class GitHubIdentityProvider extends AbstractOAuth2IdentityProvider imple public static final String AUTH_URL = "https://github.com/login/oauth/authorize"; public static final String TOKEN_URL = "https://github.com/login/oauth/access_token"; public static final String PROFILE_URL = "https://api.github.com/user"; + public static final String EMAIL_URL = "https://api.github.com/user/emails"; public static final String DEFAULT_SCOPE = "user:email"; public GitHubIdentityProvider(KeycloakSession session, OAuth2IdentityProviderConfig config) { @@ -78,12 +81,35 @@ public class GitHubIdentityProvider extends AbstractOAuth2IdentityProvider imple try { JsonNode profile = SimpleHttp.doGet(PROFILE_URL, session).header("Authorization", "Bearer " + accessToken).asJson(); - return extractIdentityFromProfile(null, profile); + BrokeredIdentityContext user = extractIdentityFromProfile(null, profile); + + if (user.getEmail() == null) { + user.setEmail(searchEmail(accessToken)); + } + + return user; } catch (Exception e) { throw new IdentityBrokerException("Could not obtain user profile from github.", e); } } + private String searchEmail(String accessToken) { + try { + ArrayNode emails = (ArrayNode) SimpleHttp.doGet(EMAIL_URL, session).header("Authorization", "Bearer " + accessToken).asJson(); + + Iterator loop = emails.elements(); + while (loop.hasNext()) { + JsonNode mail = loop.next(); + if (mail.get("primary").asBoolean()) { + return getJsonProperty(mail, "email"); + } + } + } catch (Exception e) { + throw new IdentityBrokerException("Could not obtain user email from github.", e); + } + throw new IdentityBrokerException("Primary email from github is not found."); + } + @Override protected String getDefaultScopes() { return DEFAULT_SCOPE;