use of org.keycloak.models.KeycloakSession in project keycloak by keycloak.
the class LastSessionRefreshCrossDCTest method testLastSessionRefreshUpdate.
@Test
public void testLastSessionRefreshUpdate(@JmxInfinispanCacheStatistics(dc = DC.FIRST, managementPortProperty = "cache.server.management.port", cacheName = InfinispanConnectionProvider.USER_SESSION_CACHE_NAME) InfinispanStatistics sessionCacheDc1Stats, @JmxInfinispanCacheStatistics(dc = DC.SECOND, managementPortProperty = "cache.server.2.management.port", cacheName = InfinispanConnectionProvider.USER_SESSION_CACHE_NAME) InfinispanStatistics sessionCacheDc2Stats, @JmxInfinispanCacheStatistics(dc = DC.FIRST, managementPortProperty = "cache.server.management.port", cacheName = InfinispanConnectionProvider.CLIENT_SESSION_CACHE_NAME) InfinispanStatistics clientSessionCacheDc1Stats, @JmxInfinispanCacheStatistics(dc = DC.SECOND, managementPortProperty = "cache.server.2.management.port", cacheName = InfinispanConnectionProvider.CLIENT_SESSION_CACHE_NAME) InfinispanStatistics clientSessionCacheDc2Stats) {
// Set the infinispan testTimeService on all started auth servers
setInfinispanTestTimeServiceOnAllStartedAuthServers();
try {
// Ensure to remove all current sessions and offline sessions
setTimeOffset(10000000);
getTestingClientForStartedNodeInDc(0).testing("test").removeExpired("test");
getTestingClientForStartedNodeInDc(1).testing("test").removeExpired("test");
setTimeOffset(0);
sessionCacheDc1Stats.reset();
sessionCacheDc2Stats.reset();
clientSessionCacheDc1Stats.reset();
clientSessionCacheDc2Stats.reset();
// Disable DC2 on loadbalancer
disableDcOnLoadBalancer(DC.SECOND);
// Get statistics
AtomicLong sessionStoresDc1 = new AtomicLong(getStores(sessionCacheDc1Stats));
AtomicLong sessionStoresDc2 = new AtomicLong(getStores(sessionCacheDc2Stats));
AtomicLong clientSessionStoresDc1 = new AtomicLong(getStores(clientSessionCacheDc1Stats));
AtomicLong clientSessionStoresDc2 = new AtomicLong(getStores(clientSessionCacheDc2Stats));
AtomicInteger lsrDc1 = new AtomicInteger(-1);
AtomicInteger lsrDc2 = new AtomicInteger(-1);
// Login
OAuthClient.AuthorizationEndpointResponse response1 = oauth.doLogin("test-user@localhost", "password");
String code = response1.getCode();
OAuthClient.AccessTokenResponse tokenResponse = oauth.doAccessTokenRequest(code, "password");
Assert.assertNotNull(tokenResponse.getAccessToken());
String sessionId = oauth.verifyToken(tokenResponse.getAccessToken()).getSessionState();
String refreshToken1 = tokenResponse.getRefreshToken();
// Assert statistics - sessions created on both DCs and created on remoteCaches too
assertStatistics("After session created", sessionId, sessionCacheDc1Stats, sessionCacheDc2Stats, clientSessionCacheDc1Stats, clientSessionCacheDc2Stats, sessionStoresDc1, sessionStoresDc2, clientSessionStoresDc1, clientSessionStoresDc2, lsrDc1, lsrDc2, true, true, true, false);
// Set time offset
setTimeOffset(100);
// refresh token on DC1
tokenResponse = oauth.doRefreshTokenRequest(refreshToken1, "password");
String refreshToken2 = tokenResponse.getRefreshToken();
Assert.assertNotNull(refreshToken2);
// Assert statistics - sessions updated on both DC1 and DC2. RemoteCaches not updated
assertStatistics("After refresh at time 100", sessionId, sessionCacheDc1Stats, sessionCacheDc2Stats, clientSessionCacheDc1Stats, clientSessionCacheDc2Stats, sessionStoresDc1, sessionStoresDc2, clientSessionStoresDc1, clientSessionStoresDc2, lsrDc1, lsrDc2, true, true, false, false);
// Set time offset
setTimeOffset(110);
// refresh token on DC1
tokenResponse = oauth.doRefreshTokenRequest(refreshToken1, "password");
String refreshToken3 = tokenResponse.getRefreshToken();
Assert.assertNotNull(refreshToken3);
// Assert statistics - sessions updated just on DC1.
// Update of DC2 is postponed (It's just 10 seconds since last message). RemoteCaches not updated
assertStatistics("After refresh at time 110", sessionId, sessionCacheDc1Stats, sessionCacheDc2Stats, clientSessionCacheDc1Stats, clientSessionCacheDc2Stats, sessionStoresDc1, sessionStoresDc2, clientSessionStoresDc1, clientSessionStoresDc2, lsrDc1, lsrDc2, true, false, false, false);
// 31 minutes after "100". Session should be still valid and not yet expired (RefreshToken will be invalid due the expiration on the JWT itself. Hence not testing refresh here)
setTimeOffset(1960);
boolean sessionValid = getTestingClientForStartedNodeInDc(1).server("test").fetch((KeycloakSession session) -> {
RealmModel realm = session.realms().getRealmByName("test");
UserSessionModel userSession = session.sessions().getUserSession(realm, sessionId);
return AuthenticationManager.isSessionValid(realm, userSession);
}, Boolean.class);
Assert.assertTrue(sessionValid);
getTestingClientForStartedNodeInDc(1).testing("test").removeExpired("test");
// Assert statistics - nothing was updated. No refresh happened and nothing was cleared during "removeExpired"
assertStatistics("After checking valid at time 1960", sessionId, sessionCacheDc1Stats, sessionCacheDc2Stats, clientSessionCacheDc1Stats, clientSessionCacheDc2Stats, sessionStoresDc1, sessionStoresDc2, clientSessionStoresDc1, clientSessionStoresDc2, lsrDc1, lsrDc2, false, false, false, false);
// 35 minutes after "100". Session not valid and will be expired by the cleaner
setTimeOffset(2200);
sessionValid = getTestingClientForStartedNodeInDc(1).server("test").fetch((KeycloakSession session) -> {
RealmModel realm = session.realms().getRealmByName("test");
UserSessionModel userSession = session.sessions().getUserSession(realm, sessionId);
return AuthenticationManager.isSessionValid(realm, userSession);
}, Boolean.class);
Assert.assertFalse(sessionValid);
// 2000 seconds after the previous. This should ensure that session would be expired from the cache due the invalid maxIdle.
// Previous read at time 2200 "refreshed" the maxIdle in the infinispan cache. This shouldn't happen in reality as an attempt to call refreshToken request on invalid session does backchannelLogout
setTimeOffset(4200);
getTestingClientForStartedNodeInDc(1).testing("test").removeExpired("test");
// Session should be removed on both DCs
try {
getTestingClientForStartedNodeInDc(0).testing("test").getLastSessionRefresh("test", sessionId, false);
Assert.fail("It wasn't expected to find the session " + sessionId);
} catch (NotFoundException nfe) {
// Expected
}
try {
getTestingClientForStartedNodeInDc(1).testing("test").getLastSessionRefresh("test", sessionId, false);
Assert.fail("It wasn't expected to find the session " + sessionId);
} catch (NotFoundException nfe) {
// Expected
}
} finally {
// Revert time service
revertInfinispanTestTimeServiceOnAllStartedAuthServers();
}
}
use of org.keycloak.models.KeycloakSession in project keycloak by keycloak.
the class JpaRealmProvider method removeClient.
@Override
public boolean removeClient(RealmModel realm, String id) {
logger.tracef("removeClient(%s, %s)%s", realm, id, getShortStackTrace());
final ClientModel client = getClientById(realm, id);
if (client == null)
return false;
session.users().preRemove(realm, client);
session.roles().removeRoles(client);
ClientEntity clientEntity = em.find(ClientEntity.class, id, LockModeType.PESSIMISTIC_WRITE);
session.getKeycloakSessionFactory().publish(new ClientModel.ClientRemovedEvent() {
@Override
public ClientModel getClient() {
return client;
}
@Override
public KeycloakSession getKeycloakSession() {
return session;
}
});
int countRemoved = em.createNamedQuery("deleteClientScopeClientMappingByClient").setParameter("clientId", clientEntity.getId()).executeUpdate();
// i have no idea why, but this needs to come before deleteScopeMapping
em.remove(clientEntity);
try {
em.flush();
} catch (RuntimeException e) {
logger.errorv("Unable to delete client entity: {0} from realm {1}", client.getClientId(), realm.getName());
throw e;
}
return true;
}
use of org.keycloak.models.KeycloakSession in project keycloak by keycloak.
the class RegistrationUserCreation method success.
@Override
public void success(FormContext context) {
MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
String email = formData.getFirst(UserModel.EMAIL);
String username = formData.getFirst(UserModel.USERNAME);
if (context.getRealm().isRegistrationEmailAsUsername()) {
username = email;
}
context.getEvent().detail(Details.USERNAME, username).detail(Details.REGISTER_METHOD, "form").detail(Details.EMAIL, email);
KeycloakSession session = context.getSession();
UserProfileProvider profileProvider = session.getProvider(UserProfileProvider.class);
UserProfile profile = profileProvider.create(UserProfileContext.REGISTRATION_USER_CREATION, formData);
UserModel user = profile.create();
user.setEnabled(true);
context.setUser(user);
context.getAuthenticationSession().setClientNote(OIDCLoginProtocol.LOGIN_HINT_PARAM, username);
context.getEvent().user(user);
context.getEvent().success();
context.newEvent().event(EventType.LOGIN);
context.getEvent().client(context.getAuthenticationSession().getClient().getClientId()).detail(Details.REDIRECT_URI, context.getAuthenticationSession().getRedirectUri()).detail(Details.AUTH_METHOD, context.getAuthenticationSession().getProtocol());
String authType = context.getAuthenticationSession().getAuthNote(Details.AUTH_TYPE);
if (authType != null) {
context.getEvent().detail(Details.AUTH_TYPE, authType);
}
}
use of org.keycloak.models.KeycloakSession in project keycloak by keycloak.
the class RegistrationUserCreation method validate.
@Override
public void validate(ValidationContext context) {
MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
context.getEvent().detail(Details.REGISTER_METHOD, "form");
KeycloakSession session = context.getSession();
UserProfileProvider profileProvider = session.getProvider(UserProfileProvider.class);
UserProfile profile = profileProvider.create(UserProfileContext.REGISTRATION_USER_CREATION, formData);
String email = profile.getAttributes().getFirstValue(UserModel.EMAIL);
String username = profile.getAttributes().getFirstValue(UserModel.USERNAME);
String firstName = profile.getAttributes().getFirstValue(UserModel.FIRST_NAME);
String lastName = profile.getAttributes().getFirstValue(UserModel.LAST_NAME);
context.getEvent().detail(Details.EMAIL, email);
context.getEvent().detail(Details.USERNAME, username);
context.getEvent().detail(Details.FIRST_NAME, firstName);
context.getEvent().detail(Details.LAST_NAME, lastName);
if (context.getRealm().isRegistrationEmailAsUsername()) {
context.getEvent().detail(Details.USERNAME, email);
}
try {
profile.validate();
} catch (ValidationException pve) {
List<FormMessage> errors = Validation.getFormErrorsFromValidation(pve.getErrors());
if (pve.hasError(Messages.EMAIL_EXISTS)) {
context.error(Errors.EMAIL_IN_USE);
} else if (pve.hasError(Messages.MISSING_EMAIL, Messages.MISSING_USERNAME, Messages.INVALID_EMAIL)) {
context.error(Errors.INVALID_REGISTRATION);
} else if (pve.hasError(Messages.USERNAME_EXISTS)) {
context.error(Errors.USERNAME_IN_USE);
}
context.validationError(formData, errors);
return;
}
context.success();
}
use of org.keycloak.models.KeycloakSession in project keycloak by keycloak.
the class DeclarativeUserProfileProvider method requestedScopePredicate.
/**
* Method used for predicate which returns true if any of the configuredScopes is requested in current auth flow.
*
* @param context to get current auth flow from
* @param configuredScopes to be evaluated
* @return
*/
private static boolean requestedScopePredicate(AttributeContext context, Set<String> configuredScopes) {
KeycloakSession session = context.getSession();
AuthenticationSessionModel authenticationSession = session.getContext().getAuthenticationSession();
if (authenticationSession == null) {
return false;
}
String requestedScopesString = authenticationSession.getClientNote(OIDCLoginProtocol.SCOPE_PARAM);
ClientModel client = authenticationSession.getClient();
return getRequestedClientScopes(requestedScopesString, client).map((csm) -> csm.getName()).anyMatch(configuredScopes::contains);
}
Aggregations