Do not challenge inside spnego authenticator is FORKED_FLOW
Closes #20637 Signed-off-by: rmartinc <rmartinc@redhat.com>
This commit is contained in:
parent
a681d8ce28
commit
43a5779f6e
3 changed files with 75 additions and 3 deletions
|
@ -21,6 +21,7 @@ import org.jboss.logging.Logger;
|
||||||
import org.keycloak.http.HttpRequest;
|
import org.keycloak.http.HttpRequest;
|
||||||
import org.keycloak.authentication.AuthenticationFlowContext;
|
import org.keycloak.authentication.AuthenticationFlowContext;
|
||||||
import org.keycloak.authentication.AuthenticationFlowError;
|
import org.keycloak.authentication.AuthenticationFlowError;
|
||||||
|
import org.keycloak.authentication.AuthenticationProcessor;
|
||||||
import org.keycloak.authentication.Authenticator;
|
import org.keycloak.authentication.Authenticator;
|
||||||
import org.keycloak.common.constants.KerberosConstants;
|
import org.keycloak.common.constants.KerberosConstants;
|
||||||
import org.keycloak.events.Errors;
|
import org.keycloak.events.Errors;
|
||||||
|
@ -61,6 +62,11 @@ public class SpnegoAuthenticator extends AbstractUsernameFormAuthenticator imple
|
||||||
HttpRequest request = context.getHttpRequest();
|
HttpRequest request = context.getHttpRequest();
|
||||||
String authHeader = request.getHttpHeaders().getRequestHeaders().getFirst(HttpHeaders.AUTHORIZATION);
|
String authHeader = request.getHttpHeaders().getRequestHeaders().getFirst(HttpHeaders.AUTHORIZATION);
|
||||||
if (authHeader == null) {
|
if (authHeader == null) {
|
||||||
|
if (context.getAuthenticationSession().getAuthNote(AuthenticationProcessor.FORKED_FROM) != null) {
|
||||||
|
// skip spnego authentication if it was forked (reset-credentials)
|
||||||
|
context.attempted();
|
||||||
|
return;
|
||||||
|
}
|
||||||
Response challenge = challengeNegotiation(context, null);
|
Response challenge = challengeNegotiation(context, null);
|
||||||
context.forceChallenge(challenge);
|
context.forceChallenge(challenge);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -17,19 +17,30 @@
|
||||||
|
|
||||||
package org.keycloak.testsuite.federation.kerberos;
|
package org.keycloak.testsuite.federation.kerberos;
|
||||||
|
|
||||||
import java.net.URI;
|
import jakarta.mail.internet.MimeMessage;
|
||||||
import java.util.List;
|
|
||||||
import jakarta.ws.rs.client.Entity;
|
import jakarta.ws.rs.client.Entity;
|
||||||
|
import jakarta.ws.rs.core.Form;
|
||||||
import jakarta.ws.rs.core.MultivaluedMap;
|
import jakarta.ws.rs.core.MultivaluedMap;
|
||||||
import jakarta.ws.rs.core.Response;
|
import jakarta.ws.rs.core.Response;
|
||||||
import org.keycloak.testsuite.Assert;
|
import java.net.URI;
|
||||||
|
import java.util.List;
|
||||||
|
import org.hamcrest.MatcherAssert;
|
||||||
|
import org.hamcrest.Matchers;
|
||||||
|
import org.jboss.arquillian.graphene.page.Page;
|
||||||
|
import org.jsoup.Jsoup;
|
||||||
|
import org.jsoup.nodes.Document;
|
||||||
|
import org.jsoup.select.Elements;
|
||||||
import org.junit.ClassRule;
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.admin.client.resource.UserResource;
|
import org.keycloak.admin.client.resource.UserResource;
|
||||||
import org.keycloak.common.constants.KerberosConstants;
|
import org.keycloak.common.constants.KerberosConstants;
|
||||||
|
import org.keycloak.events.Details;
|
||||||
|
import org.keycloak.events.EventType;
|
||||||
import org.keycloak.federation.kerberos.CommonKerberosConfig;
|
import org.keycloak.federation.kerberos.CommonKerberosConfig;
|
||||||
import org.keycloak.federation.kerberos.KerberosConfig;
|
import org.keycloak.federation.kerberos.KerberosConfig;
|
||||||
import org.keycloak.federation.kerberos.KerberosFederationProviderFactory;
|
import org.keycloak.federation.kerberos.KerberosFederationProviderFactory;
|
||||||
|
import org.keycloak.models.Constants;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.representations.idm.ComponentRepresentation;
|
import org.keycloak.representations.idm.ComponentRepresentation;
|
||||||
import org.keycloak.representations.idm.ErrorRepresentation;
|
import org.keycloak.representations.idm.ErrorRepresentation;
|
||||||
|
@ -37,10 +48,16 @@ import org.keycloak.representations.idm.UserProfileAttributeMetadata;
|
||||||
import org.keycloak.representations.idm.UserRepresentation;
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
import org.keycloak.storage.UserStorageProvider;
|
import org.keycloak.storage.UserStorageProvider;
|
||||||
import org.keycloak.testsuite.ActionURIUtils;
|
import org.keycloak.testsuite.ActionURIUtils;
|
||||||
|
import org.keycloak.testsuite.Assert;
|
||||||
import org.keycloak.testsuite.KerberosEmbeddedServer;
|
import org.keycloak.testsuite.KerberosEmbeddedServer;
|
||||||
import org.keycloak.testsuite.admin.ApiUtil;
|
import org.keycloak.testsuite.admin.ApiUtil;
|
||||||
import org.keycloak.testsuite.arquillian.annotation.UncaughtServerErrorExpected;
|
import org.keycloak.testsuite.arquillian.annotation.UncaughtServerErrorExpected;
|
||||||
|
import org.keycloak.testsuite.pages.InfoPage;
|
||||||
|
import org.keycloak.testsuite.pages.LoginPasswordUpdatePage;
|
||||||
|
import org.keycloak.testsuite.util.GreenMailRule;
|
||||||
import org.keycloak.testsuite.util.KerberosRule;
|
import org.keycloak.testsuite.util.KerberosRule;
|
||||||
|
import org.keycloak.testsuite.util.MailUtils;
|
||||||
|
import org.keycloak.testsuite.util.OAuthClient;
|
||||||
|
|
||||||
import static org.keycloak.userprofile.UserProfileUtil.USER_METADATA_GROUP;
|
import static org.keycloak.userprofile.UserProfileUtil.USER_METADATA_GROUP;
|
||||||
|
|
||||||
|
@ -56,6 +73,14 @@ public class KerberosStandaloneTest extends AbstractKerberosSingleRealmTest {
|
||||||
@ClassRule
|
@ClassRule
|
||||||
public static KerberosRule kerberosRule = new KerberosRule(PROVIDER_CONFIG_LOCATION, KerberosEmbeddedServer.DEFAULT_KERBEROS_REALM);
|
public static KerberosRule kerberosRule = new KerberosRule(PROVIDER_CONFIG_LOCATION, KerberosEmbeddedServer.DEFAULT_KERBEROS_REALM);
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public GreenMailRule greenMail = new GreenMailRule();
|
||||||
|
|
||||||
|
@Page
|
||||||
|
protected LoginPasswordUpdatePage loginPasswordUpdatePage;
|
||||||
|
|
||||||
|
@Page
|
||||||
|
protected InfoPage infoPage;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected KerberosRule getKerberosRule() {
|
protected KerberosRule getKerberosRule() {
|
||||||
|
@ -213,4 +238,40 @@ public class KerberosStandaloneTest extends AbstractKerberosSingleRealmTest {
|
||||||
johnResource.update(john);
|
johnResource.update(john);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResetCredentials() throws Exception {
|
||||||
|
// request reset-credentials
|
||||||
|
String resetUri = OAuthClient.AUTH_SERVER_ROOT + "/realms/test/login-actions/reset-credentials";
|
||||||
|
String actionUri;
|
||||||
|
try (Response response = client.target(resetUri).queryParam(Constants.CLIENT_ID, oauth.getClientId()).request().get()) {
|
||||||
|
Assert.assertEquals(200, response.getStatus());
|
||||||
|
Document theResponsePage = Jsoup.parse(response.readEntity(String.class));
|
||||||
|
Elements forms = theResponsePage.select("form[id=kc-reset-password-form]");
|
||||||
|
Assert.assertEquals(1, forms.size());
|
||||||
|
actionUri = forms.get(0).attr("action");
|
||||||
|
Assert.assertNotNull(actionUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
// continue the reset providing the user to change email
|
||||||
|
spnegoSchemeFactory.setCredentials("hnelson", "incorrectpassword"); // this should not be used, error if auth requested
|
||||||
|
Form form = new Form();
|
||||||
|
form.param("username", "test-user@localhost");
|
||||||
|
try (Response response = client.target(actionUri).request().post(Entity.form(form))) {
|
||||||
|
Assert.assertEquals(200, response.getStatus());
|
||||||
|
MatcherAssert.assertThat(response.readEntity(String.class), Matchers.containsString("You should receive an email shortly with further instructions."));
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the email from green mail
|
||||||
|
MimeMessage message = greenMail.getLastReceivedMessage();
|
||||||
|
Assert.assertNotNull(message);
|
||||||
|
String changePasswordUrl = MailUtils.getPasswordResetEmailLink(message);
|
||||||
|
|
||||||
|
// perform the password change using the email url
|
||||||
|
driver.navigate().to(changePasswordUrl.trim());
|
||||||
|
loginPasswordUpdatePage.assertCurrent();
|
||||||
|
loginPasswordUpdatePage.changePassword("resetPassword", "resetPassword");
|
||||||
|
events.expectRequiredAction(EventType.UPDATE_PASSWORD).client(oauth.getClientId()).detail(Details.USERNAME, "test-user@localhost");
|
||||||
|
infoPage.assertCurrent();
|
||||||
|
Assert.assertEquals("Your account has been updated.", infoPage.getInfo());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,5 +50,10 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"smtpServer": {
|
||||||
|
"from": "auto@keycloak.org",
|
||||||
|
"host": "localhost",
|
||||||
|
"port": "3025"
|
||||||
|
},
|
||||||
"eventsListeners": ["jboss-logging", "event-queue"]
|
"eventsListeners": ["jboss-logging", "event-queue"]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue