keycloak-uncached

Changes

Details

diff --git a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.0.0.Final.xml b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.0.0.Final.xml
index edc976e..1700e39 100644
--- a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.0.0.Final.xml
+++ b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.0.0.Final.xml
@@ -92,6 +92,7 @@
             <column name="SESSION_ID" type="VARCHAR(255)"/>
             <column name="TIME" type="BIGINT"/>
             <column name="TYPE" type="VARCHAR(255)"/>
+            <column name="EVENT_GROUP" type="VARCHAR(255)"/>
             <column name="USER_ID" type="VARCHAR(255)"/>
         </createTable>
         <createTable tableName="FED_PROVIDERS">
@@ -196,6 +197,12 @@
             </column>
             <column name="VALUE" type="VARCHAR(255)"/>
         </createTable>
+        <createTable tableName="REALM_ENABLED_EVENT_TYPES">
+            <column name="REALM_ID" type="VARCHAR(36)">
+                <constraints nullable="false"/>
+            </column>
+            <column name="VALUE" type="VARCHAR(255)"/>
+        </createTable>
         <createTable tableName="REALM_REQUIRED_CREDENTIAL">
             <column name="TYPE" type="VARCHAR(255)">
                 <constraints nullable="false"/>
@@ -405,6 +412,7 @@
         <addForeignKeyConstraint baseColumnNames="CHILD_ROLE" baseTableName="COMPOSITE_ROLE" constraintName="FK_GR7THLLB9LU8Q4VQA4524JJY8" referencedColumnNames="ID" referencedTableName="KEYCLOAK_ROLE"/>
         <addForeignKeyConstraint baseColumnNames="ROLE_ID" baseTableName="REALM_DEFAULT_ROLES" constraintName="FK_H4WPD7W4HSOOLNI3H0SW7BTJE" referencedColumnNames="ID" referencedTableName="KEYCLOAK_ROLE"/>
         <addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="REALM_EVENTS_LISTENERS" constraintName="FK_H846O4H0W8EPX5NXEV9F5Y69J" referencedColumnNames="ID" referencedTableName="REALM"/>
+        <addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="REALM_ENABLED_EVENT_TYPES" constraintName="FK_H846O4H0W8EPX5NWEDRF5Y69J" referencedColumnNames="ID" referencedTableName="REALM"/>
         <addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="REALM_APPLICATION" constraintName="FK_L5QGA3RFME47335JY8JXYXH3I" referencedColumnNames="ID" referencedTableName="CLIENT"/>
         <addForeignKeyConstraint baseColumnNames="CLIENT_ID" baseTableName="WEB_ORIGINS" constraintName="FK_LOJPHO213XCX4WNKOG82SSRFY" referencedColumnNames="ID" referencedTableName="CLIENT"/>
         <addForeignKeyConstraint baseColumnNames="APPLICATION_ID" baseTableName="APPLICATION_DEFAULT_ROLES" constraintName="FK_MAYLTS7KLWQW2H8M2B5JOYTKY" referencedColumnNames="ID" referencedTableName="CLIENT"/>
