keycloak-aplcache
Changes
testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java 20(+19 -1)
testsuite/integration/src/test/java/org/keycloak/testsuite/broker/OIDCKeyCloakServerBrokerBasicTest.java 25(+25 -0)
Details
diff --git a/server-spi/src/main/java/org/keycloak/broker/provider/AbstractIdentityProvider.java b/server-spi/src/main/java/org/keycloak/broker/provider/AbstractIdentityProvider.java
index ce3a27d..5532606 100755
--- a/server-spi/src/main/java/org/keycloak/broker/provider/AbstractIdentityProvider.java
+++ b/server-spi/src/main/java/org/keycloak/broker/provider/AbstractIdentityProvider.java
@@ -63,12 +63,12 @@ public abstract class AbstractIdentityProvider<C extends IdentityProviderModel>
}
@Override
- public Response keycloakInitiatedBrowserLogout(UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
+ public Response keycloakInitiatedBrowserLogout(KeycloakSession session, UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
return null;
}
@Override
- public void backchannelLogout(UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
+ public void backchannelLogout(KeycloakSession session, UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
}
diff --git a/server-spi/src/main/java/org/keycloak/broker/provider/IdentityProvider.java b/server-spi/src/main/java/org/keycloak/broker/provider/IdentityProvider.java
index 0fa4993..b14572e 100755
--- a/server-spi/src/main/java/org/keycloak/broker/provider/IdentityProvider.java
+++ b/server-spi/src/main/java/org/keycloak/broker/provider/IdentityProvider.java
@@ -79,9 +79,9 @@ public interface IdentityProvider<C extends IdentityProviderModel> extends Provi
* @param identity
* @return
*/
- Response retrieveToken(FederatedIdentityModel identity);
+ Response retrieveToken(KeycloakSession session, FederatedIdentityModel identity);
- void backchannelLogout(UserSessionModel userSession, UriInfo uriInfo, RealmModel realm);
+ void backchannelLogout(KeycloakSession session, UserSessionModel userSession, UriInfo uriInfo, RealmModel realm);
/**
* Called when a Keycloak application initiates a logout through the browser. This is expected to do a logout
@@ -92,7 +92,7 @@ public interface IdentityProvider<C extends IdentityProviderModel> extends Provi
* @param realm
* @return null if this is not supported by this provider
*/
- Response keycloakInitiatedBrowserLogout(UserSessionModel userSession, UriInfo uriInfo, RealmModel realm);
+ Response keycloakInitiatedBrowserLogout(KeycloakSession session, UserSessionModel userSession, UriInfo uriInfo, RealmModel realm);
/**
* Export a representation of the IdentityProvider in a specific format. For example, a SAML EntityDescriptor
diff --git a/server-spi/src/main/java/org/keycloak/broker/provider/IdentityProviderFactory.java b/server-spi/src/main/java/org/keycloak/broker/provider/IdentityProviderFactory.java
index e5ac7fd..fba8e64 100755
--- a/server-spi/src/main/java/org/keycloak/broker/provider/IdentityProviderFactory.java
+++ b/server-spi/src/main/java/org/keycloak/broker/provider/IdentityProviderFactory.java
@@ -47,7 +47,6 @@ public interface IdentityProviderFactory<T extends IdentityProvider> extends Pro
* <p>Creates an {@link IdentityProvider} based on the configuration from
* <code>inputStream</code>.</p>
*
- * @param model The model containing the common abd basic configuration for an identity provider.
* @param inputStream The input stream from where configuration will be loaded from..
* @return
*/
diff --git a/services/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java b/services/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java
index 182099b..bad6d19 100755
--- a/services/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java
+++ b/services/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java
@@ -54,6 +54,7 @@ import java.util.regex.Pattern;
public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityProviderConfig> extends AbstractIdentityProvider<C> {
protected static final Logger logger = Logger.getLogger(AbstractOAuth2IdentityProvider.class);
+ public static final String OAUTH2_GRANT_TYPE_REFRESH_TOKEN = "refresh_token";
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";
@@ -97,7 +98,7 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
}
@Override
- public Response retrieveToken(FederatedIdentityModel identity) {
+ public Response retrieveToken(KeycloakSession session, FederatedIdentityModel identity) {
return Response.ok(identity.getToken()).build();
}
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 be5edaa..7e19ea6 100755
--- a/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java
+++ b/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java
@@ -24,6 +24,7 @@ import org.keycloak.broker.provider.util.SimpleHttp;
import org.keycloak.broker.provider.AuthenticationRequest;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.IdentityBrokerException;
+import org.keycloak.common.util.Time;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
@@ -31,6 +32,7 @@ import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.JWSInputException;
import org.keycloak.jose.jws.crypto.RSAProvider;
import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.representations.AccessTokenResponse;
@@ -41,6 +43,7 @@ import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.IdentityBrokerService;
import org.keycloak.services.resources.RealmsResource;
+import org.keycloak.truststore.JSSETruststoreConfigurator;
import org.keycloak.util.JsonSerialization;
import org.keycloak.common.util.PemUtils;
@@ -130,9 +133,9 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
}
@Override
- public void backchannelLogout(UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
+ public void backchannelLogout(KeycloakSession session, UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
if (getConfig().getLogoutUrl() == null || getConfig().getLogoutUrl().trim().equals("") || !getConfig().isBackchannelSupported()) return;
- String idToken = userSession.getNote(FEDERATED_ID_TOKEN);
+ String idToken = getIDTokenForLogout(session, userSession);
if (idToken == null) return;
backchannelLogout(userSession, idToken);
}
@@ -156,9 +159,9 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
@Override
- public Response keycloakInitiatedBrowserLogout(UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
+ public Response keycloakInitiatedBrowserLogout(KeycloakSession session, UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
if (getConfig().getLogoutUrl() == null || getConfig().getLogoutUrl().trim().equals("")) return null;
- String idToken = userSession.getNote(FEDERATED_ID_TOKEN);
+ String idToken = getIDTokenForLogout(session, userSession);
if (idToken != null && getConfig().isBackchannelSupported()) {
backchannelLogout(userSession, idToken);
return null;
@@ -177,6 +180,47 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
}
}
+ /**
+ * Returns access token response as a string from a refresh token invocation on the remote OIDC broker
+ *
+ * @param session
+ * @param userSession
+ * @return
+ */
+ public String refreshToken(KeycloakSession session, UserSessionModel userSession) {
+ String refreshToken = userSession.getNote(FEDERATED_REFRESH_TOKEN);
+ JSSETruststoreConfigurator configurator = new JSSETruststoreConfigurator(session);
+ try {
+ return SimpleHttp.doPost(getConfig().getTokenUrl())
+ .param("refresh_token", refreshToken)
+ .param(OAUTH2_PARAMETER_GRANT_TYPE, OAUTH2_GRANT_TYPE_REFRESH_TOKEN)
+ .param(OAUTH2_PARAMETER_CLIENT_ID, getConfig().getClientId())
+ .param(OAUTH2_PARAMETER_CLIENT_SECRET, getConfig().getClientSecret())
+ .sslFactory(configurator.getSSLSocketFactory())
+ .hostnameVerifier(configurator.getHostnameVerifier()).asString();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private String getIDTokenForLogout(KeycloakSession session, UserSessionModel userSession) {
+ long exp = Long.parseLong(userSession.getNote(FEDERATED_TOKEN_EXPIRATION));
+ int currentTime = Time.currentTime();
+ if (exp > 0 && currentTime > exp) {
+ String response = refreshToken(session, userSession);
+ AccessTokenResponse tokenResponse = null;
+ try {
+ tokenResponse = JsonSerialization.readValue(response, AccessTokenResponse.class);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return tokenResponse.getIdToken();
+ } else {
+ return userSession.getNote(FEDERATED_ID_TOKEN);
+
+ }
+ }
+
@Override
protected UriBuilder createAuthorizationUrl(AuthenticationRequest request) {
UriBuilder authorizationUrl = super.createAuthorizationUrl(request);
@@ -322,6 +366,10 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
@Override
public void attachUserSession(UserSessionModel userSession, ClientSessionModel clientSession, BrokeredIdentityContext context) {
AccessTokenResponse tokenResponse = (AccessTokenResponse)context.getContextData().get(FEDERATED_ACCESS_TOKEN_RESPONSE);
+ int currentTime = Time.currentTime();
+ long expiration = tokenResponse.getExpiresIn() > 0 ? tokenResponse.getExpiresIn() + currentTime : 0;
+ userSession.setNote(FEDERATED_TOKEN_EXPIRATION, Long.toString(expiration));
+ userSession.setNote(FEDERATED_REFRESH_TOKEN, tokenResponse.getRefreshToken());
userSession.setNote(FEDERATED_ACCESS_TOKEN, tokenResponse.getToken());
userSession.setNote(FEDERATED_ID_TOKEN, tokenResponse.getIdToken());
}
diff --git a/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java b/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java
index 5605ea6..3d9a536 100755
--- a/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java
+++ b/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java
@@ -31,6 +31,7 @@ import org.keycloak.dom.saml.v2.protocol.ResponseType;
import org.keycloak.events.EventBuilder;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.FederatedIdentityModel;
+import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.saml.JaxrsSAML2BindingBuilder;
@@ -145,12 +146,12 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
}
@Override
- public Response retrieveToken(FederatedIdentityModel identity) {
+ public Response retrieveToken(KeycloakSession session, FederatedIdentityModel identity) {
return Response.ok(identity.getToken()).build();
}
@Override
- public void backchannelLogout(UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
+ public void backchannelLogout(KeycloakSession session, UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
String singleLogoutServiceUrl = getConfig().getSingleLogoutServiceUrl();
if (singleLogoutServiceUrl == null || singleLogoutServiceUrl.trim().equals("") || !getConfig().isBackchannelSupported()) return;
SAML2LogoutRequestBuilder logoutBuilder = buildLogoutRequest(userSession, uriInfo, realm, singleLogoutServiceUrl);
@@ -170,12 +171,12 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
}
@Override
- public Response keycloakInitiatedBrowserLogout(UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
+ public Response keycloakInitiatedBrowserLogout(KeycloakSession session, UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
String singleLogoutServiceUrl = getConfig().getSingleLogoutServiceUrl();
if (singleLogoutServiceUrl == null || singleLogoutServiceUrl.trim().equals("")) return null;
if (getConfig().isBackchannelSupported()) {
- backchannelLogout(userSession, uriInfo, realm);
+ backchannelLogout(session, userSession, uriInfo, realm);
return null;
} else {
try {
diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
index b169f7c..33ed98e 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -125,7 +125,7 @@ public class AuthenticationManager {
if (brokerId != null) {
IdentityProvider identityProvider = IdentityBrokerService.getIdentityProvider(session, realm, brokerId);
try {
- identityProvider.backchannelLogout(userSession, uriInfo, realm);
+ identityProvider.backchannelLogout(session, userSession, uriInfo, realm);
} catch (Exception e) {
}
}
@@ -221,7 +221,7 @@ public class AuthenticationManager {
String brokerId = userSession.getNote(Details.IDENTITY_PROVIDER);
if (brokerId != null) {
IdentityProvider identityProvider = IdentityBrokerService.getIdentityProvider(session, realm, brokerId);
- Response response = identityProvider.keycloakInitiatedBrowserLogout(userSession, uriInfo, realm);
+ Response response = identityProvider.keycloakInitiatedBrowserLogout(session, userSession, uriInfo, realm);
if (response != null) return response;
}
return finishBrowserLogout(session, realm, userSession, uriInfo, connection, headers);
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 a1539ca..09c2218 100755
--- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
+++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
@@ -227,7 +227,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
this.event.success();
- return corsResponse(identityProvider.retrieveToken(identity), clientModel);
+ return corsResponse(identityProvider.retrieveToken(session, identity), clientModel);
}
return corsResponse(badRequest("Identity Provider [" + providerId + "] does not support this operation."), clientModel);
diff --git a/services/src/main/java/org/keycloak/social/twitter/TwitterIdentityProvider.java b/services/src/main/java/org/keycloak/social/twitter/TwitterIdentityProvider.java
index a48a9c8..044dc0d 100755
--- a/services/src/main/java/org/keycloak/social/twitter/TwitterIdentityProvider.java
+++ b/services/src/main/java/org/keycloak/social/twitter/TwitterIdentityProvider.java
@@ -185,7 +185,7 @@ public class TwitterIdentityProvider extends AbstractIdentityProvider<OAuth2Iden
}
@Override
- public Response retrieveToken(FederatedIdentityModel identity) {
+ public Response retrieveToken(KeycloakSession session, FederatedIdentityModel identity) {
return Response.ok(identity.getToken()).type(MediaType.APPLICATION_JSON).build();
}
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java
index 51a9044..52245d8 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java
@@ -22,6 +22,7 @@ import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.keycloak.authentication.authenticators.broker.IdpReviewProfileAuthenticatorFactory;
+import org.keycloak.common.util.Time;
import org.keycloak.models.AuthenticatorConfigModel;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.IdentityProviderModel;
@@ -115,6 +116,8 @@ public abstract class AbstractIdentityProviderTest {
protected KeycloakSession session;
+ protected int logoutTimeOffset = 0;
+
@Before
public void onBefore() {
this.session = brokerServerRule.startSession();
@@ -160,11 +163,26 @@ public abstract class AbstractIdentityProviderTest {
assertEquals(getProviderId(), federatedIdentityModel.getIdentityProvider());
assertEquals(federatedUser.getUsername(), federatedIdentityModel.getUserName());
- driver.navigate().to("http://localhost:8081/test-app/logout");
+ // test access token timeot on logout
+ if (logoutTimeOffset > 0) {
+ Time.setOffset(logoutTimeOffset);
+ }
+ try {
+ driver.navigate().to("http://localhost:8081/test-app/logout");
+ } finally {
+ Time.setOffset(0);
+ }
+
+ String afterLogoutUrl = driver.getCurrentUrl();
+ String afterLogoutPageSource = driver.getPageSource();
+ System.out.println("afterLogoutUrl: " + afterLogoutUrl);
+ //System.out.println("after logout page source: " + afterLogoutPageSource);
+
driver.navigate().to("http://localhost:8081/test-app");
assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/realm-with-broker/protocol/openid-connect/auth"));
return federatedUser;
+
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/OIDCKeyCloakServerBrokerBasicTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/OIDCKeyCloakServerBrokerBasicTest.java
index 308cb85..3349e8c 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/OIDCKeyCloakServerBrokerBasicTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/OIDCKeyCloakServerBrokerBasicTest.java
@@ -19,9 +19,13 @@ package org.keycloak.testsuite.broker;
import org.junit.ClassRule;
import org.junit.Test;
+import org.keycloak.admin.client.Keycloak;
+import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.AccessTokenResponse;
+import org.keycloak.representations.idm.IdentityProviderRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.Urls;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.testsuite.Constants;
@@ -34,6 +38,7 @@ import org.keycloak.util.JsonSerialization;
import org.openqa.selenium.NoSuchElementException;
import java.io.IOException;
+import java.util.List;
import javax.ws.rs.core.UriBuilder;
@@ -118,6 +123,26 @@ public class OIDCKeyCloakServerBrokerBasicTest extends AbstractKeycloakIdentityP
}
@Test
+ public void testLogoutWorksWithTokenTimeout() {
+ Keycloak keycloak = Keycloak.getInstance("http://localhost:8081/auth", "master", "admin", "admin", org.keycloak.models.Constants.ADMIN_CLI_CLIENT_ID);
+ RealmRepresentation realm = keycloak.realm("realm-with-oidc-identity-provider").toRepresentation();
+ assertNotNull(realm);
+ int oldLifespan = realm.getAccessTokenLifespan();
+ realm.setAccessTokenLifespan(1);
+ keycloak.realm("realm-with-oidc-identity-provider").update(realm);
+ IdentityProviderRepresentation idp = keycloak.realm("realm-with-broker").identityProviders().get("kc-oidc-idp").toRepresentation();
+ idp.getConfig().put("backchannelSupported", "false");
+ keycloak.realm("realm-with-broker").identityProviders().get("kc-oidc-idp").update(idp);
+ logoutTimeOffset = 2;
+ super.testSuccessfulAuthentication();
+ logoutTimeOffset = 0;
+ realm.setAccessTokenLifespan(oldLifespan);
+ keycloak.realm("realm-with-oidc-identity-provider").update(realm);
+ idp.getConfig().put("backchannelSupported", "true");
+ keycloak.realm("realm-with-broker").identityProviders().get("kc-oidc-idp").update(idp);
+ }
+
+ @Test
public void testSuccessfulAuthenticationWithoutUpdateProfile() {
super.testSuccessfulAuthenticationWithoutUpdateProfile();
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/provider/CustomIdentityProvider.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/provider/CustomIdentityProvider.java
index f5888fa..058f101 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/provider/CustomIdentityProvider.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/provider/CustomIdentityProvider.java
@@ -20,6 +20,7 @@ import org.keycloak.broker.provider.AbstractIdentityProvider;
import org.keycloak.broker.provider.AuthenticationRequest;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
import javax.ws.rs.core.Response;
@@ -38,7 +39,7 @@ public class CustomIdentityProvider extends AbstractIdentityProvider<IdentityPro
}
@Override
- public Response retrieveToken(FederatedIdentityModel identity) {
+ public Response retrieveToken(KeycloakSession session, FederatedIdentityModel identity) {
return null;
}
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/provider/social/CustomSocialProvider.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/provider/social/CustomSocialProvider.java
index c74a33b..b473be1 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/provider/social/CustomSocialProvider.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/provider/social/CustomSocialProvider.java
@@ -21,6 +21,7 @@ import org.keycloak.broker.provider.AuthenticationRequest;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.broker.social.SocialIdentityProvider;
+import org.keycloak.models.KeycloakSession;
import javax.ws.rs.core.Response;
@@ -39,7 +40,7 @@ public class CustomSocialProvider extends AbstractIdentityProvider<IdentityProvi
}
@Override
- public Response retrieveToken(FederatedIdentityModel identity) {
+ public Response retrieveToken(KeycloakSession session, FederatedIdentityModel identity) {
return null;
}
}