Details
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 b7a8b62..8bfb995 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 0fabb1f..4e2b52a 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 <T> List<T> getCredentialProviders(RealmModel realm, Class<T> type) {
List<T> list = new LinkedList<T>();
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 aeb58b2..af4fd22 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);
+ }
+
+
+
+
+ }
+
+
+
+
}