mirror of
https://github.com/keycloak/keycloak.git
synced 2026-02-03 20:39:33 -05:00
Merge 26dcfe21ef into 047230a052
This commit is contained in:
commit
d6bf8ec43a
3 changed files with 117 additions and 8 deletions
|
|
@ -29,12 +29,20 @@ public class DefaultAlternativeLookupProvider implements AlternativeLookupProvid
|
|||
}
|
||||
}
|
||||
|
||||
IdentityProviderModel idp = session.identityProviders().getAllStream(IdentityProviderQuery.any())
|
||||
List<IdentityProviderModel> idps = session.identityProviders().getAllStream(IdentityProviderQuery.any())
|
||||
.filter(i -> issuerUrl.equals(i.getConfig().get(IdentityProviderModel.ISSUER)))
|
||||
.findFirst().orElse(null);
|
||||
if (idp != null && idp.getAlias() != null) {
|
||||
lookupCache.put(alternativeKey, idp.getAlias());
|
||||
.limit(2)
|
||||
.toList();
|
||||
IdentityProviderModel idp = null;
|
||||
if (idps.size() == 1) {
|
||||
idp = idps.get(0);
|
||||
if (idp.getAlias() != null) {
|
||||
lookupCache.put(alternativeKey, idp.getAlias());
|
||||
}
|
||||
} else if (idps.size() > 1) {
|
||||
throw new RuntimeException("Multiple IDPs match the same issuer: " + idps.stream().map(IdentityProviderModel::getAlias).toList());
|
||||
}
|
||||
|
||||
return idp;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,21 +48,44 @@ public class FederatedClientAuthConflictsTest {
|
|||
createIdp("idp1", "http://127.0.0.1:8500");
|
||||
createIdp("idp2", "http://127.0.0.1:8500");
|
||||
|
||||
createClient("myclient", "external1", "idp1");
|
||||
|
||||
// Should fail as there are two IdPs with the same issuer URL
|
||||
AccessTokenResponse response = oAuthClient.clientCredentialsGrantRequest().clientJwt(createDefaultToken("external1", "http://127.0.0.1:8500")).send();
|
||||
Assertions.assertFalse(response.isSuccess());
|
||||
Assertions.assertEquals("Invalid client or Invalid client credentials", response.getErrorDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangedIssuer() {
|
||||
IdentityProviderRepresentation idp1 = createIdp("idp1", "http://127.0.0.1:8500");
|
||||
|
||||
ClientRepresentation clientRep = createClient("myclient", "external1", "idp1");
|
||||
|
||||
// Should pass as the first matching IdP by alias is always used
|
||||
// Should fail as there are two IdPs with the same issuer URL
|
||||
AccessTokenResponse response = oAuthClient.clientCredentialsGrantRequest().clientJwt(createDefaultToken("external1", "http://127.0.0.1:8500")).send();
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("myclient", events.poll().getClientId());
|
||||
|
||||
clientRep.getAttributes().put(FederatedJWTClientAuthenticator.JWT_CREDENTIAL_ISSUER_KEY, "idp2");
|
||||
createIdp("idp2", "http://127.0.0.1:8500");
|
||||
|
||||
clientRep.getAttributes().put(FederatedJWTClientAuthenticator.JWT_CREDENTIAL_ISSUER_KEY, "idp2");
|
||||
realm.admin().clients().get(clientRep.getId()).update(clientRep);
|
||||
|
||||
// Should fail since it's using the second IdP
|
||||
// Should fail since the old entry is still cached
|
||||
response = oAuthClient.clientCredentialsGrantRequest().clientJwt(createDefaultToken("external1", "http://127.0.0.1:8500")).send();
|
||||
Assertions.assertFalse(response.isSuccess());
|
||||
Assertions.assertNull(events.poll().getClientId());
|
||||
Assertions.assertEquals("Invalid client or Invalid client credentials", response.getErrorDescription());
|
||||
|
||||
// Update old entry, so next read will invalidate it
|
||||
idp1.getConfig().put(IdentityProviderModel.ISSUER, "http://127.0.0.1:8501");
|
||||
realm.admin().identityProviders().get(idp1.getAlias()).update(idp1);
|
||||
|
||||
// Should succeed as entry is updated in the cache
|
||||
events.clear();
|
||||
response = oAuthClient.clientCredentialsGrantRequest().clientJwt(createDefaultToken("external1", "http://127.0.0.1:8500")).send();
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("myclient", events.poll().getClientId());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright 2026 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.tests.model;
|
||||
|
||||
import org.keycloak.cache.AlternativeLookupProvider;
|
||||
import org.keycloak.models.IdentityProviderModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.testframework.annotations.InjectRealm;
|
||||
import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
|
||||
import org.keycloak.testframework.realm.ManagedRealm;
|
||||
import org.keycloak.testframework.remote.annotations.TestOnServer;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
|
||||
@KeycloakIntegrationTest
|
||||
public class AlternativeLookupProviderTest {
|
||||
|
||||
@InjectRealm(attachTo = "master")
|
||||
ManagedRealm realm;
|
||||
|
||||
@TestOnServer
|
||||
public void testDuplicateIssuerFoundInDatabase(KeycloakSession session) {
|
||||
try {
|
||||
IdentityProviderModel idp = createModel("kubernetes1", "kubernetes");
|
||||
idp.getConfig().put("issuer", "https://localhost");
|
||||
session.identityProviders().create(idp);
|
||||
|
||||
idp = createModel("kubernetes2", "kubernetes");
|
||||
idp.getConfig().put("issuer", "https://localhost");
|
||||
session.identityProviders().create(idp);
|
||||
|
||||
RuntimeException ex = Assertions.assertThrows(RuntimeException.class, () ->
|
||||
session.getProvider(AlternativeLookupProvider.class).lookupIdentityProviderFromIssuer(session, "https://localhost")
|
||||
);
|
||||
Assertions.assertEquals("Multiple IDPs match the same issuer: [kubernetes1, kubernetes2]", ex.getMessage());
|
||||
|
||||
} finally {
|
||||
session.identityProviders().remove("kubernetes1");
|
||||
session.identityProviders().remove("kubernetes2");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected IdentityProviderModel createModel(String alias, String providerId) {
|
||||
return createModel(alias, providerId,true);
|
||||
}
|
||||
|
||||
protected IdentityProviderModel createModel(String alias, String providerId, boolean enabled) {
|
||||
return createModel(alias, alias, providerId, enabled);
|
||||
}
|
||||
|
||||
protected IdentityProviderModel createModel(String alias, String displayName, String providerId, boolean enabled) {
|
||||
IdentityProviderModel idp = new IdentityProviderModel();
|
||||
|
||||
idp.setAlias(alias);
|
||||
idp.setDisplayName(displayName);
|
||||
idp.setProviderId(providerId);
|
||||
idp.setEnabled(enabled);
|
||||
return idp;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Loading…
Reference in a new issue