public void run() { final ArrayList<LoginEvent> events = new ArrayList<LoginEvent>(TRANSACTION_SIZE + 1); while (run) { try { LoginEvent take = queue.poll(2, TimeUnit.SECONDS); if (take == null) { continue; } try { events.add(take); queue.drainTo(events, TRANSACTION_SIZE); for (LoginEvent event : events) { if (event instanceof FailedLogin) { logFailure(event); } else { logSuccess(event); } } Collections.sort( events); // we sort to avoid deadlock due to ordered updates. Maybe I'm overthinking // this. KeycloakSession session = factory.createSession(); try { for (LoginEvent event : events) { if (event instanceof FailedLogin) { failure(session, event); } } session.getTransaction().commit(); } catch (Exception e) { session.getTransaction().rollback(); throw e; } finally { for (LoginEvent event : events) { if (event instanceof FailedLogin) { ((FailedLogin) event).latch.countDown(); } } events.clear(); session.close(); } } catch (Exception e) { logger.error("Failed processing event", e); } } catch (InterruptedException e) { break; } finally { shutdownLatch.countDown(); } } }
public void transformIDToken( KeycloakSession session, IDToken token, RealmModel realm, ClientModel client, UserModel user, UserSessionModel userSession, ClientSessionModel clientSession) { Set<ProtocolMapperModel> mappings = new ClientSessionCode(realm, clientSession).getRequestedProtocolMappers(); KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); for (ProtocolMapperModel mapping : mappings) { ProtocolMapper mapper = (ProtocolMapper) sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper()); if (mapper == null || !(mapper instanceof OIDCIDTokenMapper)) continue; token = ((OIDCIDTokenMapper) mapper) .transformIDToken(token, mapping, session, userSession, clientSession); } }
@Override public void postInit(KeycloakSessionFactory factory) { factory.register( event -> { if (event instanceof ClientRemovedEvent) { KeycloakSession keycloakSession = ((ClientRemovedEvent) event).getKeycloakSession(); AuthorizationProvider provider = keycloakSession.getProvider(AuthorizationProvider.class); PolicyStore policyStore = provider.getStoreFactory().getPolicyStore(); ClientModel removedClient = ((ClientRemovedEvent) event).getClient(); policyStore .findByType(getId()) .forEach( policy -> { List<String> clients = new ArrayList<>(); for (String clientId : getClients(policy)) { if (!clientId.equals(removedClient.getId())) { clients.add(clientId); } } try { if (clients.isEmpty()) { policyStore .findDependentPolicies(policy.getId()) .forEach( dependentPolicy -> { dependentPolicy.removeAssociatedPolicy(policy); }); policyStore.delete(policy.getId()); } else { policy .getConfig() .put("clients", JsonSerialization.writeValueAsString(clients)); } } catch (IOException e) { throw new RuntimeException( "Error while synchronizing clients with policy [" + policy.getName() + "].", e); } }); } }); }
@Override public void postInit(final KeycloakSessionFactory factory) { // Max count of worker errors. Initialization will end with exception when this number is // reached final int maxErrors = config.getInt("maxErrors", 20); // Count of sessions to be computed in each segment final int sessionsPerSegment = config.getInt("sessionsPerSegment", 100); factory.register( new ProviderEventListener() { @Override public void onEvent(ProviderEvent event) { if (event instanceof PostMigrationEvent) { loadPersistentSessions(factory, maxErrors, sessionsPerSegment); } } }); }