diff --git a/broker/oidc/pom.xml b/broker/oidc/pom.xml
index 478cb4738c..5bd4d543e6 100755
--- a/broker/oidc/pom.xml
+++ b/broker/oidc/pom.xml
@@ -15,6 +15,11 @@
jar
+
+ org.keycloak
+ keycloak-core
+ ${project.version}
+
org.keycloak
keycloak-broker-core
diff --git a/broker/oidc/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java b/broker/oidc/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java
index f2245e3c22..274171c326 100755
--- a/broker/oidc/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java
+++ b/broker/oidc/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java
@@ -33,9 +33,11 @@ import org.keycloak.events.EventType;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
+import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.services.managers.EventsManager;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.flows.Flows;
+import org.keycloak.util.JsonSerialization;
import javax.ws.rs.GET;
import javax.ws.rs.QueryParam;
@@ -47,6 +49,7 @@ import javax.ws.rs.core.UriInfo;
import java.io.IOException;
import java.net.URI;
import java.util.HashMap;
+import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -57,6 +60,9 @@ public abstract class AbstractOAuth2IdentityProvider notes, String response) {
+ AccessTokenResponse tokenResponse = null;
+ try {
+ tokenResponse = JsonSerialization.readValue(response, AccessTokenResponse.class);
+ } catch (IOException e) {
+ throw new IdentityBrokerException("Could not decode access token response.", e);
+ }
+ String accessToken = tokenResponse.getToken();
+ notes.put(FEDERATED_ACCESS_TOKEN, accessToken);
+ notes.put(FEDERATED_REFRESH_TOKEN, tokenResponse.getRefreshToken());
+ notes.put(FEDERATED_TOKEN_EXPIRATION, Long.toString(tokenResponse.getExpiresIn()));
if (accessToken == null) {
throw new IdentityBrokerException("No access token from server.");
@@ -164,6 +177,7 @@ public abstract class AbstractOAuth2IdentityProvider userNotes = new HashMap();
+ FederatedIdentity federatedIdentity = getFederatedIdentity(userNotes, response);
if (getConfig().isStoreToken()) {
federatedIdentity.setToken(response);
}
- return callback.authenticated(new HashMap(), getConfig(), federatedIdentity, state);
+ return callback.authenticated(userNotes, getConfig(), federatedIdentity, state);
}
} catch (Exception e) {
logger.error("Failed to make identity provider oauth callback", e);
diff --git a/broker/oidc/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java b/broker/oidc/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java
old mode 100644
new mode 100755
index 2c43d61d3d..3e052728cc
--- a/broker/oidc/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java
+++ b/broker/oidc/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java
@@ -22,10 +22,32 @@ import org.keycloak.broker.oidc.util.SimpleHttp;
import org.keycloak.broker.provider.AuthenticationRequest;
import org.keycloak.broker.provider.FederatedIdentity;
import org.keycloak.broker.provider.IdentityBrokerException;
+import org.keycloak.broker.provider.IdentityProvider;
+import org.keycloak.events.Errors;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
import org.keycloak.jose.jws.JWSInput;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.representations.AccessTokenResponse;
+import org.keycloak.representations.IDToken;
+import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.services.managers.EventsManager;
+import org.keycloak.services.messages.Messages;
+import org.keycloak.services.resources.IdentityBrokerService;
+import org.keycloak.services.resources.RealmsResource;
+import org.keycloak.services.resources.flows.Flows;
+import org.keycloak.util.JsonSerialization;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
import java.io.IOException;
+import java.util.Map;
/**
* @author Pedro Igor
@@ -33,8 +55,8 @@ import java.io.IOException;
public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider {
public static final String OAUTH2_PARAMETER_PROMPT = "prompt";
- public static final String OIDC_PARAMETER_ID_TOKEN = "id_token";
public static final String SCOPE_OPENID = "openid";
+ public static final String FEDERATED_ID_TOKEN = "FEDERATED_ID_TOKEN";
public OIDCIdentityProvider(OIDCIdentityProviderConfig config) {
super(config);
@@ -46,6 +68,54 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider notes, String response) {
+ AccessTokenResponse tokenResponse = null;
+ try {
+ tokenResponse = JsonSerialization.readValue(response, AccessTokenResponse.class);
+ } catch (IOException e) {
+ throw new IdentityBrokerException("Could not decode access token response.", e);
+ }
+ String accessToken = tokenResponse.getToken();
if (accessToken == null) {
throw new IdentityBrokerException("No access_token from server.");
}
- String idToken = extractTokenFromResponse(response, OIDC_PARAMETER_ID_TOKEN);
+ String encodedIdToken = tokenResponse.getIdToken();
- validateIdToken(idToken);
+ notes.put(FEDERATED_ACCESS_TOKEN, accessToken);
+ notes.put(FEDERATED_ID_TOKEN, encodedIdToken);
+ notes.put(FEDERATED_REFRESH_TOKEN, tokenResponse.getRefreshToken());
+ notes.put(FEDERATED_TOKEN_EXPIRATION, Long.toString(tokenResponse.getExpiresIn()));
+
+
+ IDToken idToken = validateIdToken(encodedIdToken);
try {
- JsonNode userInfo = SimpleHttp.doGet(getConfig().getUserInfoUrl())
- .header("Authorization", "Bearer " + accessToken)
- .asJson();
+ String id = idToken.getSubject();
+ String name = idToken.getName();
+ String preferredUsername = idToken.getPreferredUsername();
+ String email = idToken.getEmail();
- String id = getJsonProperty(userInfo, "sub");
- String name = getJsonProperty(userInfo, "name");
- String preferredUsername = getJsonProperty(userInfo, "preferred_username");
- String email = getJsonProperty(userInfo, "email");
+ if (id == null || name == null || preferredUsername == null || email == null && getConfig().getUserInfoUrl() != null) {
+ JsonNode userInfo = SimpleHttp.doGet(getConfig().getUserInfoUrl())
+ .header("Authorization", "Bearer " + accessToken)
+ .asJson();
+
+ id = getJsonProperty(userInfo, "sub");
+ name = getJsonProperty(userInfo, "name");
+ preferredUsername = getJsonProperty(userInfo, "preferred_username");
+ email = getJsonProperty(userInfo, "email");
+ }
FederatedIdentity identity = new FederatedIdentity(id);
@@ -106,16 +195,16 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider otherClaims = new HashMap();
+
+
+
public String getToken() {
return token;
}
@@ -96,4 +105,15 @@ public class AccessTokenResponse {
public void setSessionState(String sessionState) {
this.sessionState = sessionState;
}
+
+ @JsonAnyGetter
+ public Map getOtherClaims() {
+ return otherClaims;
+ }
+
+ @JsonAnySetter
+ public void setOtherClaims(String name, Object value) {
+ otherClaims.put(name, value);
+ }
+
}
diff --git a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
index a835b66441..4d4f41b9fe 100755
--- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
+++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
@@ -76,7 +76,6 @@ import static org.keycloak.models.UserModel.RequiredAction.UPDATE_PROFILE;
*
* @author Pedro Igor
*/
-@Path("/broker")
public class IdentityBrokerService implements IdentityProvider.AuthenticationCallback {
private static final Logger LOGGER = Logger.getLogger(IdentityBrokerService.class);
diff --git a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
index 0feccb47ec..1f43e9af0e 100755
--- a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
@@ -79,6 +79,10 @@ public class RealmsResource {
return uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getProtocol");
}
+ public static UriBuilder brokerUrl(UriInfo uriInfo) {
+ return uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getBrokerService");
+ }
+
@Path("{realm}/login-status-iframe.html")
@Deprecated
public Object getLoginStatusIframe(final @PathParam("realm") String name,