keycloak-aplcache

Details

diff --git a/distribution/demo-dist/src/main/xslt/standalone.xsl b/distribution/demo-dist/src/main/xslt/standalone.xsl
index 882d1b1..7c0b3c1 100755
--- a/distribution/demo-dist/src/main/xslt/standalone.xsl
+++ b/distribution/demo-dist/src/main/xslt/standalone.xsl
@@ -89,6 +89,7 @@
                     <eviction max-entries="10000" strategy="LRU"/>
                 </local-cache>
                 <local-cache name="sessions"/>
+                <local-cache name="authenticationSessions"/>
                 <local-cache name="offlineSessions"/>
                 <local-cache name="loginFailures"/>
                 <local-cache name="authorization"/>
diff --git a/distribution/server-overlay/src/main/cli/keycloak-install-base.cli b/distribution/server-overlay/src/main/cli/keycloak-install-base.cli
index f24502a..b8a7e89 100644
--- a/distribution/server-overlay/src/main/cli/keycloak-install-base.cli
+++ b/distribution/server-overlay/src/main/cli/keycloak-install-base.cli
@@ -6,6 +6,7 @@ embed-server --server-config=standalone.xml
 /subsystem=infinispan/cache-container=keycloak/local-cache=users:add()
 /subsystem=infinispan/cache-container=keycloak/local-cache=users/eviction=EVICTION:add(max-entries=10000,strategy=LRU)
 /subsystem=infinispan/cache-container=keycloak/local-cache=sessions:add()
+/subsystem=infinispan/cache-container=keycloak/local-cache=authenticationSessions:add()
 /subsystem=infinispan/cache-container=keycloak/local-cache=offlineSessions:add()
 /subsystem=infinispan/cache-container=keycloak/local-cache=loginFailures:add()
 /subsystem=infinispan/cache-container=keycloak/local-cache=work:add()
diff --git a/distribution/server-overlay/src/main/cli/keycloak-install-ha-base.cli b/distribution/server-overlay/src/main/cli/keycloak-install-ha-base.cli
index ec2b56f..e092374 100644
--- a/distribution/server-overlay/src/main/cli/keycloak-install-ha-base.cli
+++ b/distribution/server-overlay/src/main/cli/keycloak-install-ha-base.cli
@@ -7,6 +7,7 @@ embed-server --server-config=standalone-ha.xml
 /subsystem=infinispan/cache-container=keycloak/local-cache=users:add()
 /subsystem=infinispan/cache-container=keycloak/local-cache=users/eviction=EVICTION:add(max-entries=10000,strategy=LRU)
 /subsystem=infinispan/cache-container=keycloak/distributed-cache=sessions:add(mode="SYNC",owners="1")
+/subsystem=infinispan/cache-container=keycloak/distributed-cache=authenticationSessions:add(mode="SYNC",owners="1")
 /subsystem=infinispan/cache-container=keycloak/distributed-cache=offlineSessions:add(mode="SYNC",owners="1")
 /subsystem=infinispan/cache-container=keycloak/distributed-cache=loginFailures:add(mode="SYNC",owners="1")
 /subsystem=infinispan/cache-container=keycloak/local-cache=authorization:add()
diff --git a/model/infinispan/src/main/java/org/keycloak/connections/infinispan/DefaultInfinispanConnectionProviderFactory.java b/model/infinispan/src/main/java/org/keycloak/connections/infinispan/DefaultInfinispanConnectionProviderFactory.java
index 934f0e8..0f63129 100755
--- a/model/infinispan/src/main/java/org/keycloak/connections/infinispan/DefaultInfinispanConnectionProviderFactory.java
+++ b/model/infinispan/src/main/java/org/keycloak/connections/infinispan/DefaultInfinispanConnectionProviderFactory.java
@@ -118,6 +118,7 @@ public class DefaultInfinispanConnectionProviderFactory implements InfinispanCon
             cacheManager.defineConfiguration(InfinispanConnectionProvider.USER_REVISIONS_CACHE_NAME, getRevisionCacheConfig(userRevisionsMaxEntries));
             cacheManager.getCache(InfinispanConnectionProvider.USER_REVISIONS_CACHE_NAME, true);
             cacheManager.getCache(InfinispanConnectionProvider.AUTHORIZATION_CACHE_NAME, true);
+            cacheManager.getCache(InfinispanConnectionProvider.AUTHENTICATION_SESSIONS_CACHE_NAME, true);
             cacheManager.getCache(InfinispanConnectionProvider.KEYS_CACHE_NAME, true);
 
             logger.debugv("Using container managed Infinispan cache container, lookup={1}", cacheContainerLookup);
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/AuthenticatedClientSessionEntity.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/AuthenticatedClientSessionEntity.java
index c7839f4..f892477 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/AuthenticatedClientSessionEntity.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/AuthenticatedClientSessionEntity.java
@@ -17,13 +17,14 @@
 
 package org.keycloak.models.sessions.infinispan.entities;
 
+import java.io.Serializable;
 import java.util.Map;
 import java.util.Set;
 
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
  */
-public class AuthenticatedClientSessionEntity {
+public class AuthenticatedClientSessionEntity implements Serializable {
 
     private String id;
     private String authMethod;
diff --git a/services/src/main/java/org/keycloak/authentication/requiredactions/VerifyEmail.java b/services/src/main/java/org/keycloak/authentication/requiredactions/VerifyEmail.java
index ad84f9d..ae56970 100755
--- a/services/src/main/java/org/keycloak/authentication/requiredactions/VerifyEmail.java
+++ b/services/src/main/java/org/keycloak/authentication/requiredactions/VerifyEmail.java
@@ -27,6 +27,8 @@ import org.keycloak.common.util.Time;
 import org.keycloak.email.EmailException;
 import org.keycloak.email.EmailTemplateProvider;
 import org.keycloak.events.Details;
+import org.keycloak.events.Errors;
+import org.keycloak.events.EventBuilder;
 import org.keycloak.events.EventType;
 import org.keycloak.forms.login.LoginFormsProvider;
 import org.keycloak.models.*;
@@ -74,8 +76,8 @@ public class VerifyEmail implements RequiredActionProvider, RequiredActionFactor
         // Do not allow resending e-mail by simple page refresh, i.e. when e-mail sent, it should be resent properly via email-verification endpoint
         if (! Objects.equals(authSession.getAuthNote(Constants.VERIFY_EMAIL_KEY), email)) {
             authSession.setAuthNote(Constants.VERIFY_EMAIL_KEY, email);
-            context.getEvent().clone().event(EventType.SEND_VERIFY_EMAIL).detail(Details.EMAIL, email).success();
-            challenge = sendVerifyEmail(context.getSession(), loginFormsProvider, context.getUser(), context.getAuthenticationSession());
+            EventBuilder event = context.getEvent().clone().event(EventType.SEND_VERIFY_EMAIL).detail(Details.EMAIL, email);
+            challenge = sendVerifyEmail(context.getSession(), loginFormsProvider, context.getUser(), context.getAuthenticationSession(), event);
         } else {
             challenge = loginFormsProvider.createResponse(UserModel.RequiredAction.VERIFY_EMAIL);
         }
@@ -126,7 +128,7 @@ public class VerifyEmail implements RequiredActionProvider, RequiredActionFactor
         return UserModel.RequiredAction.VERIFY_EMAIL.name();
     }
 
-    private Response sendVerifyEmail(KeycloakSession session, LoginFormsProvider forms, UserModel user, AuthenticationSessionModel authSession) throws UriBuilderException, IllegalArgumentException {
+    private Response sendVerifyEmail(KeycloakSession session, LoginFormsProvider forms, UserModel user, AuthenticationSessionModel authSession, EventBuilder event) throws UriBuilderException, IllegalArgumentException {
         RealmModel realm = session.getContext().getRealm();
         UriInfo uriInfo = session.getContext().getUri();
 
@@ -144,9 +146,10 @@ public class VerifyEmail implements RequiredActionProvider, RequiredActionFactor
 
         try {
             session.getProvider(EmailTemplateProvider.class).setRealm(realm).setUser(user).sendVerifyEmail(link, expirationInMinutes);
+            event.success();
         } catch (EmailException e) {
             logger.error("Failed to send verification email", e);
-            return forms.createResponse(RequiredAction.VERIFY_EMAIL);
+            event.error(Errors.EMAIL_SEND_FAILED);
         }
 
         return forms.createResponse(UserModel.RequiredAction.VERIFY_EMAIL);
diff --git a/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java b/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java
index 82cbddf..24e1a89 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/PolicyEvaluationService.java
@@ -237,6 +237,7 @@ public class PolicyEvaluationService {
 
                     AuthenticationSessionModel authSession = keycloakSession.authenticationSessions().createAuthenticationSession(id, realm, clientModel);
                     authSession.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
+                    authSession.setAuthenticatedUser(userModel);
                     userSession = keycloakSession.sessions().createUserSession(id, realm, userModel, userModel.getUsername(), "127.0.0.1", "passwd", false, null, null);
 
                     AuthenticationManager.setRolesAndMappersInSession(authSession);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/TrustStoreEmailTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/TrustStoreEmailTest.java
index 59d277c..7fb9692 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/TrustStoreEmailTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/TrustStoreEmailTest.java
@@ -18,17 +18,23 @@ package org.keycloak.testsuite.account;
 
 import org.jboss.arquillian.graphene.page.Page;
 import org.junit.After;
+import org.junit.Rule;
 import org.junit.Test;
+import org.keycloak.events.Details;
+import org.keycloak.events.Errors;
+import org.keycloak.events.EventType;
+import org.keycloak.representations.idm.EventRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.representations.idm.UserRepresentation;
 import org.keycloak.testsuite.AbstractTestRealmKeycloakTest;
+import org.keycloak.testsuite.Assert;
+import org.keycloak.testsuite.AssertEvents;
 import org.keycloak.testsuite.admin.ApiUtil;
 import org.keycloak.testsuite.auth.page.AuthRealm;
 import org.keycloak.testsuite.auth.page.account.AccountManagement;
 import org.keycloak.testsuite.auth.page.login.OIDCLogin;
 import org.keycloak.testsuite.auth.page.login.VerifyEmail;
 import org.keycloak.testsuite.util.MailServerConfiguration;
-import org.keycloak.testsuite.util.RealmRepUtil;
 import org.keycloak.testsuite.util.SslMailServer;
 
 import static org.junit.Assert.assertEquals;
@@ -54,6 +60,9 @@ public class TrustStoreEmailTest extends AbstractTestRealmKeycloakTest {
     @Page
     private VerifyEmail testRealmVerifyEmailPage;
 
+    @Rule
+    public AssertEvents events = new AssertEvents(this);
+
     @Override
     public void configureTestRealm(RealmRepresentation testRealm) {
         log.info("enable verify email and configure smtp server to run with ssl in test realm");
@@ -86,6 +95,15 @@ public class TrustStoreEmailTest extends AbstractTestRealmKeycloakTest {
         accountManagement.navigateTo();
         testRealmLoginPage.form().login(user.getUsername(), "password");
 
+        EventRepresentation sendEvent = events.expectRequiredAction(EventType.SEND_VERIFY_EMAIL)
+                .user(user.getId())
+                .client("account")
+                .detail(Details.USERNAME, "test-user@localhost")
+                .detail(Details.EMAIL, "test-user@localhost")
+                .removeDetail(Details.REDIRECT_URI)
+                .assertEvent();
+        String mailCodeId = sendEvent.getDetails().get(Details.CODE_ID);
+
         assertEquals("You need to verify your email address to activate your account.",
                 testRealmVerifyEmailPage.getFeedbackText());
 
@@ -96,6 +114,23 @@ public class TrustStoreEmailTest extends AbstractTestRealmKeycloakTest {
 
         driver.navigate().to(verifyEmailUrl);
 
+        events.expectRequiredAction(EventType.VERIFY_EMAIL)
+                .user(user.getId())
+                .client("account")
+                .detail(Details.USERNAME, "test-user@localhost")
+                .detail(Details.EMAIL, "test-user@localhost")
+                .detail(Details.CODE_ID, mailCodeId)
+                .removeDetail(Details.REDIRECT_URI)
+                .assertEvent();
+
+        events.expectLogin()
+                .client("account")
+                .user(user.getId())
+                .session(mailCodeId)
+                .detail(Details.USERNAME, "test-user@localhost")
+                .removeDetail(Details.REDIRECT_URI)
+                .assertEvent();
+
         assertCurrentUrlStartsWith(accountManagement);
         accountManagement.signOut();
         testRealmLoginPage.form().login(user.getUsername(), "password");
@@ -103,15 +138,27 @@ public class TrustStoreEmailTest extends AbstractTestRealmKeycloakTest {
     }
 
     @Test
-    public void verifyEmailWithSslWrongCertificate() {
+    public void verifyEmailWithSslWrongCertificate() throws Exception {
         UserRepresentation user = ApiUtil.findUserByUsername(testRealm(), "test-user@localhost");
 
         SslMailServer.startWithSsl(this.getClass().getClassLoader().getResource(SslMailServer.INVALID_KEY).getFile());
         accountManagement.navigateTo();
         loginPage.form().login(user.getUsername(), "password");
 
-        assertEquals("Failed to send email, please try again later.\n" +
-                        "« Back to Application",
-                testRealmVerifyEmailPage.getErrorMessage());
+        events.expectRequiredAction(EventType.SEND_VERIFY_EMAIL_ERROR)
+                .error(Errors.EMAIL_SEND_FAILED)
+                .user(user.getId())
+                .client("account")
+                .detail(Details.USERNAME, "test-user@localhost")
+                .detail(Details.EMAIL, "test-user@localhost")
+                .removeDetail(Details.REDIRECT_URI)
+                .assertEvent();
+
+        // Email wasn't send
+        Assert.assertNull(SslMailServer.getLastReceivedMessage());
+
+        // Email wasn't send, but we won't notify end user about that. Admin is aware due to the error in the logs and the SEND_VERIFY_EMAIL_ERROR event.
+        assertEquals("You need to verify your email address to activate your account.",
+                testRealmVerifyEmailPage.getFeedbackText());
     }
 }
\ No newline at end of file
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakServerDeploymentProcessor.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakServerDeploymentProcessor.java
index 96078ff..8567376 100755
--- a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakServerDeploymentProcessor.java
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakServerDeploymentProcessor.java
@@ -41,7 +41,7 @@ import java.util.List;
 public class KeycloakServerDeploymentProcessor implements DeploymentUnitProcessor {
 
     private static final String[] CACHES = new String[] {
-        "realms", "users","sessions","offlineSessions","loginFailures","work","authorization","keys"
+        "realms", "users","sessions","authenticationSessions","offlineSessions","loginFailures","work","authorization","keys"
     };
 
     // This param name is defined again in Keycloak Services class
diff --git a/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-infinispan.xml b/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-infinispan.xml
index 205c1f5..83f7654 100755
--- a/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-infinispan.xml
+++ b/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-infinispan.xml
@@ -32,6 +32,7 @@
                     <eviction max-entries="10000" strategy="LRU"/>
                 </local-cache>
                 <local-cache name="sessions"/>
+                <local-cache name="authenticationSessions"/>
                 <local-cache name="offlineSessions"/>
                 <local-cache name="loginFailures"/>
                 <local-cache name="work"/>
@@ -97,6 +98,7 @@
                     <eviction max-entries="10000" strategy="LRU"/>
                 </local-cache>
                 <distributed-cache name="sessions" mode="SYNC" owners="1"/>
+                <distributed-cache name="authenticationSessions" mode="SYNC" owners="1"/>
                 <distributed-cache name="offlineSessions" mode="SYNC" owners="1"/>
                 <distributed-cache name="loginFailures" mode="SYNC" owners="1"/>
                 <local-cache name="authorization">
diff --git a/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-infinispan2.xml b/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-infinispan2.xml
index 95bcffd..5e706dc 100755
--- a/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-infinispan2.xml
+++ b/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-infinispan2.xml
@@ -32,6 +32,7 @@
                     <eviction max-entries="10000" strategy="LRU"/>
                 </local-cache>
                 <local-cache name="sessions"/>
+                <local-cache name="authenticationSessions"/>
                 <local-cache name="offlineSessions"/>
                 <local-cache name="loginFailures"/>
                 <local-cache name="work"/>
@@ -100,6 +101,7 @@
                     <eviction max-entries="10000" strategy="LRU"/>
                 </local-cache>
                 <distributed-cache name="sessions" mode="SYNC" owners="1"/>
+                <distributed-cache name="authenticationSessions" mode="SYNC" owners="1"/>
                 <distributed-cache name="offlineSessions" mode="SYNC" owners="1"/>
                 <distributed-cache name="loginFailures" mode="SYNC" owners="1"/>
                 <local-cache name="authorization">