From 56f9aa41d07bcb08696d0966f75b9ca5a0edfccd Mon Sep 17 00:00:00 2001 From: Bill Burke Date: Wed, 14 Dec 2016 15:04:53 -0500 Subject: [PATCH] KEYCLOAK-3451 --- .../browser/SpnegoAuthenticator.java | 5 ++ .../UserCredentialStoreManager.java | 2 +- .../federation/KerberosStandaloneTest.java | 56 +++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/browser/SpnegoAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/browser/SpnegoAuthenticator.java index b7a8b6263b..8bfb995316 100755 --- a/services/src/main/java/org/keycloak/authentication/authenticators/browser/SpnegoAuthenticator.java +++ b/services/src/main/java/org/keycloak/authentication/authenticators/browser/SpnegoAuthenticator.java @@ -89,6 +89,11 @@ public class SpnegoAuthenticator extends AbstractUsernameFormAuthenticator imple CredentialValidationOutput output = context.getSession().userCredentialManager().authenticate(context.getSession(), context.getRealm(), spnegoCredential); + if (output == null) { + logger.warn("Received kerberos token, but there is no user storage provider that handles kerberos credentials."); + context.attempted(); + return; + } if (output.getAuthStatus() == CredentialValidationOutput.Status.AUTHENTICATED) { context.setUser(output.getAuthenticatedUser()); if (output.getState() != null && !output.getState().isEmpty()) { diff --git a/services/src/main/java/org/keycloak/credential/UserCredentialStoreManager.java b/services/src/main/java/org/keycloak/credential/UserCredentialStoreManager.java index 0fabb1fe21..4e2b52a3cf 100644 --- a/services/src/main/java/org/keycloak/credential/UserCredentialStoreManager.java +++ b/services/src/main/java/org/keycloak/credential/UserCredentialStoreManager.java @@ -146,7 +146,7 @@ public class UserCredentialStoreManager implements UserCredentialManager, OnUser protected List getCredentialProviders(RealmModel realm, Class type) { List list = new LinkedList(); for (ProviderFactory f : session.getKeycloakSessionFactory().getProviderFactories(CredentialProvider.class)) { - if (!Types.supports(CredentialInputUpdater.class, f, CredentialProviderFactory.class)) continue; + if (!Types.supports(type, f, CredentialProviderFactory.class)) continue; list.add((T)session.getProvider(CredentialProvider.class, f.getId())); } return list; diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/KerberosStandaloneTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/KerberosStandaloneTest.java index aeb58b20fb..af4fd225d2 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/KerberosStandaloneTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/KerberosStandaloneTest.java @@ -25,6 +25,7 @@ import org.junit.Test; import org.junit.rules.RuleChain; import org.junit.rules.TestRule; import org.junit.runners.MethodSorters; +import org.keycloak.authentication.authenticators.browser.SpnegoAuthenticator; import org.keycloak.common.constants.KerberosConstants; import org.keycloak.common.util.MultivaluedHashMap; import org.keycloak.federation.kerberos.CommonKerberosConfig; @@ -45,6 +46,8 @@ import org.keycloak.utils.CredentialHelper; import javax.ws.rs.core.Response; import java.net.URL; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Test of KerberosFederationProvider (Kerberos not backed by LDAP) @@ -189,5 +192,58 @@ public class KerberosStandaloneTest extends AbstractKerberosTest { } } + /** + * KEYCLOAK-3451 + * + * Test that if there is no User Storage Provider that can handle kerberos we can still login + * + * @throws Exception + */ + @Test + public void noProvider() throws Exception { + KeycloakSession session = keycloakRule.startSession(); + try { + RealmModel realm = session.realms().getRealm("test"); + realm.removeComponent(kerberosModel); + } finally { + keycloakRule.stopSession(session, true); + } + /* + To do this we do a valid kerberos login. The authenticator will obtain a valid token, but there will + be no user storage provider that can process it. This means we should be on the login page. + We do this through a JAX-RS client request. We extract the action URL from the login page, and stuff it + into selenium then just perform a regular login. + */ + Response spnegoResponse = spnegoLogin("hnelson", "secret"); + String context = spnegoResponse.readEntity(String.class); + spnegoResponse.close(); + Pattern pattern = Pattern.compile("action=\"([^\"]+)\""); + Matcher m = pattern.matcher(context); + Assert.assertTrue(m.find()); + String url = m.group(1); + driver.navigate().to(url); + Assert.assertTrue(loginPage.isCurrent()); + loginPage.login("test-user@localhost", "password"); + String pageSource = driver.getPageSource(); + Assert.assertTrue(pageSource.contains("Kerberos Test") && pageSource.contains("Kerberos servlet secured content")); + + + events.clear(); + session = keycloakRule.startSession(); + try { + RealmModel realm = session.realms().getRealm("test"); + realm.addComponentModel(kerberosModel); + } finally { + keycloakRule.stopSession(session, true); + } + + + + + } + + + + }