diff --git a/model/api/src/main/java/org/keycloak/migration/MigrationModel.java b/model/api/src/main/java/org/keycloak/migration/MigrationModel.java
index df24b3d009..cb08418238 100755
--- a/model/api/src/main/java/org/keycloak/migration/MigrationModel.java
+++ b/model/api/src/main/java/org/keycloak/migration/MigrationModel.java
@@ -11,7 +11,7 @@ public interface MigrationModel {
/**
* Must have the form of major.minor.micro as the version is parsed and numbers are compared
*/
- public static final String LATEST_VERSION = "1.3.0.Beta1";
+ public static final String LATEST_VERSION = "1.4.0";
String getStoredVersion();
void setStoredVersion(String version);
diff --git a/model/api/src/main/java/org/keycloak/migration/MigrationModelManager.java b/model/api/src/main/java/org/keycloak/migration/MigrationModelManager.java
index 722bc5e021..b7910037fb 100755
--- a/model/api/src/main/java/org/keycloak/migration/MigrationModelManager.java
+++ b/model/api/src/main/java/org/keycloak/migration/MigrationModelManager.java
@@ -2,6 +2,7 @@ package org.keycloak.migration;
import org.jboss.logging.Logger;
import org.keycloak.migration.migrators.MigrateTo1_3_0;
+import org.keycloak.migration.migrators.MigrateTo1_4_0;
import org.keycloak.migration.migrators.MigrationTo1_2_0_CR1;
import org.keycloak.models.KeycloakSession;
@@ -33,6 +34,12 @@ public class MigrationModelManager {
}
new MigrateTo1_3_0().migrate(session);
}
+ if (stored == null || stored.lessThan(MigrateTo1_4_0.VERSION)) {
+ if (stored != null) {
+ logger.debug("Migrating older model to 1.4.0 updates");
+ }
+ new MigrateTo1_4_0().migrate(session);
+ }
model.setStoredVersion(MigrationModel.LATEST_VERSION);
}
diff --git a/model/api/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java b/model/api/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java
new file mode 100755
index 0000000000..cc15d00e89
--- /dev/null
+++ b/model/api/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java
@@ -0,0 +1,28 @@
+package org.keycloak.migration.migrators;
+
+import org.keycloak.migration.ModelVersion;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.utils.DefaultAuthenticationFlows;
+
+import java.util.List;
+
+/**
+ * @author Bill Burke
+ * @version $Revision: 1 $
+ */
+public class MigrateTo1_4_0 {
+ public static final ModelVersion VERSION = new ModelVersion("1.4.0");
+
+
+ public void migrate(KeycloakSession session) {
+ List realms = session.realms().getRealms();
+ for (RealmModel realm : realms) {
+ if (realm.getAuthenticationFlows().size() == 0) {
+ DefaultAuthenticationFlows.addFlows(realm);
+ }
+
+ }
+
+ }
+}
diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
index af6a67166d..f7d73866bc 100755
--- a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
+++ b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
@@ -19,6 +19,7 @@ import org.keycloak.protocol.oidc.TokenManager;
import org.keycloak.services.ErrorPage;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.BruteForceProtector;
+import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.messages.Messages;
import javax.ws.rs.core.Response;
@@ -317,6 +318,13 @@ public class AuthenticationProcessor {
public String getForwardedErrorMessage() {
return AuthenticationProcessor.this.forwardedErrorMessage;
}
+
+ @Override
+ public String generateAccessCode() {
+ ClientSessionCode accessCode = new ClientSessionCode(getRealm(), getClientSession());
+ accessCode.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
+ return accessCode.getCode();
+ }
}
public static class AuthException extends RuntimeException {
@@ -518,10 +526,7 @@ public class AuthenticationProcessor {
if (model.isUserSetupAllowed()) {
logger.debugv("authenticator SETUP_REQUIRED: {0}", authenticatorModel.getProviderId());
clientSession.setAuthenticatorStatus(model.getId(), UserSessionModel.AuthenticatorStatus.SETUP_REQUIRED);
- String requiredAction = authenticator.getRequiredAction();
- if (!authUser.getRequiredActions().contains(requiredAction)) {
- authUser.addRequiredAction(requiredAction);
- }
+ authenticator.setRequiredActions(session, realm, clientSession.getAuthenticatedUser());
continue;
} else {
throw new AuthException(Error.CREDENTIAL_SETUP_REQUIRED);
diff --git a/services/src/main/java/org/keycloak/authentication/Authenticator.java b/services/src/main/java/org/keycloak/authentication/Authenticator.java
index ee9d43500b..8245f82fe7 100755
--- a/services/src/main/java/org/keycloak/authentication/Authenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/Authenticator.java
@@ -13,7 +13,12 @@ public interface Authenticator extends Provider {
boolean requiresUser();
void authenticate(AuthenticatorContext context);
boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user);
- String getRequiredAction();
+
+ /**
+ * Set actions to configure authenticator
+ *
+ */
+ void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user);
}
diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticatorContext.java b/services/src/main/java/org/keycloak/authentication/AuthenticatorContext.java
index a8f5aadc8f..637d3a8399 100755
--- a/services/src/main/java/org/keycloak/authentication/AuthenticatorContext.java
+++ b/services/src/main/java/org/keycloak/authentication/AuthenticatorContext.java
@@ -73,4 +73,11 @@ public interface AuthenticatorContext {
* whatever form is challenging.
*/
String getForwardedErrorMessage();
+
+ /**
+ * Generates access code and updates clientsession timestamp
+ *
+ * @return
+ */
+ String generateAccessCode();
}
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/AbstractFormAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/AbstractFormAuthenticator.java
index 44d11fdbf9..9184034e20 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/AbstractFormAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/AbstractFormAuthenticator.java
@@ -5,9 +5,7 @@ import org.keycloak.authentication.AuthenticationProcessor;
import org.keycloak.authentication.AuthenticatorContext;
import org.keycloak.events.Errors;
import org.keycloak.login.LoginFormsProvider;
-import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.UserModel;
-import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.LoginActionsService;
@@ -29,22 +27,21 @@ public class AbstractFormAuthenticator {
}
protected LoginFormsProvider loginForm(AuthenticatorContext context) {
- ClientSessionCode code = new ClientSessionCode(context.getRealm(), context.getClientSession());
- code.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
- URI action = getActionUrl(context, code, LOGIN_FORM_ACTION);
+ String accessCode = context.generateAccessCode();
+ URI action = getActionUrl(context, accessCode, LOGIN_FORM_ACTION);
LoginFormsProvider provider = context.getSession().getProvider(LoginFormsProvider.class)
.setUser(context.getUser())
.setActionUri(action)
- .setClientSessionCode(code.getCode());
+ .setClientSessionCode(accessCode);
if (context.getForwardedErrorMessage() != null) {
provider.setError(context.getForwardedErrorMessage());
}
return provider;
}
- public static URI getActionUrl(AuthenticatorContext context, ClientSessionCode code, String action) {
+ public static URI getActionUrl(AuthenticatorContext context, String code, String action) {
return LoginActionsService.authenticationFormProcessor(context.getUriInfo())
- .queryParam(OAuth2Constants.CODE, code.getCode())
+ .queryParam(OAuth2Constants.CODE, code)
.queryParam(ACTION, action)
.build(context.getRealm().getName());
}
@@ -52,25 +49,21 @@ public class AbstractFormAuthenticator {
protected Response invalidUser(AuthenticatorContext context) {
return loginForm(context)
.setError(Messages.INVALID_USER)
- .setClientSessionCode(new ClientSessionCode(context.getRealm(), context.getClientSession()).getCode())
.createLogin();
}
protected Response disabledUser(AuthenticatorContext context) {
return loginForm(context)
- .setClientSessionCode(new ClientSessionCode(context.getRealm(), context.getClientSession()).getCode())
.setError(Messages.ACCOUNT_DISABLED).createLogin();
}
protected Response temporarilyDisabledUser(AuthenticatorContext context) {
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();
}
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/CookieAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/CookieAuthenticator.java
index 1455b2f6c9..a4d64301d5 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/CookieAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/CookieAuthenticator.java
@@ -38,8 +38,7 @@ public class CookieAuthenticator implements Authenticator {
}
@Override
- public String getRequiredAction() {
- return null;
+ public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
}
@Override
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/LoginFormOTPAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/LoginFormOTPAuthenticator.java
index bac37f7822..56ef93a96b 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/LoginFormOTPAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/LoginFormOTPAuthenticator.java
@@ -68,8 +68,11 @@ public class LoginFormOTPAuthenticator extends LoginFormUsernameAuthenticator {
}
@Override
- public String getRequiredAction() {
- return UserModel.RequiredAction.CONFIGURE_TOTP.name();
+ public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
+ if (!user.getRequiredActions().contains(UserModel.RequiredAction.CONFIGURE_TOTP.name())) {
+ user.addRequiredAction(UserModel.RequiredAction.CONFIGURE_TOTP.name());
+ }
+
}
@Override
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/LoginFormPasswordAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/LoginFormPasswordAuthenticator.java
index fb393e2fe7..cdd49b95fd 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/LoginFormPasswordAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/LoginFormPasswordAuthenticator.java
@@ -70,8 +70,11 @@ public class LoginFormPasswordAuthenticator extends LoginFormUsernameAuthenticat
}
@Override
- public String getRequiredAction() {
- return UserModel.RequiredAction.UPDATE_PASSWORD.name();
+ public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
+ if (!user.getRequiredActions().contains(UserModel.RequiredAction.UPDATE_PASSWORD.name())) {
+ user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD.name());
+ }
+
}
@Override
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/LoginFormUsernameAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/LoginFormUsernameAuthenticator.java
index 62e964318d..6c3759a6c7 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/LoginFormUsernameAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/LoginFormUsernameAuthenticator.java
@@ -111,8 +111,7 @@ public class LoginFormUsernameAuthenticator extends AbstractFormAuthenticator im
}
@Override
- public String getRequiredAction() {
- return null;
+ public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
}
@Override
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/OTPFormAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/OTPFormAuthenticator.java
index 325f3cd77d..bce060b4da 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/OTPFormAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/OTPFormAuthenticator.java
@@ -11,7 +11,6 @@ import org.keycloak.models.RealmModel;
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 javax.ws.rs.core.MultivaluedMap;
@@ -69,11 +68,11 @@ public class OTPFormAuthenticator extends AbstractFormAuthenticator implements A
}
protected Response challenge(AuthenticatorContext context, String error) {
- ClientSessionCode clientSessionCode = new ClientSessionCode(context.getRealm(), context.getClientSession());
- URI action = AbstractFormAuthenticator.getActionUrl(context, clientSessionCode, TOTP_FORM_ACTION);
+ String accessCode = context.generateAccessCode();
+ URI action = AbstractFormAuthenticator.getActionUrl(context, accessCode, TOTP_FORM_ACTION);
LoginFormsProvider forms = context.getSession().getProvider(LoginFormsProvider.class)
.setActionUri(action)
- .setClientSessionCode(clientSessionCode.getCode());
+ .setClientSessionCode(accessCode);
if (error != null) forms.setError(error);
return forms.createLoginTotp();
@@ -85,8 +84,11 @@ public class OTPFormAuthenticator extends AbstractFormAuthenticator implements A
}
@Override
- public String getRequiredAction() {
- return UserModel.RequiredAction.CONFIGURE_TOTP.name();
+ public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
+ if (!user.getRequiredActions().contains(UserModel.RequiredAction.CONFIGURE_TOTP.name())) {
+ user.addRequiredAction(UserModel.RequiredAction.CONFIGURE_TOTP.name());
+ }
+
}
@Override
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/SpnegoAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/SpnegoAuthenticator.java
index 3970fa8916..eb6c1eeea0 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/SpnegoAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/SpnegoAuthenticator.java
@@ -15,7 +15,6 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
-import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.messages.Messages;
import javax.ws.rs.core.HttpHeaders;
@@ -131,9 +130,8 @@ public class SpnegoAuthenticator extends AbstractFormAuthenticator implements Au
* @return
*/
protected Response optionalChallengeRedirect(AuthenticatorContext context, String negotiateHeader) {
- ClientSessionCode code = new ClientSessionCode(context.getRealm(), context.getClientSession());
- code.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
- URI action = getActionUrl(context, code, KERBEROS_DISABLED);
+ String accessCode = context.generateAccessCode();
+ URI action = getActionUrl(context, accessCode, KERBEROS_DISABLED);
StringBuilder builder = new StringBuilder();
@@ -162,11 +160,10 @@ public class SpnegoAuthenticator extends AbstractFormAuthenticator implements Au
}
protected Response formChallenge(AuthenticatorContext context, String negotiateHeader) {
- ClientSessionCode code = new ClientSessionCode(context.getRealm(), context.getClientSession());
- code.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
- URI action = getActionUrl(context, code, KERBEROS_DISABLED);
+ String accessCode = context.generateAccessCode();
+ URI action = getActionUrl(context, accessCode, KERBEROS_DISABLED);
return context.getSession().getProvider(LoginFormsProvider.class)
- .setClientSessionCode(new ClientSessionCode(context.getRealm(), context.getClientSession()).getCode())
+ .setClientSessionCode(accessCode)
.setActionUri(action)
.setStatus(Response.Status.UNAUTHORIZED)
.setResponseHeader(HttpHeaders.WWW_AUTHENTICATE, negotiateHeader)
@@ -181,8 +178,7 @@ public class SpnegoAuthenticator extends AbstractFormAuthenticator implements Au
}
@Override
- public String getRequiredAction() {
- return null;
+ public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
}
@Override