KEYCLOAK-2691
This commit is contained in:
1 parent
811085f9bd
commit
239816f4f5
13 files changed
+168
-66
No files matched your search
@@ -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) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -73,15 +73,15 @@ public interface IdentityProvider<C extends IdentityProviderModel> extends Provi
|
||||
Response performLogin(AuthenticationRequest request);
|
||||
|
||||
/**
|
||||
* <p>Returns a {@link javax.ws.rs.core.Response} containing the token previously stored during the authentication process for a
|
||||
* <p>Returns a {@link Response} containing the token previously stored during the authentication process for a
|
||||
* specific user.</p>
|
||||
*
|
||||
* @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
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -19,14 +19,13 @@ package org.keycloak.broker.oidc;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.common.ClientConnection;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.broker.provider.util.SimpleHttp;
|
||||
import org.keycloak.broker.provider.AbstractIdentityProvider;
|
||||
import org.keycloak.broker.provider.AuthenticationRequest;
|
||||
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||
import org.keycloak.broker.provider.IdentityBrokerException;
|
||||
import org.keycloak.truststore.JSSETruststoreConfigurator;
|
||||
import org.keycloak.broker.provider.util.SimpleHttp;
|
||||
import org.keycloak.common.ClientConnection;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.EventType;
|
||||
@@ -35,6 +34,7 @@ import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.services.ErrorPage;
|
||||
import org.keycloak.services.messages.Messages;
|
||||
import org.keycloak.truststore.JSSETruststoreConfigurator;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.QueryParam;
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -20,10 +20,12 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.broker.oidc.mappers.AbstractJsonUserAttributeMapper;
|
||||
import org.keycloak.broker.oidc.util.JsonSimpleHttp;
|
||||
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.broker.provider.util.SimpleHttp;
|
||||
import org.keycloak.common.util.PemUtils;
|
||||
import org.keycloak.common.util.Time;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.EventType;
|
||||
@@ -31,6 +33,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,8 +44,8 @@ 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;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
@@ -51,7 +54,6 @@ 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.security.PublicKey;
|
||||
|
||||
@@ -130,9 +132,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 +158,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 +179,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 +365,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());
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -18,21 +18,31 @@ package org.keycloak.services.managers;
|
||||
|
||||
import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
|
||||
import org.jboss.resteasy.spi.HttpRequest;
|
||||
import org.keycloak.common.ClientConnection;
|
||||
import org.keycloak.RSATokenVerifier;
|
||||
import org.keycloak.common.VerificationException;
|
||||
import org.keycloak.authentication.RequiredActionContext;
|
||||
import org.keycloak.authentication.RequiredActionContextResult;
|
||||
import org.keycloak.authentication.RequiredActionFactory;
|
||||
import org.keycloak.authentication.RequiredActionProvider;
|
||||
import org.keycloak.broker.provider.IdentityProvider;
|
||||
import org.keycloak.common.ClientConnection;
|
||||
import org.keycloak.common.VerificationException;
|
||||
import org.keycloak.common.util.Time;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.jose.jws.JWSBuilder;
|
||||
import org.keycloak.forms.login.LoginFormsProvider;
|
||||
import org.keycloak.models.*;
|
||||
import org.keycloak.jose.jws.JWSBuilder;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.ClientSessionModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RequiredActionProviderModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserConsentModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.protocol.LoginProtocol;
|
||||
import org.keycloak.protocol.LoginProtocol.Error;
|
||||
@@ -44,9 +54,13 @@ import org.keycloak.services.messages.Messages;
|
||||
import org.keycloak.services.resources.IdentityBrokerService;
|
||||
import org.keycloak.services.resources.RealmsResource;
|
||||
import org.keycloak.services.util.CookieHelper;
|
||||
import org.keycloak.common.util.Time;
|
||||
|
||||
import javax.ws.rs.core.*;
|
||||
import javax.ws.rs.core.Cookie;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
import javax.ws.rs.core.NewCookie;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.net.URI;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -125,7 +139,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 +235,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);
|
||||
@@ -363,9 +377,9 @@ public class AuthenticationManager {
|
||||
|
||||
|
||||
public static Response redirectAfterSuccessfulFlow(KeycloakSession session, RealmModel realm, UserSessionModel userSession,
|
||||
ClientSessionModel clientSession,
|
||||
HttpRequest request, UriInfo uriInfo, ClientConnection clientConnection,
|
||||
EventBuilder event) {
|
||||
ClientSessionModel clientSession,
|
||||
HttpRequest request, UriInfo uriInfo, ClientConnection clientConnection,
|
||||
EventBuilder event) {
|
||||
LoginProtocol protocol = session.getProvider(LoginProtocol.class, clientSession.getAuthMethod());
|
||||
protocol.setRealm(realm)
|
||||
.setHttpHeaders(request.getHttpHeaders())
|
||||
@@ -406,8 +420,8 @@ public class AuthenticationManager {
|
||||
|
||||
}
|
||||
public static Response nextActionAfterAuthentication(KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession,
|
||||
ClientConnection clientConnection,
|
||||
HttpRequest request, UriInfo uriInfo, EventBuilder event) {
|
||||
ClientConnection clientConnection,
|
||||
HttpRequest request, UriInfo uriInfo, EventBuilder event) {
|
||||
Response requiredAction = actionRequired(session, userSession, clientSession, clientConnection, request, uriInfo, event);
|
||||
if (requiredAction != null) return requiredAction;
|
||||
return finishedRequiredActions(session, userSession, clientSession, clientConnection, request, uriInfo, event);
|
||||
@@ -472,8 +486,8 @@ public class AuthenticationManager {
|
||||
|
||||
|
||||
public static Response actionRequired(final KeycloakSession session, final UserSessionModel userSession, final ClientSessionModel clientSession,
|
||||
final ClientConnection clientConnection,
|
||||
final HttpRequest request, final UriInfo uriInfo, final EventBuilder event) {
|
||||
final ClientConnection clientConnection,
|
||||
final HttpRequest request, final UriInfo uriInfo, final EventBuilder event) {
|
||||
final RealmModel realm = clientSession.getRealm();
|
||||
final UserModel user = userSession.getUser();
|
||||
final ClientModel client = clientSession.getClient();
|
||||
|
||||
@@ -16,21 +16,22 @@
|
||||
*/
|
||||
package org.keycloak.services.resources;
|
||||
|
||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.jboss.resteasy.spi.HttpRequest;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.authentication.AuthenticationProcessor;
|
||||
import org.keycloak.authentication.authenticators.broker.AbstractIdpAuthenticator;
|
||||
import org.keycloak.authentication.authenticators.broker.util.PostBrokerLoginConstants;
|
||||
import org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext;
|
||||
import org.keycloak.common.ClientConnection;
|
||||
import org.keycloak.authentication.AuthenticationProcessor;
|
||||
import org.keycloak.broker.provider.AuthenticationRequest;
|
||||
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||
import org.keycloak.broker.provider.IdentityBrokerException;
|
||||
import org.keycloak.broker.provider.IdentityProvider;
|
||||
import org.keycloak.broker.provider.IdentityProviderFactory;
|
||||
import org.keycloak.broker.provider.IdentityProviderMapper;
|
||||
import org.keycloak.broker.social.SocialIdentityProvider;
|
||||
import org.keycloak.common.ClientConnection;
|
||||
import org.keycloak.common.util.ObjectUtil;
|
||||
import org.keycloak.common.util.Time;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
@@ -53,28 +54,30 @@ import org.keycloak.models.utils.FormMessage;
|
||||
import org.keycloak.protocol.oidc.TokenManager;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.services.ErrorPage;
|
||||
import org.keycloak.services.ErrorResponse;
|
||||
import org.keycloak.services.ServicesLogger;
|
||||
import org.keycloak.services.Urls;
|
||||
import org.keycloak.services.managers.AppAuthManager;
|
||||
import org.keycloak.services.managers.AuthenticationManager.AuthResult;
|
||||
import org.keycloak.services.managers.ClientSessionCode;
|
||||
import org.keycloak.services.messages.Messages;
|
||||
import org.keycloak.services.ErrorResponse;
|
||||
import org.keycloak.services.ErrorPage;
|
||||
import org.keycloak.services.ServicesLogger;
|
||||
import org.keycloak.services.Urls;
|
||||
import org.keycloak.services.util.CacheControlUtil;
|
||||
import org.keycloak.services.validation.Validation;
|
||||
import org.keycloak.broker.social.SocialIdentityProvider;
|
||||
import org.keycloak.common.util.ObjectUtil;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.OPTIONS;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
@@ -227,7 +230,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);
|
||||
|
||||
@@ -17,12 +17,13 @@
|
||||
package org.keycloak.social.twitter;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.common.ClientConnection;
|
||||
import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
|
||||
import org.keycloak.broker.provider.AbstractIdentityProvider;
|
||||
import org.keycloak.broker.provider.AuthenticationRequest;
|
||||
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||
import org.keycloak.broker.provider.IdentityBrokerException;
|
||||
import org.keycloak.broker.social.SocialIdentityProvider;
|
||||
import org.keycloak.common.ClientConnection;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.models.ClientModel;
|
||||
@@ -30,10 +31,9 @@ import org.keycloak.models.ClientSessionModel;
|
||||
import org.keycloak.models.FederatedIdentityModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.services.ErrorPage;
|
||||
import org.keycloak.services.managers.ClientSessionCode;
|
||||
import org.keycloak.services.messages.Messages;
|
||||
import org.keycloak.services.ErrorPage;
|
||||
import org.keycloak.broker.social.SocialIdentityProvider;
|
||||
import twitter4j.Twitter;
|
||||
import twitter4j.TwitterFactory;
|
||||
import twitter4j.auth.AccessToken;
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
+20
-7
@@ -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;
|
||||
@@ -54,17 +55,12 @@ import javax.mail.MessagingException;
|
||||
import javax.mail.Multipart;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author pedroigor
|
||||
@@ -115,6 +111,8 @@ public abstract class AbstractIdentityProviderTest {
|
||||
|
||||
protected KeycloakSession session;
|
||||
|
||||
protected int logoutTimeOffset = 0;
|
||||
|
||||
@Before
|
||||
public void onBefore() {
|
||||
this.session = brokerServerRule.startSession();
|
||||
@@ -160,11 +158,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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+25
-3
@@ -19,23 +19,25 @@ package org.keycloak.testsuite.broker;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.Keycloak;
|
||||
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;
|
||||
import org.keycloak.testsuite.KeycloakServer;
|
||||
import org.keycloak.testsuite.pages.AccountApplicationsPage;
|
||||
import org.keycloak.testsuite.pages.OAuthGrantPage;
|
||||
import org.keycloak.testsuite.rule.AbstractKeycloakRule;
|
||||
import org.keycloak.testsuite.rule.WebResource;
|
||||
import org.keycloak.testsuite.KeycloakServer;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
import org.openqa.selenium.NoSuchElementException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.fail;
|
||||
@@ -117,6 +119,26 @@ public class OIDCKeyCloakServerBrokerBasicTest extends AbstractKeycloakIdentityP
|
||||
super.testSuccessfulAuthentication();
|
||||
}
|
||||
|
||||
@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();
|
||||
|
||||
+2
-1
@@ -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;
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -18,9 +18,10 @@ package org.keycloak.testsuite.broker.provider.social;
|
||||
|
||||
import org.keycloak.broker.provider.AbstractIdentityProvider;
|
||||
import org.keycloak.broker.provider.AuthenticationRequest;
|
||||
import org.keycloak.broker.social.SocialIdentityProvider;
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user