Details
diff --git a/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java b/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java
index 8f971b8..19b6dc2 100755
--- a/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java
+++ b/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java
@@ -243,16 +243,19 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
String preferredUsername = (String)idToken.getOtherClaims().get(IDToken.PREFERRED_USERNAME);
String email = (String)idToken.getOtherClaims().get(IDToken.EMAIL);
- if (getConfig().getUserInfoUrl() != null && (id == null || name == null || preferredUsername == null || email == null) ) {
- SimpleHttp request = JsonSimpleHttp.doGet(getConfig().getUserInfoUrl())
- .header("Authorization", "Bearer " + accessToken);
- JsonNode userInfo = JsonSimpleHttp.asJson(request);
-
- id = getJsonProperty(userInfo, "sub");
- name = getJsonProperty(userInfo, "name");
- preferredUsername = getJsonProperty(userInfo, "preferred_username");
- email = getJsonProperty(userInfo, "email");
- AbstractJsonUserAttributeMapper.storeUserProfileForMapper(identity, userInfo, getConfig().getAlias());
+ if (!getConfig().isDisableUserInfoService()) {
+ String userInfoUrl = getUserInfoUrl();
+ if (userInfoUrl != null && (id == null || name == null || preferredUsername == null || email == null)) {
+ SimpleHttp request = JsonSimpleHttp.doGet(userInfoUrl)
+ .header("Authorization", "Bearer " + accessToken);
+ JsonNode userInfo = JsonSimpleHttp.asJson(request);
+
+ id = getJsonProperty(userInfo, "sub");
+ name = getJsonProperty(userInfo, "name");
+ preferredUsername = getJsonProperty(userInfo, "preferred_username");
+ email = getJsonProperty(userInfo, "email");
+ AbstractJsonUserAttributeMapper.storeUserProfileForMapper(identity, userInfo, getConfig().getAlias());
+ }
}
identity.getContextData().put(FEDERATED_ACCESS_TOKEN_RESPONSE, tokenResponse);
identity.getContextData().put(VALIDATED_ID_TOKEN, idToken);
@@ -287,6 +290,11 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
}
}
+ protected String getUserInfoUrl() {
+ return getConfig().getUserInfoUrl();
+ }
+
+
private String verifyAccessToken(AccessTokenResponse tokenResponse) {
String accessToken = tokenResponse.getToken();
diff --git a/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProviderConfig.java b/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProviderConfig.java
index e7fdfd2..c594f7f 100755
--- a/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProviderConfig.java
+++ b/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProviderConfig.java
@@ -93,6 +93,15 @@ public class OIDCIdentityProviderConfig extends OAuth2IdentityProviderConfig {
getConfig().put("backchannelSupported", String.valueOf(backchannel));
}
+ public boolean isDisableUserInfoService() {
+ String disableUserInfo = getConfig().get("disableUserInfo");
+ return disableUserInfo == null ? false : Boolean.valueOf(disableUserInfo);
+ }
+
+ public void setDisableUserInfoService(boolean disable) {
+ getConfig().put("disableUserInfo", String.valueOf(disable));
+ }
+
diff --git a/services/src/main/java/org/keycloak/social/google/GoogleIdentityProvider.java b/services/src/main/java/org/keycloak/social/google/GoogleIdentityProvider.java
index 060f51a..29429d0 100755
--- a/services/src/main/java/org/keycloak/social/google/GoogleIdentityProvider.java
+++ b/services/src/main/java/org/keycloak/social/google/GoogleIdentityProvider.java
@@ -16,9 +16,12 @@
*/
package org.keycloak.social.google;
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.broker.oidc.OIDCIdentityProvider;
import org.keycloak.broker.oidc.OIDCIdentityProviderConfig;
import org.keycloak.broker.social.SocialIdentityProvider;
+import org.keycloak.common.ClientConnection;
+import org.keycloak.common.util.KeycloakUriBuilder;
import org.keycloak.models.KeycloakSession;
/**
@@ -31,7 +34,7 @@ public class GoogleIdentityProvider extends OIDCIdentityProvider implements Soci
public static final String PROFILE_URL = "https://www.googleapis.com/plus/v1/people/me/openIdConnect";
public static final String DEFAULT_SCOPE = "openid profile email";
- public GoogleIdentityProvider(KeycloakSession session, OIDCIdentityProviderConfig config) {
+ public GoogleIdentityProvider(KeycloakSession session, GoogleIdentityProviderConfig config) {
super(session, config);
config.setAuthorizationUrl(AUTH_URL);
config.setTokenUrl(TOKEN_URL);
@@ -42,4 +45,19 @@ public class GoogleIdentityProvider extends OIDCIdentityProvider implements Soci
protected String getDefaultScopes() {
return DEFAULT_SCOPE;
}
+
+ @Override
+ protected String getUserInfoUrl() {
+ String uri = super.getUserInfoUrl();
+ if (((GoogleIdentityProviderConfig)getConfig()).isUserIp()) {
+ ClientConnection connection = ResteasyProviderFactory.getContextData(ClientConnection.class);
+ if (connection != null) {
+ uri = KeycloakUriBuilder.fromUri(super.getUserInfoUrl()).queryParam("userIp", connection.getRemoteAddr()).build().toString();
+ }
+
+ }
+ logger.debugv("GOOGLE userInfoUrl: {0}", uri);
+ return uri;
+ }
+
}
diff --git a/services/src/main/java/org/keycloak/social/google/GoogleIdentityProviderConfig.java b/services/src/main/java/org/keycloak/social/google/GoogleIdentityProviderConfig.java
new file mode 100644
index 0000000..859bacd
--- /dev/null
+++ b/services/src/main/java/org/keycloak/social/google/GoogleIdentityProviderConfig.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * 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.keycloak.social.google;
+
+import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
+import org.keycloak.broker.oidc.OIDCIdentityProviderConfig;
+import org.keycloak.models.IdentityProviderModel;
+
+/**
+ * @author Vlastimil Elias (velias at redhat dot com)
+ */
+public class GoogleIdentityProviderConfig extends OIDCIdentityProviderConfig {
+
+ public GoogleIdentityProviderConfig(IdentityProviderModel model) {
+ super(model);
+ }
+
+ public boolean isUserIp() {
+ String userIp = getConfig().get("userIp");
+ return userIp == null ? false : Boolean.valueOf(userIp);
+ }
+
+ public void setUserIp(boolean ip) {
+ getConfig().put("userIp", String.valueOf(ip));
+ }
+
+}
diff --git a/services/src/main/java/org/keycloak/social/google/GoogleIdentityProviderFactory.java b/services/src/main/java/org/keycloak/social/google/GoogleIdentityProviderFactory.java
index 6db6219..b35fd17 100755
--- a/services/src/main/java/org/keycloak/social/google/GoogleIdentityProviderFactory.java
+++ b/services/src/main/java/org/keycloak/social/google/GoogleIdentityProviderFactory.java
@@ -36,7 +36,7 @@ public class GoogleIdentityProviderFactory extends AbstractIdentityProviderFacto
@Override
public GoogleIdentityProvider create(KeycloakSession session, IdentityProviderModel model) {
- return new GoogleIdentityProvider(session, new OIDCIdentityProviderConfig(model));
+ return new GoogleIdentityProvider(session, new GoogleIdentityProviderConfig(model));
}
@Override
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java
index 25e046f..2d66c66 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java
@@ -92,6 +92,11 @@ public class AdapterTest {
public AdapterTestStrategy testStrategy = new AdapterTestStrategy("http://localhost:8081/auth", "http://localhost:8081", keycloakRule);
@Test
+ public void testIDE() throws Exception {
+ Thread.sleep(100000000);
+ }
+
+ @Test
public void testLoginSSOAndLogout() throws Exception {
testStrategy.testLoginSSOMax();
diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
index ef8ef74..dd892de 100644
--- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
@@ -434,6 +434,10 @@ store-tokens=Store Tokens
identity-provider.store-tokens.tooltip=Enable/disable if tokens must be stored after authenticating users.
stored-tokens-readable=Stored Tokens Readable
identity-provider.stored-tokens-readable.tooltip=Enable/disable if new users can read any stored tokens. This assigns the broker.read-token role.
+disableUserInfo=Disable User Info
+identity-provider.disableUserInfo.tooltip=Disable usage of User Info service to obtain additional user information? Default is to use this OIDC service.
+userIp=Use userIp Param
+identity-provider.google-userIp.tooltip=Set 'userIp' query parameter when invoking on Google's User Info service. This will use the user's ip address. Useful if Google is throttling access to the User Info service.
update-profile-on-first-login=Update Profile on First Login
on=On
on-missing-info=On missing info
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-google-ext.html b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-google-ext.html
index e69de29..9d6632d 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-google-ext.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-google-ext.html
@@ -0,0 +1,7 @@
+<div class="form-group">
+ <label class="col-md-2 control-label" for="userIp">{{:: 'userIp' | translate}}</label>
+ <div class="col-md-6">
+ <input ng-model="identityProvider.config.userIp" id="userIp" onoffswitchvalue on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
+ </div>
+ <kc-tooltip>{{:: 'identity-provider.google-userIp.tooltip' | translate}}</kc-tooltip>
+</div>
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
index 2c51dd5..d5c0d85 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
@@ -65,6 +65,13 @@
<kc-tooltip>{{:: 'identity-provider.enabled.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
+ <label class="col-md-2 control-label" for="disableUserInfo">{{:: 'disableUserInfo' | translate}}</label>
+ <div class="col-md-6">
+ <input ng-model="identityProvider.config.disableUserInfo" id="disableUserInfo" onoffswitchvalue on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
+ </div>
+ <kc-tooltip>{{:: 'identity-provider.disableUserInfo.tooltip' | translate}}</kc-tooltip>
+ </div>
+ <div class="form-group">
<label class="col-md-2 control-label" for="trustEmail">{{:: 'trust-email' | translate}}</label>
<div class="col-md-6">
<input ng-model="identityProvider.trustEmail" name="identityProvider.trustEmail" id="trustEmail" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />