keycloak-aplcache

more

6/3/2015 7:51:57 PM

Details

diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
index 570b9ca..c27fb1e 100755
--- a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
+++ b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
@@ -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);
 
     }
 
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 0657e8a..20099f4 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/AbstractFormAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/AbstractFormAuthenticator.java
@@ -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);
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 98f532a..3995b3a 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/LoginFormPasswordAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/LoginFormPasswordAuthenticator.java
@@ -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;
         }
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 b5bf2d0..cf0d4fa 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/OTPFormAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/OTPFormAuthenticator.java
@@ -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();
     }
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
index 85e4067..a5baa07 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
@@ -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) {
diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
index 3ada879..0cfca7a 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -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) {
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/KerberosLdapTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/KerberosLdapTest.java
old mode 100644
new mode 100755
index 8086500..6db2d85
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/KerberosLdapTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/KerberosLdapTest.java
@@ -18,11 +18,13 @@ import org.keycloak.federation.ldap.kerberos.LDAPProviderKerberosConfig;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserFederationProvider;
 import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.testsuite.AssertEvents;
 import org.keycloak.testsuite.rule.KerberosRule;
 import org.keycloak.testsuite.rule.KeycloakRule;
 import org.keycloak.testsuite.rule.WebRule;
+import org.keycloak.testsuite.utils.CredentialHelper;
 
 /**
  * Test of LDAPFederationProvider (Kerberos backed by LDAP)
@@ -41,6 +43,7 @@ public class KerberosLdapTest extends AbstractKerberosTest {
 
         @Override
         public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
+            CredentialHelper.setRequiredCredential(CredentialRepresentation.KERBEROS, appRealm);
             URL url = getClass().getResource("/kerberos-test/kerberos-app-keycloak.json");
             keycloakRule.deployApplication("kerberos-portal", "/kerberos-portal", KerberosCredDelegServlet.class, url.getPath(), "user");
 
@@ -126,7 +129,7 @@ public class KerberosLdapTest extends AbstractKerberosTest {
                 .client("kerberos-app")
                 .user(keycloakRule.getUser("test", "jduke").getId())
                 .detail(Details.REDIRECT_URI, KERBEROS_APP_URL)
-                .detail(Details.AUTH_METHOD, "spnego")
+                //.detail(Details.AUTH_METHOD, "spnego")
                 .detail(Details.USERNAME, "jduke")
                 .assertEvent();
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTest.java
index 644fff3..c373780 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTest.java
@@ -145,9 +145,9 @@ public class LoginTest {
 
             loginPage.assertCurrent();
 
-            Assert.assertEquals("Invalid username or password.", loginPage.getError());
+            Assert.assertEquals("Account is disabled, contact admin.", loginPage.getError());
 
-            events.expectLogin().user(userId).session((String) null).error("invalid_user_credentials").detail(Details.USERNAME, "login-test").assertEvent();
+            events.expectLogin().user(userId).session((String) null).error("user_disabled").detail(Details.USERNAME, "login-test").assertEvent();
         } finally {
             keycloakRule.configure(new KeycloakRule.KeycloakSetup() {
                 @Override
@@ -225,7 +225,7 @@ public class LoginTest {
         driver.navigate().to(oauth.getLoginFormUrl().toString() + "&prompt=none");
         Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
 
-        events.expectLogin().user(userId).removeDetail(Details.USERNAME).detail(Details.AUTH_METHOD, "sso").assertEvent();
+        events.expectLogin().user(userId).removeDetail(Details.USERNAME).assertEvent();
     }
     
     @Test
@@ -359,7 +359,7 @@ public class LoginTest {
         Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
         Assert.assertNotNull(oauth.getCurrentQuery().get(OAuth2Constants.CODE));
 
-        events.expectLogin().user(userId).detail(Details.USERNAME, "login@test.com").assertEvent();
+        events.expectLogin().user(userId).assertEvent();
     }
 
     @Test
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java
index 45795da..e13fa0e 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java
@@ -110,9 +110,11 @@ public class LoginTotpTest {
         loginTotpPage.assertCurrent();
 
         loginTotpPage.login("123456");
+        loginTotpPage.assertCurrent();
+        Assert.assertEquals("Invalid authenticator code.", loginPage.getError());
 
-        loginPage.assertCurrent();
-        Assert.assertEquals("Invalid username or password.", loginPage.getError());
+        //loginPage.assertCurrent();  // Invalid authenticator code.
+        //Assert.assertEquals("Invalid username or password.", loginPage.getError());
 
         events.expectLogin().error("invalid_user_credentials").session((String) null).assertEvent();
     }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/SSOTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/SSOTest.java
index 2f78c6d..f80118b 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/SSOTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/SSOTest.java
@@ -92,7 +92,7 @@ public class SSOTest {
 
         assertTrue(profilePage.isCurrent());
 
-        String sessionId2 = events.expectLogin().detail(Details.AUTH_METHOD, "sso").removeDetail(Details.USERNAME).client("test-app").assertEvent().getSessionId();
+        String sessionId2 = events.expectLogin().removeDetail(Details.USERNAME).client("test-app").assertEvent().getSessionId();
 
         assertEquals(sessionId, sessionId2);
 
@@ -139,7 +139,7 @@ public class SSOTest {
 
             oauth2.openLoginForm();
 
-            events.expectLogin().session(login2.getSessionId()).detail(Details.AUTH_METHOD, "sso").removeDetail(Details.USERNAME).assertEvent();
+            events.expectLogin().session(login2.getSessionId()).removeDetail(Details.USERNAME).assertEvent();
             Assert.assertEquals(RequestType.AUTH_RESPONSE, RequestType.valueOf(driver2.getTitle()));
             Assert.assertNotNull(oauth2.getCurrentQuery().get(OAuth2Constants.CODE));