diff --git a/core/src/main/java/org/keycloak/representations/idm/RealmEventsConfigRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RealmEventsConfigRepresentation.java
index acadc95..a88a75d 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RealmEventsConfigRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RealmEventsConfigRepresentation.java
@@ -10,6 +10,7 @@ public class RealmEventsConfigRepresentation {
     protected boolean eventsEnabled;
     protected Long eventsExpiration;
     protected List<String> eventsListeners;
+    protected List<String> enabledEventTypes;
 
     public boolean isEventsEnabled() {
         return eventsEnabled;
@@ -34,4 +35,12 @@ public class RealmEventsConfigRepresentation {
     public void setEventsListeners(List<String> eventsListeners) {
         this.eventsListeners = eventsListeners;
     }
+
+    public List<String> getEnabledEventTypes() {
+        return enabledEventTypes;
+    }
+
+    public void setEnabledEventTypes(List<String> enabledEventTypes) {
+        this.enabledEventTypes = enabledEventTypes;
+    }
 }
diff --git a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
index 8a4727b..b350e38 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
@@ -68,6 +68,7 @@ public class RealmRepresentation {
     protected Boolean eventsEnabled;
     protected Long eventsExpiration;
     protected List<String> eventsListeners;
+    protected List<String> enabledEventTypes;
     private List<IdentityProviderRepresentation> identityProviders;
     private List<ProtocolMapperRepresentation> protocolMappers;
     private Boolean identityFederationEnabled;
@@ -503,6 +504,14 @@ public class RealmRepresentation {
     public void setEventsListeners(List<String> eventsListeners) {
         this.eventsListeners = eventsListeners;
     }
+    
+    public List<String> getEnabledEventTypes() {
+        return enabledEventTypes;
+    }
+
+    public void setEnabledEventTypes(List<String> enabledEventTypes) {
+        this.enabledEventTypes = enabledEventTypes;
+    }
 
     public List<UserFederationProviderRepresentation> getUserFederationProviders() {
         return userFederationProviders;
diff --git a/events/api/src/main/java/org/keycloak/events/Details.java b/events/api/src/main/java/org/keycloak/events/Details.java
index d24390c..75c71ff 100755
--- a/events/api/src/main/java/org/keycloak/events/Details.java
+++ b/events/api/src/main/java/org/keycloak/events/Details.java
@@ -14,6 +14,9 @@ public interface Details {
     String AUTH_METHOD = "auth_method";
     String IDENTITY_PROVIDER = "identity_provider";
     String IDENTITY_PROVIDER_IDENTITY = "identity_provider_identity";
+    String IDENTITY_PROVIDER_ALIAS = "identity_provider_alias";
+    String IDENTITY_PROVIDER_FACTORY = "identity_provider_factory";
+    String IDENTITY_PROVIDER_FACTORY_IDENTITY = "identity_provider_factory_identity";
     String REGISTER_METHOD = "register_method";
     String USERNAME = "username";
     String REMEMBER_ME = "remember_me";
@@ -23,4 +26,20 @@ public interface Details {
     String UPDATED_REFRESH_TOKEN_ID = "updated_refresh_token_id";
     String NODE_HOST = "node_host";
     String REASON = "reason";
+    
+    String REALM_ID = "realm_id";
+    String REALM_NAME = "realm_name";
+    String REALM_REQUIRED_SSL = "realm_required_ssl";
+    
+    String APPLICATION_CLUSTER_NODE = "application_cluster_node";
+    
+    String ROLE_ID = "role_id";
+    String ROLE_NAME = "role_name";
+    
+    String PROVIDER_ID = "provider_id";
+    String PROVIDER_NAME = "provider_name";
+    
+    String SERVER_VERSION = "server_version";
+    String SERVER_TIME = "server_time";
+    
 }
diff --git a/events/api/src/main/java/org/keycloak/events/Event.java b/events/api/src/main/java/org/keycloak/events/Event.java
index 0099e83..cebd418 100644
--- a/events/api/src/main/java/org/keycloak/events/Event.java
+++ b/events/api/src/main/java/org/keycloak/events/Event.java
@@ -11,6 +11,8 @@ public class Event {
     private long time;
 
     private EventType type;
+    
+    private EventGroup eventGroup;
 
     private String realmId;
 
@@ -41,6 +43,14 @@ public class Event {
     public void setType(EventType type) {
         this.type = type;
     }
+    
+    public EventGroup getEventGroup() {
+        return eventGroup;
+    }
+
+    public void setEventGroup(EventGroup group) {
+        this.eventGroup = group;
+    }
 
     public String getRealmId() {
         return realmId;
@@ -102,6 +112,7 @@ public class Event {
         Event clone = new Event();
         clone.time = time;
         clone.type = type;
+        clone.eventGroup = eventGroup;
         clone.realmId = realmId;
         clone.clientId = clientId;
         clone.userId = userId;
diff --git a/events/api/src/main/java/org/keycloak/events/EventBuilder.java b/events/api/src/main/java/org/keycloak/events/EventBuilder.java
index 8ab6857..0ad60ac 100644
--- a/events/api/src/main/java/org/keycloak/events/EventBuilder.java
+++ b/events/api/src/main/java/org/keycloak/events/EventBuilder.java
@@ -1,26 +1,40 @@
 package org.keycloak.events;
 
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
 import org.jboss.logging.Logger;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionModel;
 
-import java.util.HashMap;
-import java.util.List;
-
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
 public class EventBuilder {
 
     private static final Logger log = Logger.getLogger(EventBuilder.class);
-
-    private List<EventListenerProvider> listeners;
+    
+    // These events are excluded by default and not persisted.
+    private EventType[] events = {EventType.VIEW_REALM,
+            EventType.VIEW_REALM_APPLICATIONS, EventType.VIEW_APPLICATION, EventType.VIEW_APPLICATION_USER_SESSIONS,
+            EventType.VIEW_IDENTITY_PROVIDER, EventType.VIEW_IDENTITY_PROVIDERS, EventType.VIEW_OAUTH_CLIENT,
+            EventType.VIEW_OAUTH_CLIENTS, EventType.VIEW_PROVIDER, EventType.VIEW_PROVIDER_FACTORIES, EventType.VIEW_USER,
+            EventType.VIEW_USER_SESSIONS, EventType.VIEW_USER_SOCIAL_LOGINS, EventType.VIEW_ROLE, EventType.VIEW_ROLES,
+            EventType.VIEW_CLIENT_CERTIFICATE, EventType.VIEW_SERVER_INFO };
+    
     private Event event;
+    private List<EventListenerProvider> listeners;
+    private Set<EventType> enabledEventTypes;
+    private Set<EventType> excludedEvents = new HashSet<EventType>(Arrays.asList(events));;
 
-    public EventBuilder(List<EventListenerProvider> listeners, RealmModel realm, String ipAddress) {
+    public EventBuilder(List<EventListenerProvider> listeners, Set<EventType> enabledEventTypes, RealmModel realm, String ipAddress) {
         this.listeners = listeners;
+        this.enabledEventTypes = enabledEventTypes;
         this.event = new Event();
 
         realm(realm);
@@ -80,6 +94,11 @@ public class EventBuilder {
         return this;
     }
 
+    public EventBuilder eventGroup(EventGroup e) {
+        event.setEventGroup(e);
+        return this;
+    }
+
     public EventBuilder detail(String key, String value) {
         if (value == null || value.equals("")) {
             return this;
@@ -88,7 +107,10 @@ public class EventBuilder {
         if (event.getDetails() == null) {
             event.setDetails(new HashMap<String, String>());
         }
-        event.getDetails().put(key, value);
+
+        if (value != null && !value.isEmpty()) {
+            event.getDetails().put(key, value);
+        }
         return this;
     }
 
@@ -138,7 +160,13 @@ public class EventBuilder {
         if (listeners != null) {
             for (EventListenerProvider l : listeners) {
                 try {
-                    l.onEvent(event);
+                    if (enabledEventTypes != null && enabledEventTypes.size() > 0) {
+                        if (enabledEventTypes.contains(event.getType())) {
+                            l.onEvent(event);
+                        }
+                    } else if (!excludedEvents.contains(event.getType())) {
+                        l.onEvent(event);
+                    }
                 } catch (Throwable t) {
                     log.error("Failed to send type to " + l, t);
                 }
diff --git a/events/api/src/main/java/org/keycloak/events/EventGroup.java b/events/api/src/main/java/org/keycloak/events/EventGroup.java
new file mode 100644
index 0000000..fccdb27
--- /dev/null
+++ b/events/api/src/main/java/org/keycloak/events/EventGroup.java
@@ -0,0 +1,12 @@
+package org.keycloak.events;
+
+/**
+ * @author <a href="mailto:giriraj.sharma27@gmail.com">Giriraj Sharma</a>
+ */
+public enum EventGroup {
+    
+    ADMIN,
+    USER,
+    EMAIL,
+    
+}
diff --git a/events/api/src/main/java/org/keycloak/events/EventType.java b/events/api/src/main/java/org/keycloak/events/EventType.java
index d66660d..3a0dc5e 100755
--- a/events/api/src/main/java/org/keycloak/events/EventType.java
+++ b/events/api/src/main/java/org/keycloak/events/EventType.java
@@ -58,4 +58,66 @@ public enum EventType {
     IDENTITY_PROVIDER_RETRIEVE_TOKEN_ERROR,
     IDENTITY_PROVIDER_ACCCOUNT_LINKING,
     IDENTITY_PROVIDER_ACCCOUNT_LINKING_ERROR,
+    
+    VIEW_REALM,
+    UPDATE_REALM,
+    DELETE_REALM,
+    IMPORT_REALM,
+    UPLOAD_REALM,
+    VIEW_REALM_APPLICATIONS,
+    SET_REALM_USER_PERMISSIONS,
+    SET_REALM_ADAPTER_CONFIGURATION,
+    
+    CREATE_APPLICATION,
+    UPDATE_APPLICATION,
+    VIEW_APPLICATION,
+    DELETE_APPLICATION,
+    
+    VIEW_APPLICATION_USER_SESSIONS,
+    INVALIDATE_APPLICATION_USER_SESSIONS,
+    INVALIDATE_APPLICATION_USER_SESSION,
+    REGISTER_APPLICATION_CLUSTER_NODE,
+    UNREGISTER_APPLICATION_CLUSTER_NODE,
+    
+    VIEW_CLIENT_CERTIFICATE,
+    GENERATE_CLIENT_CERTIFICATE,
+    UPLOAD_CLIENT_CERTIFICATE,
+    DOWNLOAD_CLIENT_CERTIFICATE,
+    
+    VIEW_IDENTITY_PROVIDER,
+    VIEW_IDENTITY_PROVIDERS,
+    IMPORT_IDENTITY_PROVIDER_CONFIG,
+    CREATE_IDENTITY_PROVIDER,
+    UPDATE_IDENTITY_PROVIDER,
+    DELETE_IDENTITY_PROVIDER,
+    
+    CREATE_OAUTH_CLIENT,
+    UPDATE_OAUTH_CLIENT,
+    VIEW_OAUTH_CLIENT,
+    VIEW_OAUTH_CLIENTS,
+    DELETE_OAUTH_CLIENT,
+    
+    VIEW_ROLE,
+    VIEW_ROLES,
+    CREATE_ROLE,
+    UPDATE_ROLE,
+    DELETE_ROLE,
+    MAKE_ROLE_COMPOSITE,
+    
+    UPDATE_USER,
+    CREATE_USER,
+    VIEW_USER,
+    DELETE_USER,
+    VIEW_USER_SESSIONS,
+    VIEW_USER_SOCIAL_LOGINS,
+    INVALIDATE_USER_SESSIONS,
+    
+    CREATE_PROVIDER,
+    VIEW_PROVIDER,
+    VIEW_PROVIDER_FACTORIES,
+    UPDATE_PROVIDER,
+    DELETE_PROVIDER,
+    
+    VIEW_SERVER_INFO,
+    
 }
diff --git a/events/jpa/src/main/java/org/keycloak/events/jpa/EventEntity.java b/events/jpa/src/main/java/org/keycloak/events/jpa/EventEntity.java
index 4a68bb3..9f0aec2 100644
--- a/events/jpa/src/main/java/org/keycloak/events/jpa/EventEntity.java
+++ b/events/jpa/src/main/java/org/keycloak/events/jpa/EventEntity.java
@@ -21,6 +21,9 @@ public class EventEntity {
 
     @Column(name="TYPE")
     private String type;
+    
+    @Column(name="EVENT_GROUP")
+    private String eventGroup;
 
     @Column(name="REALM_ID")
     private String realmId;
@@ -67,6 +70,14 @@ public class EventEntity {
         this.type = type;
     }
 
+    public String getEventGroup() {
+        return eventGroup;
+    }
+
+    public void setEventGroup(String eventGroup) {
+        this.eventGroup = eventGroup;
+    }
+    
     public String getRealmId() {
         return realmId;
     }
diff --git a/events/jpa/src/main/java/org/keycloak/events/jpa/JpaEventStoreProvider.java b/events/jpa/src/main/java/org/keycloak/events/jpa/JpaEventStoreProvider.java
index 40b3840..c604426 100755
--- a/events/jpa/src/main/java/org/keycloak/events/jpa/JpaEventStoreProvider.java
+++ b/events/jpa/src/main/java/org/keycloak/events/jpa/JpaEventStoreProvider.java
@@ -4,12 +4,14 @@ import org.codehaus.jackson.map.ObjectMapper;
 import org.codehaus.jackson.type.TypeReference;
 import org.jboss.logging.Logger;
 import org.keycloak.events.Event;
+import org.keycloak.events.EventGroup;
 import org.keycloak.events.EventQuery;
 import org.keycloak.events.EventStoreProvider;
 import org.keycloak.events.EventType;
 
 import javax.persistence.EntityManager;
 import javax.persistence.EntityTransaction;
+
 import java.io.IOException;
 import java.util.Map;
 import java.util.Set;
@@ -70,6 +72,7 @@ public class JpaEventStoreProvider implements EventStoreProvider {
         e.setId(UUID.randomUUID().toString());
         e.setTime(o.getTime());
         e.setType(o.getType().toString());
+        e.setEventGroup(o.getEventGroup().toString());
         e.setRealmId(o.getRealmId());
         e.setClientId(o.getClientId());
         e.setUserId(o.getUserId());
@@ -88,6 +91,7 @@ public class JpaEventStoreProvider implements EventStoreProvider {
         Event e = new Event();
         e.setTime(o.getTime());
         e.setType(EventType.valueOf(o.getType()));
+        e.setEventGroup(EventGroup.valueOf(o.getEventGroup()));
         e.setRealmId(o.getRealmId());
         e.setClientId(o.getClientId());
         e.setUserId(o.getUserId());
diff --git a/events/mongo/src/main/java/org/keycloak/events/mongo/MongoEventStoreProvider.java b/events/mongo/src/main/java/org/keycloak/events/mongo/MongoEventStoreProvider.java
index 368ef20..8118189 100755
--- a/events/mongo/src/main/java/org/keycloak/events/mongo/MongoEventStoreProvider.java
+++ b/events/mongo/src/main/java/org/keycloak/events/mongo/MongoEventStoreProvider.java
@@ -3,7 +3,9 @@ package org.keycloak.events.mongo;
 import com.mongodb.BasicDBObject;
 import com.mongodb.DBCollection;
 import com.mongodb.DBObject;
+
 import org.keycloak.events.Event;
+import org.keycloak.events.EventGroup;
 import org.keycloak.events.EventQuery;
 import org.keycloak.events.EventStoreProvider;
 import org.keycloak.events.EventType;
@@ -63,6 +65,7 @@ public class MongoEventStoreProvider implements EventStoreProvider {
         BasicDBObject e = new BasicDBObject();
         e.put("time", o.getTime());
         e.put("type", o.getType().toString());
+        e.put("group", o.getEventGroup().toString());
         e.put("realmId", o.getRealmId());
         e.put("clientId", o.getClientId());
         e.put("userId", o.getUserId());
@@ -85,6 +88,7 @@ public class MongoEventStoreProvider implements EventStoreProvider {
         Event e = new Event();
         e.setTime(o.getLong("time"));
         e.setType(EventType.valueOf(o.getString("type")));
+        e.setEventGroup(EventGroup.valueOf(o.getString("group")));
         e.setRealmId(o.getString("realmId"));
         e.setClientId(o.getString("clientId"));
         e.setUserId(o.getString("userId"));
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
index 656ce93..3aa8fb1 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
@@ -1238,6 +1238,19 @@ module.controller('RealmEventsConfigCtrl', function($scope, eventsConfig, RealmE
     });
 
     $scope.eventListeners = serverInfo.eventListeners;
+    
+    // Admin can choose any number of these eventTypes for persistence.
+	// By default, admin view events are not persisted.
+    $scope.enabledEventTypes = [{tag:'LOGIN'}, {tag:'REGISTER'}, {tag:'LOGOUT'}, {tag:'CODE_TO_TOKEN'},
+    	{tag:'REFRESH_TOKEN'}, {tag:'VALIDATE_ACCESS_TOKEN'}, {tag:'LOGIN_ERROR'}, {tag:'REGISTER_ERROR'},
+    	{tag:'LOGOUT_ERROR'}, {tag:'CODE_TO_TOKEN_ERROR'}, {tag:'REFRESH_TOKEN_ERROR'}, {tag:'VALIDATE_ACCESS_TOKEN_ERROR'},
+    	{tag:'UPDATE_EMAIL'}, {tag:'UPDATE_PROFILE'}, {tag:'UPDATE_PASSWORD'}, {tag:'UPDATE_TOTP'},
+    	{tag:'UPLOAD_REALM'}, {tag:'IMPORT_REALM'}, {tag:'UPDATE_REALM'}, {tag:'DELETE_REALM'},
+    	{tag:'CREATE_USER'}, {tag:'UPDATE_USER'}, {tag:'DELETE_USER'}, {tag:'VIEW_USER_SESSIONS'},
+    	{tag:'CREATE_APPLICATION'}, {tag:'UPDATE_APPLICATION'}, {tag:'DELETE_APPLICATION'}, {tag:'VIEW_APPLICATION'},
+    	{tag:'CREATE_OAUTH_CLIENT'}, {tag:'UPDATE_OAUTH_CLIENT'}, {tag:'VIEW_OAUTH_CLIENT'}, {tag:'DELETE_OAUTH_CLIENT'},
+    	{tag:'CREATE_PROVIDER'}, {tag:'UPDATE_PROVIDER'}, {tag:'DELETE_PROVIDER'}, {tag:'VIEW_ROLE'},
+    	{tag:'CREATE_ROLE'}, {tag:'UPDATE_ROLE'}, {tag:'DELETE_ROLE'}, {tag:'VIEW_SERVER_INFO'}]
 
     var oldCopy = angular.copy($scope.eventsConfig);
     $scope.changed = false;
@@ -1282,10 +1295,18 @@ module.controller('RealmEventsCtrl', function($scope, RealmEvents, realm) {
     $scope.realm = realm;
     $scope.page = 0;
     
-    $scope.eventTypes = [{tag:'LOGIN'}, {tag:'REGISTER'}, {tag:'LOGOUT'}, {tag:'CODE_TO_TOKEN'}, {tag:'REFRESH_TOKEN'},
-                         {tag:'LOGIN_ERROR'}, {tag:'REGISTER_ERROR'}, {tag:'LOGOUT_ERROR'}, {tag:'CODE_TO_TOKEN_ERROR'}, {tag:'REFRESH_TOKEN_ERROR'},
-                         {tag:'VALIDATE_ACCESS_TOKEN'}, {tag:'VALIDATE_ACCESS_TOKEN_ERROR'}, {tag:'SOCIAL_LINK'}, {tag:'SOCIAL_LINK_ERROR'}, {tag:'REMOVE_FEDERATED_IDENTITY'},
-                         {tag:'REMOVE_SOCIAL_LINK_ERROR'}, {tag:'UPDATE_EMAIL'}, {tag:'UPDATE_PROFILE'}, {tag:'UPDATE_PASSWORD'}, {tag:'UPDATE_TOTP'}];
+    // Admin can filter events view by selecting any one or multiple of these events.
+    $scope.eventTypes = [{tag:'LOGIN'}, {tag:'REGISTER'}, {tag:'LOGOUT'}, {tag:'CODE_TO_TOKEN'}, 
+                         {tag:'REFRESH_TOKEN'}, {tag:'LOGIN_ERROR'}, {tag:'REGISTER_ERROR'}, {tag:'LOGOUT_ERROR'},
+                         {tag:'CODE_TO_TOKEN_ERROR'}, {tag:'REFRESH_TOKEN_ERROR'}, {tag:'VALIDATE_ACCESS_TOKEN'}, {tag:'VALIDATE_ACCESS_TOKEN_ERROR'}, 
+                         {tag:'SOCIAL_LINK'}, {tag:'SOCIAL_LINK_ERROR'}, {tag:'REMOVE_FEDERATED_IDENTITY'}, {tag:'REMOVE_SOCIAL_LINK_ERROR'},
+                         {tag:'UPDATE_EMAIL'}, {tag:'UPDATE_PROFILE'}, {tag:'UPDATE_PASSWORD'}, {tag:'UPDATE_TOTP'},
+                         {tag:'UPLOAD_REALM'}, {tag:'IMPORT_REALM'}, {tag:'UPDATE_REALM'}, {tag:'DELETE_REALM'},
+                     	 {tag:'CREATE_USER'}, {tag:'UPDATE_USER'}, {tag:'DELETE_USER'}, {tag:'VIEW_USER_SESSIONS'},
+                     	 {tag:'CREATE_APPLICATION'}, {tag:'UPDATE_APPLICATION'}, {tag:'DELETE_APPLICATION'}, {tag:'VIEW_APPLICATION'},
+                     	 {tag:'CREATE_OAUTH_CLIENT'}, {tag:'UPDATE_OAUTH_CLIENT'}, {tag:'VIEW_OAUTH_CLIENT'}, {tag:'DELETE_OAUTH_CLIENT'},
+                     	 {tag:'CREATE_PROVIDER'}, {tag:'UPDATE_PROVIDER'}, {tag:'DELETE_PROVIDER'}, {tag:'VIEW_ROLE'},
+                     	 {tag:'CREATE_ROLE'}, {tag:'UPDATE_ROLE'}, {tag:'DELETE_ROLE'}, {tag:'VIEW_SERVER_INFO'}];
 
     $scope.query = {
         id : realm.realm,
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-events.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-events.html
index 27843f3..b743752 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-events.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-events.html
@@ -34,7 +34,7 @@
       			            <label class="col-sm-2 control-label" for="eventType">Event Type</label>
                     	    <div class="col-sm-5">
                                 <select ui-select2 id="reqActions" ng-model="query.type" data-placeholder="Select event types..." multiple>
-                                    <option ng-repeat="event in eventTypes|orderBy:'tag'">{{event.tag}}</option>
+                                    <option ng-repeat="event in eventTypes">{{event.tag}}</option>
                                 </select>
 			                </div>
 			            </div>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-events-config.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-events-config.html
index 9ce707b..38d5864 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-events-config.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-events-config.html
@@ -52,6 +52,19 @@
 
                     <span tooltip-placement="right" tooltip="Configure what listeners receive events for the realm." class="fa fa-info-circle"></span>
                 </div>
+                
+                <div class="form-group" data-ng-show="eventsConfig.eventsEnabled">
+                    <label class="col-sm-2 control-label" for="enabledEventTypes" class="control-label">Event Types</label>
+
+                    <div class="col-sm-5">
+                        <select ui-select2 ng-model="eventsConfig.enabledEventTypes" data-placeholder="Select an event type(s)..." multiple>
+                            <option ng-repeat="type in enabledEventTypes" value="{{type.tag}}">{{type.tag}}</option>
+                        </select>
+                    </div>
+
+                    <span tooltip-placement="right" tooltip="Configure what event types persist for the realm." class="fa fa-info-circle"></span>
+                </div>
+                
             </fieldset>
 
             <div class="pull-right form-actions" data-ng-show="access.manageEvents">
diff --git a/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java b/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java
index 678fb33..50d2892 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java
@@ -62,6 +62,7 @@ public class RealmEntity extends AbstractIdentifiableEntity {
     private boolean eventsEnabled;
     private long eventsExpiration;
     private List<String> eventsListeners = new ArrayList<String>();
+    private List<String> enabledEventTypes = new ArrayList<String>();
 
     private String adminAppId;
 
@@ -380,6 +381,14 @@ public class RealmEntity extends AbstractIdentifiableEntity {
         this.eventsListeners = eventsListeners;
     }
 
+    public List<String> getEnabledEventTypes() {
+        return enabledEventTypes;
+    }
+
+    public void setEnabledEventTypes(List<String> enabledEventTypes) {
+        this.enabledEventTypes = enabledEventTypes;
+    }
+    
     public String getAdminAppId() {
         return adminAppId;
     }
diff --git a/model/api/src/main/java/org/keycloak/models/RealmModel.java b/model/api/src/main/java/org/keycloak/models/RealmModel.java
index f74d54c..f0c5ebf 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java
@@ -236,6 +236,10 @@ public interface RealmModel extends RoleContainerModel {
     Set<String> getEventsListeners();
 
     void setEventsListeners(Set<String> listeners);
+    
+    Set<String> getEnabledEventTypes();
+
+    void setEnabledEventTypes(Set<String> enabledEventTypes);
 
     ApplicationModel getMasterAdminApp();
 
diff --git a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index 1ff0b01..78a64ca 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -116,6 +116,9 @@ public class ModelToRepresentation {
         if (realm.getEventsListeners() != null) {
             rep.setEventsListeners(new LinkedList<String>(realm.getEventsListeners()));
         }
+        if (realm.getEnabledEventTypes() != null) {
+            rep.setEnabledEventTypes(new LinkedList<String>(realm.getEnabledEventTypes()));
+        }
 
         rep.setVerifyEmail(realm.isVerifyEmail());
         rep.setResetPasswordAllowed(realm.isResetPasswordAllowed());
@@ -182,6 +185,11 @@ public class ModelToRepresentation {
         if (realm.getEventsListeners() != null) {
             rep.setEventsListeners(new LinkedList<String>(realm.getEventsListeners()));
         }
+        
+        if(realm.getEnabledEventTypes() != null) {
+            rep.setEnabledEventTypes(new LinkedList<String>(realm.getEnabledEventTypes()));
+        }
+        
         return rep;
     }
 
diff --git a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index 85e724c..41e97c8 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -357,6 +357,7 @@ public class RepresentationToModel {
         if (rep.isEventsEnabled() != null) realm.setEventsEnabled(rep.isEventsEnabled());
         if (rep.getEventsExpiration() != null) realm.setEventsExpiration(rep.getEventsExpiration());
         if (rep.getEventsListeners() != null) realm.setEventsListeners(new HashSet<String>(rep.getEventsListeners()));
+        if (rep.getEnabledEventTypes() != null) realm.setEnabledEventTypes(new HashSet<String>(rep.getEnabledEventTypes()));
 
         if (rep.getPasswordPolicy() != null) realm.setPasswordPolicy(new PasswordPolicy(rep.getPasswordPolicy()));
 
diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java
index 5894784..975bf29 100755
--- a/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java
+++ b/model/file/src/main/java/org/keycloak/models/file/adapter/RealmAdapter.java
@@ -46,6 +46,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+
 import org.keycloak.connections.file.InMemoryModel;
 import org.keycloak.models.ModelDuplicateException;
 import org.keycloak.models.UserModel;
@@ -1038,6 +1039,20 @@ public class RealmAdapter implements RealmModel {
             realm.setEventsListeners(Collections.EMPTY_LIST);
         }
     }
+    
+    @Override
+    public Set<String> getEnabledEventTypes() {
+        return new HashSet<String>(realm.getEnabledEventTypes());
+    }
+
+    @Override
+    public void setEnabledEventTypes(Set<String> enabledEventTypes) {
+        if (enabledEventTypes != null) {
+            realm.setEnabledEventTypes(new ArrayList<String>(enabledEventTypes));
+        } else {
+            realm.setEnabledEventTypes(Collections.EMPTY_LIST);
+        }        
+    }
 
     @Override
     public ApplicationModel getMasterAdminApp() {
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java
index a4ce5bb..5bbe905 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java
@@ -79,6 +79,7 @@ public class CachedRealm {
     private boolean eventsEnabled;
     private long eventsExpiration;
     private Set<String> eventsListeners = new HashSet<String>();
+    private Set<String> enabledEventTypes = new HashSet<String>();
     private List<String> defaultRoles = new LinkedList<String>();
     private Map<String, String> realmRoles = new HashMap<String, String>();
     private Map<String, String> applications = new HashMap<String, String>();
@@ -146,6 +147,7 @@ public class CachedRealm {
         eventsEnabled = model.isEventsEnabled();
         eventsExpiration = model.getEventsExpiration();
         eventsListeners.addAll(model.getEventsListeners());
+        enabledEventTypes.addAll(model.getEnabledEventTypes());
         defaultRoles.addAll(model.getDefaultRoles());
         masterAdminApp = model.getMasterAdminApp().getId();
 
@@ -348,6 +350,10 @@ public class CachedRealm {
     public Set<String> getEventsListeners() {
         return eventsListeners;
     }
+    
+    public Set<String> getEnabledEventTypes() {
+        return enabledEventTypes;
+    }
 
     public List<UserFederationProviderModel> getUserFederationProviders() {
         return userFederationProviders;
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
index 16c1d34..0cafa72 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
@@ -807,6 +807,18 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
+    public Set<String> getEnabledEventTypes() {
+        if (updated != null) return updated.getEnabledEventTypes();
+        return cached.getEnabledEventTypes();
+    }
+
+    @Override
+    public void setEnabledEventTypes(Set<String> enabledEventTypes) {
+        getDelegateForUpdate();
+        updated.setEnabledEventTypes(enabledEventTypes);        
+    }
+    
+    @Override
     public ApplicationModel getMasterAdminApp() {
         return cacheSession.getRealm(Config.getAdminRealm()).getApplicationById(cached.getMasterAdminApp());
     }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
index 9fbf077..b2a851a 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
@@ -129,6 +129,11 @@ public class RealmEntity {
     @Column(name="VALUE")
     @CollectionTable(name="REALM_EVENTS_LISTENERS", joinColumns={ @JoinColumn(name="REALM_ID") })
     protected Set<String> eventsListeners = new HashSet<String>();
+    
+    @ElementCollection
+    @Column(name="VALUE")
+    @CollectionTable(name="REALM_ENABLED_EVENT_TYPES", joinColumns={ @JoinColumn(name="REALM_ID") })
+    protected Set<String> enabledEventTypes = new HashSet<String>();
 
     @OneToOne
     @JoinColumn(name="MASTER_ADMIN_APP")
@@ -418,7 +423,15 @@ public class RealmEntity {
     public void setEventsListeners(Set<String> eventsListeners) {
         this.eventsListeners = eventsListeners;
     }
+    
+    public Set<String> getEnabledEventTypes() {
+        return enabledEventTypes;
+    }
 
+    public void setEnabledEventTypes(Set<String> enabledEventTypes) {
+        this.enabledEventTypes = enabledEventTypes;
+    }
+    
     public ApplicationEntity getMasterAdminApp() {
         return masterAdminApp;
     }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
index 132b949..9a01119 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
@@ -23,6 +23,7 @@ import org.keycloak.models.utils.KeycloakModelUtils;
 
 import javax.persistence.EntityManager;
 import javax.persistence.TypedQuery;
+
 import java.security.Key;
 import java.security.PrivateKey;
 import java.security.PublicKey;
@@ -1139,6 +1140,17 @@ public class RealmAdapter implements RealmModel {
         realm.setEventsListeners(listeners);
         em.flush();
     }
+    
+    @Override
+    public Set<String> getEnabledEventTypes() {
+        return realm.getEnabledEventTypes();
+    }
+
+    @Override
+    public void setEnabledEventTypes(Set<String> enabledEventTypes) {
+        realm.setEnabledEventTypes(enabledEventTypes);
+        em.flush();
+    }
 
     @Override
     public ApplicationModel getMasterAdminApp() {
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
index ba0c8d7..12f9e77 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
@@ -2,6 +2,7 @@ package org.keycloak.models.mongo.keycloak.adapters;
 
 import com.mongodb.DBObject;
 import com.mongodb.QueryBuilder;
+
 import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
 import org.keycloak.enums.SslRequired;
 import org.keycloak.models.ApplicationModel;
@@ -1046,6 +1047,21 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
     }
 
     @Override
+    public Set<String> getEnabledEventTypes() {
+        return new HashSet<String>(realm.getEnabledEventTypes());
+    }
+
+    @Override
+    public void setEnabledEventTypes(Set<String> enabledEventTypes) {
+        if (enabledEventTypes != null) {
+            realm.setEnabledEventTypes(new ArrayList<String>(enabledEventTypes));
+        } else {
+            realm.setEnabledEventTypes(Collections.EMPTY_LIST);
+        }
+        updateRealm();
+    }
+
+    @Override
     public ApplicationModel getMasterAdminApp() {
         MongoApplicationEntity appData = getMongoStore().loadEntity(MongoApplicationEntity.class, realm.getAdminAppId(), invocationContext);
         return appData != null ? new ApplicationAdapter(session, this, appData, invocationContext) : null;
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 66197b7..9cb6c0e 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
@@ -9,6 +9,7 @@ import org.keycloak.constants.AdapterConstants;
 import org.keycloak.events.Details;
 import org.keycloak.events.Errors;
 import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventGroup;
 import org.keycloak.events.EventType;
 import org.keycloak.login.LoginFormsProvider;
 import org.keycloak.models.ApplicationModel;
@@ -35,6 +36,7 @@ import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
+
 import java.util.List;
 
 /**
@@ -88,7 +90,7 @@ public class AuthorizationEndpoint {
         this.authManager = authManager;
         this.realm = realm;
         this.event = event;
-        event.event(EventType.LOGIN);
+        event.eventGroup(EventGroup.USER).event(EventType.LOGIN);
     }
 
     @GET
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java
index a61c811..eb27a27 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java
@@ -9,6 +9,7 @@ import org.keycloak.OAuthErrorException;
 import org.keycloak.events.Details;
 import org.keycloak.events.Errors;
 import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventGroup;
 import org.keycloak.events.EventType;
 import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
@@ -70,7 +71,7 @@ public class LogoutEndpoint {
         this.tokenManager = tokenManager;
         this.authManager = authManager;
         this.realm = realm;
-        this.event = event;
+        this.event = event.eventGroup(EventGroup.USER);
     }
 
     /**
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java
index bd211e4..cbeca60 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java
@@ -9,6 +9,7 @@ import org.keycloak.constants.AdapterConstants;
 import org.keycloak.events.Details;
 import org.keycloak.events.Errors;
 import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventGroup;
 import org.keycloak.events.EventType;
 import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
@@ -40,6 +41,7 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
+
 import java.util.Map;
 
 /**
@@ -85,7 +87,7 @@ public class TokenEndpoint {
         this.tokenManager = tokenManager;
         this.authManager = authManager;
         this.realm = realm;
-        this.event = event;
+        this.event = event.eventGroup(EventGroup.USER);
     }
 
     @POST
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
index b41e972..bdb807b 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
@@ -26,6 +26,7 @@ import org.keycloak.OAuthErrorException;
 import org.keycloak.RSATokenVerifier;
 import org.keycloak.events.Details;
 import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventGroup;
 import org.keycloak.events.EventType;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
@@ -54,6 +55,7 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 import javax.ws.rs.core.UriInfo;
+
 import java.util.HashMap;
 import java.util.Map;
 
@@ -114,6 +116,7 @@ public class UserInfoEndpoint {
 
     private Response issueUserInfo(String tokenString) {
         EventBuilder event = new EventsManager(realm, session, clientConnection).createEventBuilder()
+                .eventGroup(EventGroup.USER)
                 .event(EventType.USER_INFO_REQUEST)
                 .detail(Details.AUTH_METHOD, Details.VALIDATE_ACCESS_TOKEN);
 
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/ValidateTokenEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/ValidateTokenEndpoint.java
index 31499d1..a3258a6 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/ValidateTokenEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/ValidateTokenEndpoint.java
@@ -9,6 +9,7 @@ import org.keycloak.RSATokenVerifier;
 import org.keycloak.events.Details;
 import org.keycloak.events.Errors;
 import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventGroup;
 import org.keycloak.events.EventType;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
@@ -22,6 +23,7 @@ import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.*;
+
 import java.util.HashMap;
 import java.util.Map;
 
@@ -51,7 +53,7 @@ public class ValidateTokenEndpoint {
     public ValidateTokenEndpoint(TokenManager tokenManager, RealmModel realm, EventBuilder event) {
         this.tokenManager = tokenManager;
         this.realm = realm;
-        this.event = event;
+        this.event = event.eventGroup(EventGroup.USER);
     }
 
     /**
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
index 5815037..3b528e2 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
@@ -26,6 +26,7 @@ import org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor;
 import org.keycloak.OAuth2Constants;
 import org.keycloak.events.Details;
 import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventGroup;
 import org.keycloak.events.EventType;
 import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientSessionModel;
@@ -185,7 +186,7 @@ public class OIDCLoginProtocol implements LoginProtocol {
     public Response finishLogout(UserSessionModel userSession) {
         String redirectUri = userSession.getNote(OIDCLoginProtocol.LOGOUT_REDIRECT_URI);
         String state = userSession.getNote(OIDCLoginProtocol.LOGOUT_STATE_PARAM);
-        event.event(EventType.LOGOUT);
+        event.eventGroup(EventGroup.USER).event(EventType.LOGOUT);
         if (redirectUri != null) {
             event.detail(Details.REDIRECT_URI, redirectUri);
         }
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java
index 6bdae4e..431d05e 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java
@@ -1,18 +1,10 @@
 package org.keycloak.protocol.oidc;
 
 import org.jboss.logging.Logger;
-import org.jboss.resteasy.annotations.cache.NoCache;
-import org.jboss.resteasy.spi.HttpRequest;
-import org.jboss.resteasy.spi.HttpResponse;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
-import org.keycloak.ClientConnection;
 import org.keycloak.OAuth2Constants;
-import org.keycloak.OAuthErrorException;
-import org.keycloak.RSATokenVerifier;
-import org.keycloak.events.Details;
-import org.keycloak.events.Errors;
 import org.keycloak.events.EventBuilder;
-import org.keycloak.events.EventType;
+import org.keycloak.events.EventGroup;
 import org.keycloak.jose.jwk.JWK;
 import org.keycloak.jose.jwk.JWKBuilder;
 import org.keycloak.login.LoginFormsProvider;
@@ -25,8 +17,6 @@ import org.keycloak.protocol.oidc.endpoints.TokenEndpoint;
 import org.keycloak.protocol.oidc.endpoints.UserInfoEndpoint;
 import org.keycloak.protocol.oidc.endpoints.ValidateTokenEndpoint;
 import org.keycloak.protocol.oidc.representations.JSONWebKeySet;
-import org.keycloak.representations.AccessToken;
-import org.keycloak.services.ErrorResponseException;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.resources.RealmsResource;
 import org.keycloak.services.resources.flows.Flows;
@@ -39,12 +29,8 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
-import javax.ws.rs.core.SecurityContext;
 import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.UriInfo;
-import javax.ws.rs.ext.Providers;
-import java.util.HashMap;
-import java.util.Map;
 
 /**
  * Resource class for the oauth/openid connect token service
@@ -73,7 +59,7 @@ public class OIDCLoginProtocolService {
     public OIDCLoginProtocolService(RealmModel realm, EventBuilder event, AuthenticationManager authManager) {
         this.realm = realm;
         this.tokenManager = new TokenManager();
-        this.event = event;
+        this.event = event.eventGroup(EventGroup.USER);
         this.authManager = authManager;
     }
 
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 f8b9bb2..53012e8 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -9,6 +9,7 @@ import org.keycloak.VerificationException;
 import org.keycloak.broker.provider.IdentityProvider;
 import org.keycloak.events.Details;
 import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventGroup;
 import org.keycloak.events.EventType;
 import org.keycloak.jose.jws.JWSBuilder;
 import org.keycloak.login.LoginFormsProvider;
@@ -43,6 +44,7 @@ import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.NewCookie;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
+
 import java.net.URI;
 import java.util.HashSet;
 import java.util.LinkedList;
@@ -374,7 +376,7 @@ public class AuthenticationManager {
         logger.debugv("processAccessCode: go to oauth page?: {0}",
                 !isResource);
 
-        event.detail(Details.CODE_ID, clientSession.getId());
+        event.eventGroup(EventGroup.USER).detail(Details.CODE_ID, clientSession.getId());
 
         Set<UserModel.RequiredAction> requiredActions = user.getRequiredActions();
         if (!requiredActions.isEmpty()) {
diff --git a/services/src/main/java/org/keycloak/services/managers/EventsManager.java b/services/src/main/java/org/keycloak/services/managers/EventsManager.java
index 6288546..0bd5e5a 100755
--- a/services/src/main/java/org/keycloak/services/managers/EventsManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/EventsManager.java
@@ -5,11 +5,14 @@ import org.keycloak.ClientConnection;
 import org.keycloak.events.EventBuilder;
 import org.keycloak.events.EventListenerProvider;
 import org.keycloak.events.EventStoreProvider;
+import org.keycloak.events.EventType;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Set;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -50,8 +53,13 @@ public class EventsManager {
                 }
             }
         }
+        
+        Set<EventType> enabledEventTypes = new HashSet<EventType>();
+        for(String type : realm.getEnabledEventTypes()) {
+            enabledEventTypes.add(EventType.valueOf(type));
+        }
 
-        return new EventBuilder(listeners, realm, clientConnection.getRemoteAddr());
+        return new EventBuilder(listeners, enabledEventTypes, realm, clientConnection.getRemoteAddr());
     }
 
 }
diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
index 4da8e12..138b0e4 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -25,6 +25,7 @@ import org.keycloak.timer.TimerProvider;
 
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.List;
 
 /**
@@ -161,6 +162,9 @@ public class RealmManager {
         if (rep.getEventsListeners() != null) {
             realm.setEventsListeners(new HashSet<String>(rep.getEventsListeners()));
         }
+        if(rep.getEnabledEventTypes() != null) {
+            realm.setEnabledEventTypes(new HashSet<String>(rep.getEnabledEventTypes()));
+        }
     }
 
     // Should be RealmManager moved to model/api instead of referencing methods this way?
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index f694661..f8cc72a 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -31,6 +31,7 @@ import org.keycloak.account.AccountProvider;
 import org.keycloak.events.Details;
 import org.keycloak.events.Event;
 import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventGroup;
 import org.keycloak.events.EventStoreProvider;
 import org.keycloak.events.EventType;
 import org.keycloak.models.*;
@@ -71,6 +72,7 @@ import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.UriInfo;
 import javax.ws.rs.core.Variant;
+
 import java.lang.reflect.Method;
 import java.net.URI;
 import java.util.HashSet;
@@ -141,7 +143,7 @@ public class AccountService {
     public AccountService(RealmModel realm, ApplicationModel application, EventBuilder event) {
         this.realm = realm;
         this.application = application;
-        this.event = event;
+        this.event = event.eventGroup(EventGroup.USER);
         this.authManager = new AppAuthManager();
     }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
index 207d89a..19c876f 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
@@ -6,9 +6,11 @@ import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.HttpRequest;
 import org.jboss.resteasy.spi.HttpResponse;
 import org.jboss.resteasy.spi.NotFoundException;
-import org.keycloak.ClientConnection;
-import org.keycloak.Config;
-import org.keycloak.Version;
+import org.keycloak.ClientConnection;
+import org.keycloak.Version;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
 import org.keycloak.freemarker.BrowserSecurityHeaderSetup;
 import org.keycloak.freemarker.FreeMarkerException;
 import org.keycloak.freemarker.FreeMarkerUtil;
@@ -28,21 +30,18 @@ import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.resources.KeycloakApplication;
 import org.keycloak.services.resources.flows.Urls;
-import org.keycloak.util.MimeTypeUtil;
 
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
-import javax.ws.rs.core.CacheControl;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 import javax.ws.rs.ext.Providers;
+
 import java.io.IOException;
-import java.io.InputStream;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.HashMap;
@@ -86,9 +85,11 @@ public class AdminConsole {
 
     protected AppAuthManager authManager;
     protected RealmModel realm;
+    private EventBuilder event;
 
-    public AdminConsole(RealmModel realm) {
+    public AdminConsole(RealmModel realm, EventBuilder event) {
         this.realm = realm;
+        this.event = event.detail(Details.REALM_NAME, realm.getName());
         this.authManager = new AppAuthManager();
     }
 
@@ -168,6 +169,12 @@ public class AdminConsole {
         if (consoleApp == null) {
             throw new NotFoundException("Could not find admin console application");
         }
+        
+        event.event(EventType.SET_REALM_ADAPTER_CONFIGURATION)
+            .client(consoleApp)
+            .detail(Details.REALM_REQUIRED_SSL, realm.getSslRequired().name().toLowerCase())
+            .success();
+        
         return new ApplicationManager().toInstallationRepresentation(realm, consoleApp, keycloak.getBaseUri(uriInfo));
 
     }
@@ -212,6 +219,8 @@ public class AdminConsole {
             logger.debug("setting up realm access for a realm user");
             addRealmAccess(realm, user, realmAccess);
         }
+        
+        event.event(EventType.SET_REALM_USER_PERMISSIONS).user(user).success();
 
         return Response.ok(new WhoAmI(user.getId(), realm.getName(), displayName, createRealm, realmAccess)).build();
     }
@@ -255,12 +264,14 @@ public class AdminConsole {
     @NoCache
     public Response logout() {
         URI redirect = AdminRoot.adminConsoleUrl(uriInfo).build(realm.getName());
-
+        
+        event.event(EventType.LOGOUT).detail(Details.REDIRECT_URI, redirect.toString()).success();
+                
         return Response.status(302).location(
                 OIDCLoginProtocolService.logoutUrl(uriInfo).queryParam("redirect_uri", redirect.toString()).build(realm.getName())
         ).build();
     }
-
+    
     protected RealmModel getAdminstrationRealm(RealmManager realmManager) {
         return realmManager.getKeycloakAdminstrationRealm();
     }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java
index 4ecdbab..f50bcd5 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java
@@ -8,6 +8,9 @@ import org.jboss.resteasy.spi.NotFoundException;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.jboss.resteasy.spi.UnauthorizedException;
 import org.keycloak.ClientConnection;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventGroup;
 import org.keycloak.jose.jws.JWSInput;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
@@ -16,6 +19,7 @@ import org.keycloak.protocol.oidc.TokenManager;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.services.managers.AppAuthManager;
 import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.services.managers.EventsManager;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.resources.Cors;
 
@@ -27,6 +31,7 @@ import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.UriInfo;
+
 import java.io.IOException;
 
 /**
@@ -70,9 +75,6 @@ public class AdminRoot {
         return base.path(AdminRoot.class);
     }
 
-
-
-
     /**
      * Convenience path to master realm admin console
      *
@@ -124,7 +126,9 @@ public class AdminRoot {
     public AdminConsole getAdminConsole(final @PathParam("realm") String name) {
         RealmManager realmManager = new RealmManager(session);
         RealmModel realm = locateRealm(name, realmManager);
-        AdminConsole service = new AdminConsole(realm);
+        EventBuilder event = new EventsManager(realm, session, clientConnection).createEventBuilder();
+        event.eventGroup(EventGroup.ADMIN).detail(Details.REALM_NAME, realm.getName());
+        AdminConsole service = new AdminConsole(realm, event);
         ResteasyProviderFactory.getInstance().injectProperties(service);
         return service;
     }
@@ -187,7 +191,9 @@ public class AdminRoot {
 
         Cors.add(request).allowedOrigins(auth.getToken()).allowedMethods("GET", "PUT", "POST", "DELETE").auth().build(response);
 
-        RealmsAdminResource adminResource = new RealmsAdminResource(auth, tokenManager);
+        EventBuilder event = new EventsManager(auth.getRealm(), session, clientConnection).createEventBuilder();
+        event.eventGroup(EventGroup.ADMIN);
+        RealmsAdminResource adminResource = new RealmsAdminResource(auth, tokenManager, event);
         ResteasyProviderFactory.getInstance().injectProperties(adminResource);
         //resourceContext.initResource(adminResource);
         return adminResource;
@@ -208,8 +214,10 @@ public class AdminRoot {
             logger.debug("authenticated admin access for: " + auth.getUser().getUsername());
         }
         Cors.add(request).allowedOrigins(auth.getToken()).allowedMethods("GET", "PUT", "POST", "DELETE").auth().build(response);
-
-        ServerInfoAdminResource adminResource = new ServerInfoAdminResource();
+        
+        EventBuilder event = new EventsManager(auth.getRealm(), session, clientConnection).createEventBuilder();
+        event.eventGroup(EventGroup.ADMIN);
+        ServerInfoAdminResource adminResource = new ServerInfoAdminResource(event);
         ResteasyProviderFactory.getInstance().injectProperties(adminResource);
         //resourceContext.initResource(adminResource);
         return adminResource;
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java
index 7df7b1e..9ec26ee 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java
@@ -5,6 +5,9 @@ import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.BadRequestException;
 import org.jboss.resteasy.spi.NotFoundException;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
 import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.ModelDuplicateException;
@@ -40,6 +43,7 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
+
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -57,8 +61,10 @@ public class ApplicationResource {
     protected static final Logger logger = Logger.getLogger(ApplicationResource.class);
     protected RealmModel realm;
     private RealmAuth auth;
+    private EventBuilder event;
     protected ApplicationModel application;
     protected KeycloakSession session;
+    
     @Context
     protected UriInfo uriInfo;
 
@@ -69,12 +75,13 @@ public class ApplicationResource {
         return (KeycloakApplication)keycloak;
     }
 
-    public ApplicationResource(RealmModel realm, RealmAuth auth, ApplicationModel applicationModel, KeycloakSession session) {
+    public ApplicationResource(RealmModel realm, RealmAuth auth, ApplicationModel applicationModel, KeycloakSession session, EventBuilder event) {
         this.realm = realm;
         this.auth = auth;
         this.application = applicationModel;
         this.session = session;
-
+        this.event = event;
+        
         auth.init(RealmAuth.Resource.APPLICATION);
     }
 
@@ -98,6 +105,9 @@ public class ApplicationResource {
 
         try {
             RepresentationToModel.updateApplication(rep, application);
+            
+            event.event(EventType.UPDATE_APPLICATION).client(application).success();
+                    
             return Response.noContent().build();
         } catch (ModelDuplicateException e) {
             return Flows.errors().exists("Application " + rep.getName() + " already exists");
@@ -115,6 +125,8 @@ public class ApplicationResource {
     @Produces(MediaType.APPLICATION_JSON)
     public ApplicationRepresentation getApplication() {
         auth.requireView();
+        
+        event.event(EventType.VIEW_APPLICATION).client(application).success();
 
         return ModelToRepresentation.toRepresentation(application);
     }
@@ -126,7 +138,7 @@ public class ApplicationResource {
      */
     @Path("certificates/{attr}")
     public ClientAttributeCertificateResource getCertficateResource(@PathParam("attr") String attributePrefix) {
-        return new ClientAttributeCertificateResource(realm, auth, application, session, attributePrefix);
+        return new ClientAttributeCertificateResource(realm, auth, application, session, attributePrefix, event);
     }
 
 
@@ -175,6 +187,8 @@ public class ApplicationResource {
     @NoCache
     public void deleteApplication() {
         auth.requireManage();
+        
+        event.event(EventType.DELETE_APPLICATION).client(application).success();
 
         new ApplicationManager(new RealmManager(session)).removeApplication(realm, application);
     }
@@ -228,7 +242,7 @@ public class ApplicationResource {
 
     @Path("roles")
     public RoleContainerResource getRoleContainerResource() {
-        return new RoleContainerResource(realm, auth, application);
+        return new RoleContainerResource(realm, auth, application, event);
     }
 
     /**
@@ -331,6 +345,9 @@ public class ApplicationResource {
             UserSessionRepresentation rep = ModelToRepresentation.toRepresentation(userSession);
             sessions.add(rep);
         }
+        
+        event.event(EventType.VIEW_APPLICATION_USER_SESSIONS).client(application).success();
+        
         return sessions;
     }
 
@@ -342,6 +359,9 @@ public class ApplicationResource {
     @POST
     public GlobalRequestResult logoutAll() {
         auth.requireManage();
+        
+        event.event(EventType.INVALIDATE_APPLICATION_USER_SESSIONS).client(application).success();
+        
         return new ResourceAdminManager().logoutApplication(uriInfo.getRequestUri(), realm, application);
     }
 
@@ -357,6 +377,8 @@ public class ApplicationResource {
         if (user == null) {
             throw new NotFoundException("User not found");
         }
+        
+        event.event(EventType.INVALIDATE_APPLICATION_USER_SESSION).client(application).user(user).success();
 
         new ResourceAdminManager().logoutUserFromApplication(uriInfo.getRequestUri(), realm, application, user, session);
     }
@@ -378,6 +400,10 @@ public class ApplicationResource {
         }
         if (logger.isDebugEnabled()) logger.debug("Register node: " + node);
         application.registerNode(node, Time.currentTime());
+        
+        event.event(EventType.REGISTER_APPLICATION_CLUSTER_NODE).client(application)
+            .detail(Details.APPLICATION_CLUSTER_NODE, node)
+            .success();
     }
 
     /**
@@ -398,6 +424,10 @@ public class ApplicationResource {
         }
 
         application.unregisterNode(node);
+        
+        event.event(EventType.UNREGISTER_APPLICATION_CLUSTER_NODE).client(application)
+            .detail(Details.APPLICATION_CLUSTER_NODE, node)
+            .success();
     }
 
     /**
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsByIdResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsByIdResource.java
index fc93f01..5c84065 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsByIdResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsByIdResource.java
@@ -1,5 +1,6 @@
 package org.keycloak.services.resources.admin;
 
+import org.keycloak.events.EventBuilder;
 import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.RealmModel;
 
@@ -8,8 +9,8 @@ import org.keycloak.models.RealmModel;
  * @version $Revision: 1 $
  */
 public class ApplicationsByIdResource extends ApplicationsResource {
-    public ApplicationsByIdResource(RealmModel realm, RealmAuth auth) {
-        super(realm, auth);
+    public ApplicationsByIdResource(RealmModel realm, RealmAuth auth, EventBuilder event) {
+        super(realm, auth, event);
     }
 
     @Override
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsResource.java
index c74a8f0..f907a04 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsResource.java
@@ -4,6 +4,9 @@ import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.NotFoundException;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
 import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.ModelDuplicateException;
@@ -23,6 +26,7 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -36,14 +40,16 @@ public class ApplicationsResource {
     protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
     protected RealmModel realm;
     private RealmAuth auth;
+    private EventBuilder event;
 
     @Context
     protected KeycloakSession session;
 
-    public ApplicationsResource(RealmModel realm, RealmAuth auth) {
+    public ApplicationsResource(RealmModel realm, RealmAuth auth, EventBuilder event) {
         this.realm = realm;
         this.auth = auth;
-
+        this.event = event;
+        
         auth.init(RealmAuth.Resource.APPLICATION);
     }
 
@@ -71,6 +77,9 @@ public class ApplicationsResource {
                 rep.add(app);
             }
         }
+        
+        event.event(EventType.VIEW_REALM_APPLICATIONS).success();
+        
         return rep;
     }
 
@@ -85,13 +94,16 @@ public class ApplicationsResource {
     @Consumes(MediaType.APPLICATION_JSON)
     public Response createApplication(final @Context UriInfo uriInfo, final ApplicationRepresentation rep) {
         auth.requireManage();
-
+        
         try {
             ApplicationModel applicationModel = RepresentationToModel.createApplication(session, realm, rep, true);
+            
+            event.event(EventType.CREATE_APPLICATION).client(applicationModel).success();
             return Response.created(uriInfo.getAbsolutePathBuilder().path(getApplicationPath(applicationModel)).build()).build();
         } catch (ModelDuplicateException e) {
             return Flows.errors().exists("Application " + rep.getName() + " already exists");
         }
+        
     }
 
     protected String getApplicationPath(ApplicationModel applicationModel) {
@@ -110,7 +122,7 @@ public class ApplicationsResource {
         if (applicationModel == null) {
             throw new NotFoundException("Could not find application: " + name);
         }
-        ApplicationResource applicationResource = new ApplicationResource(realm, auth, applicationModel, session);
+        ApplicationResource applicationResource = new ApplicationResource(realm, auth, applicationModel, session, event);
         ResteasyProviderFactory.getInstance().injectProperties(applicationResource);
         //resourceContext.initResource(applicationResource);
         return applicationResource;
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java
index 4510dc2..670f671 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java
@@ -6,6 +6,9 @@ import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
 import org.jboss.resteasy.spi.BadRequestException;
 import org.jboss.resteasy.spi.NotAcceptableException;
 import org.jboss.resteasy.spi.NotFoundException;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
@@ -21,6 +24,7 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.UriInfo;
+
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -39,18 +43,20 @@ import java.util.Map;
  * @version $Revision: 1 $
  */
 public class ClientAttributeCertificateResource {
+    
     public static final String PRIVATE_KEY = "private.key";
     public static final String X509CERTIFICATE = "certificate";
 
     protected RealmModel realm;
     private RealmAuth auth;
+    private EventBuilder event;
     protected ClientModel client;
     protected KeycloakSession session;
     protected String attributePrefix;
     protected String privateAttribute;
     protected String certificateAttribute;
 
-    public ClientAttributeCertificateResource(RealmModel realm, RealmAuth auth, ClientModel client, KeycloakSession session, String attributePrefix) {
+    public ClientAttributeCertificateResource(RealmModel realm, RealmAuth auth, ClientModel client, KeycloakSession session, String attributePrefix, EventBuilder event) {
         this.realm = realm;
         this.auth = auth;
         this.client = client;
@@ -58,6 +64,7 @@ public class ClientAttributeCertificateResource {
         this.attributePrefix = attributePrefix;
         this.privateAttribute = attributePrefix + "." + PRIVATE_KEY;
         this.certificateAttribute = attributePrefix + "." + X509CERTIFICATE;
+        this.event = event;
     }
 
     public static class ClientKeyPairInfo {
@@ -93,6 +100,9 @@ public class ClientAttributeCertificateResource {
         ClientKeyPairInfo info = new ClientKeyPairInfo();
         info.setCertificate(client.getAttribute(certificateAttribute));
         info.setPrivateKey(client.getAttribute(privateAttribute));
+        
+        event.event(EventType.VIEW_CLIENT_CERTIFICATE).client(client).success();
+
         return info;
     }
 
@@ -131,6 +141,9 @@ public class ClientAttributeCertificateResource {
         ClientKeyPairInfo info = new ClientKeyPairInfo();
         info.setCertificate(client.getAttribute(certificateAttribute));
         info.setPrivateKey(client.getAttribute(privateAttribute));
+        
+        event.event(EventType.GENERATE_CLIENT_CERTIFICATE).client(client).success();
+                
         return info;
     }
 
@@ -187,8 +200,9 @@ public class ClientAttributeCertificateResource {
             client.setAttribute(certificateAttribute, certPem);
             info.setCertificate(certPem);
         }
-
-
+        
+        event.event(EventType.UPLOAD_CLIENT_CERTIFICATE).client(client).success();
+                
         return info;
     }
 
@@ -314,6 +328,9 @@ public class ClientAttributeCertificateResource {
             stream.flush();
             stream.close();
             byte[] rtn = stream.toByteArray();
+            
+            event.event(EventType.DOWNLOAD_CLIENT_CERTIFICATE).client(client).success();
+            
             return rtn;
         } catch (Exception e) {
             throw new RuntimeException(e);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java
index a5c0f50..de931b5 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java
@@ -4,6 +4,9 @@ import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.keycloak.broker.provider.IdentityProvider;
 import org.keycloak.broker.provider.IdentityProviderFactory;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
 import org.keycloak.models.ClientIdentityProviderMappingModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.FederatedIdentityModel;
@@ -29,6 +32,7 @@ import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -43,18 +47,26 @@ public class IdentityProviderResource {
     private final RealmModel realm;
     private final KeycloakSession session;
     private final IdentityProviderModel identityProviderModel;
+    private EventBuilder event;
 
-    public IdentityProviderResource(RealmAuth auth, RealmModel realm, KeycloakSession session, IdentityProviderModel identityProviderModel) {
+    public IdentityProviderResource(RealmAuth auth, RealmModel realm, KeycloakSession session, IdentityProviderModel identityProviderModel, EventBuilder event) {
         this.realm = realm;
         this.session = session;
         this.identityProviderModel = identityProviderModel;
         this.auth = auth;
+        this.event = event;
     }
 
     @GET
     @NoCache
     @Produces("application/json")
     public IdentityProviderRepresentation getIdentityProvider() {
+        
+        event.event(EventType.VIEW_IDENTITY_PROVIDER)
+            .detail(Details.IDENTITY_PROVIDER, identityProviderModel.getProviderId())
+            .detail(Details.IDENTITY_PROVIDER_ALIAS, identityProviderModel.getAlias())
+            .success();
+        
         return ModelToRepresentation.toRepresentation(this.identityProviderModel);
     }
 
@@ -64,7 +76,14 @@ public class IdentityProviderResource {
         this.auth.requireManage();
         removeClientIdentityProviders(this.realm.getApplications(), this.identityProviderModel);
         removeClientIdentityProviders(this.realm.getOAuthClients(), this.identityProviderModel);
-        this.realm.removeIdentityProviderByAlias(this.identityProviderModel.getAlias());
+
+        this.realm.removeIdentityProviderByAlias(this.identityProviderModel.getAlias());
+        
+        event.event(EventType.DELETE_IDENTITY_PROVIDER)
+            .detail(Details.IDENTITY_PROVIDER, identityProviderModel.getProviderId())
+            .detail(Details.IDENTITY_PROVIDER_ALIAS, identityProviderModel.getAlias())
+            .success();
+
         return Response.noContent().build();
     }
 
@@ -89,6 +108,11 @@ public class IdentityProviderResource {
                 updateClientsAfterProviderAliasChange(this.realm.getOAuthClients(), oldProviderId, newProviderId);
                 updateUsersAfterProviderAliasChange(this.session.users().getUsers(this.realm), oldProviderId, newProviderId);
             }
+            
+            event.event(EventType.UPDATE_IDENTITY_PROVIDER)
+                .detail(Details.IDENTITY_PROVIDER, identityProviderModel.getProviderId())
+                .detail(Details.IDENTITY_PROVIDER_ALIAS, identityProviderModel.getAlias())
+                .success();
 
             return Response.noContent().build();
         } catch (ModelDuplicateException e) {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java
index afae00b..19ec301 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java
@@ -8,8 +8,9 @@ import org.jboss.resteasy.spi.NotFoundException;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.broker.provider.IdentityProvider;
 import org.keycloak.broker.provider.IdentityProviderFactory;
-import org.keycloak.models.ClientIdentityProviderMappingModel;
-import org.keycloak.models.ClientModel;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
 import org.keycloak.models.IdentityProviderModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.ModelDuplicateException;
@@ -32,6 +33,7 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
@@ -48,11 +50,13 @@ public class IdentityProvidersResource {
     private final RealmModel realm;
     private final KeycloakSession session;
     private RealmAuth auth;
+    private EventBuilder event;
 
-    public IdentityProvidersResource(RealmModel realm, KeycloakSession session, RealmAuth auth) {
+    public IdentityProvidersResource(RealmModel realm, KeycloakSession session, RealmAuth auth, EventBuilder event) {
         this.realm = realm;
         this.session = session;
         this.auth = auth;
+        this.event = event;
         this.auth.init(RealmAuth.Resource.IDENTITY_PROVIDER);
     }
 
@@ -65,6 +69,11 @@ public class IdentityProvidersResource {
         IdentityProviderFactory providerFactory = getProviderFactorytById(providerId);
 
         if (providerFactory != null) {
+            event.event(EventType.VIEW_IDENTITY_PROVIDERS)
+                .detail(Details.IDENTITY_PROVIDER_FACTORY, providerFactory.getId())
+                .detail(Details.IDENTITY_PROVIDER_FACTORY_IDENTITY, providerFactory.getName())
+                .success();
+            
             return Response.ok(providerFactory).build();
         }
 
@@ -83,6 +92,12 @@ public class IdentityProvidersResource {
         InputStream inputStream = file.getBody(InputStream.class, null);
         IdentityProviderFactory providerFactory = getProviderFactorytById(providerId);
         Map<String, String> config = providerFactory.parseConfig(inputStream);
+        
+        event.event(EventType.IMPORT_IDENTITY_PROVIDER_CONFIG)
+            .detail(Details.IDENTITY_PROVIDER_FACTORY, providerFactory.getId())
+            .detail(Details.IDENTITY_PROVIDER_FACTORY_IDENTITY, providerFactory.getName())
+            .success();
+        
         return config;
     }
 
@@ -104,6 +119,12 @@ public class IdentityProvidersResource {
         }
         IdentityProviderFactory providerFactory = getProviderFactorytById(providerId);
         Map<String, String> config = providerFactory.parseConfig(inputStream);
+        
+        event.event(EventType.IMPORT_IDENTITY_PROVIDER_CONFIG)
+            .detail(Details.IDENTITY_PROVIDER_FACTORY, providerFactory.getId())
+            .detail(Details.IDENTITY_PROVIDER_FACTORY_IDENTITY, providerFactory.getName())
+            .success();
+        
         return config;
     }
 
@@ -119,6 +140,8 @@ public class IdentityProvidersResource {
         for (IdentityProviderModel identityProviderModel : realm.getIdentityProviders()) {
             representations.add(ModelToRepresentation.toRepresentation(identityProviderModel));
         }
+        
+        event.event(EventType.VIEW_IDENTITY_PROVIDERS).success();
 
         return representations;
     }
@@ -131,7 +154,12 @@ public class IdentityProvidersResource {
 
         try {
             this.realm.addIdentityProvider(RepresentationToModel.toModel(representation));
-
+            
+            event.event(EventType.CREATE_IDENTITY_PROVIDER)
+                .detail(Details.IDENTITY_PROVIDER, representation.getProviderId())
+                .detail(Details.IDENTITY_PROVIDER_ALIAS, representation.getAlias())
+                .success();
+            
             return Response.created(uriInfo.getAbsolutePathBuilder().path(representation.getProviderId()).build()).build();
         } catch (ModelDuplicateException e) {
             return Flows.errors().exists("Identity Provider " + representation.getAlias() + " already exists");
@@ -153,9 +181,14 @@ public class IdentityProvidersResource {
         if (identityProviderModel == null) {
             throw new NotFoundException("Could not find identity provider: " + alias);
         }
-
-        IdentityProviderResource identityProviderResource = new IdentityProviderResource(this.auth, realm, session, identityProviderModel);
+        
+        IdentityProviderResource identityProviderResource = new IdentityProviderResource(this.auth, realm, session, identityProviderModel, event);
         ResteasyProviderFactory.getInstance().injectProperties(identityProviderResource);
+        
+        event.event(EventType.VIEW_IDENTITY_PROVIDER)
+            .detail(Details.IDENTITY_PROVIDER, identityProviderModel.getProviderId())
+            .detail(Details.IDENTITY_PROVIDER_ALIAS, identityProviderModel.getAlias())
+            .success();
 
         return identityProviderResource;
     }
@@ -180,4 +213,4 @@ public class IdentityProvidersResource {
 
         return allProviders;
     }
-}
+}
\ No newline at end of file
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java
index b69fb83..ea9a69a 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java
@@ -4,6 +4,9 @@ import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.NotFoundException;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.ModelDuplicateException;
 import org.keycloak.models.OAuthClientModel;
@@ -31,6 +34,7 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
+
 import java.io.IOException;
 
 /**
@@ -43,6 +47,7 @@ public class OAuthClientResource  {
     protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
     protected RealmModel realm;
     private RealmAuth auth;
+    private EventBuilder event;
     protected OAuthClientModel oauthClient;
     protected KeycloakSession session;
     @Context
@@ -55,11 +60,12 @@ public class OAuthClientResource  {
         return (KeycloakApplication)application;
     }
 
-    public OAuthClientResource(RealmModel realm, RealmAuth auth, OAuthClientModel oauthClient, KeycloakSession session) {
+    public OAuthClientResource(RealmModel realm, RealmAuth auth, OAuthClientModel oauthClient, KeycloakSession session, EventBuilder event) {
         this.realm = realm;
         this.auth = auth;
         this.oauthClient = oauthClient;
         this.session = session;
+        this.event = event;
 
         auth.init(RealmAuth.Resource.CLIENT);
     }
@@ -84,7 +90,7 @@ public class OAuthClientResource  {
      */
     @Path("certificates/{attr}")
     public ClientAttributeCertificateResource getCertficateResource(@PathParam("attr") String attributePrefix) {
-        return new ClientAttributeCertificateResource(realm, auth, oauthClient, session, attributePrefix);
+        return new ClientAttributeCertificateResource(realm, auth, oauthClient, session, attributePrefix, event);
     }
 
 
@@ -102,6 +108,8 @@ public class OAuthClientResource  {
 
         try {
             RepresentationToModel.updateOAuthClient(session, rep, oauthClient);
+            event.event(EventType.UPDATE_OAUTH_CLIENT).client(oauthClient).success();
+            
             return Response.noContent().build();
         } catch (ModelDuplicateException e) {
             return Flows.errors().exists("Client " + rep.getName() + " already exists");
@@ -118,7 +126,9 @@ public class OAuthClientResource  {
     @Produces(MediaType.APPLICATION_JSON)
     public OAuthClientRepresentation getOAuthClient() {
         auth.requireView();
-
+        
+        event.event(EventType.VIEW_OAUTH_CLIENT).client(oauthClient).success();
+        
         return ModelToRepresentation.toRepresentation(oauthClient);
     }
 
@@ -150,7 +160,9 @@ public class OAuthClientResource  {
     @NoCache
     public void deleteOAuthClient() {
         auth.requireManage();
-
+        
+        event.event(EventType.DELETE_OAUTH_CLIENT).client(oauthClient).success();
+        
         new OAuthClientManager(new RealmManager(session)).removeClient(realm, oauthClient);
     }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsByIdResource.java b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsByIdResource.java
index b7cfb1a..5f19949 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsByIdResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsByIdResource.java
@@ -1,38 +1,17 @@
 package org.keycloak.services.resources.admin;
 
-import org.jboss.logging.Logger;
-import org.jboss.resteasy.annotations.cache.NoCache;
-import org.jboss.resteasy.spi.NotFoundException;
-import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.events.EventBuilder;
 import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ModelDuplicateException;
 import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.RealmModel;
-import org.keycloak.models.utils.ModelToRepresentation;
-import org.keycloak.models.utils.RepresentationToModel;
-import org.keycloak.representations.idm.OAuthClientRepresentation;
-import org.keycloak.services.resources.flows.Flows;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-import java.util.ArrayList;
-import java.util.List;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
 public class OAuthClientsByIdResource extends OAuthClientsResource {
-    public OAuthClientsByIdResource(RealmModel realm, RealmAuth auth, KeycloakSession session) {
-        super(realm, auth, session);
+    public OAuthClientsByIdResource(RealmModel realm, RealmAuth auth, KeycloakSession session, EventBuilder event) {
+        super(realm, auth, session, event);
     }
 
     @Override
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java
index a2c387c..f76e002 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java
@@ -4,6 +4,9 @@ import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.NotFoundException;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.ModelDuplicateException;
 import org.keycloak.models.OAuthClientModel;
@@ -23,6 +26,7 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -33,9 +37,9 @@ import java.util.List;
 public class OAuthClientsResource {
     protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
     protected RealmModel realm;
-
+    private EventBuilder event;
     protected KeycloakSession session;
-
+    
     /*
     @Context
     protected ResourceContext resourceContext;
@@ -43,11 +47,12 @@ public class OAuthClientsResource {
     */
     private RealmAuth auth;
 
-    public OAuthClientsResource(RealmModel realm, RealmAuth auth, KeycloakSession session) {
+    public OAuthClientsResource(RealmModel realm, RealmAuth auth, KeycloakSession session, EventBuilder event) {
         this.auth = auth;
         this.realm = realm;
         this.session = session;
-
+        this.event = event;
+        
         auth.init(RealmAuth.Resource.CLIENT);
     }
 
@@ -73,6 +78,9 @@ public class OAuthClientsResource {
                 rep.add(client);
             }
         }
+        
+        event.event(EventType.VIEW_OAUTH_CLIENTS).success();
+        
         return rep;
     }
 
@@ -90,10 +98,13 @@ public class OAuthClientsResource {
 
         try {
             OAuthClientModel oauth = RepresentationToModel.createOAuthClient(session, rep, realm);
+            event.event(EventType.CREATE_OAUTH_CLIENT).client(oauth).success();
+            
             return Response.created(uriInfo.getAbsolutePathBuilder().path(getClientPath(oauth)).build()).build();
         } catch (ModelDuplicateException e) {
             return Flows.errors().exists("Client " + rep.getName() + " already exists");
         }
+        
     }
 
     protected String getClientPath(OAuthClientModel oauth) {
@@ -114,7 +125,7 @@ public class OAuthClientsResource {
         if (oauth == null) {
             throw new NotFoundException("OAuth Client not found");
         }
-        OAuthClientResource oAuthClientResource = new OAuthClientResource(realm, auth, oauth, session);
+        OAuthClientResource oAuthClientResource = new OAuthClientResource(realm, auth, oauth, session, event);
         ResteasyProviderFactory.getInstance().injectProperties(oAuthClientResource);
         //resourceContext.initResource(oAuthClientResource);
         return oAuthClientResource;
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
index e62b4ba..75a5416 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -26,6 +26,7 @@ import org.jboss.resteasy.spi.NotFoundException;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.ClientConnection;
 import org.keycloak.events.Event;
+import org.keycloak.events.EventBuilder;
 import org.keycloak.events.EventQuery;
 import org.keycloak.events.EventStoreProvider;
 import org.keycloak.events.EventType;
@@ -63,6 +64,7 @@ public class RealmAdminResource {
     protected RealmAuth auth;
     protected RealmModel realm;
     private TokenManager tokenManager;
+    private EventBuilder event;
 
     @Context
     protected KeycloakSession session;
@@ -75,12 +77,13 @@ public class RealmAdminResource {
 
     @Context
     protected HttpHeaders headers;
-
-    public RealmAdminResource(RealmAuth auth, RealmModel realm, TokenManager tokenManager) {
+
+    public RealmAdminResource(RealmAuth auth, RealmModel realm, TokenManager tokenManager, EventBuilder event) {
         this.auth = auth;
         this.realm = realm;
         this.tokenManager = tokenManager;
-
+        this.event = event;
+        
         auth.init(RealmAuth.Resource.REALM);
     }
 
@@ -102,7 +105,7 @@ public class RealmAdminResource {
      */
     @Path("applications")
     public ApplicationsResource getApplications() {
-        ApplicationsResource applicationsResource = new ApplicationsResource(realm, auth);
+        ApplicationsResource applicationsResource = new ApplicationsResource(realm, auth, event);
         ResteasyProviderFactory.getInstance().injectProperties(applicationsResource);
         //resourceContext.initResource(applicationsResource);
         return applicationsResource;
@@ -115,7 +118,7 @@ public class RealmAdminResource {
      */
     @Path("applications-by-id")
     public ApplicationsByIdResource getApplicationsById() {
-        ApplicationsByIdResource applicationsResource = new ApplicationsByIdResource(realm, auth);
+        ApplicationsByIdResource applicationsResource = new ApplicationsByIdResource(realm, auth, event);
         ResteasyProviderFactory.getInstance().injectProperties(applicationsResource);
         //resourceContext.initResource(applicationsResource);
         return applicationsResource;
@@ -128,7 +131,7 @@ public class RealmAdminResource {
      */
     @Path("oauth-clients")
     public OAuthClientsResource getOAuthClients() {
-        OAuthClientsResource oauth = new OAuthClientsResource(realm, auth, session);
+        OAuthClientsResource oauth = new OAuthClientsResource(realm, auth, session, event);
         ResteasyProviderFactory.getInstance().injectProperties(oauth);
         //resourceContext.initResource(oauth);
         return oauth;
@@ -141,7 +144,7 @@ public class RealmAdminResource {
      */
     @Path("oauth-clients-by-id")
     public OAuthClientsByIdResource getOAuthClientsById() {
-        OAuthClientsByIdResource oauth = new OAuthClientsByIdResource(realm, auth, session);
+        OAuthClientsByIdResource oauth = new OAuthClientsByIdResource(realm, auth, session, event);
         ResteasyProviderFactory.getInstance().injectProperties(oauth);
         //resourceContext.initResource(oauth);
         return oauth;
@@ -154,7 +157,7 @@ public class RealmAdminResource {
      */
     @Path("roles")
     public RoleContainerResource getRoleContainerResource() {
-        return new RoleContainerResource(realm, auth, realm);
+        return new RoleContainerResource(realm, auth, realm, event);
     }
 
     /**
@@ -177,13 +180,18 @@ public class RealmAdminResource {
                 CacheUserProvider cache = (CacheUserProvider)session.userStorage();
                 rep.setUserCacheEnabled(cache.isEnabled());
             }
+            
+            event.event(EventType.VIEW_REALM).success();
+            
             return rep;
         } else {
             auth.requireAny();
 
             RealmRepresentation rep = new RealmRepresentation();
             rep.setRealm(realm.getName());
-
+            
+            event.event(EventType.VIEW_REALM).success();
+            
             return rep;
         }
     }
@@ -218,7 +226,9 @@ public class RealmAdminResource {
             for (final UserFederationProviderModel fedProvider : federationProviders) {
                 usersSyncManager.refreshPeriodicSyncForProvider(session.getKeycloakSessionFactory(), session.getProvider(TimerProvider.class), fedProvider, realm.getId());
             }
-
+            
+            event.event(EventType.UPDATE_REALM).success();
+            
             return Response.noContent().build();
         } catch (ModelDuplicateException e) {
             return Flows.errors().exists("Realm " + rep.getRealm() + " already exists");
@@ -236,6 +246,8 @@ public class RealmAdminResource {
         if (!new RealmManager(session).removeRealm(realm)) {
             throw new NotFoundException("Realm doesn't exist");
         }
+        
+        event.event(EventType.DELETE_REALM).success();
     }
 
     /**
@@ -245,7 +257,7 @@ public class RealmAdminResource {
      */
     @Path("users")
     public UsersResource users() {
-        UsersResource users = new UsersResource(realm, auth, tokenManager);
+        UsersResource users = new UsersResource(realm, auth, tokenManager, event);
         ResteasyProviderFactory.getInstance().injectProperties(users);
         //resourceContext.initResource(users);
         return users;
@@ -253,7 +265,7 @@ public class RealmAdminResource {
 
     @Path("user-federation")
     public UserFederationResource userFederation() {
-        UserFederationResource fed = new UserFederationResource(realm, auth);
+        UserFederationResource fed = new UserFederationResource(realm, auth, event);
         ResteasyProviderFactory.getInstance().injectProperties(fed);
         //resourceContext.initResource(fed);
         return fed;
@@ -266,7 +278,7 @@ public class RealmAdminResource {
      */
     @Path("roles-by-id")
     public RoleByIdResource rolesById() {
-        RoleByIdResource resource = new RoleByIdResource(realm, auth);
+        RoleByIdResource resource = new RoleByIdResource(realm, auth, event);
         ResteasyProviderFactory.getInstance().injectProperties(resource);
         //resourceContext.initResource(resource);
         return resource;
@@ -473,6 +485,6 @@ public class RealmAdminResource {
 
     @Path("identity-provider")
     public IdentityProvidersResource getIdentityProviderResource() {
-        return new IdentityProvidersResource(realm, session, this.auth);
+        return new IdentityProvidersResource(realm, session, this.auth, event);
     }
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
index e434738..947e732 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
@@ -6,6 +6,10 @@ import org.jboss.resteasy.plugins.providers.multipart.InputPart;
 import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
 import org.jboss.resteasy.spi.NotFoundException;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventGroup;
+import org.keycloak.events.EventType;
 import org.keycloak.models.AdminRoles;
 import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.KeycloakSession;
@@ -33,6 +37,7 @@ import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
+
 import java.io.IOException;
 import java.net.URI;
 import java.util.ArrayList;
@@ -49,10 +54,12 @@ public class RealmsAdminResource {
     protected static final Logger logger = Logger.getLogger(RealmsAdminResource.class);
     protected AdminAuth auth;
     protected TokenManager tokenManager;
+    private EventBuilder event;
 
-    public RealmsAdminResource(AdminAuth auth, TokenManager tokenManager) {
+    public RealmsAdminResource(AdminAuth auth, TokenManager tokenManager, EventBuilder event) {
         this.auth = auth;
         this.tokenManager = tokenManager;
+        this.event = event;
     }
 
     public static final CacheControl noCache = new CacheControl();
@@ -72,7 +79,6 @@ public class RealmsAdminResource {
     @Context
     protected KeycloakApplication keycloak;
 
-
     /**
      * Returns a list of realms.  This list is filtered based on what realms the caller is allowed to view.
      *
@@ -135,6 +141,9 @@ public class RealmsAdminResource {
 
             URI location = AdminRoot.realmsUrl(uriInfo).path(realm.getName()).build();
             logger.debugv("imported realm success, sending back: {0}", location.toString());
+            
+            event.event(EventType.IMPORT_REALM).detail(Details.REALM_NAME, realm.getName()).success();
+            
             return Response.created(location).build();
         } catch (ModelDuplicateException e) {
             return Flows.errors().exists("Realm " + rep.getRealm() + " already exists");
@@ -181,8 +190,10 @@ public class RealmsAdminResource {
                 URI location = AdminRoot.realmsUrl(uriInfo).path(realm.getName()).build();
                 return Response.created(location).build();
             }
+            
+            event.event(EventType.UPLOAD_REALM).detail(Details.REALM_NAME, realm.getName()).success();
         }
-
+        
         return Response.noContent().build();
     }
 
@@ -224,8 +235,9 @@ public class RealmsAdminResource {
         } else {
             realmAuth = new RealmAuth(auth, realm.getApplicationByName(realmManager.getRealmAdminApplicationName(auth.getRealm())));
         }
-
-        RealmAdminResource adminResource = new RealmAdminResource(realmAuth, realm, tokenManager);
+        
+        event.detail(Details.REALM_NAME, realm.getName());
+        RealmAdminResource adminResource = new RealmAdminResource(realmAuth, realm, tokenManager, event);
         ResteasyProviderFactory.getInstance().injectProperties(adminResource);
         //resourceContext.initResource(adminResource);
         return adminResource;
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java
index 96c71f2..0775976 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java
@@ -3,7 +3,11 @@ package org.keycloak.services.resources.admin;
 import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.NotFoundException;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
 import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
@@ -18,6 +22,8 @@ import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+
 import java.util.List;
 import java.util.Set;
 
@@ -31,12 +37,17 @@ public class RoleByIdResource extends RoleResource {
     protected static final Logger logger = Logger.getLogger(RoleByIdResource.class);
     private final RealmModel realm;
     private final RealmAuth auth;
+    private EventBuilder event;
+
+    @Context
+    protected KeycloakSession session;
 
-    public RoleByIdResource(RealmModel realm, RealmAuth auth) {
+    public RoleByIdResource(RealmModel realm, RealmAuth auth, EventBuilder event) {
         super(realm);
 
         this.realm = realm;
         this.auth = auth;
+        this.event = event;
     }
 
     /**
@@ -52,6 +63,12 @@ public class RoleByIdResource extends RoleResource {
     public RoleRepresentation getRole(final @PathParam("role-id") String id) {
         RoleModel roleModel = getRoleModel(id);
         auth.requireView();
+        
+        event.event(EventType.VIEW_ROLE)
+            .detail(Details.ROLE_ID, roleModel.getId())
+            .detail(Details.ROLE_NAME, roleModel.getName())
+            .success();
+        
         return getRole(roleModel);
     }
 
@@ -88,6 +105,11 @@ public class RoleByIdResource extends RoleResource {
         RoleModel role = getRoleModel(id);
         auth.requireManage();
         deleteRole(role);
+        
+        event.event(EventType.DELETE_ROLE)
+            .detail(Details.ROLE_ID, role.getId())
+            .detail(Details.ROLE_NAME, role.getName())
+            .success();
     }
 
     /**
@@ -103,6 +125,11 @@ public class RoleByIdResource extends RoleResource {
         RoleModel role = getRoleModel(id);
         auth.requireManage();
         updateRole(rep, role);
+        
+        event.event(EventType.UPDATE_ROLE)
+            .detail(Details.ROLE_ID, role.getId())
+            .detail(Details.ROLE_NAME, role.getName())
+            .success();
     }
 
     /**
@@ -118,6 +145,11 @@ public class RoleByIdResource extends RoleResource {
         RoleModel role = getRoleModel(id);
         auth.requireManage();
         addComposites(roles, role);
+        
+        event.event(EventType.MAKE_ROLE_COMPOSITE)
+            .detail(Details.ROLE_ID, role.getId())
+            .detail(Details.ROLE_NAME, role.getName())
+            .success();
     }
 
     /**
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java
index 5ee76af..f01841d 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleContainerResource.java
@@ -2,6 +2,9 @@ package org.keycloak.services.resources.admin;
 
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.NotFoundException;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
 import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ModelDuplicateException;
 import org.keycloak.models.RealmModel;
@@ -22,6 +25,7 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
@@ -34,12 +38,14 @@ public class RoleContainerResource extends RoleResource {
     private final RealmModel realm;
     private final RealmAuth auth;
     protected RoleContainerModel roleContainer;
+    private EventBuilder event;
 
-    public RoleContainerResource(RealmModel realm, RealmAuth auth, RoleContainerModel roleContainer) {
+    public RoleContainerResource(RealmModel realm, RealmAuth auth, RoleContainerModel roleContainer, EventBuilder event) {
         super(realm);
         this.realm = realm;
         this.auth = auth;
         this.roleContainer = roleContainer;
+        this.event = event;
     }
 
     /**
@@ -58,6 +64,9 @@ public class RoleContainerResource extends RoleResource {
         for (RoleModel roleModel : roleModels) {
             roles.add(ModelToRepresentation.toRepresentation(roleModel));
         }
+        
+        event.event(EventType.VIEW_ROLES).success();
+        
         return roles;
     }
 
@@ -76,6 +85,12 @@ public class RoleContainerResource extends RoleResource {
         try {
             RoleModel role = roleContainer.addRole(rep.getName());
             role.setDescription(rep.getDescription());
+            
+            event.event(EventType.CREATE_ROLE)
+                .detail(Details.ROLE_ID, role.getId())
+                .detail(Details.ROLE_NAME, role.getName())
+                .success();
+            
             return Response.created(uriInfo.getAbsolutePathBuilder().path(role.getName()).build()).build();
         } catch (ModelDuplicateException e) {
             return Flows.errors().exists("Role with name " + rep.getName() + " already exists");
@@ -99,6 +114,12 @@ public class RoleContainerResource extends RoleResource {
         if (roleModel == null) {
             throw new NotFoundException("Could not find role: " + roleName);
         }
+        
+        event.event(EventType.VIEW_ROLE)
+            .detail(Details.ROLE_ID, roleModel.getId())
+            .detail(Details.ROLE_NAME, roleModel.getName())
+            .success();
+        
         return getRole(roleModel);
     }
 
@@ -118,6 +139,11 @@ public class RoleContainerResource extends RoleResource {
             throw new NotFoundException("Could not find role: " + roleName);
         }
         deleteRole(role);
+        
+        event.event(EventType.DELETE_ROLE)
+            .detail(Details.ROLE_ID, role.getId())
+            .detail(Details.ROLE_NAME, role.getName())
+            .success();
     }
 
     /**
@@ -139,6 +165,12 @@ public class RoleContainerResource extends RoleResource {
         }
         try {
             updateRole(rep, role);
+            
+            event.event(EventType.UPDATE_ROLE)
+                .detail(Details.ROLE_ID, role.getId())
+                .detail(Details.ROLE_NAME, role.getName())
+                .success();
+            
             return Response.noContent().build();
         } catch (ModelDuplicateException e) {
             return Flows.errors().exists("Role with name " + rep.getName() + " already exists");
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java
index 80ba402..df75c51 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java
@@ -3,7 +3,10 @@ package org.keycloak.services.resources.admin;
 import org.keycloak.Version;
 import org.keycloak.broker.provider.IdentityProvider;
 import org.keycloak.broker.provider.IdentityProviderFactory;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventBuilder;
 import org.keycloak.events.EventListenerProvider;
+import org.keycloak.events.EventType;
 import org.keycloak.exportimport.ApplicationImporter;
 import org.keycloak.exportimport.ApplicationImporterFactory;
 import org.keycloak.freemarker.Theme;
@@ -23,6 +26,7 @@ import org.keycloak.social.SocialIdentityProvider;
 
 import javax.ws.rs.GET;
 import javax.ws.rs.core.Context;
+
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;
@@ -40,7 +44,13 @@ public class ServerInfoAdminResource {
 
     @Context
     private KeycloakSession session;
-
+    
+    private EventBuilder event;
+    
+    public ServerInfoAdminResource(EventBuilder event) {
+        this.event = event;
+    }
+    
     /**
      * Returns a list of themes, social providers, auth providers, and event listeners available on this server
      *
@@ -60,6 +70,12 @@ public class ServerInfoAdminResource {
         setProviders(info);
         setProtocolMapperTypes(info);
         setBuiltinProtocolMappers(info);
+        
+        event.event(EventType.VIEW_SERVER_INFO)
+            .detail(Details.SERVER_VERSION, info.version)
+            .detail(Details.SERVER_TIME, info.serverTime)
+            .success();
+        
         return info;
     }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationResource.java
index 47f1b65..1dad039 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationResource.java
@@ -11,6 +11,9 @@ import org.keycloak.models.UserFederationProvider;
 import org.keycloak.models.UserFederationProviderFactory;
 import org.keycloak.models.UserFederationProviderModel;
 import org.keycloak.constants.KerberosConstants;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
 import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.provider.ProviderFactory;
 import org.keycloak.representations.idm.UserFederationProviderFactoryRepresentation;
@@ -30,6 +33,7 @@ import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
+
 import java.util.LinkedList;
 import java.util.List;
 
@@ -45,16 +49,19 @@ public class UserFederationResource {
     protected RealmModel realm;
 
     protected  RealmAuth auth;
-
+    
+    private EventBuilder event;
+    
     @Context
     protected UriInfo uriInfo;
-
+    
     @Context
     protected KeycloakSession session;
 
-    public UserFederationResource(RealmModel realm, RealmAuth auth) {
+    public UserFederationResource(RealmModel realm, RealmAuth auth, EventBuilder event) {
         this.auth = auth;
         this.realm = realm;
+        this.event = event;
 
         auth.init(RealmAuth.Resource.USER);
     }
@@ -77,11 +84,14 @@ public class UserFederationResource {
             rep.setOptions(((UserFederationProviderFactory)factory).getConfigurationOptions());
             providers.add(rep);
         }
+        
+        event.event(EventType.VIEW_PROVIDER_FACTORIES).success();
+        
         return providers;
     }
 
     /**
-     * Get List of available provider factories
+     * Get a provider
      *
      * @return
      */
@@ -98,6 +108,9 @@ public class UserFederationResource {
             UserFederationProviderFactoryRepresentation rep = new UserFederationProviderFactoryRepresentation();
             rep.setId(factory.getId());
             rep.setOptions(((UserFederationProviderFactory)factory).getConfigurationOptions());
+            
+            event.event(EventType.VIEW_PROVIDER).detail(Details.PROVIDER_ID, rep.getId()).success();
+            
             return rep;
         }
         throw new NotFoundException("Could not find provider");
@@ -122,7 +135,12 @@ public class UserFederationResource {
                 rep.getFullSyncPeriod(), rep.getChangedSyncPeriod(), rep.getLastSync());
         new UsersSyncManager().refreshPeriodicSyncForProvider(session.getKeycloakSessionFactory(), session.getProvider(TimerProvider.class), model, realm.getId());
         checkKerberosCredential(model);
-
+        
+        event.event(EventType.CREATE_PROVIDER)
+            .detail(Details.PROVIDER_ID, model.getId())
+            .detail(Details.PROVIDER_NAME, model.getProviderName())
+            .success();
+        
         return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build();
     }
 
@@ -146,6 +164,11 @@ public class UserFederationResource {
         realm.updateUserFederationProvider(model);
         new UsersSyncManager().refreshPeriodicSyncForProvider(session.getKeycloakSessionFactory(), session.getProvider(TimerProvider.class), model, realm.getId());
         checkKerberosCredential(model);
+        
+        event.event(EventType.UPDATE_PROVIDER)
+            .detail(Details.PROVIDER_ID, model.getId())
+            .detail(Details.PROVIDER_NAME, model.getProviderName())
+            .success();
     }
 
     /**
@@ -161,9 +184,16 @@ public class UserFederationResource {
         auth.requireView();
         for (UserFederationProviderModel model : realm.getUserFederationProviders()) {
             if (model.getId().equals(id)) {
+                
+                event.event(EventType.VIEW_PROVIDER)
+                    .detail(Details.PROVIDER_ID, model.getId())
+                    .detail(Details.PROVIDER_NAME, model.getProviderName())
+                    .success();
+                
                 return ModelToRepresentation.toRepresentation(model);
             }
         }
+        
         throw new NotFoundException("could not find provider");
     }
 
@@ -179,6 +209,11 @@ public class UserFederationResource {
         UserFederationProviderModel model = new UserFederationProviderModel(id, null, null, -1, null, -1, -1, 0);
         realm.removeUserFederationProvider(model);
         new UsersSyncManager().removePeriodicSyncForProvider(session.getProvider(TimerProvider.class), model);
+        
+        event.event(EventType.DELETE_PROVIDER)
+            .detail(Details.PROVIDER_ID, model.getId())
+            .detail(Details.PROVIDER_NAME, model.getProviderName())
+            .success();
     }
 
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
index e860ea8..f66ec2e 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
@@ -7,6 +7,9 @@ import org.jboss.resteasy.spi.NotFoundException;
 import org.keycloak.ClientConnection;
 import org.keycloak.email.EmailException;
 import org.keycloak.email.EmailProvider;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
 import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
@@ -24,7 +27,6 @@ import org.keycloak.models.UserSessionModel;
 import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.models.utils.RepresentationToModel;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
-import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.protocol.oidc.TokenManager;
 import org.keycloak.protocol.oidc.utils.RedirectUtils;
 import org.keycloak.representations.idm.ApplicationMappingsRepresentation;
@@ -57,6 +59,7 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.UriInfo;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -79,6 +82,8 @@ public class UsersResource {
     private RealmAuth auth;
 
     private TokenManager tokenManager;
+    
+    private EventBuilder event;
 
     @Context
     protected ClientConnection clientConnection;
@@ -91,11 +96,12 @@ public class UsersResource {
 
     @Context
     protected HttpHeaders headers;
-
-    public UsersResource(RealmModel realm, RealmAuth auth, TokenManager tokenManager) {
+    
+    public UsersResource(RealmModel realm, RealmAuth auth, TokenManager tokenManager, EventBuilder event) {
         this.auth = auth;
         this.realm = realm;
         this.tokenManager = tokenManager;
+        this.event = event;
 
         auth.init(RealmAuth.Resource.USER);
     }
@@ -120,10 +126,15 @@ public class UsersResource {
             }
             updateUserFromRep(user, rep);
 
+            event.event(EventType.UPDATE_USER)
+                .user(user)
+                .detail(Details.USERNAME, user.getUsername())
+                .success();
+            
             if (session.getTransaction().isActive()) {
                 session.getTransaction().commit();
             }
-
+            
             return Response.noContent().build();
         } catch (ModelDuplicateException e) {
             return Flows.errors().exists("User exists with same username or email");
@@ -155,11 +166,16 @@ public class UsersResource {
         try {
             UserModel user = session.users().addUser(realm, rep.getUsername());
             updateUserFromRep(user, rep);
-
+            
+            event.event(EventType.CREATE_USER)
+                .user(user)
+                .detail(Details.USERNAME, user.getUsername())
+                .success();
+            
             if (session.getTransaction().isActive()) {
                 session.getTransaction().commit();
             }
-
+            
             return Response.created(uriInfo.getAbsolutePathBuilder().path(user.getUsername()).build()).build();
         } catch (ModelDuplicateException e) {
             if (session.getTransaction().isActive()) {
@@ -220,6 +236,12 @@ public class UsersResource {
         if (user == null) {
             throw new NotFoundException("User not found");
         }
+        
+        event.event(EventType.VIEW_USER)
+            .user(user)
+            .detail(Details.USERNAME, user.getUsername())
+            .success();
+        
         return ModelToRepresentation.toRepresentation(user);
     }
 
@@ -245,6 +267,12 @@ public class UsersResource {
             UserSessionRepresentation rep = ModelToRepresentation.toRepresentation(session);
             reps.add(rep);
         }
+        
+        event.event(EventType.VIEW_USER_SESSIONS)
+            .user(user)
+            .detail(Details.USERNAME, user.getUsername())
+            .success();
+
         return reps;
     }
 
@@ -276,6 +304,12 @@ public class UsersResource {
                 }
             }
         }
+        
+        event.event(EventType.VIEW_USER_SOCIAL_LOGINS)
+            .user(user)
+            .detail(Details.USERNAME, user.getUsername())
+            .success();
+        
         return result;
     }
 
@@ -326,10 +360,16 @@ public class UsersResource {
         if (user == null) {
             throw new NotFoundException("User not found");
         }
+
         List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm, user);
         for (UserSessionModel userSession : userSessions) {
             AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers);
         }
+        
+        event.event(EventType.INVALIDATE_USER_SESSIONS)
+            .user(user)
+            .detail(Details.USERNAME, user.getUsername())
+            .success();
     }
 
     /**
@@ -350,6 +390,12 @@ public class UsersResource {
 
         boolean removed = new UserManager(session).removeUser(realm, user);
         if (removed) {
+            
+            event.event(EventType.DELETE_USER)
+                .user(user)
+                .detail(Details.USERNAME, user.getUsername())
+                .success();
+            
             return Response.noContent().build();
         } else {
             return Flows.errors().error("User couldn't be deleted", Response.Status.BAD_REQUEST);
diff --git a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
index 7a4bea5..251130d 100755
--- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
+++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
@@ -29,6 +29,7 @@ import org.keycloak.broker.provider.IdentityProviderFactory;
 import org.keycloak.events.Details;
 import org.keycloak.events.Errors;
 import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventGroup;
 import org.keycloak.events.EventType;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
@@ -61,6 +62,7 @@ import javax.ws.rs.PathParam;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.*;
 import javax.ws.rs.core.Response.Status;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -109,7 +111,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
     }
 
     public void init() {
-        this.event = new EventsManager(this.realmModel, this.session, this.clientConnection).createEventBuilder().event(EventType.IDENTITY_PROVIDER_LOGIN);
+        this.event = new EventsManager(this.realmModel, this.session, this.clientConnection).createEventBuilder().event(EventType.IDENTITY_PROVIDER_LOGIN).eventGroup(EventGroup.USER);
     }
 
     @GET
diff --git a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
index 5b40535..a802182 100755
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
@@ -29,6 +29,7 @@ import org.keycloak.email.EmailProvider;
 import org.keycloak.events.Details;
 import org.keycloak.events.Errors;
 import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventGroup;
 import org.keycloak.events.EventType;
 import org.keycloak.jose.jws.JWSBuilder;
 import org.keycloak.login.LoginFormsProvider;
@@ -63,6 +64,7 @@ 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;
@@ -132,7 +134,7 @@ public class LoginActionsService {
     public LoginActionsService(RealmModel realm, AuthenticationManager authManager, EventBuilder event) {
         this.realm = realm;
         this.authManager = authManager;
-        this.event = event;
+        this.event = event.eventGroup(EventGroup.USER);
     }
 
     private boolean checkSsl() {
diff --git a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
index 1f43e9a..22aab14 100755
--- a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
@@ -5,6 +5,7 @@ import org.jboss.resteasy.spi.NotFoundException;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.ClientConnection;
 import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventGroup;
 import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.Constants;
 import org.keycloak.models.KeycloakSession;
@@ -130,6 +131,7 @@ public class RealmsResource {
         RealmManager realmManager = new RealmManager(session);
         RealmModel realm = locateRealm(name, realmManager);
         EventBuilder event = new EventsManager(realm, session, clientConnection).createEventBuilder();
+        event.eventGroup(EventGroup.USER);
         AuthenticationManager authManager = new AuthenticationManager(protector);
         LoginActionsService service = new LoginActionsService(realm, authManager, event);
         ResteasyProviderFactory.getInstance().injectProperties(service);
@@ -143,6 +145,7 @@ public class RealmsResource {
         RealmManager realmManager = new RealmManager(session);
         RealmModel realm = locateRealm(name, realmManager);
         EventBuilder event = new EventsManager(realm, session, clientConnection).createEventBuilder();
+        event.eventGroup(EventGroup.USER);
         ClientsManagementService service = new ClientsManagementService(realm, event);
         ResteasyProviderFactory.getInstance().injectProperties(service);
         return service;
@@ -169,6 +172,7 @@ public class RealmsResource {
         }
 
         EventBuilder event = new EventsManager(realm, session, clientConnection).createEventBuilder();
+        event.eventGroup(EventGroup.USER);
         AccountService accountService = new AccountService(realm, application, event);
         ResteasyProviderFactory.getInstance().injectProperties(accountService);
         //resourceContext.initResource(accountService);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/events/EventStoreProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/events/EventStoreProviderTest.java
index f5f81ff..b82c73a 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/events/EventStoreProviderTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/events/EventStoreProviderTest.java
@@ -6,6 +6,7 @@ import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Test;
 import org.keycloak.events.Event;
+import org.keycloak.events.EventGroup;
 import org.keycloak.events.EventStoreProvider;
 import org.keycloak.events.EventType;
 import org.keycloak.models.KeycloakSession;
@@ -185,6 +186,7 @@ public class EventStoreProviderTest {
         Event e = new Event();
         e.setTime(time);
         e.setType(event);
+        e.setEventGroup(EventGroup.USER);
         e.setRealmId(realmId);
         e.setClientId(clientId);
         e.setUserId(userId);