Skip to content

Add cache for IdentityProviderStorageProvider.getForLogin - #1

Open
linxia0415 wants to merge 2 commits into
mainfrom
pr-32918
Open

Add cache for IdentityProviderStorageProvider.getForLogin#1
linxia0415 wants to merge 2 commits into
mainfrom
pr-32918

Conversation

@linxia0415

@linxia0415 linxia0415 commented Jun 3, 2026

Copy link
Copy Markdown

Closes #32573

Summary by CodeRabbit

  • New Features

    • Improved identity provider filtering during login to respect organization-specific linkage and public broker settings.
  • Performance

    • Enhanced caching mechanism for identity provider lookups to improve authentication performance.
  • Bug Fixes

    • Fixed identity provider enabled status validation in organization-aware login flows.
  • Chores

    • Removed legacy dependency configuration.

sguilhen and others added 2 commits September 16, 2024 14:34
Closes #32573

Signed-off-by: Stefan Guilhen <sguilhen@redhat.com>
@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR implements login-specific caching for identity providers with organization-aware predicate filtering. It extends the Infinispan storage provider with dedicated login cache keys and query methods, restricts login-eligible IDPs based on organization and public broker configuration, and validates caching behavior through a comprehensive integration test.

Changes

Login IDP Caching and Organization Scoping

Layer / File(s) Summary
Login predicate contract with organization and public broker gating
server-spi/src/main/java/org/keycloak/models/IdentityProviderStorageProvider.java
LoginFilter.getLoginPredicate() now gates login-eligible IDPs by organization membership: realm-level IDPs or those marked public via OrganizationModel.BROKER_PUBLIC config are login-eligible.
Infinispan login cache implementation with key building and invalidation
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/idp/InfinispanIdentityProviderStorageProvider.java
Adds login cache key builder, getForLogin(FetchMode, organizationId) query method with revisioned caching and session-miss invalidation, and lifecycle hooks that register login-cache invalidations conditional on login-qualification changes.
Login form filtering with enabled IDP check
services/src/main/java/org/keycloak/organization/forms/login/freemarker/model/OrganizationAwareIdentityProviderBean.java
searchForIdentityProviders adds idp.isEnabled() filter in public-org-linked and all-brokers branches to exclude disabled IDPs from login form results.
Integration test for login cache behavior and invalidation
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/cache/OrganizationCacheTest.java
Test testCacheIDPForLogin validates login cache population, non-invalidation when login-qualification is unchanged, invalidation when login availability changes, and cache repopulation after org linking.

Sequence Diagram

sequenceDiagram
  participant Caller
  participant getForLogin
  participant Cache
  participant Delegate
  participant InvalidationHelper
  
  Caller->>getForLogin: getForLogin(FetchMode, organizationId)
  getForLogin->>Cache: Check revisioned cache key
  alt Cache Hit
    Cache-->>getForLogin: Return cached IDPs
  else Cache Miss
    getForLogin->>Delegate: getForLogin(FetchMode, organizationId)
    Delegate-->>getForLogin: Stream of IDPs
    getForLogin->>Cache: Store revisioned results
    getForLogin->>InvalidationHelper: Check for missing IDPs
    alt IDP Missing
      InvalidationHelper->>Cache: Invalidate login caches
    end
  end
  getForLogin-->>Caller: Return IDPs
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 A login cache springs forth with care,
Organization walls hold IDPs fair,
Predicates parse who may roam the form,
Tests validate the caching norm,
Infinispan hops with revisioned cheer!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main change: adding caching functionality for the getForLogin method in IdentityProviderStorageProvider.
Description check ✅ Passed The description references the closed issue (#32573) and includes the repository's template note, providing basic context for the changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch pr-32918

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/cache/OrganizationCacheTest.java`:
- Around line 380-382: The cleanup callback is using the hardcoded string
"alias" instead of the actual Identity Provider alias; update the cleanup
registration to reference the real alias (e.g., use the variable holding the
alias or call idpRep.getAlias()) when calling
testRealm().identityProviders().get(... )::remove so the created IDP is
correctly removed; ensure you apply the same change to both occurrences around
the test (lines referencing get("alias") that follow
identityProviders().create(idpRep) and similar blocks).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6dc46167-2a12-4c74-8926-56774ba84b1e

📥 Commits

Reviewing files that changed from the base of the PR and between d2b4c19 and 14ea805.

📒 Files selected for processing (5)
  • .github/dependabot.yml
  • model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/idp/InfinispanIdentityProviderStorageProvider.java
  • server-spi/src/main/java/org/keycloak/models/IdentityProviderStorageProvider.java
  • services/src/main/java/org/keycloak/organization/forms/login/freemarker/model/OrganizationAwareIdentityProviderBean.java
  • testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/cache/OrganizationCacheTest.java
💤 Files with no reviewable changes (1)
  • .github/dependabot.yml

Comment on lines +380 to +382
testRealm().identityProviders().create(idpRep).close();
getCleanup().addCleanup(testRealm().identityProviders().get("alias")::remove);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Cleanup registration uses hardcoded literal "alias" instead of actual IDP alias.

The cleanup callbacks reference testRealm().identityProviders().get("alias") but "alias" is a string literal, not the variable. This won't properly clean up the created IDPs after the test.

Proposed fix
         for (int i = 0; i < 20; i++) {
             IdentityProviderRepresentation idpRep = new IdentityProviderRepresentation();
-            idpRep.setAlias("idp-alias-" + i);
+            String alias = "idp-alias-" + i;
+            idpRep.setAlias(alias);
             idpRep.setEnabled((i % 2) == 0); // half of the IDPs will be disabled and won't qualify for login.
             idpRep.setDisplayName("Broker " + i);
             idpRep.setProviderId("keycloak-oidc");
             if (i >= 10)
                 idpRep.getConfig().put(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString());
             testRealm().identityProviders().create(idpRep).close();
-            getCleanup().addCleanup(testRealm().identityProviders().get("alias")::remove);
+            getCleanup().addCleanup(testRealm().identityProviders().get(alias)::remove);
         }

And similarly for line 425:

         testRealm().identityProviders().create(idpRep).close();
-        getCleanup().addCleanup(testRealm().identityProviders().get("alias")::remove);
+        getCleanup().addCleanup(testRealm().identityProviders().get("idp-alias-20")::remove);

Also applies to: 424-426

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/cache/OrganizationCacheTest.java`
around lines 380 - 382, The cleanup callback is using the hardcoded string
"alias" instead of the actual Identity Provider alias; update the cleanup
registration to reference the real alias (e.g., use the variable holding the
alias or call idpRep.getAlias()) when calling
testRealm().identityProviders().get(... )::remove so the created IDP is
correctly removed; ensure you apply the same change to both occurrences around
the test (lines referencing get("alias") that follow
identityProviders().create(idpRep) and similar blocks).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants