commit
1085a1da62
24 changed files with 625 additions and 137 deletions
|
@ -18,14 +18,17 @@ public class DefaultAuthenticationFlows {
|
|||
public static final String REGISTRATION_FLOW = "registration";
|
||||
public static final String REGISTRATION_FORM_FLOW = "registration form";
|
||||
public static final String BROWSER_FLOW = "browser";
|
||||
public static final String DIRECT_GRANT_FLOW = "direct grant";
|
||||
public static final String LOGIN_FORMS_FLOW = "forms";
|
||||
|
||||
public static void addFlows(RealmModel realm) {
|
||||
if (realm.getFlowByAlias(BROWSER_FLOW) == null) browserFlow(realm);
|
||||
if (realm.getFlowByAlias(DIRECT_GRANT_FLOW) == null) directGrantFlow(realm, false);
|
||||
if (realm.getFlowByAlias(REGISTRATION_FLOW) == null) registrationFlow(realm);
|
||||
}
|
||||
public static void migrateFlows(RealmModel realm) {
|
||||
browserFlow(realm, true);
|
||||
directGrantFlow(realm, true);
|
||||
if (realm.getFlowByAlias(REGISTRATION_FLOW) == null) registrationFlow(realm);
|
||||
}
|
||||
|
||||
|
@ -123,6 +126,55 @@ public class DefaultAuthenticationFlows {
|
|||
return false;
|
||||
}
|
||||
|
||||
public static void directGrantFlow(RealmModel realm, boolean migrate) {
|
||||
AuthenticationFlowModel grant = new AuthenticationFlowModel();
|
||||
grant.setAlias(DIRECT_GRANT_FLOW);
|
||||
grant.setDescription("OpenID Connect Resource Owner Grant");
|
||||
grant.setProviderId("basic-flow");
|
||||
grant.setTopLevel(true);
|
||||
grant.setBuiltIn(true);
|
||||
grant = realm.addAuthenticationFlow(grant);
|
||||
|
||||
// username
|
||||
AuthenticationExecutionModel execution = new AuthenticationExecutionModel();
|
||||
execution.setParentFlow(grant.getId());
|
||||
execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
|
||||
execution.setAuthenticator("direct-grant-validate-username");
|
||||
execution.setPriority(10);
|
||||
execution.setUserSetupAllowed(false);
|
||||
execution.setAutheticatorFlow(false);
|
||||
realm.addAuthenticatorExecution(execution);
|
||||
|
||||
// password
|
||||
execution = new AuthenticationExecutionModel();
|
||||
execution.setParentFlow(grant.getId());
|
||||
execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
|
||||
if (migrate && !hasCredentialType(realm, RequiredCredentialModel.PASSWORD.getType())) {
|
||||
execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED);
|
||||
}
|
||||
execution.setAuthenticator("direct-grant-validate-password");
|
||||
execution.setPriority(20);
|
||||
execution.setUserSetupAllowed(false);
|
||||
execution.setAutheticatorFlow(false);
|
||||
realm.addAuthenticatorExecution(execution);
|
||||
|
||||
// otp
|
||||
execution = new AuthenticationExecutionModel();
|
||||
execution.setParentFlow(grant.getId());
|
||||
execution.setRequirement(AuthenticationExecutionModel.Requirement.OPTIONAL);
|
||||
if (migrate && hasCredentialType(realm, RequiredCredentialModel.TOTP.getType())) {
|
||||
execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
|
||||
}
|
||||
execution.setAuthenticator("direct-grant-validate-otp");
|
||||
execution.setPriority(30);
|
||||
execution.setUserSetupAllowed(false);
|
||||
execution.setAutheticatorFlow(false);
|
||||
realm.addAuthenticatorExecution(execution);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static void browserFlow(RealmModel realm, boolean migrate) {
|
||||
AuthenticationFlowModel browser = new AuthenticationFlowModel();
|
||||
browser.setAlias(BROWSER_FLOW);
|
||||
|
|
|
@ -3,7 +3,7 @@ package org.keycloak.authentication;
|
|||
import org.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.spi.HttpRequest;
|
||||
import org.keycloak.ClientConnection;
|
||||
import org.keycloak.authentication.authenticators.AbstractFormAuthenticator;
|
||||
import org.keycloak.authentication.authenticators.browser.AbstractFormAuthenticator;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
|
@ -561,9 +561,18 @@ public class AuthenticationProcessor {
|
|||
validateUser(authUser);
|
||||
AuthenticationFlow authenticationFlow = createFlowExecution(this.flowId, null);
|
||||
Response challenge = authenticationFlow.processFlow();
|
||||
if (challenge != null) return challenge;
|
||||
return challenge;
|
||||
}
|
||||
|
||||
public Response attachSessionExecutionRequiredActions() {
|
||||
attachSession();
|
||||
return AuthenticationManager.actionRequired(session, userSession, clientSession, connection, request, uriInfo, event);
|
||||
}
|
||||
|
||||
public void attachSession() {
|
||||
String username = clientSession.getAuthenticatedUser().getUsername();
|
||||
String attemptedUsername = clientSession.getNote(AbstractFormAuthenticator.ATTEMPTED_USERNAME);
|
||||
if (attemptedUsername != null) username = attemptedUsername;
|
||||
if (userSession == null) { // if no authenticator attached a usersession
|
||||
userSession = session.sessions().createUserSession(realm, clientSession.getAuthenticatedUser(), username, connection.getRemoteAddr(), "form", false, null, null);
|
||||
userSession.setState(UserSessionModel.State.LOGGING_IN);
|
||||
|
@ -573,8 +582,10 @@ public class AuthenticationProcessor {
|
|||
event.user(userSession.getUser())
|
||||
.detail(Details.USERNAME, username)
|
||||
.session(userSession);
|
||||
}
|
||||
|
||||
return AuthenticationManager.actionRequired(session, userSession, clientSession, connection, request, uriInfo, event);
|
||||
public void evaluateRequiredActionTriggers() {
|
||||
AuthenticationManager.evaluateRequiredActionTriggers(session, userSession, clientSession, connection, request, uriInfo, event, realm, clientSession.getAuthenticatedUser());
|
||||
}
|
||||
|
||||
public Response finishAuthentication() {
|
||||
|
|
|
@ -105,6 +105,9 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
|
|||
}
|
||||
|
||||
AuthenticatorFactory factory = (AuthenticatorFactory) processor.getSession().getKeycloakSessionFactory().getProviderFactory(Authenticator.class, model.getAuthenticator());
|
||||
if (factory == null) {
|
||||
throw new AuthenticationProcessor.AuthException("Could not find AuthenticatorFactory for: " + model.getAuthenticator(), AuthenticationProcessor.Error.INTERNAL_ERROR);
|
||||
}
|
||||
Authenticator authenticator = factory.create();
|
||||
AuthenticationProcessor.logger.debugv("authenticator: {0}", factory.getId());
|
||||
UserModel authUser = processor.getClientSession().getAuthenticatedUser();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.authentication.authenticators;
|
||||
package org.keycloak.authentication.authenticators.browser;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.OAuth2Constants;
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.authentication.authenticators;
|
||||
package org.keycloak.authentication.authenticators.browser;
|
||||
|
||||
import org.keycloak.authentication.Authenticator;
|
||||
import org.keycloak.authentication.AuthenticatorContext;
|
|
@ -1,10 +1,9 @@
|
|||
package org.keycloak.authentication.authenticators;
|
||||
package org.keycloak.authentication.authenticators.browser;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.authentication.Authenticator;
|
||||
import org.keycloak.authentication.AuthenticatorFactory;
|
||||
import org.keycloak.models.AuthenticationExecutionModel;
|
||||
import org.keycloak.models.AuthenticatorConfigModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
|
@ -1,11 +1,10 @@
|
|||
package org.keycloak.authentication.authenticators;
|
||||
package org.keycloak.authentication.authenticators.browser;
|
||||
|
||||
import org.keycloak.authentication.AuthenticationProcessor;
|
||||
import org.keycloak.authentication.Authenticator;
|
||||
import org.keycloak.authentication.AuthenticatorContext;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.login.LoginFormsProvider;
|
||||
import org.keycloak.models.AuthenticatorConfigModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
|
@ -1,10 +1,9 @@
|
|||
package org.keycloak.authentication.authenticators;
|
||||
package org.keycloak.authentication.authenticators.browser;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.authentication.Authenticator;
|
||||
import org.keycloak.authentication.AuthenticatorFactory;
|
||||
import org.keycloak.models.AuthenticationExecutionModel;
|
||||
import org.keycloak.models.AuthenticatorConfigModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.models.UserCredentialModel;
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.authentication.authenticators;
|
||||
package org.keycloak.authentication.authenticators.browser;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.spi.HttpRequest;
|
||||
|
@ -8,24 +8,19 @@ import org.keycloak.authentication.AuthenticatorContext;
|
|||
import org.keycloak.constants.KerberosConstants;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.login.LoginFormsProvider;
|
||||
import org.keycloak.models.ClientSessionModel;
|
||||
import org.keycloak.models.CredentialValidationOutput;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.services.messages.Messages;
|
||||
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.keycloak.util.HtmlUtils.escapeAttribute;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
|
@ -1,10 +1,9 @@
|
|||
package org.keycloak.authentication.authenticators;
|
||||
package org.keycloak.authentication.authenticators.browser;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.authentication.Authenticator;
|
||||
import org.keycloak.authentication.AuthenticatorFactory;
|
||||
import org.keycloak.models.AuthenticationExecutionModel;
|
||||
import org.keycloak.models.AuthenticatorConfigModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.models.UserCredentialModel;
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.authentication.authenticators;
|
||||
package org.keycloak.authentication.authenticators.browser;
|
||||
|
||||
import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
|
||||
import org.keycloak.authentication.AuthenticationProcessor;
|
||||
|
@ -6,7 +6,6 @@ import org.keycloak.authentication.Authenticator;
|
|||
import org.keycloak.authentication.AuthenticatorContext;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.login.LoginFormsProvider;
|
||||
import org.keycloak.models.AuthenticatorConfigModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
|
@ -1,10 +1,9 @@
|
|||
package org.keycloak.authentication.authenticators;
|
||||
package org.keycloak.authentication.authenticators.browser;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.authentication.Authenticator;
|
||||
import org.keycloak.authentication.AuthenticatorFactory;
|
||||
import org.keycloak.models.AuthenticationExecutionModel;
|
||||
import org.keycloak.models.AuthenticatorConfigModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.models.UserCredentialModel;
|
|
@ -0,0 +1,59 @@
|
|||
package org.keycloak.authentication.authenticators.directgrant;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.authentication.Authenticator;
|
||||
import org.keycloak.authentication.AuthenticatorContext;
|
||||
import org.keycloak.authentication.AuthenticatorFactory;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public abstract class AbstractDirectGrantAuthenticator implements Authenticator, AuthenticatorFactory {
|
||||
public Response errorResponse(int status, String error, String errorDescription) {
|
||||
Map<String, String> e = new HashMap<String, String>();
|
||||
e.put(OAuth2Constants.ERROR, error);
|
||||
if (errorDescription != null) {
|
||||
e.put(OAuth2Constants.ERROR_DESCRIPTION, errorDescription);
|
||||
}
|
||||
return Response.status(status).entity(e).type(MediaType.APPLICATION_JSON_TYPE).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void action(AuthenticatorContext context) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authenticator create() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authenticator create(KeycloakSession session) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
package org.keycloak.authentication.authenticators.directgrant;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.authentication.AuthenticationProcessor;
|
||||
import org.keycloak.authentication.AuthenticatorContext;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.models.AuthenticationExecutionModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ValidateOTP extends AbstractDirectGrantAuthenticator {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ValidateOTP.class);
|
||||
public static final String PROVIDER_ID = "direct-grant-validate-otp";
|
||||
|
||||
@Override
|
||||
public void authenticate(AuthenticatorContext context) {
|
||||
if (!isConfigured(context.getSession(), context.getRealm(), context.getUser())) {
|
||||
if (context.getExecution().isOptional()) {
|
||||
context.attempted();
|
||||
} else if (context.getExecution().isRequired()) {
|
||||
context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
|
||||
Response challengeResponse = errorResponse(Response.Status.UNAUTHORIZED.getStatusCode(), "invalid_grant", "Invalid user credentials");
|
||||
context.failure(AuthenticationProcessor.Error.INVALID_USER, challengeResponse);
|
||||
}
|
||||
return;
|
||||
}
|
||||
MultivaluedMap<String, String> inputData = context.getHttpRequest().getDecodedFormParameters();
|
||||
List<UserCredentialModel> credentials = new LinkedList<>();
|
||||
String otp = inputData.getFirst(CredentialRepresentation.TOTP);
|
||||
if (otp == null) {
|
||||
if (context.getUser() != null) {
|
||||
context.getEvent().user(context.getUser());
|
||||
}
|
||||
context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
|
||||
Response challengeResponse = errorResponse(Response.Status.UNAUTHORIZED.getStatusCode(), "invalid_grant", "Invalid user credentials");
|
||||
context.failure(AuthenticationProcessor.Error.INVALID_USER, challengeResponse);
|
||||
return;
|
||||
}
|
||||
credentials.add(UserCredentialModel.totp(otp));
|
||||
boolean valid = context.getSession().users().validCredentials(context.getRealm(), context.getUser(), credentials);
|
||||
if (!valid) {
|
||||
context.getEvent().user(context.getUser());
|
||||
context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
|
||||
Response challengeResponse = errorResponse(Response.Status.UNAUTHORIZED.getStatusCode(), "invalid_grant", "Invalid user credentials");
|
||||
context.failure(AuthenticationProcessor.Error.INVALID_USER, challengeResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
context.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requiresUser() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isConfigured(KeycloakSession session, RealmModel realm, UserModel user) {
|
||||
return session.users().configuredForCredentialType(UserCredentialModel.TOTP, realm, user) && user.isTotp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayType() {
|
||||
return "OTP";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReferenceCategory() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConfigurable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
|
||||
AuthenticationExecutionModel.Requirement.REQUIRED,
|
||||
AuthenticationExecutionModel.Requirement.OPTIONAL,
|
||||
AuthenticationExecutionModel.Requirement.DISABLED
|
||||
};
|
||||
|
||||
@Override
|
||||
public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
|
||||
return REQUIREMENT_CHOICES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpText() {
|
||||
return "Validates the one time password supplied as a 'totp' form parameter in direct grant request";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProviderConfigProperty> getConfigProperties() {
|
||||
return new LinkedList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_ID;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
package org.keycloak.authentication.authenticators.directgrant;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.authentication.AuthenticationProcessor;
|
||||
import org.keycloak.authentication.AuthenticatorContext;
|
||||
import org.keycloak.authentication.authenticators.browser.AbstractFormAuthenticator;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.models.AuthenticationExecutionModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelDuplicateException;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.services.managers.AuthenticationManager;
|
||||
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ValidatePassword extends AbstractDirectGrantAuthenticator {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ValidatePassword.class);
|
||||
public static final String PROVIDER_ID = "direct-grant-validate-password";
|
||||
|
||||
@Override
|
||||
public void authenticate(AuthenticatorContext context) {
|
||||
MultivaluedMap<String, String> inputData = context.getHttpRequest().getDecodedFormParameters();
|
||||
List<UserCredentialModel> credentials = new LinkedList<>();
|
||||
String password = inputData.getFirst(CredentialRepresentation.PASSWORD);
|
||||
if (password == null) {
|
||||
if (context.getUser() != null) {
|
||||
context.getEvent().user(context.getUser());
|
||||
}
|
||||
context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
|
||||
Response challengeResponse = errorResponse(Response.Status.UNAUTHORIZED.getStatusCode(), "invalid_grant", "Invalid user credentials");
|
||||
context.failure(AuthenticationProcessor.Error.INVALID_USER, challengeResponse);
|
||||
return;
|
||||
}
|
||||
credentials.add(UserCredentialModel.password(password));
|
||||
boolean valid = context.getSession().users().validCredentials(context.getRealm(), context.getUser(), credentials);
|
||||
if (!valid) {
|
||||
context.getEvent().user(context.getUser());
|
||||
context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
|
||||
Response challengeResponse = errorResponse(Response.Status.UNAUTHORIZED.getStatusCode(), "invalid_grant", "Invalid user credentials");
|
||||
context.failure(AuthenticationProcessor.Error.INVALID_USER, challengeResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
context.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requiresUser() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayType() {
|
||||
return "Password";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReferenceCategory() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConfigurable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
|
||||
AuthenticationExecutionModel.Requirement.REQUIRED,
|
||||
AuthenticationExecutionModel.Requirement.DISABLED
|
||||
};
|
||||
|
||||
@Override
|
||||
public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
|
||||
return REQUIREMENT_CHOICES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpText() {
|
||||
return "Validates the password supplied as a 'password' form parameter in direct grant request";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProviderConfigProperty> getConfigProperties() {
|
||||
return new LinkedList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_ID;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
package org.keycloak.authentication.authenticators.directgrant;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.authentication.AuthenticationProcessor;
|
||||
import org.keycloak.authentication.Authenticator;
|
||||
import org.keycloak.authentication.AuthenticatorContext;
|
||||
import org.keycloak.authentication.AuthenticatorFactory;
|
||||
import org.keycloak.authentication.authenticators.browser.AbstractFormAuthenticator;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.models.AuthenticationExecutionModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.models.ModelDuplicateException;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
import org.keycloak.services.managers.AuthenticationManager;
|
||||
import org.keycloak.services.messages.Messages;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ValidateUsername extends AbstractDirectGrantAuthenticator {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ValidateUsername.class);
|
||||
public static final String PROVIDER_ID = "direct-grant-validate-username";
|
||||
|
||||
@Override
|
||||
public void authenticate(AuthenticatorContext context) {
|
||||
MultivaluedMap<String, String> inputData = context.getHttpRequest().getDecodedFormParameters();
|
||||
String username = inputData.getFirst(AuthenticationManager.FORM_USERNAME);
|
||||
if (username == null) {
|
||||
context.getEvent().error(Errors.USER_NOT_FOUND);
|
||||
Response challengeResponse = errorResponse(Response.Status.UNAUTHORIZED.getStatusCode(), "invalid_request", "Missing parameter: username");
|
||||
context.failure(AuthenticationProcessor.Error.INVALID_USER, challengeResponse);
|
||||
return;
|
||||
}
|
||||
context.getEvent().detail(Details.USERNAME, username);
|
||||
context.getClientSession().setNote(AbstractFormAuthenticator.ATTEMPTED_USERNAME, username);
|
||||
|
||||
UserModel user = null;
|
||||
try {
|
||||
user = KeycloakModelUtils.findUserByNameOrEmail(context.getSession(), context.getRealm(), username);
|
||||
} catch (ModelDuplicateException mde) {
|
||||
logger.error(mde.getMessage(), mde);
|
||||
Response challengeResponse = errorResponse(Response.Status.UNAUTHORIZED.getStatusCode(), "invalid_request", "Invalid user credentials");
|
||||
context.failure(AuthenticationProcessor.Error.INVALID_USER, challengeResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (user == null) {
|
||||
context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
|
||||
Response challengeResponse = errorResponse(Response.Status.UNAUTHORIZED.getStatusCode(), "invalid_grant", "Invalid user credentials");
|
||||
context.failure(AuthenticationProcessor.Error.INVALID_USER, challengeResponse);
|
||||
return;
|
||||
}
|
||||
if (!user.isEnabled()) {
|
||||
context.getEvent().user(user);
|
||||
context.getEvent().error(Errors.USER_DISABLED);
|
||||
Response challengeResponse = errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "invalid_grant", "Account disabled");
|
||||
context.failure(AuthenticationProcessor.Error.INVALID_USER, challengeResponse);
|
||||
return;
|
||||
}
|
||||
if (context.getRealm().isBruteForceProtected()) {
|
||||
if (context.getProtector().isTemporarilyDisabled(context.getSession(), context.getRealm(), user.getUsername())) {
|
||||
context.getEvent().user(user);
|
||||
context.getEvent().error(Errors.USER_TEMPORARILY_DISABLED);
|
||||
Response challengeResponse = errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "invalid_grant", "Account temporarily disabled");
|
||||
context.failure(AuthenticationProcessor.Error.INVALID_USER, challengeResponse);
|
||||
return;
|
||||
}
|
||||
}
|
||||
context.setUser(user);
|
||||
context.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requiresUser() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayType() {
|
||||
return "Username Validation";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReferenceCategory() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConfigurable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
|
||||
AuthenticationExecutionModel.Requirement.REQUIRED
|
||||
};
|
||||
|
||||
@Override
|
||||
public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
|
||||
return REQUIREMENT_CHOICES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpText() {
|
||||
return "Validates the username supplied as a 'username' form parameter in direct grant request";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProviderConfigProperty> getConfigProperties() {
|
||||
return new LinkedList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_ID;
|
||||
}
|
||||
}
|
|
@ -277,6 +277,9 @@ public class AuthorizationEndpoint {
|
|||
Response challenge = null;
|
||||
try {
|
||||
challenge = processor.authenticateOnly();
|
||||
if (challenge == null) {
|
||||
challenge = processor.attachSessionExecutionRequiredActions();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return processor.handleBrowserException(e);
|
||||
}
|
||||
|
|
|
@ -5,11 +5,13 @@ import org.jboss.resteasy.spi.HttpRequest;
|
|||
import org.keycloak.ClientConnection;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.OAuthErrorException;
|
||||
import org.keycloak.authentication.AuthenticationProcessor;
|
||||
import org.keycloak.constants.AdapterConstants;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.models.AuthenticationFlowModel;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.ClientSessionModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
@ -17,6 +19,7 @@ import org.keycloak.models.RealmModel;
|
|||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.models.UserSessionProvider;
|
||||
import org.keycloak.models.utils.DefaultAuthenticationFlows;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.protocol.oidc.TokenManager;
|
||||
|
@ -307,46 +310,38 @@ public class TokenEndpoint {
|
|||
public Response buildResourceOwnerPasswordCredentialsGrant() {
|
||||
event.detail(Details.AUTH_METHOD, "oauth_credentials").detail(Details.RESPONSE_TYPE, "token");
|
||||
|
||||
String username = formParams.getFirst(AuthenticationManager.FORM_USERNAME);
|
||||
if (username == null) {
|
||||
event.error(Errors.USERNAME_MISSING);
|
||||
throw new ErrorResponseException("invalid_request", "Missing parameter: username", Response.Status.UNAUTHORIZED);
|
||||
if (client.isConsentRequired()) {
|
||||
throw new ErrorResponseException("invalid_client", "Client requires user consent", Response.Status.BAD_REQUEST);
|
||||
}
|
||||
event.detail(Details.USERNAME, username);
|
||||
|
||||
UserModel user = KeycloakModelUtils.findUserByNameOrEmail(session, realm, username);
|
||||
if (user != null) event.user(user);
|
||||
|
||||
AuthenticationManager.AuthenticationStatus authenticationStatus = authManager.authenticateForm(session, clientConnection, realm, formParams);
|
||||
Map<String, String> err;
|
||||
|
||||
switch (authenticationStatus) {
|
||||
case SUCCESS:
|
||||
break;
|
||||
case ACCOUNT_TEMPORARILY_DISABLED:
|
||||
case ACTIONS_REQUIRED:
|
||||
event.error(Errors.USER_TEMPORARILY_DISABLED);
|
||||
throw new ErrorResponseException("invalid_grant", "Account temporarily disabled", Response.Status.BAD_REQUEST);
|
||||
case ACCOUNT_DISABLED:
|
||||
event.error(Errors.USER_DISABLED);
|
||||
throw new ErrorResponseException("invalid_grant", "Account disabled", Response.Status.BAD_REQUEST);
|
||||
default:
|
||||
event.error(Errors.INVALID_USER_CREDENTIALS);
|
||||
throw new ErrorResponseException("invalid_grant", "Invalid user credentials", Response.Status.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
String scope = formParams.getFirst(OAuth2Constants.SCOPE);
|
||||
|
||||
UserSessionProvider sessions = session.sessions();
|
||||
|
||||
UserSessionModel userSession = sessions.createUserSession(realm, user, username, clientConnection.getRemoteAddr(), "oauth_credentials", false, null, null);
|
||||
event.session(userSession);
|
||||
|
||||
ClientSessionModel clientSession = sessions.createClientSession(realm, client);
|
||||
clientSession.setAuthMethod(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
|
||||
clientSession.setNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
|
||||
AuthenticationFlowModel flow = realm.getFlowByAlias(DefaultAuthenticationFlows.DIRECT_GRANT_FLOW);
|
||||
String flowId = flow.getId();
|
||||
AuthenticationProcessor processor = new AuthenticationProcessor();
|
||||
processor.setClientSession(clientSession)
|
||||
.setFlowId(flowId)
|
||||
.setConnection(clientConnection)
|
||||
.setEventBuilder(event)
|
||||
.setProtector(authManager.getProtector())
|
||||
.setRealm(realm)
|
||||
.setSession(session)
|
||||
.setUriInfo(uriInfo)
|
||||
.setRequest(request);
|
||||
Response challenge = processor.authenticateOnly();
|
||||
if (challenge != null) return challenge;
|
||||
processor.evaluateRequiredActionTriggers();
|
||||
UserModel user = clientSession.getAuthenticatedUser();
|
||||
if (user.getRequiredActions() != null && user.getRequiredActions().size() > 0) {
|
||||
throw new ErrorResponseException("invalid_grant", "Account is not fully set up", Response.Status.BAD_REQUEST);
|
||||
|
||||
TokenManager.attachClientSession(userSession, clientSession);
|
||||
}
|
||||
processor.attachSession();
|
||||
UserSessionModel userSession = processor.getUserSession();
|
||||
|
||||
AccessTokenResponse res = tokenManager.responseBuilder(realm, client, event, session, userSession, clientSession)
|
||||
.generateAccessToken(session, scope, client, user, userSession, clientSession)
|
||||
|
@ -354,6 +349,7 @@ public class TokenEndpoint {
|
|||
.generateIDToken()
|
||||
.build();
|
||||
|
||||
|
||||
event.success();
|
||||
|
||||
return Cors.add(request, Response.ok(res, MediaType.APPLICATION_JSON_TYPE)).auth().allowedOrigins(client).allowedMethods("POST").exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS).build();
|
||||
|
|
|
@ -429,66 +429,7 @@ public class AuthenticationManager {
|
|||
final UserModel user = userSession.getUser();
|
||||
final ClientModel client = clientSession.getClient();
|
||||
|
||||
RequiredActionContext context = new RequiredActionContext() {
|
||||
@Override
|
||||
public EventBuilder getEvent() {
|
||||
return event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RealmModel getRealm() {
|
||||
return realm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientSessionModel getClientSession() {
|
||||
return clientSession;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserSessionModel getUserSession() {
|
||||
return userSession;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientConnection getConnection() {
|
||||
return clientConnection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UriInfo getUriInfo() {
|
||||
return uriInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeycloakSession getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpRequest getHttpRequest() {
|
||||
return request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateAccessCode(String action) {
|
||||
ClientSessionCode code = new ClientSessionCode(getRealm(), getClientSession());
|
||||
code.setAction(action);
|
||||
return code.getCode();
|
||||
}
|
||||
};
|
||||
|
||||
// see if any required actions need triggering, i.e. an expired password
|
||||
for (RequiredActionProviderModel model : realm.getRequiredActionProviders()) {
|
||||
if (!model.isEnabled()) continue;
|
||||
RequiredActionProvider provider = session.getProvider(RequiredActionProvider.class, model.getProviderId());
|
||||
provider.evaluateTriggers(context);
|
||||
}
|
||||
RequiredActionContext context = evaluateRequiredActionTriggers(session, userSession, clientSession, clientConnection, request, uriInfo, event, realm, user);
|
||||
|
||||
|
||||
logger.debugv("processAccessCode: go to oauth page?: {0}", client.isConsentRequired());
|
||||
|
@ -554,6 +495,70 @@ public class AuthenticationManager {
|
|||
|
||||
}
|
||||
|
||||
public static RequiredActionContext evaluateRequiredActionTriggers(final KeycloakSession session, final UserSessionModel userSession, final ClientSessionModel clientSession, final ClientConnection clientConnection, final HttpRequest request, final UriInfo uriInfo, final EventBuilder event, final RealmModel realm, final UserModel user) {
|
||||
RequiredActionContext context = new RequiredActionContext() {
|
||||
@Override
|
||||
public EventBuilder getEvent() {
|
||||
return event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RealmModel getRealm() {
|
||||
return realm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientSessionModel getClientSession() {
|
||||
return clientSession;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserSessionModel getUserSession() {
|
||||
return userSession;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientConnection getConnection() {
|
||||
return clientConnection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UriInfo getUriInfo() {
|
||||
return uriInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeycloakSession getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpRequest getHttpRequest() {
|
||||
return request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateAccessCode(String action) {
|
||||
ClientSessionCode code = new ClientSessionCode(getRealm(), getClientSession());
|
||||
code.setAction(action);
|
||||
return code.getCode();
|
||||
}
|
||||
};
|
||||
|
||||
// see if any required actions need triggering, i.e. an expired password
|
||||
for (RequiredActionProviderModel model : realm.getRequiredActionProviders()) {
|
||||
if (!model.isEnabled()) continue;
|
||||
RequiredActionProvider provider = session.getProvider(RequiredActionProvider.class, model.getProviderId());
|
||||
provider.evaluateTriggers(context);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
protected static AuthResult verifyIdentityToken(KeycloakSession session, RealmModel realm, UriInfo uriInfo, ClientConnection connection, boolean checkActive, String tokenString, HttpHeaders headers) {
|
||||
try {
|
||||
|
|
|
@ -23,14 +23,10 @@ package org.keycloak.services.resources;
|
|||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.spi.HttpRequest;
|
||||
import org.jboss.resteasy.spi.InternalServerErrorException;
|
||||
import org.keycloak.ClientConnection;
|
||||
import org.keycloak.authentication.AuthenticationProcessor;
|
||||
import org.keycloak.authentication.AuthenticatorUtil;
|
||||
import org.keycloak.authentication.RequiredActionContext;
|
||||
import org.keycloak.authentication.RequiredActionProvider;
|
||||
import org.keycloak.authentication.authenticators.AbstractFormAuthenticator;
|
||||
import org.keycloak.authentication.authenticators.UsernamePasswordFormFactory;
|
||||
import org.keycloak.email.EmailException;
|
||||
import org.keycloak.email.EmailProvider;
|
||||
import org.keycloak.events.Details;
|
||||
|
@ -55,8 +51,6 @@ import org.keycloak.models.utils.DefaultAuthenticationFlows;
|
|||
import org.keycloak.models.utils.FormMessage;
|
||||
import org.keycloak.models.utils.TimeBasedOTP;
|
||||
import org.keycloak.protocol.LoginProtocol;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
|
||||
import org.keycloak.protocol.oidc.TokenManager;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.services.managers.AuthenticationManager;
|
||||
|
@ -84,7 +78,6 @@ import javax.ws.rs.core.Response;
|
|||
import javax.ws.rs.core.UriBuilder;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import javax.ws.rs.ext.Providers;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
|
|
@ -5,16 +5,10 @@ import org.keycloak.authentication.AuthenticatorFactory;
|
|||
import org.keycloak.authentication.ConfigurableAuthenticatorFactory;
|
||||
import org.keycloak.authentication.FormAction;
|
||||
import org.keycloak.authentication.FormActionFactory;
|
||||
import org.keycloak.authentication.authenticators.OTPFormAuthenticatorFactory;
|
||||
import org.keycloak.authentication.authenticators.SpnegoAuthenticatorFactory;
|
||||
import org.keycloak.authentication.authenticators.UsernamePasswordFormFactory;
|
||||
import org.keycloak.models.AuthenticationExecutionModel;
|
||||
import org.keycloak.models.AuthenticationFlowModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.utils.DefaultAuthenticationFlows;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
|
||||
/**
|
||||
* used to set an execution a state based on type.
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
org.keycloak.authentication.authenticators.CookieAuthenticatorFactory
|
||||
org.keycloak.authentication.authenticators.UsernamePasswordFormFactory
|
||||
org.keycloak.authentication.authenticators.OTPFormAuthenticatorFactory
|
||||
org.keycloak.authentication.authenticators.SpnegoAuthenticatorFactory
|
||||
org.keycloak.authentication.authenticators.browser.CookieAuthenticatorFactory
|
||||
org.keycloak.authentication.authenticators.browser.UsernamePasswordFormFactory
|
||||
org.keycloak.authentication.authenticators.browser.OTPFormAuthenticatorFactory
|
||||
org.keycloak.authentication.authenticators.browser.SpnegoAuthenticatorFactory
|
||||
org.keycloak.authentication.authenticators.directgrant.ValidateOTP
|
||||
org.keycloak.authentication.authenticators.directgrant.ValidatePassword
|
||||
org.keycloak.authentication.authenticators.directgrant.ValidateUsername
|
|
@ -18,7 +18,7 @@ import org.junit.Assert;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.adapters.HttpClientBuilder;
|
||||
import org.keycloak.authentication.authenticators.SpnegoAuthenticator;
|
||||
import org.keycloak.authentication.authenticators.browser.SpnegoAuthenticator;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.federation.kerberos.CommonKerberosConfig;
|
||||
import org.keycloak.constants.KerberosConstants;
|
||||
|
|
|
@ -86,7 +86,6 @@ public class ResourceOwnerPasswordCredentialsGrantTest {
|
|||
.client("resource-owner")
|
||||
.user(userId)
|
||||
.session(accessToken.getSessionState())
|
||||
.detail(Details.AUTH_METHOD, "oauth_credentials")
|
||||
.detail(Details.RESPONSE_TYPE, "token")
|
||||
.detail(Details.TOKEN_ID, accessToken.getId())
|
||||
.detail(Details.REFRESH_TOKEN_ID, refreshToken.getId())
|
||||
|
@ -123,7 +122,6 @@ public class ResourceOwnerPasswordCredentialsGrantTest {
|
|||
events.expectLogin()
|
||||
.client("resource-owner")
|
||||
.session(accessToken.getSessionState())
|
||||
.detail(Details.AUTH_METHOD, "oauth_credentials")
|
||||
.detail(Details.RESPONSE_TYPE, "token")
|
||||
.detail(Details.TOKEN_ID, accessToken.getId())
|
||||
.detail(Details.REFRESH_TOKEN_ID, refreshToken.getId())
|
||||
|
@ -178,7 +176,6 @@ public class ResourceOwnerPasswordCredentialsGrantTest {
|
|||
events.expectLogin()
|
||||
.client("resource-owner")
|
||||
.session((String) null)
|
||||
.detail(Details.AUTH_METHOD, "oauth_credentials")
|
||||
.detail(Details.RESPONSE_TYPE, "token")
|
||||
.removeDetail(Details.CODE_ID)
|
||||
.removeDetail(Details.REDIRECT_URI)
|
||||
|
@ -201,7 +198,6 @@ public class ResourceOwnerPasswordCredentialsGrantTest {
|
|||
.client("resource-owner")
|
||||
.user((String) null)
|
||||
.session((String) null)
|
||||
.detail(Details.AUTH_METHOD, "oauth_credentials")
|
||||
.detail(Details.RESPONSE_TYPE, "token")
|
||||
.detail(Details.USERNAME, "invalid")
|
||||
.removeDetail(Details.CODE_ID)
|
||||
|
|
Loading…
Reference in a new issue