broker oidc logout
This commit is contained in:
parent
f546358d66
commit
410953fc5f
7 changed files with 165 additions and 27 deletions
|
@ -15,6 +15,11 @@
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-core</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-broker-core</artifactId>
|
<artifactId>keycloak-broker-core</artifactId>
|
||||||
|
|
|
@ -33,9 +33,11 @@ import org.keycloak.events.EventType;
|
||||||
import org.keycloak.models.FederatedIdentityModel;
|
import org.keycloak.models.FederatedIdentityModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.representations.AccessTokenResponse;
|
||||||
import org.keycloak.services.managers.EventsManager;
|
import org.keycloak.services.managers.EventsManager;
|
||||||
import org.keycloak.services.messages.Messages;
|
import org.keycloak.services.messages.Messages;
|
||||||
import org.keycloak.services.resources.flows.Flows;
|
import org.keycloak.services.resources.flows.Flows;
|
||||||
|
import org.keycloak.util.JsonSerialization;
|
||||||
|
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
import javax.ws.rs.QueryParam;
|
import javax.ws.rs.QueryParam;
|
||||||
|
@ -47,6 +49,7 @@ import javax.ws.rs.core.UriInfo;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@ -57,6 +60,9 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
|
||||||
protected static final Logger logger = Logger.getLogger(AbstractOAuth2IdentityProvider.class);
|
protected static final Logger logger = Logger.getLogger(AbstractOAuth2IdentityProvider.class);
|
||||||
|
|
||||||
public static final String OAUTH2_GRANT_TYPE_AUTHORIZATION_CODE = "authorization_code";
|
public static final String OAUTH2_GRANT_TYPE_AUTHORIZATION_CODE = "authorization_code";
|
||||||
|
public static final String FEDERATED_ACCESS_TOKEN = "FEDERATED_ACCESS_TOKEN";
|
||||||
|
public static final String FEDERATED_REFRESH_TOKEN = "FEDERATED_REFRESH_TOKEN";
|
||||||
|
public static final String FEDERATED_TOKEN_EXPIRATION = "FEDERATED_TOKEN_EXPIRATION";
|
||||||
protected static ObjectMapper mapper = new ObjectMapper();
|
protected static ObjectMapper mapper = new ObjectMapper();
|
||||||
|
|
||||||
public static final String OAUTH2_PARAMETER_ACCESS_TOKEN = "access_token";
|
public static final String OAUTH2_PARAMETER_ACCESS_TOKEN = "access_token";
|
||||||
|
@ -69,7 +75,6 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
|
||||||
public static final String OAUTH2_PARAMETER_CLIENT_SECRET = "client_secret";
|
public static final String OAUTH2_PARAMETER_CLIENT_SECRET = "client_secret";
|
||||||
public static final String OAUTH2_PARAMETER_GRANT_TYPE = "grant_type";
|
public static final String OAUTH2_PARAMETER_GRANT_TYPE = "grant_type";
|
||||||
|
|
||||||
protected AuthenticationCallback callback;
|
|
||||||
|
|
||||||
public AbstractOAuth2IdentityProvider(C config) {
|
public AbstractOAuth2IdentityProvider(C config) {
|
||||||
super(config);
|
super(config);
|
||||||
|
@ -81,8 +86,7 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object callback(RealmModel realm, AuthenticationCallback callback) {
|
public Object callback(RealmModel realm, AuthenticationCallback callback) {
|
||||||
this.callback = callback;
|
return new Endpoint(callback, realm);
|
||||||
return new Endpoint(realm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -124,8 +128,17 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected FederatedIdentity getFederatedIdentity(String response) {
|
protected FederatedIdentity getFederatedIdentity(Map<String, String> notes, String response) {
|
||||||
String accessToken = extractTokenFromResponse(response, OAUTH2_PARAMETER_ACCESS_TOKEN);
|
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) {
|
if (accessToken == null) {
|
||||||
throw new IdentityBrokerException("No access token from server.");
|
throw new IdentityBrokerException("No access token from server.");
|
||||||
|
@ -164,6 +177,7 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
|
||||||
protected abstract String getDefaultScopes();
|
protected abstract String getDefaultScopes();
|
||||||
|
|
||||||
protected class Endpoint {
|
protected class Endpoint {
|
||||||
|
protected AuthenticationCallback callback;
|
||||||
protected RealmModel realm;
|
protected RealmModel realm;
|
||||||
|
|
||||||
@Context
|
@Context
|
||||||
|
@ -178,7 +192,8 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
|
||||||
@Context
|
@Context
|
||||||
protected UriInfo uriInfo;
|
protected UriInfo uriInfo;
|
||||||
|
|
||||||
public Endpoint(RealmModel realm) {
|
public Endpoint(AuthenticationCallback callback, RealmModel realm) {
|
||||||
|
this.callback = callback;
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,13 +220,14 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
|
||||||
.param(OAUTH2_PARAMETER_REDIRECT_URI, uriInfo.getAbsolutePath().toString())
|
.param(OAUTH2_PARAMETER_REDIRECT_URI, uriInfo.getAbsolutePath().toString())
|
||||||
.param(OAUTH2_PARAMETER_GRANT_TYPE, OAUTH2_GRANT_TYPE_AUTHORIZATION_CODE).asString();
|
.param(OAUTH2_PARAMETER_GRANT_TYPE, OAUTH2_GRANT_TYPE_AUTHORIZATION_CODE).asString();
|
||||||
|
|
||||||
FederatedIdentity federatedIdentity = getFederatedIdentity(response);
|
HashMap<String, String> userNotes = new HashMap<String, String>();
|
||||||
|
FederatedIdentity federatedIdentity = getFederatedIdentity(userNotes, response);
|
||||||
|
|
||||||
if (getConfig().isStoreToken()) {
|
if (getConfig().isStoreToken()) {
|
||||||
federatedIdentity.setToken(response);
|
federatedIdentity.setToken(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
return callback.authenticated(new HashMap<String, String>(), getConfig(), federatedIdentity, state);
|
return callback.authenticated(userNotes, getConfig(), federatedIdentity, state);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("Failed to make identity provider oauth callback", e);
|
logger.error("Failed to make identity provider oauth callback", e);
|
||||||
|
|
120
broker/oidc/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java
Normal file → Executable file
120
broker/oidc/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java
Normal file → Executable file
|
@ -22,10 +22,32 @@ import org.keycloak.broker.oidc.util.SimpleHttp;
|
||||||
import org.keycloak.broker.provider.AuthenticationRequest;
|
import org.keycloak.broker.provider.AuthenticationRequest;
|
||||||
import org.keycloak.broker.provider.FederatedIdentity;
|
import org.keycloak.broker.provider.FederatedIdentity;
|
||||||
import org.keycloak.broker.provider.IdentityBrokerException;
|
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.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.UriBuilder;
|
||||||
|
import javax.ws.rs.core.UriInfo;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Pedro Igor
|
* @author Pedro Igor
|
||||||
|
@ -33,8 +55,8 @@ import java.io.IOException;
|
||||||
public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIdentityProviderConfig> {
|
public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIdentityProviderConfig> {
|
||||||
|
|
||||||
public static final String OAUTH2_PARAMETER_PROMPT = "prompt";
|
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 SCOPE_OPENID = "openid";
|
||||||
|
public static final String FEDERATED_ID_TOKEN = "FEDERATED_ID_TOKEN";
|
||||||
|
|
||||||
public OIDCIdentityProvider(OIDCIdentityProviderConfig config) {
|
public OIDCIdentityProvider(OIDCIdentityProviderConfig config) {
|
||||||
super(config);
|
super(config);
|
||||||
|
@ -46,6 +68,54 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object callback(RealmModel realm, AuthenticationCallback callback) {
|
||||||
|
return new OIDCEndpoint(callback, realm);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class OIDCEndpoint extends Endpoint {
|
||||||
|
public OIDCEndpoint(AuthenticationCallback callback, RealmModel realm) {
|
||||||
|
super(callback, realm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("logout_response")
|
||||||
|
public Response logoutResponse(@Context UriInfo uriInfo,
|
||||||
|
@QueryParam("state") String state) {
|
||||||
|
UserSessionModel userSession = session.sessions().getUserSession(realm, state);
|
||||||
|
if (userSession == null) {
|
||||||
|
logger.error("no valid user session");
|
||||||
|
EventBuilder event = new EventsManager(realm, session, clientConnection).createEventBuilder();
|
||||||
|
event.event(EventType.LOGOUT);
|
||||||
|
event.error(Errors.USER_SESSION_NOT_FOUND);
|
||||||
|
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
|
||||||
|
}
|
||||||
|
if (userSession.getState() != UserSessionModel.State.LOGGING_OUT) {
|
||||||
|
logger.error("usersession in different state");
|
||||||
|
EventBuilder event = new EventsManager(realm, session, clientConnection).createEventBuilder();
|
||||||
|
event.event(EventType.LOGOUT);
|
||||||
|
event.error(Errors.USER_SESSION_NOT_FOUND);
|
||||||
|
return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, headers, Messages.SESSION_NOT_ACTIVE);
|
||||||
|
}
|
||||||
|
return AuthenticationManager.finishBrowserLogout(session, realm, userSession, uriInfo, clientConnection, headers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response keycloakInitiatedBrowserLogout(UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
|
||||||
|
if (getConfig().getLogoutUrl() == null) return null;
|
||||||
|
UriBuilder logoutUri = UriBuilder.fromUri(getConfig().getLogoutUrl())
|
||||||
|
.queryParam("state", userSession.getId());
|
||||||
|
String idToken = userSession.getNote(FEDERATED_ID_TOKEN);
|
||||||
|
if (idToken != null) logoutUri.queryParam("id_token_hint", idToken);
|
||||||
|
String redirect = RealmsResource.brokerUrl(uriInfo)
|
||||||
|
.path(IdentityBrokerService.class, "getEndpoint")
|
||||||
|
.path(OIDCEndpoint.class, "logoutResponse")
|
||||||
|
.build(realm.getName(), getConfig().getAlias()).toString();
|
||||||
|
logoutUri.queryParam("post_logout_redirect_uri", redirect);
|
||||||
|
return Response.status(302).location(logoutUri.build()).build();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected UriBuilder createAuthorizationUrl(AuthenticationRequest request) {
|
protected UriBuilder createAuthorizationUrl(AuthenticationRequest request) {
|
||||||
UriBuilder authorizationUrl = super.createAuthorizationUrl(request);
|
UriBuilder authorizationUrl = super.createAuthorizationUrl(request);
|
||||||
|
@ -59,26 +129,45 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected FederatedIdentity getFederatedIdentity(String response) {
|
protected FederatedIdentity getFederatedIdentity(Map<String, String> notes, String response) {
|
||||||
String accessToken = extractTokenFromResponse(response, OAUTH2_PARAMETER_ACCESS_TOKEN);
|
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) {
|
if (accessToken == null) {
|
||||||
throw new IdentityBrokerException("No access_token from server.");
|
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 {
|
try {
|
||||||
|
String id = idToken.getSubject();
|
||||||
|
String name = idToken.getName();
|
||||||
|
String preferredUsername = idToken.getPreferredUsername();
|
||||||
|
String email = idToken.getEmail();
|
||||||
|
|
||||||
|
if (id == null || name == null || preferredUsername == null || email == null && getConfig().getUserInfoUrl() != null) {
|
||||||
JsonNode userInfo = SimpleHttp.doGet(getConfig().getUserInfoUrl())
|
JsonNode userInfo = SimpleHttp.doGet(getConfig().getUserInfoUrl())
|
||||||
.header("Authorization", "Bearer " + accessToken)
|
.header("Authorization", "Bearer " + accessToken)
|
||||||
.asJson();
|
.asJson();
|
||||||
|
|
||||||
String id = getJsonProperty(userInfo, "sub");
|
id = getJsonProperty(userInfo, "sub");
|
||||||
String name = getJsonProperty(userInfo, "name");
|
name = getJsonProperty(userInfo, "name");
|
||||||
String preferredUsername = getJsonProperty(userInfo, "preferred_username");
|
preferredUsername = getJsonProperty(userInfo, "preferred_username");
|
||||||
String email = getJsonProperty(userInfo, "email");
|
email = getJsonProperty(userInfo, "email");
|
||||||
|
}
|
||||||
|
|
||||||
FederatedIdentity identity = new FederatedIdentity(id);
|
FederatedIdentity identity = new FederatedIdentity(id);
|
||||||
|
|
||||||
|
@ -106,16 +195,16 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateIdToken(String idToken) {
|
private IDToken validateIdToken(String encodedToken) {
|
||||||
if (idToken == null) {
|
if (encodedToken == null) {
|
||||||
throw new IdentityBrokerException("No id_token from server.");
|
throw new IdentityBrokerException("No id_token from server.");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
JsonNode idTokenInfo = asJsonNode(decodeJWS(idToken));
|
IDToken idToken = new JWSInput(encodedToken).readJsonContent(IDToken.class);
|
||||||
|
|
||||||
String aud = getJsonProperty(idTokenInfo, "aud");
|
String aud = idToken.getAudience();
|
||||||
String iss = getJsonProperty(idTokenInfo, "iss");
|
String iss = idToken.getIssuer();
|
||||||
|
|
||||||
if (aud != null && !aud.equals(getConfig().getClientId())) {
|
if (aud != null && !aud.equals(getConfig().getClientId())) {
|
||||||
throw new RuntimeException("Wrong audience from id_token..");
|
throw new RuntimeException("Wrong audience from id_token..");
|
||||||
|
@ -128,12 +217,13 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
|
||||||
|
|
||||||
for (String trustedIssuer : issuers) {
|
for (String trustedIssuer : issuers) {
|
||||||
if (iss != null && iss.equals(trustedIssuer.trim())) {
|
if (iss != null && iss.equals(trustedIssuer.trim())) {
|
||||||
return;
|
return idToken;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IdentityBrokerException("Wrong issuer from id_token..");
|
throw new IdentityBrokerException("Wrong issuer from id_token..");
|
||||||
}
|
}
|
||||||
|
return idToken;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IdentityBrokerException("Could not decode id token.", e);
|
throw new IdentityBrokerException("Could not decode id token.", e);
|
||||||
}
|
}
|
||||||
|
|
4
broker/oidc/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProviderConfig.java
Normal file → Executable file
4
broker/oidc/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProviderConfig.java
Normal file → Executable file
|
@ -35,4 +35,8 @@ public class OIDCIdentityProviderConfig extends OAuth2IdentityProviderConfig {
|
||||||
public String getIssuer() {
|
public String getIssuer() {
|
||||||
return getConfig().get("issuer");
|
return getConfig().get("issuer");
|
||||||
}
|
}
|
||||||
|
public String getLogoutUrl() {
|
||||||
|
return getConfig().get("logoutUrl");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
package org.keycloak.representations;
|
package org.keycloak.representations;
|
||||||
|
|
||||||
|
import org.codehaus.jackson.annotate.JsonAnyGetter;
|
||||||
|
import org.codehaus.jackson.annotate.JsonAnySetter;
|
||||||
import org.codehaus.jackson.annotate.JsonProperty;
|
import org.codehaus.jackson.annotate.JsonProperty;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OAuth 2.0 Access Token Response json
|
* OAuth 2.0 Access Token Response json
|
||||||
*
|
*
|
||||||
|
@ -33,6 +38,10 @@ public class AccessTokenResponse {
|
||||||
@JsonProperty("session-state")
|
@JsonProperty("session-state")
|
||||||
protected String sessionState;
|
protected String sessionState;
|
||||||
|
|
||||||
|
protected Map<String, Object> otherClaims = new HashMap<String, Object>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public String getToken() {
|
public String getToken() {
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
@ -96,4 +105,15 @@ public class AccessTokenResponse {
|
||||||
public void setSessionState(String sessionState) {
|
public void setSessionState(String sessionState) {
|
||||||
this.sessionState = sessionState;
|
this.sessionState = sessionState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsonAnyGetter
|
||||||
|
public Map<String, Object> getOtherClaims() {
|
||||||
|
return otherClaims;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonAnySetter
|
||||||
|
public void setOtherClaims(String name, Object value) {
|
||||||
|
otherClaims.put(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,6 @@ import static org.keycloak.models.UserModel.RequiredAction.UPDATE_PROFILE;
|
||||||
*
|
*
|
||||||
* @author Pedro Igor
|
* @author Pedro Igor
|
||||||
*/
|
*/
|
||||||
@Path("/broker")
|
|
||||||
public class IdentityBrokerService implements IdentityProvider.AuthenticationCallback {
|
public class IdentityBrokerService implements IdentityProvider.AuthenticationCallback {
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(IdentityBrokerService.class);
|
private static final Logger LOGGER = Logger.getLogger(IdentityBrokerService.class);
|
||||||
|
|
|
@ -79,6 +79,10 @@ public class RealmsResource {
|
||||||
return uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getProtocol");
|
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")
|
@Path("{realm}/login-status-iframe.html")
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public Object getLoginStatusIframe(final @PathParam("realm") String name,
|
public Object getLoginStatusIframe(final @PathParam("realm") String name,
|
||||||
|
|
Loading…
Reference in a new issue