more
This commit is contained in:
1 parent
c12fe28b2d
commit
b54061fc3f
10 files changed
+120
-32
No files matched your search
@@ -38,6 +38,7 @@ public class AuthenticationProcessor {
|
||||
protected EventBuilder event;
|
||||
protected HttpRequest request;
|
||||
protected String flowId;
|
||||
protected boolean userSessionCreated;
|
||||
|
||||
|
||||
public static enum Status {
|
||||
@@ -79,6 +80,14 @@ public class AuthenticationProcessor {
|
||||
return session;
|
||||
}
|
||||
|
||||
public UserSessionModel getUserSession() {
|
||||
return userSession;
|
||||
}
|
||||
|
||||
public boolean isUserSessionCreated() {
|
||||
return userSessionCreated;
|
||||
}
|
||||
|
||||
public AuthenticationProcessor setRealm(RealmModel realm) {
|
||||
this.realm = realm;
|
||||
return this;
|
||||
@@ -339,6 +348,40 @@ public class AuthenticationProcessor {
|
||||
throw new AuthException(Error.UNKNOWN_USER);
|
||||
}
|
||||
return authenticationComplete();
|
||||
}
|
||||
|
||||
public Response authenticateOnly() throws AuthException {
|
||||
event.event(EventType.LOGIN);
|
||||
event.client(clientSession.getClient().getClientId())
|
||||
.detail(Details.REDIRECT_URI, clientSession.getRedirectUri())
|
||||
.detail(Details.AUTH_METHOD, clientSession.getAuthMethod());
|
||||
String authType = clientSession.getNote(Details.AUTH_TYPE);
|
||||
if (authType != null) {
|
||||
event.detail(Details.AUTH_TYPE, authType);
|
||||
}
|
||||
UserModel authUser = clientSession.getAuthenticatedUser();
|
||||
validateUser(authUser);
|
||||
Response challenge = processFlow(flowId);
|
||||
if (challenge != null) return challenge;
|
||||
|
||||
String username = clientSession.getAuthenticatedUser().getUsername();
|
||||
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);
|
||||
userSessionCreated = true;
|
||||
}
|
||||
TokenManager.attachClientSession(userSession, clientSession);
|
||||
event.user(userSession.getUser())
|
||||
.detail(Details.USERNAME, username)
|
||||
.session(userSession);
|
||||
|
||||
return AuthenticationManager.actionRequired(session, userSession, clientSession, connection, request, uriInfo, event);
|
||||
}
|
||||
|
||||
public Response finishAuthentication() {
|
||||
event.success();
|
||||
RealmModel realm = clientSession.getRealm();
|
||||
return AuthenticationManager.redirectAfterSuccessfulFlow(session, realm , userSession, clientSession, request, uriInfo, connection);
|
||||
|
||||
}
|
||||
|
||||
|
||||
+18
-3
@@ -43,15 +43,28 @@ public class AbstractFormAuthenticator {
|
||||
}
|
||||
|
||||
protected Response invalidUser(AuthenticatorContext context) {
|
||||
return loginForm(context).setError(Messages.INVALID_USER).createLogin();
|
||||
return loginForm(context)
|
||||
.setError(Messages.INVALID_USER)
|
||||
.setClientSessionCode(new ClientSessionCode(context.getRealm(), context.getClientSession()).getCode())
|
||||
.createLogin();
|
||||
}
|
||||
|
||||
protected Response disabledUser(AuthenticatorContext context) {
|
||||
return loginForm(context).setError(Messages.ACCOUNT_DISABLED).createLogin();
|
||||
return loginForm(context)
|
||||
.setClientSessionCode(new ClientSessionCode(context.getRealm(), context.getClientSession()).getCode())
|
||||
.setError(Messages.ACCOUNT_DISABLED).createLogin();
|
||||
}
|
||||
|
||||
protected Response temporarilyDisabledUser(AuthenticatorContext context) {
|
||||
return loginForm(context).setError(Messages.ACCOUNT_TEMPORARILY_DISABLED).createLogin();
|
||||
return loginForm(context)
|
||||
.setClientSessionCode(new ClientSessionCode(context.getRealm(), context.getClientSession()).getCode())
|
||||
.setError(Messages.ACCOUNT_TEMPORARILY_DISABLED).createLogin();
|
||||
}
|
||||
|
||||
protected Response invalidCredentials(AuthenticatorContext context) {
|
||||
return loginForm(context)
|
||||
.setClientSessionCode(new ClientSessionCode(context.getRealm(), context.getClientSession()).getCode())
|
||||
.setError(Messages.INVALID_USER).createLogin();
|
||||
}
|
||||
|
||||
public boolean invalidUser(AuthenticatorContext context, UserModel user) {
|
||||
@@ -62,6 +75,7 @@ public class AbstractFormAuthenticator {
|
||||
return true;
|
||||
}
|
||||
if (!user.isEnabled()) {
|
||||
context.getEvent().user(user);
|
||||
context.getEvent().error(Errors.USER_DISABLED);
|
||||
Response challengeResponse = disabledUser(context);
|
||||
context.failureChallenge(AuthenticationProcessor.Error.USER_DISABLED, challengeResponse);
|
||||
@@ -69,6 +83,7 @@ public class AbstractFormAuthenticator {
|
||||
}
|
||||
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 = temporarilyDisabledUser(context);
|
||||
context.failureChallenge(AuthenticationProcessor.Error.USER_TEMPORARILY_DISABLED, challengeResponse);
|
||||
|
||||
+6
-7
@@ -35,26 +35,25 @@ public class LoginFormPasswordAuthenticator extends LoginFormUsernameAuthenticat
|
||||
validatePassword(context);
|
||||
}
|
||||
|
||||
protected Response badPassword(AuthenticatorContext context) {
|
||||
return loginForm(context).setError(Messages.INVALID_USER).createLogin();
|
||||
}
|
||||
|
||||
|
||||
public void validatePassword(AuthenticatorContext context) {
|
||||
MultivaluedMap<String, String> inputData = context.getHttpRequest().getFormParameters();
|
||||
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 = badPassword(context);
|
||||
Response challengeResponse = invalidCredentials(context);
|
||||
context.failureChallenge(AuthenticationProcessor.Error.INVALID_CREDENTIALS, 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 = badPassword(context);
|
||||
Response challengeResponse = invalidCredentials(context);
|
||||
context.failureChallenge(AuthenticationProcessor.Error.INVALID_CREDENTIALS, challengeResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
+8
-7
@@ -12,6 +12,7 @@ import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.services.managers.ClientSessionCode;
|
||||
import org.keycloak.services.messages.Messages;
|
||||
import org.keycloak.services.resources.LoginActionsService;
|
||||
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
@@ -34,7 +35,7 @@ public class OTPFormAuthenticator extends AbstractFormAuthenticator implements A
|
||||
@Override
|
||||
public void authenticate(AuthenticatorContext context) {
|
||||
if (!isActionUrl(context)) {
|
||||
Response challengeResponse = challenge(context);
|
||||
Response challengeResponse = challenge(context, null);
|
||||
context.challenge(challengeResponse);
|
||||
return;
|
||||
}
|
||||
@@ -46,34 +47,34 @@ public class OTPFormAuthenticator extends AbstractFormAuthenticator implements A
|
||||
List<UserCredentialModel> credentials = new LinkedList<>();
|
||||
String password = inputData.getFirst(CredentialRepresentation.TOTP);
|
||||
if (password == null) {
|
||||
Response challengeResponse = challenge(context);
|
||||
Response challengeResponse = challenge(context, null);
|
||||
context.challenge(challengeResponse);
|
||||
return;
|
||||
}
|
||||
credentials.add(UserCredentialModel.totp(password));
|
||||
boolean valid = context.getSession().users().validCredentials(context.getRealm(), context.getUser(), credentials);
|
||||
if (!valid) {
|
||||
context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
|
||||
Response challengeResponse = challenge(context);
|
||||
context.getEvent().user(context.getUser())
|
||||
.error(Errors.INVALID_USER_CREDENTIALS);
|
||||
Response challengeResponse = challenge(context, Messages.INVALID_TOTP);
|
||||
context.failureChallenge(AuthenticationProcessor.Error.INVALID_CREDENTIALS, challengeResponse);
|
||||
return;
|
||||
}
|
||||
context.success();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean requiresUser() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected Response challenge(AuthenticatorContext context) {
|
||||
protected Response challenge(AuthenticatorContext context, String error) {
|
||||
ClientSessionCode clientSessionCode = new ClientSessionCode(context.getRealm(), context.getClientSession());
|
||||
URI action = AbstractFormAuthenticator.getActionUrl(context, clientSessionCode);
|
||||
LoginFormsProvider forms = context.getSession().getProvider(LoginFormsProvider.class)
|
||||
.setActionUri(action)
|
||||
.setClientSessionCode(clientSessionCode.getCode());
|
||||
|
||||
if (error != null) forms.setError(error);
|
||||
|
||||
return forms.createLoginTotp();
|
||||
}
|
||||
|
||||
+15
-1
@@ -277,7 +277,21 @@ public class AuthorizationEndpoint {
|
||||
.setUriInfo(uriInfo)
|
||||
.setRequest(request);
|
||||
|
||||
return processor.authenticate();
|
||||
Response challenge = processor.authenticateOnly();
|
||||
|
||||
if (challenge != null && prompt != null && prompt.equals("none")) {
|
||||
if (processor.isUserSessionCreated()) {
|
||||
session.sessions().removeUserSession(realm, processor.getUserSession());
|
||||
}
|
||||
OIDCLoginProtocol oauth = new OIDCLoginProtocol(session, realm, uriInfo, headers, event);
|
||||
return oauth.cancelLogin(clientSession);
|
||||
}
|
||||
|
||||
if (challenge == null) {
|
||||
return processor.finishAuthentication();
|
||||
} else {
|
||||
return challenge;
|
||||
}
|
||||
}
|
||||
|
||||
protected Response oldBrowserAuthentication(String accessCode) {
|
||||
|
||||
@@ -425,6 +425,17 @@ public class AuthenticationManager {
|
||||
public static Response nextActionAfterAuthentication(KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession,
|
||||
ClientConnection clientConnection,
|
||||
HttpRequest request, UriInfo uriInfo, EventBuilder event) {
|
||||
Response requiredAction = actionRequired(session, userSession, clientSession, clientConnection, request, uriInfo, event);
|
||||
if (requiredAction != null) return requiredAction;
|
||||
event.success();
|
||||
RealmModel realm = clientSession.getRealm();
|
||||
return redirectAfterSuccessfulFlow(session, realm , userSession, clientSession, request, uriInfo, clientConnection);
|
||||
|
||||
}
|
||||
|
||||
public static Response actionRequired(KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession,
|
||||
ClientConnection clientConnection,
|
||||
HttpRequest request, UriInfo uriInfo, EventBuilder event) {
|
||||
RealmModel realm = clientSession.getRealm();
|
||||
UserModel user = userSession.getUser();
|
||||
isForcePasswordUpdateRequired(realm, user);
|
||||
@@ -442,7 +453,7 @@ public class AuthenticationManager {
|
||||
if (!requiredActions.isEmpty()) {
|
||||
Iterator<String> i = user.getRequiredActions().iterator();
|
||||
String action = i.next();
|
||||
|
||||
|
||||
if (action.equals(UserModel.RequiredAction.VERIFY_EMAIL.name()) && Validation.isEmpty(user.getEmail())) {
|
||||
if (i.hasNext())
|
||||
action = i.next();
|
||||
@@ -502,12 +513,12 @@ public class AuthenticationManager {
|
||||
.createOAuthGrant(clientSession);
|
||||
}
|
||||
}
|
||||
|
||||
event.success();
|
||||
return redirectAfterSuccessfulFlow(session, realm , userSession, clientSession, request, uriInfo, clientConnection);
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private static void isForcePasswordUpdateRequired(RealmModel realm, UserModel user) {
|
||||
int daysToExpirePassword = realm.getPasswordPolicy().getDaysToExpirePassword();
|
||||
if(daysToExpirePassword != -1) {
|
||||
|
||||
Reference in new issue
Block a user