diff --git a/build.sh b/build.sh
index 84efdf7b37f26e7a7083bbb402aeced4609a152e..ef4f10565705b3eb3d0fae54b60de23671f356bf 100755
--- a/build.sh
+++ b/build.sh
@@ -38,6 +38,7 @@ docker build --build-arg BUILD_DATE=$(date -Iseconds) \
     .
 
 
+
 BUGSNAG_KEY=""
 eval $(grep -e "^\\s*BUGSNAG_KEY" Dockerfile | tr '\\' ' ')
 
diff --git a/pom.xml b/pom.xml
index fb47d331018bbd301afd6350b5136c2f5f2020e5..20a6f066122779eab771ca0d012dbcc4a8e8a208 100644
--- a/pom.xml
+++ b/pom.xml
@@ -84,7 +84,6 @@
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-security</artifactId>
-
         </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
diff --git a/src/main/java/eu/hbp/mip/configuration/SecurityConfiguration.java b/src/main/java/eu/hbp/mip/configuration/SecurityConfiguration.java
index a92879577926739b703e4d015a1a64caa1ed5b87..adc3df815fbc74d27f78e8bbf661ff31fc168a89 100644
--- a/src/main/java/eu/hbp/mip/configuration/SecurityConfiguration.java
+++ b/src/main/java/eu/hbp/mip/configuration/SecurityConfiguration.java
@@ -1,10 +1,7 @@
 package eu.hbp.mip.configuration;
 
 import eu.hbp.mip.model.UserInfo;
-import eu.hbp.mip.utils.CORSFilter;
-import eu.hbp.mip.utils.CustomLoginUrlAuthenticationEntryPoint;
-import eu.hbp.mip.utils.HTTPUtil;
-import eu.hbp.mip.utils.UserActionLogging;
+import eu.hbp.mip.utils.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -16,14 +13,17 @@ import org.springframework.boot.context.embedded.FilterRegistrationBean;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.http.*;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.AuthorityUtils;
 import org.springframework.security.oauth2.client.OAuth2ClientContext;
 import org.springframework.security.oauth2.client.OAuth2RestTemplate;
 import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter;
 import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter;
-import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
+import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails;
 import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
 import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
 import org.springframework.security.web.access.channel.ChannelProcessingFilter;
@@ -34,13 +34,13 @@ import org.springframework.security.web.csrf.CsrfFilter;
 import org.springframework.security.web.csrf.CsrfToken;
 import org.springframework.security.web.csrf.CsrfTokenRepository;
 import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestTemplate;
 import org.springframework.web.filter.OncePerRequestFilter;
 import org.springframework.web.util.WebUtils;
-import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.AuthorityUtils;
-
 
+import javax.net.ssl.*;
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
 import javax.servlet.ServletException;
@@ -48,34 +48,14 @@ import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
+import java.net.URI;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
-//newlyadded for logout
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpMethod;
-import org.springframework.http.MediaType;
-import org.springframework.http.RequestEntity;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.client.RestTemplate;
-import org.springframework.util.LinkedMultiValueMap;
-import org.springframework.util.MultiValueMap;
-import java.net.URI;
-
-
-import java.security.SecureRandom;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-
 
 // See https://spring.io/guides/tutorials/spring-boot-oauth2/ for reference about configuring OAuth2 login
 // also http://cscarioni.blogspot.ch/2013/04/pro-spring-security-and-oauth-2.html
@@ -84,186 +64,178 @@ import javax.net.ssl.X509TrustManager;
 @EnableOAuth2Client
 public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
 
-   private static final Logger LOGGER = LoggerFactory.getLogger(SecurityConfiguration.class);
-
-   @Autowired
-   private OAuth2ClientContext oauth2ClientContext;
-
-   /**
-    * Enable HBP collab authentication (1) or disable it (0). Default is 1
-    */
-   @Value("#{'${hbp.authentication.enabled:1}'}")
-   private boolean authentication;
-
-   /**
-    * Absolute URL to redirect to when login is required
-    */
-   @Value("#{'${frontend.loginUrl:/login/hbp}'}")
-   private String loginUrl;
- 
-	/**
-    * Absolute URL to redirect to when logout is required
-    */
-   @Value("#{'${hbp.client.logoutUri}'}")
-   private String logoutUri;
-
-   /**
-    * Absolute URL to redirect to after successful login
-    */
-   @Value("#{'${frontend.redirectAfterLoginUrl:http://frontend/home}'}")
-   private String frontendRedirectAfterLogin;
-
-   /**
-    * Absolute URL to redirect to after logout has occurred
-    */
-   @Value("#{'${frontend.redirectAfterLogoutUrl:/login/hbp}'}")
-   private String redirectAfterLogoutUrl;
-
-   /**
-    * URL to revoke auth token
-    */
-   @Value("#{'${hbp.resource.revokeTokenUri:https://services.humanbrainproject.eu/oidc/revoke}'}")
-   private String revokeTokenURI;
-   
-   
-
-//    @Autowired
-//    private HttpServletRequest request;
-
-   @Override
-   protected void configure(HttpSecurity http) throws Exception {
-	   disableCertificateValidation();
-       // @formatter:off
-       http.addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class);
-
-       if (authentication) {
-           http.antMatcher("/**")
-                   .authorizeRequests()
-                   .antMatchers(
-                           "/", "/login/**", "/health/**", "/info/**", "/metrics/**", "/trace/**", "/frontend/**", "/webjars/**", "/v2/api-docs", "/swagger-ui.html", "/swagger-resources/**"
-                   )
-				   .permitAll()
-                   .antMatchers("/galaxy*","/galaxy/*").hasRole("Data Manager")
-				   //.anyRequest().authenticated()
-				   .anyRequest().hasRole("Researcher")
-                   .and().exceptionHandling().authenticationEntryPoint(new CustomLoginUrlAuthenticationEntryPoint(loginUrl))
-                   .and().logout().addLogoutHandler(authLogoutHandler()).logoutSuccessUrl(redirectAfterLogoutUrl)
-                   .and().logout().permitAll()
-                   .and().csrf().ignoringAntMatchers("/logout").csrfTokenRepository(csrfTokenRepository())
-				   .and().addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
-                   .addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
-       }
-       else {
+    private static final Logger LOGGER = LoggerFactory.getLogger(SecurityConfiguration.class);
+
+    @Autowired
+    private OAuth2ClientContext oauth2ClientContext;
+
+    /**
+     * Enable HBP collab authentication (1) or disable it (0). Default is 1
+     */
+    @Value("#{'${hbp.authentication.enabled:1}'}")
+    private boolean authentication;
+
+    /**
+     * Absolute URL to redirect to when login is required
+     */
+    @Value("#{'${frontend.loginUrl:/login/hbp}'}")
+    private String loginUrl;
+
+    /**
+     * Absolute URL to redirect to when logout is required
+     */
+    @Value("#{'${hbp.client.logoutUri}'}")
+    private String logoutUri;
+
+    /**
+     * Absolute URL to redirect to after successful login
+     */
+    @Value("#{'${frontend.redirectAfterLoginUrl:http://frontend/home}'}")
+    private String frontendRedirectAfterLogin;
+
+    /**
+     * Absolute URL to redirect to after logout has occurred
+     */
+    @Value("#{'${frontend.redirectAfterLogoutUrl:/login/hbp}'}")
+    private String redirectAfterLogoutUrl;
+
+    /**
+     * URL to revoke auth token
+     */
+    @Value("#{'${hbp.resource.revokeTokenUri:https://services.humanbrainproject.eu/oidc/revoke}'}")
+    private String revokeTokenURI;
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        disableCertificateValidation();
+        // @formatter:off
+        http.addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class);
+
+        if (authentication) {
+            http.antMatcher("/**")
+                    .authorizeRequests()
+                    .antMatchers(
+                            "/", "/login/**", "/health/**", "/info/**", "/metrics/**", "/trace/**", "/frontend/**", "/webjars/**", "/v2/api-docs", "/swagger-ui.html", "/swagger-resources/**"
+                    )
+                    .permitAll()
+                    .antMatchers("/galaxy*", "/galaxy/*").hasRole("Data Manager")
+                    //.anyRequest().authenticated()
+                    .anyRequest().hasRole("Researcher")
+                    .and().exceptionHandling().authenticationEntryPoint(new CustomLoginUrlAuthenticationEntryPoint(loginUrl))
+                    .accessDeniedHandler(new CustomAccessDeniedHandler())
+                    .and().logout().addLogoutHandler(authLogoutHandler()).logoutSuccessUrl(redirectAfterLogoutUrl)
+                    .and().logout().permitAll()
+                    .and().csrf().ignoringAntMatchers("/logout").csrfTokenRepository(csrfTokenRepository())
+                    .and().addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
+                    .addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
+        } else {
             http.antMatcher("/**")
                     .authorizeRequests()
                     .antMatchers("/**").permitAll().and().csrf().disable();
-       }
-   }
-
-   private Filter ssoFilter() {
-       OAuth2ClientAuthenticationProcessingFilter hbpFilter = new OAuth2ClientAuthenticationProcessingFilter("/login/hbp");
-       OAuth2RestTemplate hbpTemplate = new OAuth2RestTemplate(hbp(), oauth2ClientContext);
-	   hbpFilter.setAuthenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler(frontendRedirectAfterLogin));
-       hbpFilter.setRestTemplate(hbpTemplate);
-       hbpFilter.setTokenServices(new UserInfoTokenServices(hbpResource().getUserInfoUri(), hbp().getClientId()));
-       return hbpFilter;
-   }
-
-   @Bean
-   public FilterRegistrationBean oauth2ClientFilterRegistration(
-           OAuth2ClientContextFilter filter) {
-       FilterRegistrationBean registration = new FilterRegistrationBean();
-       registration.setFilter(filter);
-       registration.setOrder(-100);
-       return registration;
-   }
-
-   @Bean(name="hbp")
-   @ConfigurationProperties("hbp.client")
-   public BaseOAuth2ProtectedResourceDetails hbp() {
-       return new AuthorizationCodeResourceDetails();
-   }
-
-   @Bean(name="hbpResource")
-   @ConfigurationProperties("hbp.resource")
-   public ResourceServerProperties hbpResource() {
-       return new ResourceServerProperties();
-   }
-
-   public boolean isAuthentication() {
-       return authentication;
-   }
-
-   public String getFrontendRedirectAfterLogin() {
-       return frontendRedirectAfterLogin;
-   }
-
-   private Filter csrfHeaderFilter() {
-       return new OncePerRequestFilter() {
-           @Override
-           protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
-                                           FilterChain filterChain) throws ServletException, IOException {
-               CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
-               if (csrf != null) {
-                   Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
-                   String token = csrf.getToken();
-                   if (cookie == null || token != null && !token.equals(cookie.getValue())) {
-                       cookie = new Cookie("XSRF-TOKEN", token);
-                       cookie.setPath("/");
-                       response.addCookie(cookie);
-                   }
-               }
-               filterChain.doFilter(request, response);
-           }
-       };
-   }
-
-   private CsrfTokenRepository csrfTokenRepository() {
-       HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
-       repository.setHeaderName("X-XSRF-TOKEN");
-       return repository;
-   }
-
-   private class CustomLogoutHandler implements LogoutHandler {
-       @Override
-       public void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) {
-
-           // Hackish way of accessing to this information...
-           final UserInfo userInfo = (UserInfo) httpServletRequest.getSession().getAttribute("userInfo");
-           if (userInfo != null) {
-               userInfo.setFakeAuth(false);
-           }
-
-           if (oauth2ClientContext == null || oauth2ClientContext.getAccessToken() == null)
-           {
-               return;
-           }
-
-           String idToken = oauth2ClientContext.getAccessToken().getAdditionalInformation().get("id_token").toString();
-
-           StringBuilder query = new StringBuilder();
-           query.append("{");
-           query.append("\"token\":");
-           query.append("\"").append(idToken).append("\"");
-           query.append("}");
-
-           try {
-               int responseCode = HTTPUtil.sendPost(revokeTokenURI, query.toString(), new StringBuilder());
-               if (responseCode != 200)
-               {
-                   LOGGER.warn("Cannot send request to OIDC server for revocation ! ");
-               }
-               else{
-                   LOGGER.info("Should be logged out");
-               }
-           } catch (IOException e) {
-               LOGGER.warn("Cannot notify logout to OIDC server !");
-               LOGGER.trace("Cannot notify logout", e);
-           }
-
-       }
-   }
-   
+        }
+    }
+
+    private Filter ssoFilter() {
+        OAuth2ClientAuthenticationProcessingFilter hbpFilter = new OAuth2ClientAuthenticationProcessingFilter("/login/hbp");
+        OAuth2RestTemplate hbpTemplate = new OAuth2RestTemplate(hbp(), oauth2ClientContext);
+        hbpFilter.setAuthenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler(frontendRedirectAfterLogin));
+        hbpFilter.setRestTemplate(hbpTemplate);
+        hbpFilter.setTokenServices(new UserInfoTokenServices(hbpResource().getUserInfoUri(), hbp().getClientId()));
+        return hbpFilter;
+    }
+
+    @Bean
+    public FilterRegistrationBean oauth2ClientFilterRegistration(
+            OAuth2ClientContextFilter filter) {
+        FilterRegistrationBean registration = new FilterRegistrationBean();
+        registration.setFilter(filter);
+        registration.setOrder(-100);
+        return registration;
+    }
+
+    @Bean(name = "hbp")
+    @ConfigurationProperties("hbp.client")
+    public BaseOAuth2ProtectedResourceDetails hbp() {
+        return new AuthorizationCodeResourceDetails();
+    }
+
+    @Bean(name = "hbpResource")
+    @ConfigurationProperties("hbp.resource")
+    public ResourceServerProperties hbpResource() {
+        return new ResourceServerProperties();
+    }
+
+    public boolean isAuthentication() {
+        return authentication;
+    }
+
+    public String getFrontendRedirectAfterLogin() {
+        return frontendRedirectAfterLogin;
+    }
+
+    private Filter csrfHeaderFilter() {
+        return new OncePerRequestFilter() {
+            @Override
+            protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
+                                            FilterChain filterChain) throws ServletException, IOException {
+                CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
+                if (csrf != null) {
+                    Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
+                    String token = csrf.getToken();
+                    if (cookie == null || token != null && !token.equals(cookie.getValue())) {
+                        cookie = new Cookie("XSRF-TOKEN", token);
+                        cookie.setPath("/");
+                        response.addCookie(cookie);
+                    }
+                }
+                filterChain.doFilter(request, response);
+            }
+        };
+    }
+
+    private CsrfTokenRepository csrfTokenRepository() {
+        HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
+        repository.setHeaderName("X-XSRF-TOKEN");
+        return repository;
+    }
+
+    private class CustomLogoutHandler implements LogoutHandler {
+        @Override
+        public void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) {
+
+            // Hackish way of accessing to this information...
+            final UserInfo userInfo = (UserInfo) httpServletRequest.getSession().getAttribute("userInfo");
+            if (userInfo != null) {
+                userInfo.setFakeAuth(false);
+            }
+
+            if (oauth2ClientContext == null || oauth2ClientContext.getAccessToken() == null) {
+                return;
+            }
+
+            String idToken = oauth2ClientContext.getAccessToken().getAdditionalInformation().get("id_token").toString();
+
+            StringBuilder query = new StringBuilder();
+            query.append("{");
+            query.append("\"token\":");
+            query.append("\"").append(idToken).append("\"");
+            query.append("}");
+
+            try {
+                int responseCode = HTTPUtil.sendPost(revokeTokenURI, query.toString(), new StringBuilder());
+                if (responseCode != 200) {
+                    LOGGER.warn("Cannot send request to OIDC server for revocation ! ");
+                } else {
+                    LOGGER.info("Should be logged out");
+                }
+            } catch (IOException e) {
+                LOGGER.warn("Cannot notify logout to OIDC server !");
+                LOGGER.trace("Cannot notify logout", e);
+            }
+
+        }
+    }
+
     @Bean
     public AuthoritiesExtractor keycloakAuthoritiesExtractor() {
         return new KeycloakAuthoritiesExtractor();
@@ -291,68 +263,69 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
             return String.join(",", authorities);
         }
     }
-	
-	
-	private LogoutHandler authLogoutHandler() {
-		return (request, response, authentication) -> {
-			logout();
-		};
+
+
+    private LogoutHandler authLogoutHandler() {
+        return (request, response, authentication) -> {
+            logout();
+        };
     }
-	
-	
-	public void logout() {
-		// POSTするリクエストパラメーターを作成
-		UserActionLogging.LogAction("refresh token ", this.oauth2ClientContext.getAccessToken().getRefreshToken().getValue());
-		RestTemplate restTemplate = new RestTemplate();
-		MultiValueMap<String, String> formParams = new LinkedMultiValueMap<>();
-		formParams.add("client_id", hbp().getClientId());
+
+
+    public void logout() {
+        // POSTするリクエストパラメーターを作成
+        UserActionLogging.LogAction("refresh token ", this.oauth2ClientContext.getAccessToken().getRefreshToken().getValue());
+        RestTemplate restTemplate = new RestTemplate();
+        MultiValueMap<String, String> formParams = new LinkedMultiValueMap<>();
+        formParams.add("client_id", hbp().getClientId());
         formParams.add("client_secret", hbp().getClientSecret());
-		formParams.add("refresh_token", this.oauth2ClientContext.getAccessToken().getRefreshToken().getValue());
-		// リクエストヘッダーを作成
-		HttpHeaders httpHeaders = new HttpHeaders();
-		httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
-		// リクエストを作成
-		UserActionLogging.LogAction("logoutUri is ", logoutUri);
-		RequestEntity<MultiValueMap<String, String>> requestEntity =
-				new RequestEntity<>(formParams, httpHeaders, HttpMethod.POST,
-						URI.create(logoutUri)); 
-		// POSTリクエスト送信(ログアウト実行)
-
-		ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class);
+        formParams.add("refresh_token", this.oauth2ClientContext.getAccessToken().getRefreshToken().getValue());
+        // リクエストヘッダーを作成
+        HttpHeaders httpHeaders = new HttpHeaders();
+        httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
+        // リクエストを作成
+        UserActionLogging.LogAction("logoutUri is ", logoutUri);
+        RequestEntity<MultiValueMap<String, String>> requestEntity =
+                new RequestEntity<>(formParams, httpHeaders, HttpMethod.POST,
+                        URI.create(logoutUri));
+        // POSTリクエスト送信(ログアウト実行)
+
+        ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class);
     }
-   
-   @Value("#{'${services.keycloak.keycloakUrl}'}")
-   private String keycloakUrl;
-   
+
+    @Value("#{'${services.keycloak.keycloakUrl}'}")
+    private String keycloakUrl;
+
     // static {
-        // disableCertificateValidation();
+    // disableCertificateValidation();
     // }
 
     public void disableCertificateValidation() {
-		LOGGER.info("disabling certificate validation host : " + keycloakUrl);
+        LOGGER.info("disabling certificate validation host : " + keycloakUrl);
         // Create a trust manager that does not validate certificate chains
-        TrustManager[] trustAllCerts = new TrustManager[] {
+        TrustManager[] trustAllCerts = new TrustManager[]{
                 new X509TrustManager() {
                     public X509Certificate[] getAcceptedIssuers() {
                         return new X509Certificate[0];
                     }
-                    public void checkClientTrusted(X509Certificate[] certs, String authType) {}
-                    public void checkServerTrusted(X509Certificate[] certs, String authType) {}
-                } };
+
+                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
+                    }
+
+                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
+                    }
+                }};
 
 
         // Ignore differences between given hostname and certificate hostname
         HostnameVerifier hv = new HostnameVerifier() {
             public boolean verify(String hostname, SSLSession session) {
-				
+
                 // System.out.println("Warning: URL Host: " + hostname + " vs. "
-                        // + session.getPeerHost());
-                if(hostname.equals(keycloakUrl) && session.getPeerHost().equals(keycloakUrl))
-                {
+                // + session.getPeerHost());
+                if (hostname.equals(keycloakUrl) && session.getPeerHost().equals(keycloakUrl)) {
                     return true;
-                }
-                else
-                {
+                } else {
                     return false;
                 }
             }
@@ -364,8 +337,9 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
             sc.init(null, trustAllCerts, new SecureRandom());
             HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
             HttpsURLConnection.setDefaultHostnameVerifier(hv);
-        } catch (Exception e) {}
+        } catch (Exception e) {
+        }
 
-    } 
+    }
 
 }
diff --git a/src/main/java/eu/hbp/mip/controllers/AlgorithmsApi.java b/src/main/java/eu/hbp/mip/controllers/AlgorithmsApi.java
index efe69c07207cd1b247b20cc9a953a37cb8bea7b5..6b92c691a633ecbd4c16ccea813fc8b3c3533742 100644
--- a/src/main/java/eu/hbp/mip/controllers/AlgorithmsApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/AlgorithmsApi.java
@@ -8,11 +8,13 @@ import com.google.gson.Gson;
 import eu.hbp.mip.controllers.galaxy.retrofit.RetroFitGalaxyClients;
 import eu.hbp.mip.controllers.galaxy.retrofit.RetrofitClientInstance;
 import eu.hbp.mip.model.AlgorithmDTO;
+import eu.hbp.mip.model.UserInfo;
 import eu.hbp.mip.model.galaxy.WorkflowDTO;
 import eu.hbp.mip.utils.HTTPUtil;
 import eu.hbp.mip.utils.UserActionLogging;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -35,6 +37,9 @@ public class AlgorithmsApi {
 
     private static final Gson gson = new Gson();
 
+    @Autowired
+    private UserInfo userInfo;
+
     @Value("#{'${services.exareme.algorithmsUrl}'}")
     private String exaremeAlgorithmsUrl;
 
@@ -47,7 +52,7 @@ public class AlgorithmsApi {
     @ApiOperation(value = "List all algorithms", response = String.class)
     @RequestMapping(method = RequestMethod.GET)
     public ResponseEntity<List<AlgorithmDTO>> getAlgorithms() {
-        UserActionLogging.LogAction("List all algorithms", "");
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "List all algorithms", "");
 
         List<AlgorithmDTO> exaremeAlgorithms = getExaremeAlgorithms();
         List<AlgorithmDTO> galaxyAlgorithms = getGalaxyWorkflows();
@@ -56,13 +61,13 @@ public class AlgorithmsApi {
         if (exaremeAlgorithms != null) {
             algorithms.addAll(exaremeAlgorithms);
         } else {
-            UserActionLogging.LogAction("List all algorithms",
+            UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "List all algorithms",
                     "Getting exareme algorithms failed and returned null");
         }
         if (galaxyAlgorithms != null) {
             algorithms.addAll(galaxyAlgorithms);
         } else {
-            UserActionLogging.LogAction("List all algorithms",
+            UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "List all algorithms",
                     "Getting galaxy workflows failed and returned null");
         }
 
@@ -75,7 +80,7 @@ public class AlgorithmsApi {
      * @return a list of AlgorithmDTOs or null if something fails
      */
     public List<AlgorithmDTO> getExaremeAlgorithms() {
-        UserActionLogging.LogAction("List exareme algorithms", "");
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "List exareme algorithms", "");
 
         List<AlgorithmDTO> algorithms = new LinkedList<>();
         // Get exareme algorithms
@@ -85,11 +90,11 @@ public class AlgorithmsApi {
 
             algorithms = gson.fromJson(response.toString(), algorithms.getClass());
         } catch (IOException e) {
-            UserActionLogging.LogAction("List exareme algorithms", "An exception occurred: " + e.getMessage());
+            UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "List exareme algorithms", "An exception occurred: " + e.getMessage());
             return null;
         }
 
-        UserActionLogging.LogAction("List exareme algorithms",
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "List exareme algorithms",
                 "Completed, returned " + algorithms.size() + " algorithms.");
         return algorithms;
     }
@@ -100,7 +105,7 @@ public class AlgorithmsApi {
      * @return a list of AlgorithmDTOs or null if something fails
      */
     public List<AlgorithmDTO> getGalaxyWorkflows() {
-        UserActionLogging.LogAction("List Galaxy workflows", "");
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "List Galaxy workflows", "");
 
         List<Workflow> workflowList = null;
         try {
@@ -110,7 +115,7 @@ public class AlgorithmsApi {
 
             workflowList = new ArrayList<>(workflowsClient.getWorkflows());
         } catch (Exception e) {
-            UserActionLogging.LogAction("List Galaxy workflows", "Error when calling list galaxy workflows: " + e.getMessage());
+            UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "List Galaxy workflows", "Error when calling list galaxy workflows: " + e.getMessage());
 
             return null;
         }
@@ -130,28 +135,28 @@ public class AlgorithmsApi {
 
                 } else {     // Something unexpected happened
                     String msgErr = gson.toJson(response.errorBody());
-                    UserActionLogging.LogAction("List Galaxy workflows", "Error Response: " + msgErr);
+                    UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "List Galaxy workflows", "Error Response: " + msgErr);
                     return null;
                 }
             } catch (Exception e) {
-                UserActionLogging.LogAction("List Galaxy workflows", "An exception occurred: " + e.getMessage());
+                UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "List Galaxy workflows", "An exception occurred: " + e.getMessage());
                 return null;
             }
         }
-        UserActionLogging.LogAction("List Galaxy workflows", "Workflows fetched: " + workflows.size());
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "List Galaxy workflows", "Workflows fetched: " + workflows.size());
 
         // Convert the workflows to algorithms
         List<AlgorithmDTO> algorithms = new LinkedList<>();
         for (WorkflowDTO workflow : workflows) {
-            UserActionLogging.LogAction("List Galaxy workflows", "Converting workflow: " + workflow);
+            UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "List Galaxy workflows", "Converting workflow: " + workflow);
 
             algorithms.add(workflow.convertToAlgorithmDTO());
 
-            UserActionLogging.LogAction("List Galaxy workflows",
+            UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "List Galaxy workflows",
                     "Converted algorithm: " + algorithms.get(algorithms.size() - 1));
         }
 
-        UserActionLogging.LogAction("List Galaxy workflows", "Completed!");
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "List Galaxy workflows", "Completed!");
         return algorithms;
     }
 }
diff --git a/src/main/java/eu/hbp/mip/controllers/ArticlesApi.java b/src/main/java/eu/hbp/mip/controllers/ArticlesApi.java
index 963b181576f0626620d76b3a0370dcb840767778..2e5fb3dc551a96cf0fd34b89cd4d159d7fcbb67f 100644
--- a/src/main/java/eu/hbp/mip/controllers/ArticlesApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/ArticlesApi.java
@@ -66,7 +66,7 @@ public class ArticlesApi {
                 }
             }
         }
-		UserActionLogging.LogAction("Get articles", "id : Get All articles");
+		UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Get articles", "id : Get All articles");
         
         return ResponseEntity.ok(articles);
     }
@@ -127,7 +127,7 @@ public class ArticlesApi {
         }
         articleRepository.save(article);
 
-		UserActionLogging.LogAction("Created article", "id : " + article.getSlug());
+		UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Created article", "id : " + article.getSlug());
         return new ResponseEntity<>(HttpStatus.CREATED);
     }
 
@@ -137,7 +137,7 @@ public class ArticlesApi {
     public ResponseEntity<Article> getAnArticle(
             @ApiParam(value = "slug", required = true) @PathVariable("slug") String slug
     ) {
-		UserActionLogging.LogAction("Getting an article", "id : " + slug);
+		UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Getting an article", "id : " + slug);
 
         User user = userInfo.getUser();
         Article article;
@@ -165,7 +165,7 @@ public class ArticlesApi {
             @ApiParam(value = "slug", required = true) @PathVariable("slug") String slug,
             @RequestBody @ApiParam(value = "Article to update", required = true) @Valid Article article
     ) {
-        UserActionLogging.LogAction("Update an article", "id : " + slug);
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Update an article", "id : " + slug);
 
         User user = userInfo.getUser();
 
diff --git a/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java b/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java
index f876e315ed224bfc667b6ff6fb9337a2bafb361f..3958d99d608fff64bfcf934ee22e5ef61a44e303 100644
--- a/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java
@@ -17,6 +17,7 @@ import eu.hbp.mip.model.galaxy.GalaxyWorkflowResult;
 import eu.hbp.mip.model.galaxy.PostWorkflowToGalaxyDtoResponse;
 import eu.hbp.mip.repositories.ExperimentRepository;
 import eu.hbp.mip.repositories.ModelRepository;
+import eu.hbp.mip.utils.ClaimUtils;
 import eu.hbp.mip.utils.HTTPUtil;
 import eu.hbp.mip.utils.UserActionLogging;
 import io.swagger.annotations.Api;
@@ -28,6 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
+import org.springframework.security.core.Authentication;
 import org.springframework.web.bind.annotation.*;
 import retrofit2.Call;
 import retrofit2.Response;
@@ -50,6 +52,9 @@ public class ExperimentApi {
 
     private static final Gson gson = new Gson();
 
+    @Autowired
+    private UserInfo userInfo;
+
     private static final Gson gsonOnlyExposed = new GsonBuilder().serializeNulls()
             .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").excludeFieldsWithoutExposeAnnotation().create();
 
@@ -68,8 +73,9 @@ public class ExperimentApi {
     @Value("#{'${services.galaxy.galaxyApiKey}'}")
     private String galaxyApiKey;
 
-    @Autowired
-    private UserInfo userInfo;
+    // Enable HBP collab authentication (1) or disable it (0). Default is 1
+    @Value("#{'${hbp.authentication.enabled:1}'}")
+    private boolean authenticationIsEnabled;
 
     @Autowired
     private ModelRepository modelRepository;
@@ -87,7 +93,7 @@ public class ExperimentApi {
         try {
             experimentUuid = UUID.fromString(uuid);
         } catch (IllegalArgumentException iae) {
-            UserActionLogging.LogAction("Get Experiment", "Invalid Experiment UUID.");
+            UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Get Experiment", "Invalid Experiment UUID.");
             return ResponseEntity.badRequest().body("Invalid Experiment UUID");
         }
 
@@ -97,19 +103,60 @@ public class ExperimentApi {
             return new ResponseEntity<>("Not found", HttpStatus.NOT_FOUND);
         }
 
-        UserActionLogging.LogAction("Get an experiment ", " uuid : " + uuid);
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Get an experiment ", " uuid : " + uuid);
 
         return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
     }
 
+
     @ApiOperation(value = "Create an experiment", response = Experiment.class)
     @RequestMapping(value = "/runAlgorithm", method = RequestMethod.POST)
-    public ResponseEntity<String> runExperiment(@RequestBody ExperimentExecutionDTO experimentExecutionDTO) {
-        UserActionLogging.LogAction("Run algorithm", "Running the algorithm...");
+    public ResponseEntity<String> runExperiment(Authentication authentication, @RequestBody ExperimentExecutionDTO experimentExecutionDTO) {
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Run algorithm", "Running the algorithm...");
+
+        if(authenticationIsEnabled) {
+            // --- Validating proper access rights on the datasets  ---
+            List<String> userClaims = Arrays.asList(authentication.getAuthorities().toString().toLowerCase()
+                    .replaceAll("[\\s+\\]\\[]", "").split(","));
+            UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "User Claims", userClaims.toString());
+
+            // Don't check for dataset claims if "super" claim exists allowing everything
+            if (!userClaims.contains(ClaimUtils.allDatasetsAllowedClaim())) {
+                // Getting the dataset from the experiment parameters
+                String experimentDatasets = null;
+                for (AlgorithmExecutionParamDTO parameter : experimentExecutionDTO.getAlgorithms().get(0).getParameters()) {
+                    if (parameter.getName().equals("dataset")) {
+                        experimentDatasets = parameter.getValue();
+                        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Run algorithm", "Found the dataset parameter!");
+                        break;
+                    }
+                }
+
+                if (experimentDatasets == null || experimentDatasets.equals("")) {
+                    UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Run algorithm",
+                            "A dataset should be specified when running an algorithm.");
+                    return ResponseEntity.badRequest().body("A dataset should be specified when running an algorithm.");
+                }
+
+                for (String dataset : experimentDatasets.split(",")) {
+                    String datasetRole = ClaimUtils.getDatasetClaim(dataset);
+                    if (!userClaims.contains(datasetRole.toLowerCase())) {
+                        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Run algorithm",
+                                "You are not allowed to use dataset: " + dataset);
+                        return ResponseEntity.status(HttpStatus.FORBIDDEN).body("You are not allowed to use dataset: " + dataset);
+                    }
+                }
+                UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Run algorithm",
+                        "User is authorized to use the datasets: " + experimentDatasets);
+            }
+        }
+
+        // --- Run the experiment ---
 
         // Get the type of algorithm
         String algorithmType = experimentExecutionDTO.getAlgorithms().get(0).getType();
 
+        // Run with the appropriate engine
         if (algorithmType.equals("workflow")) {
             return runGalaxyWorkflow(experimentExecutionDTO);
         } else {
@@ -122,7 +169,7 @@ public class ExperimentApi {
     public ResponseEntity<String> markExperimentAsViewed(
             @ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
 
-        UserActionLogging.LogAction("Mark an experiment as viewed", " uuid : " + uuid);
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Mark an experiment as viewed", " uuid : " + uuid);
 
         Experiment experiment;
         UUID experimentUuid;
@@ -130,8 +177,7 @@ public class ExperimentApi {
         try {
             experimentUuid = UUID.fromString(uuid);
         } catch (IllegalArgumentException iae) {
-            //LOGGER.trace("Invalid UUID", iae);
-            //LOGGER.warn("An invalid Experiment UUID was received !");
+            UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Mark an experiment as viewed", "Invalid Experiment UUID" + uuid);
             return ResponseEntity.badRequest().body("Invalid Experiment UUID");
         }
 
@@ -141,7 +187,7 @@ public class ExperimentApi {
         experiment.setResultsViewed(true);
         experimentRepository.save(experiment);
 
-        UserActionLogging.LogAction("Experiment updated (marked as viewed)", " ");
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Experiment updated (marked as viewed)", " ");
 
         return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
     }
@@ -151,7 +197,7 @@ public class ExperimentApi {
     public ResponseEntity<String> markExperimentAsShared(
             @ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
 
-        UserActionLogging.LogAction("Mark an experiment as shared", " uuid : " + uuid);
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Mark an experiment as shared", " uuid : " + uuid);
 
         return doMarkExperimentAsShared(uuid, true);
     }
@@ -160,7 +206,7 @@ public class ExperimentApi {
     @RequestMapping(value = "/{uuid}/markAsUnshared", method = RequestMethod.GET)
     public ResponseEntity<String> markExperimentAsUnshared(
             @ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
-        UserActionLogging.LogAction("Mark an experiment as unshared", " uuid : " + uuid);
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Mark an experiment as unshared", " uuid : " + uuid);
 
         return doMarkExperimentAsShared(uuid, false);
     }
@@ -170,7 +216,7 @@ public class ExperimentApi {
     public ResponseEntity<String> listExperiments(
             @ApiParam(value = "maxResultCount") @RequestParam int maxResultCount) {
 
-        UserActionLogging.LogAction("List experiments", " maxResultCount : " + maxResultCount);
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "List experiments", " maxResultCount : " + maxResultCount);
 
         return doListExperiments(false, null);
     }
@@ -180,7 +226,7 @@ public class ExperimentApi {
     public ResponseEntity<String> listExperiments(@ApiParam(value = "slug") @RequestParam("slug") String modelSlug,
                                                   @ApiParam(value = "maxResultCount") @RequestParam("maxResultCount") int maxResultCount) {
 
-        UserActionLogging.LogAction("List experiments", " modelSlug : " + modelSlug);
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "List experiments", " modelSlug : " + modelSlug);
 
         if (maxResultCount <= 0 && (modelSlug == null || "".equals(modelSlug))) {
             return new ResponseEntity<>("You must provide at least a slug or a limit of result",
@@ -192,8 +238,8 @@ public class ExperimentApi {
 
     @ApiOperation(value = "list my experiments", response = Experiment.class, responseContainer = "List")
     @RequestMapping(method = RequestMethod.GET, params = {"mine"})
-    public ResponseEntity<String> listMyExperiments(@ApiParam(value = "mine") @RequestParam("mine") boolean mine) {
-        UserActionLogging.LogAction("List my experiments", " mine : " + mine);
+    public ResponseEntity<String> listMyExperiments(Authentication authentication, @ApiParam(value = "mine") @RequestParam("mine") boolean mine) {
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "List my experiments", " mine : " + mine);
 
         return doListExperiments(true, null);
     }
@@ -244,14 +290,14 @@ public class ExperimentApi {
         experiment.setShared(shared);
         experimentRepository.save(experiment);
 
-        UserActionLogging.LogAction("Experiment updated (marked as shared)", "");
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Experiment updated (marked as shared)", "");
 
         return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
     }
 
     /* -------------------------------  EXPERIMENT MODEL METHODS  ----------------------------------------------------*/
 
-    public Experiment createExperiment(ExperimentExecutionDTO experimentExecutionDTO){
+    public Experiment createExperiment(ExperimentExecutionDTO experimentExecutionDTO) {
         User user = userInfo.getUser();
 
         Experiment experiment = new Experiment();
@@ -263,31 +309,31 @@ public class ExperimentApi {
         experiment.setName(experimentExecutionDTO.getName());
         experimentRepository.save(experiment);
 
-        UserActionLogging.LogAction("Created an experiment", " id : " + experiment.getUuid());
-        UserActionLogging.LogAction("Created an experiment", " algorithms : " + experiment.getAlgorithms());
-        UserActionLogging.LogAction("Created an experiment", " model : " + experiment.getModel().getSlug());
-        UserActionLogging.LogAction("Created an experiment", " name : " + experiment.getName());
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Created an experiment", " id : " + experiment.getUuid());
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Created an experiment", " algorithms : " + experiment.getAlgorithms());
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Created an experiment", " model : " + experiment.getModel().getSlug());
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Created an experiment", " name : " + experiment.getName());
         return experiment;
     }
 
     private void saveExperiment(Experiment experiment) {
-        UserActionLogging.LogAction("Saved an experiment", " id : " + experiment.getUuid());
-        UserActionLogging.LogAction("Saved an experiment", " algorithms : " + experiment.getAlgorithms());
-        UserActionLogging.LogAction("Saved an experiment", " model : " + experiment.getModel().getSlug());
-        UserActionLogging.LogAction("Saved an experiment", " name : " + experiment.getName());
-        UserActionLogging.LogAction("Saved an experiment", " historyId : " + experiment.getWorkflowHistoryId());
-        UserActionLogging.LogAction("Saved an experiment", " status : " + experiment.getWorkflowStatus());
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Saved an experiment", " id : " + experiment.getUuid());
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Saved an experiment", " algorithms : " + experiment.getAlgorithms());
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Saved an experiment", " model : " + experiment.getModel().getSlug());
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Saved an experiment", " name : " + experiment.getName());
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Saved an experiment", " historyId : " + experiment.getWorkflowHistoryId());
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Saved an experiment", " status : " + experiment.getWorkflowStatus());
 
         experimentRepository.save(experiment);
 
-        UserActionLogging.LogAction("Experiment saved", "");
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Experiment saved", "");
     }
 
     private void finishExperiment(Experiment experiment) {
         experiment.setFinished(new Date());
         experimentRepository.save(experiment);
 
-        UserActionLogging.LogThreadAction("Experiment finished!", "");
+        UserActionLogging.LogAction("Experiment finished!", "");
     }
 
     /* --------------------------------------  EXAREME CALLS ---------------------------------------------------------*/
@@ -299,7 +345,7 @@ public class ExperimentApi {
      * @return the response to be returned
      */
     public ResponseEntity<String> runExaremeAlgorithm(ExperimentExecutionDTO experimentExecutionDTO) {
-        UserActionLogging.LogAction("Run exareme algorithm", "Running the algorithm...");
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Run exareme algorithm", "Running the algorithm...");
 
         Experiment experiment = createExperiment(experimentExecutionDTO);
 
@@ -312,26 +358,26 @@ public class ExperimentApi {
 
         String body = gson.toJson(algorithmParameters);
         String url = queryExaremeUrl + "/" + algorithmName;
-        UserActionLogging.LogAction("Run exareme algorithm", "url: " + url + ", body: " + body);
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Run exareme algorithm", "url: " + url + ", body: " + body);
 
         ResponseEntity<String> response = new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
-        UserActionLogging.LogAction("Run exareme algorithm",
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Run exareme algorithm",
                 "Completed, returning: " + experiment.toString());
 
-        UserActionLogging.LogAction("Run exareme algorithm",
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Run exareme algorithm",
                 "Starting exareme execution thread");
         new Thread(() -> {
-            // ATTENTION: Inside the Thread only LogThreadAction should be used, not LogAction!
-            UserActionLogging.LogThreadAction("Run exareme algorithm",
+            // ATTENTION: Inside the Thread only LogAction should be used, not LogAction!
+            UserActionLogging.LogAction("Run exareme algorithm",
                     "Thread started!");
 
             try {
-                UserActionLogging.LogThreadAction("Run exareme algorithm",
+                UserActionLogging.LogAction("Run exareme algorithm",
                         "Thread started!");
                 StringBuilder results = new StringBuilder();
                 int code = HTTPUtil.sendPost(url, body, results);
 
-                UserActionLogging.LogThreadAction("Run exareme algorithm",
+                UserActionLogging.LogAction("Run exareme algorithm",
                         "Algorithm finished with code: " + code);
 
                 // Results are stored in the experiment object
@@ -339,18 +385,18 @@ public class ExperimentApi {
                 experiment.setHasError(code >= 400);
                 experiment.setHasServerError(code >= 500);
             } catch (Exception e) {
-                UserActionLogging.LogThreadAction("Run exareme algorithm",
+                UserActionLogging.LogAction("Run exareme algorithm",
                         "There was an exception: " + e.getMessage());
 
                 experiment.setHasError(true);
                 experiment.setHasServerError(true);
                 experiment.setResult(e.getMessage());
             }
-            UserActionLogging.LogThreadAction("Run exareme algorithm",
+            UserActionLogging.LogAction("Run exareme algorithm",
                     "Finished the experiment: " + experiment.toString());
             finishExperiment(experiment);
 
-            UserActionLogging.LogThreadAction("Run exareme algorithm",
+            UserActionLogging.LogAction("Run exareme algorithm",
                     "Finished!");
         }).start();
 
@@ -367,7 +413,7 @@ public class ExperimentApi {
      * @return the response to be returned
      */
     public ResponseEntity<String> runGalaxyWorkflow(ExperimentExecutionDTO experimentExecutionDTO) {
-        UserActionLogging.LogAction("Run workflow", "Running a workflow...");
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Run workflow", "Running a workflow...");
 
         Experiment experiment = createExperiment(experimentExecutionDTO);
 
@@ -397,7 +443,7 @@ public class ExperimentApi {
             }
         }
         if (workflow == null) {
-            UserActionLogging.LogAction("Run workflow",
+            UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Run workflow",
                     "Could not find algorithm code: " + workflowId);
             return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                     .body(new ErrorResponse("Could not find galaxy algorithm.").toString());
@@ -416,7 +462,7 @@ public class ExperimentApi {
 
         // Create the request client
         RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
-        UserActionLogging.LogAction("Run workflow", "Running Galaxy workflow with id: " + workflow.getId());
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Run workflow", "Running Galaxy workflow with id: " + workflow.getId());
 
         // Call Galaxy to run the workflow
         Call<PostWorkflowToGalaxyDtoResponse> call = service.postWorkflowToGalaxy(workflow.getId(), galaxyApiKey, requestBodyJson);
@@ -425,7 +471,7 @@ public class ExperimentApi {
 
             if (response.code() == 200) {       // Call succeeded
                 String responseBody = gson.toJson(response.body());
-                UserActionLogging.LogAction("Run workflow", "Response: " + responseBody);
+                UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Run workflow", "Response: " + responseBody);
 
                 String historyId = (String) new JSONObject(responseBody).get("history_id");
                 experiment.setWorkflowHistoryId(historyId);
@@ -435,7 +481,7 @@ public class ExperimentApi {
 
             } else {     // Something unexpected happened
                 String msgErr = gson.toJson(response.errorBody());
-                UserActionLogging.LogAction("Run workflow", "Error Response: " + msgErr);
+                UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Run workflow", "Error Response: " + msgErr);
 
                 // Values are read from streams.
                 JSONObject jObjectError = new JSONObject(msgErr);
@@ -447,7 +493,7 @@ public class ExperimentApi {
             }
 
         } catch (Exception e) {
-            UserActionLogging.LogAction("Run workflow", "An exception occurred: " + e.getMessage());
+            UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Run workflow", "An exception occurred: " + e.getMessage());
             experiment.setHasError(true);
             experiment.setHasServerError(true);
             experiment.setResult(e.getMessage());
@@ -457,75 +503,75 @@ public class ExperimentApi {
         // Start the process of fetching the status
         updateWorkflowExperiment(experiment);
 
-        UserActionLogging.LogAction("Run workflow", "Run workflow completed!");
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Run workflow", "Run workflow completed!");
 
         return new ResponseEntity(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
     }
 
 
     /**
-     *  This method creates a thread that will fetch the workflow result when it is ready
+     * This method creates a thread that will fetch the workflow result when it is ready
      *
-     * @param experiment    will be used to fetch it's workflow status, it should have the workflowHistoryId initialized
-     *                      and the result should not already be fetched
-     * @return              nothing, just updates the experiment
+     * @param experiment will be used to fetch it's workflow status, it should have the workflowHistoryId initialized
+     *                   and the result should not already be fetched
+     * @return nothing, just updates the experiment
      */
     public void updateWorkflowExperiment(Experiment experiment) {
 
         if (experiment == null) {
-            UserActionLogging.LogAction("Update workflow experiment", "The experiment does not exist.");
+            UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Update workflow experiment", "The experiment does not exist.");
             return;
         }
 
-        UserActionLogging.LogAction("Update workflow experiment",
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Update workflow experiment",
                 " Experiment id : " + experiment.getUuid());
 
         if (experiment.getWorkflowHistoryId() == null) {
-            UserActionLogging.LogAction("Update workflow experiment", "History Id does not exist.");
+            UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Update workflow experiment", "History Id does not exist.");
             return;
         }
 
-        UserActionLogging.LogAction("Update workflow experiment", "Starting Thread..." );
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Update workflow experiment", "Starting Thread...");
         new Thread(() -> {
-            while(true) {
-                // ATTENTION: Inside the Thread only LogThreadAction should be used, not LogAction!
-                UserActionLogging.LogThreadAction("Update workflow experiment", "Thread is running...");
+            while (true) {
+                // ATTENTION: Inside the Thread only LogAction should be used, not LogAction!
+                UserActionLogging.LogAction("Update workflow experiment", "Thread is running...");
 
                 try {
                     sleep(2000);
                 } catch (InterruptedException e) {
-                    UserActionLogging.LogThreadAction("Update workflow experiment",
+                    UserActionLogging.LogAction("Update workflow experiment",
                             "Sleep was disrupted: " + e.getMessage());
                 }
 
-                UserActionLogging.LogThreadAction("Update workflow experiment",
+                UserActionLogging.LogAction("Update workflow experiment",
                         "Fetching status for experiment Id: " + experiment.getUuid());
 
                 String state = getWorkflowStatus(experiment.getWorkflowHistoryId());
-                UserActionLogging.LogThreadAction("Update workflow experiment", "State is: " + state);
+                UserActionLogging.LogAction("Update workflow experiment", "State is: " + state);
 
                 switch (state) {
                     case "running":
                         // Do nothing, when the experiment is created the status is set to running
-                        UserActionLogging.LogThreadAction("Update workflow experiment",
+                        UserActionLogging.LogAction("Update workflow experiment",
                                 "Workflow is still running.");
                         break;
 
                     case "completed":
                         // Get only the job result that is visible
                         List<GalaxyWorkflowResult> workflowJobsResults = getWorkflowResults(experiment.getWorkflowHistoryId());
-                        UserActionLogging.LogThreadAction("Update workflow experiment",
+                        UserActionLogging.LogAction("Update workflow experiment",
                                 "Results are: " + workflowJobsResults.toString());
 
                         boolean resultFound = false;
                         for (GalaxyWorkflowResult jobResult : workflowJobsResults) {
                             if (jobResult.getVisible()) {
-                                UserActionLogging.LogThreadAction("Update workflow experiment",
+                                UserActionLogging.LogAction("Update workflow experiment",
                                         "Visible result are: " + jobResult.getId());
 
                                 String result = getWorkflowResultBody(experiment.getWorkflowHistoryId(), jobResult.getId());
 
-                                UserActionLogging.LogThreadAction("Update workflow experiment", "Result: " + result);
+                                UserActionLogging.LogAction("Update workflow experiment", "Result: " + result);
                                 if (result == null) {
                                     experiment.setHasError(true);
                                     experiment.setHasServerError(true);
@@ -537,7 +583,7 @@ public class ExperimentApi {
                         }
 
                         if (!resultFound) {      // If there is no visible result
-                            UserActionLogging.LogThreadAction("Update workflow experiment", "No visible result");
+                            UserActionLogging.LogAction("Update workflow experiment", "No visible result");
                             experiment.setResult("[" + new ErrorResponse("The workflow has no visible result.").toString() + "]");
                             experiment.setHasError(true);
                             experiment.setHasServerError(true);
@@ -549,18 +595,18 @@ public class ExperimentApi {
                     case "error":
                         // Get the job result that failed
                         workflowJobsResults = getWorkflowResults(experiment.getWorkflowHistoryId());
-                        UserActionLogging.LogThreadAction("Update workflow experiment",
+                        UserActionLogging.LogAction("Update workflow experiment",
                                 "Error results are: " + workflowJobsResults.toString());
 
                         boolean failedJobFound = false;
                         for (GalaxyWorkflowResult jobResult : workflowJobsResults) {
                             if (jobResult.getState().equals("error")) {
-                                UserActionLogging.LogThreadAction("Update workflow experiment",
+                                UserActionLogging.LogAction("Update workflow experiment",
                                         "Failed job is: " + jobResult.getId());
 
                                 String result = getWorkflowJobError(jobResult.getId());
 
-                                UserActionLogging.LogThreadAction("Update workflow experiment", "Job result: " + result);
+                                UserActionLogging.LogAction("Update workflow experiment", "Job result: " + result);
                                 if (result == null) {
                                     experiment.setHasError(true);
                                     experiment.setHasServerError(true);
@@ -572,7 +618,7 @@ public class ExperimentApi {
                         }
 
                         if (!failedJobFound) {      // If there is no visible failed job
-                            UserActionLogging.LogThreadAction("Update workflow experiment", "No failed result");
+                            UserActionLogging.LogAction("Update workflow experiment", "No failed result");
                             experiment.setResult("[" + new ErrorResponse("The workflow has no failed result.").toString() + "]");
                             experiment.setHasError(true);
                             experiment.setHasServerError(true);
@@ -590,7 +636,7 @@ public class ExperimentApi {
 
                 // If result exists return
                 if (experiment.getResult() != null) {
-                    UserActionLogging.LogThreadAction("Update workflow experiment",
+                    UserActionLogging.LogAction("Update workflow experiment",
                             "Result exists: " + experiment.getResult());
                     return;
                 }
@@ -607,8 +653,8 @@ public class ExperimentApi {
      * "completed"         ->      When the workflow completed successfully
      */
     public String getWorkflowStatus(String historyId) {
-        // ATTENTION: This function is used from a Thread. Only LogThreadAction should be used, not LogAction!
-        UserActionLogging.LogThreadAction("Get workflow status", " History Id : " + historyId);
+        // ATTENTION: This function is used from a Thread. Only LogAction should be used, not LogAction!
+        UserActionLogging.LogAction("Get workflow status", " History Id : " + historyId);
 
         // Create the request client
         RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
@@ -618,15 +664,15 @@ public class ExperimentApi {
         try {
             Response<Object> response = call.execute();
             if (response.code() >= 400) {
-                UserActionLogging.LogThreadAction("Get workflow status", " Response code: "
+                UserActionLogging.LogAction("Get workflow status", " Response code: "
                         + response.code() + "" + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
                 return "internalError";
             }
             result = new Gson().toJson(response.body());
-            UserActionLogging.LogThreadAction("Get workflow status", " Result: " + result);
+            UserActionLogging.LogAction("Get workflow status", " Result: " + result);
 
         } catch (IOException e) {
-            UserActionLogging.LogThreadAction("Get workflow status"
+            UserActionLogging.LogAction("Get workflow status"
                     , " An exception happened: " + e.getMessage());
             return "internalError";
         }
@@ -636,12 +682,12 @@ public class ExperimentApi {
             JSONObject resultJson = new JSONObject(result);
             state = resultJson.getString("state");
         } catch (JSONException e) {
-            UserActionLogging.LogThreadAction("Get workflow status"
+            UserActionLogging.LogAction("Get workflow status"
                     , " An exception happened: " + e.getMessage());
             return "internalError";
         }
 
-        UserActionLogging.LogThreadAction("Get workflow status", " Completed!");
+        UserActionLogging.LogAction("Get workflow status", " Completed!");
         switch (state) {
             case "ok":
                 return "completed";
@@ -662,7 +708,7 @@ public class ExperimentApi {
      * @return a List<GalaxyWorkflowResult>   or null when an error occurred
      */
     public List<GalaxyWorkflowResult> getWorkflowResults(String historyId) {
-        UserActionLogging.LogThreadAction("Get workflow results", " historyId : " + historyId);
+        UserActionLogging.LogAction("Get workflow results", " historyId : " + historyId);
 
         RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
         Call<List<GalaxyWorkflowResult>> call = service.getWorkflowResultsFromGalaxy(historyId, galaxyApiKey);
@@ -671,20 +717,20 @@ public class ExperimentApi {
         try {
             Response<List<GalaxyWorkflowResult>> response = call.execute();
             if (response.code() >= 400) {
-                UserActionLogging.LogThreadAction("Get workflow results", " Response code: "
+                UserActionLogging.LogAction("Get workflow results", " Response code: "
                         + response.code() + "" + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
                 return null;
             }
             getGalaxyWorkflowResultList = response.body();
-            UserActionLogging.LogThreadAction("Get workflow results", " Result: " + response.body());
+            UserActionLogging.LogAction("Get workflow results", " Result: " + response.body());
 
         } catch (IOException e) {
-            UserActionLogging.LogThreadAction("Get workflow results"
+            UserActionLogging.LogAction("Get workflow results"
                     , " An exception happened: " + e.getMessage());
             return null;
         }
 
-        UserActionLogging.LogThreadAction("Get workflow results", " Completed!");
+        UserActionLogging.LogAction("Get workflow results", " Completed!");
         return getGalaxyWorkflowResultList;
 
     }
@@ -695,7 +741,7 @@ public class ExperimentApi {
      * @return the result of the specific workflow job, null if there was an error
      */
     public String getWorkflowResultBody(String historyId, String contentId) {
-        UserActionLogging.LogThreadAction("Get workflow results Body", " historyId : " + historyId);
+        UserActionLogging.LogAction("Get workflow results Body", " historyId : " + historyId);
 
         RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
         Call<Object> call =
@@ -705,20 +751,20 @@ public class ExperimentApi {
         try {
             Response<Object> response = call.execute();
             if (response.code() >= 400) {
-                UserActionLogging.LogThreadAction("Get workflow results Body", " Response code: "
+                UserActionLogging.LogAction("Get workflow results Body", " Response code: "
                         + response.code() + "" + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
                 return null;
             }
             resultJson = new Gson().toJson(response.body());
-            UserActionLogging.LogThreadAction("Get workflow results Body", " Result: " + resultJson);
+            UserActionLogging.LogAction("Get workflow results Body", " Result: " + resultJson);
 
         } catch (IOException e) {
-            UserActionLogging.LogThreadAction("Get workflow results Body",
+            UserActionLogging.LogAction("Get workflow results Body",
                     " An exception happened: " + e.getMessage());
             return null;
         }
 
-        UserActionLogging.LogThreadAction("Get workflow results Body", " Completed!");
+        UserActionLogging.LogAction("Get workflow results Body", " Completed!");
         return resultJson;
     }
 
@@ -728,7 +774,7 @@ public class ExperimentApi {
      * @return the error that was produced or null if an error occurred
      */
     public String getWorkflowJobError(String jobId) {
-        UserActionLogging.LogThreadAction("Get workflow job error", " jobId : " + jobId);
+        UserActionLogging.LogAction("Get workflow job error", " jobId : " + jobId);
 
         RetroFitGalaxyClients service = RetrofitClientInstance.getRetrofitInstance().create(RetroFitGalaxyClients.class);
         Call<Object> callError = service.getErrorMessageOfWorkflowFromGalaxy(jobId, galaxyApiKey);
@@ -738,7 +784,7 @@ public class ExperimentApi {
         try {
             Response<Object> response = callError.execute();
             if (response.code() >= 400) {
-                UserActionLogging.LogThreadAction("Get workflow job error", "Response code: "
+                UserActionLogging.LogAction("Get workflow job error", "Response code: "
                         + response.code() + " with body: " + (response.errorBody() != null ? response.errorBody().string() : " "));
                 return null;
             }
@@ -748,19 +794,19 @@ public class ExperimentApi {
             JsonElement jsonElement = new JsonParser().parse(jsonString);
             JsonObject rootObject = jsonElement.getAsJsonObject();
             fullError = rootObject.get("stderr").getAsString();
-            UserActionLogging.LogThreadAction("Get workflow job error", "Error: " + fullError);
+            UserActionLogging.LogAction("Get workflow job error", "Error: " + fullError);
 
             String[] arrOfStr = fullError.split("ValueError", 0);
             String specError = arrOfStr[arrOfStr.length - 1];
             returnError = specError.substring(1);
-            UserActionLogging.LogThreadAction("Get workflow job error", "Parsed Error: " + returnError);
+            UserActionLogging.LogAction("Get workflow job error", "Parsed Error: " + returnError);
 
         } catch (IOException e) {
-            UserActionLogging.LogThreadAction("Get workflow job error", "Exception: " + e.getMessage());
+            UserActionLogging.LogAction("Get workflow job error", "Exception: " + e.getMessage());
             return null;
         }
 
-        UserActionLogging.LogThreadAction("Get workflow job error", "Completed successfully!");
+        UserActionLogging.LogAction("Get workflow job error", "Completed successfully!");
 
         return returnError;
     }
diff --git a/src/main/java/eu/hbp/mip/controllers/FilesAPI.java b/src/main/java/eu/hbp/mip/controllers/FilesAPI.java
index 5acdb38ca88a851cb96a3c375c51165b1e157531..3b4ec96ab88749ea8cfb64777c8bd79f090fa12d 100644
--- a/src/main/java/eu/hbp/mip/controllers/FilesAPI.java
+++ b/src/main/java/eu/hbp/mip/controllers/FilesAPI.java
@@ -36,12 +36,12 @@ public class FilesAPI {
     public ResponseEntity<Void> getProtectedFile(
             @ApiParam(value = "filename", required = true) @PathVariable("filename") String filename
     ) {
-        UserActionLogging.LogAction("Get protected file", " filename : " + filename);
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Get protected file", " filename : " + filename);
 
         String filepath = "/protected/" + filename;
         String user = userInfo.getUser().getUsername();
         String time = LocalDateTime.now().toString();
-        UserActionLogging.LogAction("User " + user + " downloaded " + filepath, "");
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Downloaded " + filepath, "");
 
         HttpHeaders headers = new HttpHeaders();
         headers.add("X-Accel-Redirect", filepath);
diff --git a/src/main/java/eu/hbp/mip/controllers/MiningApi.java b/src/main/java/eu/hbp/mip/controllers/MiningApi.java
index 3adcc6269e8120147c6c81367c91b928c1d5d486..fba6ecf93718de3a4a4eea7b34af56e81e8e23a0 100644
--- a/src/main/java/eu/hbp/mip/controllers/MiningApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/MiningApi.java
@@ -51,7 +51,7 @@ public class MiningApi {
     @ApiOperation(value = "Create a histogram on Exareme", response = String.class)
     @RequestMapping(value = "/histograms", method = RequestMethod.POST)
     public ResponseEntity runExaremeHistograms(@RequestBody List<HashMap<String, String>> queryList) {
-        UserActionLogging.LogAction("Run an histogram", "");
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Run an histogram", "");
 
         String query = gson.toJson(queryList);
         String url = queryExaremeUrl + "/" + "MULTIPLE_HISTOGRAMS";
@@ -69,7 +69,7 @@ public class MiningApi {
     @ApiOperation(value = "Create a descriptive statistic on Exareme", response = String.class)
     @RequestMapping(value = "/descriptive_stats", method = RequestMethod.POST)
     public ResponseEntity runExaremeDescriptiveStats(@RequestBody List<HashMap<String, String>> queryList) {
-        UserActionLogging.LogAction("Run descriptive stats", "");
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Run descriptive stats", "");
 
         String query = gson.toJson(queryList);
         String url = queryExaremeUrl + "/" + "DESCRIPTIVE_STATS";
@@ -87,7 +87,7 @@ public class MiningApi {
     @ApiOperation(value = "Check if a formula is valid", response = String.class)
     @RequestMapping(value = "/checkFormula", method = RequestMethod.POST)
     public ResponseEntity checkFormulaValidity(String formula) {
-        UserActionLogging.LogAction("Check Formula Validity", "");
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Check Formula Validity", "");
 
         return ResponseEntity.ok("");
     }
diff --git a/src/main/java/eu/hbp/mip/controllers/ModelsApi.java b/src/main/java/eu/hbp/mip/controllers/ModelsApi.java
index 02ee9ac6b25b353876566a7261a7e6deba962574..633c01783d340a9b76bd71723fc62dd16db16fb1 100644
--- a/src/main/java/eu/hbp/mip/controllers/ModelsApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/ModelsApi.java
@@ -54,7 +54,7 @@ public class ModelsApi {
             @ApiParam(value = "Only ask own models") @RequestParam(value = "own", required = false) Boolean own,
             @ApiParam(value = "Only ask published models") @RequestParam(value = "valid", required = false) Boolean valid
     )  {
-        UserActionLogging.LogAction("Get models","");
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Get models","");
 
         User user = userInfo.getUser();
 
@@ -98,7 +98,7 @@ public class ModelsApi {
             @RequestBody @ApiParam(value = "Model to create", required = true) Model model
     )  {
 
-        UserActionLogging.LogAction("Create a model","");
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Create a model","");
 
         User user = userInfo.getUser();
 
@@ -129,7 +129,7 @@ public class ModelsApi {
         }
         modelRepository.save(model);
 
-        UserActionLogging.LogAction("Model saved (also saved model.config and model.query)"," id : " + model.getSlug());
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Model saved (also saved model.config and model.query)"," id : " + model.getSlug());
 
         return ResponseEntity.status(HttpStatus.CREATED).body(model);
     }
@@ -192,7 +192,7 @@ public class ModelsApi {
     public ResponseEntity<Model> getAModel(
             @ApiParam(value = "slug", required = true) @PathVariable("slug") String slug
     )  {
-        UserActionLogging.LogAction("Get a model", " id : " + slug);
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Get a model", " id : " + slug);
 
         User user = userInfo.getUser();
 
@@ -224,7 +224,7 @@ public class ModelsApi {
             @ApiParam(value = "slug", required = true) @PathVariable("slug") String slug,
             @RequestBody @ApiParam(value = "Model to update", required = true) Model model
     )  {
-        UserActionLogging.LogAction("Update a model", " id : "+ slug);
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Update a model", " id : "+ slug);
 
         User user = userInfo.getUser();
         Model oldModel = modelRepository.findOne(slug);
@@ -269,7 +269,7 @@ public class ModelsApi {
         datasetRepository.save(model.getDataset());
         modelRepository.save(model);
 
-        UserActionLogging.LogAction("Model updated (also saved/updated model.config and model.query)", " id : "+ slug);
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Model updated (also saved/updated model.config and model.query)", " id : "+ slug);
 
         return new ResponseEntity<>(HttpStatus.NO_CONTENT);
     }
diff --git a/src/main/java/eu/hbp/mip/controllers/PathologiesApi.java b/src/main/java/eu/hbp/mip/controllers/PathologiesApi.java
index 27f635d3278e9a2990489b4a3c01bd0d9851c34a..b7914e2215693126dfed7658b9bfa7e07796dec6 100644
--- a/src/main/java/eu/hbp/mip/controllers/PathologiesApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/PathologiesApi.java
@@ -4,12 +4,20 @@
 
 package eu.hbp.mip.controllers;
 
-import com.fasterxml.jackson.core.type.TypeReference;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import eu.hbp.mip.model.PathologyDTO;
+import eu.hbp.mip.model.PathologyDTO.PathologyDatasetDTO;
+import eu.hbp.mip.model.UserInfo;
+import eu.hbp.mip.utils.ClaimUtils;
 import eu.hbp.mip.utils.CustomResourceLoader;
+import eu.hbp.mip.utils.UserActionLogging;
 import io.swagger.annotations.Api;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.core.io.Resource;
-import org.springframework.core.io.ResourceLoader;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.core.Authentication;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RestController;
@@ -18,7 +26,9 @@ import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
-import eu.hbp.mip.utils.UserActionLogging;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 
@@ -27,25 +37,78 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 @Api(value = "/pathologies")
 public class PathologiesApi {
 
-    @RequestMapping(name = "/pathologies", method = RequestMethod.GET)
-    public String getPathologies() {
-		UserActionLogging.LogAction("load the pathologies", "");
-		
-        return loadPathologies();
-    }
+    private static final Gson gson = new Gson();
+
+    @Autowired
+    private UserInfo userInfo;
+
+    // Enable HBP collab authentication (1) or disable it (0). Default is 1
+    @Value("#{'${hbp.authentication.enabled:1}'}")
+    private boolean authenticationIsEnabled;
 
     @Autowired
     private CustomResourceLoader resourceLoader;
-    private String loadPathologies() {
 
-        Resource resource  = resourceLoader.getResource("file:/opt/portal/api/pathologies.json");
-        String result;
+    @RequestMapping(name = "/pathologies", method = RequestMethod.GET)
+    public ResponseEntity<String> getPathologies(Authentication authentication) {
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Load all the pathologies", "");
+
+        // Load pathologies from file
+        Resource resource = resourceLoader.getResource("file:/opt/portal/api/pathologies.json");
+        List<PathologyDTO> allPathologies;
         try {
-            result = convertInputStreamToString(resource.getInputStream());
+            allPathologies = gson.fromJson(convertInputStreamToString(resource.getInputStream()), new TypeToken<List<PathologyDTO>>() {
+            }.getType());
         } catch (IOException e) {
-            result = "{\"error\" : \"The pathologies.json file could not be read.\"}";
+            return ResponseEntity.badRequest().body("The pathologies.json file could not be read.");
+        }
+
+        // If authentication is disabled return everything
+        if (!authenticationIsEnabled) {
+            return ResponseEntity.ok().body(gson.toJson(allPathologies));
         }
-        return result;
+
+        // --- Providing only the allowed pathologies/datasets to the user  ---
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(),
+                "Load all the pathologies", "Filter out the unauthorised datasets.");
+
+        List<String> userClaims = Arrays.asList(authentication.getAuthorities().toString().toLowerCase()
+                .replaceAll("[\\s+\\]\\[]", "").split(","));
+
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(),
+                "Load all the pathologies", "User Claims: " + userClaims);
+
+        // If the "dataset_all" claim exists then return everything
+        if (userClaims.contains(ClaimUtils.allDatasetsAllowedClaim())) {
+            return ResponseEntity.ok().body(gson.toJson(allPathologies));
+        }
+
+        List<PathologyDTO> userPathologies = new ArrayList<>();
+        for (PathologyDTO curPathology : allPathologies) {
+            UserActionLogging.LogUserAction(userInfo.getUser().getUsername(),
+                    "Load all the pathologies", "Pathology: " + curPathology);
+
+            List<PathologyDatasetDTO> userPathologyDatasets = new ArrayList<PathologyDatasetDTO>();
+            for (PathologyDatasetDTO dataset : curPathology.getDatasets()) {
+                if (userClaims.contains(ClaimUtils.getDatasetClaim(dataset.getCode()))) {
+                    userPathologyDatasets.add(dataset);
+                }
+            }
+
+            if (userPathologyDatasets.size() > 0) {
+                UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Load all the pathologies",
+                        "Added pathology '" + curPathology.getLabel() + " with datasets: '" + userPathologyDatasets + "'");
+
+                PathologyDTO userPathology = new PathologyDTO();
+                userPathology.setCode(curPathology.getCode());
+                userPathology.setLabel(curPathology.getLabel());
+                userPathology.setMetadataHierarchy(curPathology.getMetadataHierarchy());
+                userPathology.setDatasets(userPathologyDatasets);
+                userPathologies.add(userPathology);
+            }
+        }
+
+        return ResponseEntity.ok().body(gson.toJson(userPathologies));
     }
 
     // Pure Java
diff --git a/src/main/java/eu/hbp/mip/controllers/SecurityApi.java b/src/main/java/eu/hbp/mip/controllers/SecurityApi.java
index 0f93c437ea8477000e1881815cce984eca36f3f8..397f1ae6c149a3693632a0b7817709d6cb2318f3 100644
--- a/src/main/java/eu/hbp/mip/controllers/SecurityApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/SecurityApi.java
@@ -5,20 +5,19 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.gson.Gson;
 import com.google.gson.JsonObject;
 import eu.hbp.mip.configuration.SecurityConfiguration;
-import org.springframework.beans.factory.annotation.Value;
 import eu.hbp.mip.model.User;
 import eu.hbp.mip.model.UserInfo;
 import eu.hbp.mip.repositories.UserRepository;
+import eu.hbp.mip.utils.UserActionLogging;
 import io.swagger.annotations.ApiParam;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.security.access.AccessDeniedException;
 import org.springframework.security.access.prepost.PreAuthorize;
-import eu.hbp.mip.utils.UserActionLogging;
+import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletResponse;
@@ -45,8 +44,8 @@ public class SecurityApi {
     @RequestMapping(path = "/user", method = RequestMethod.GET)
     public Object user(Principal principal, HttpServletResponse response) {
         ObjectMapper mapper = new ObjectMapper();
-		
-		UserActionLogging.LogAction("get user from /user","");
+
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "get user from /user", "");
         try {
             String userJSON = mapper.writeValueAsString(userInfo.getUser());
             Cookie cookie = new Cookie("user", URLEncoder.encode(userJSON, "UTF-8"));
@@ -77,9 +76,9 @@ public class SecurityApi {
             user.setAgreeNDA(agreeNDA);
             userRepository.save(user);
         }
-		
-		UserActionLogging.LogAction("user agreeNDA","");
-		
+
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "user agreeNDA", "");
+
         return new ResponseEntity<>(HttpStatus.NO_CONTENT);
     }
 
@@ -106,16 +105,15 @@ public class SecurityApi {
      */
 
     @RequestMapping(path = "/galaxy", method = RequestMethod.GET, produces = "application/json")
-	@PreAuthorize("hasRole('Data Manager')")
+    @PreAuthorize("hasRole('Data Manager')")
     @ResponseStatus(value = HttpStatus.OK)
-    public ResponseEntity getGalaxyConfiguration(){
+    public ResponseEntity getGalaxyConfiguration() {
         String stringEncoded = Base64.getEncoder().encodeToString((galaxyUsername + ":" + galaxyPassword).getBytes());
         JsonObject object = new JsonObject();
         object.addProperty("authorization", stringEncoded);
         object.addProperty("context", galaxyContext);
-		UserActionLogging.LogAction("get galaxy information","");
-		
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "get galaxy information", "");
+
         return ResponseEntity.ok(gson.toJson(object));
     }
-
 }
diff --git a/src/main/java/eu/hbp/mip/controllers/StatsApi.java b/src/main/java/eu/hbp/mip/controllers/StatsApi.java
index a92adecde01cb383ce4c677b2476b27afa862437..56d25679321043aec77613e0d028c0332ef49604 100644
--- a/src/main/java/eu/hbp/mip/controllers/StatsApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/StatsApi.java
@@ -3,16 +3,15 @@
  */
 
 package eu.hbp.mip.controllers;
-import eu.hbp.mip.utils.UserActionLogging;
+
 import eu.hbp.mip.model.GeneralStats;
+import eu.hbp.mip.model.UserInfo;
 import eu.hbp.mip.repositories.ArticleRepository;
 import eu.hbp.mip.repositories.UserRepository;
+import eu.hbp.mip.utils.UserActionLogging;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
@@ -24,19 +23,20 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 @RequestMapping(value = "/stats", produces = {APPLICATION_JSON_VALUE})
 @Api(value = "/stats", description = "the stats API")
 public class StatsApi {
-
-    
     @Autowired
     private UserRepository userRepository;
 
+    @Autowired
+    private UserInfo userInfo;
+
     @Autowired
     private ArticleRepository articleRepository;
 
 
     @ApiOperation(value = "Get general statistics", response = GeneralStats.class)
     @RequestMapping(method = RequestMethod.GET)
-    public ResponseEntity<GeneralStats> getGeneralStatistics()  {
-        UserActionLogging.LogAction("Get statistics (count on users, articles and variables)","");
+    public ResponseEntity<GeneralStats> getGeneralStatistics() {
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Get statistics (count on users, articles and variables)", "");
 
         GeneralStats stats = new GeneralStats();
 
diff --git a/src/main/java/eu/hbp/mip/controllers/UsersApi.java b/src/main/java/eu/hbp/mip/controllers/UsersApi.java
index ed3104eb807ab844c25f20df69fac2c200ed0bf2..0620c34e444315dc6c472c304539f9c6b5d8d28d 100644
--- a/src/main/java/eu/hbp/mip/controllers/UsersApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/UsersApi.java
@@ -4,12 +4,13 @@
 
 package eu.hbp.mip.controllers;
 
-import eu.hbp.mip.utils.UserActionLogging;
-import io.swagger.annotations.*;
 import eu.hbp.mip.model.User;
+import eu.hbp.mip.model.UserInfo;
 import eu.hbp.mip.repositories.UserRepository;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import eu.hbp.mip.utils.UserActionLogging;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -27,12 +28,15 @@ public class UsersApi {
     @Autowired
     private UserRepository userRepository;
 
+    @Autowired
+    private UserInfo userInfo;
+
     @ApiOperation(value = "Get a user", response = User.class)
     @RequestMapping(value = "/{username}", method = RequestMethod.GET)
     public ResponseEntity<User> getAUser(
             @ApiParam(value = "username", required = true) @PathVariable("username") String username
-    )  {
-        UserActionLogging.LogAction("Get a user","");
+    ) {
+        UserActionLogging.LogUserAction(userInfo.getUser().getUsername(), "Get a user", "");
 
         return ResponseEntity.ok(userRepository.findOne(username));
     }
diff --git a/src/main/java/eu/hbp/mip/model/PathologyDTO.java b/src/main/java/eu/hbp/mip/model/PathologyDTO.java
new file mode 100644
index 0000000000000000000000000000000000000000..e447ba6053a6126c66ce20910cc78af07b6988e1
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/model/PathologyDTO.java
@@ -0,0 +1,77 @@
+package eu.hbp.mip.model;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.List;
+
+public class PathologyDTO {
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public Object getMetadataHierarchy() {
+        return metadataHierarchy;
+    }
+
+    public void setMetadataHierarchy(Object metadataHierarchy) {
+        this.metadataHierarchy = metadataHierarchy;
+    }
+
+    public List<PathologyDatasetDTO> getDatasets() {
+        return datasets;
+    }
+
+    public void setDatasets(List<PathologyDatasetDTO> datasets) {
+        this.datasets = datasets;
+    }
+
+    @SerializedName("code")
+    private String code;
+
+    @SerializedName("label")
+    private String label;
+
+    @SerializedName("metadataHierarchy")
+    private Object metadataHierarchy;
+
+    @SerializedName("datasets")
+    private List<PathologyDatasetDTO> datasets;
+
+    public static class PathologyDatasetDTO {
+        @SerializedName("code")
+        private String code;
+
+        @SerializedName("label")
+        private String label;
+
+        public String getCode() {
+            return code;
+        }
+
+        public void setCode(String code) {
+            this.code = code;
+        }
+
+        public String getLabel() {
+            return label;
+        }
+
+        public void setLabel(String label) {
+            this.label = label;
+        }
+    }
+
+}
diff --git a/src/main/java/eu/hbp/mip/utils/ClaimUtils.java b/src/main/java/eu/hbp/mip/utils/ClaimUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..f9bd98b5886df396f233e95655f3e6240ac63b47
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/utils/ClaimUtils.java
@@ -0,0 +1,11 @@
+package eu.hbp.mip.utils;
+
+public class ClaimUtils {
+    public static String allDatasetsAllowedClaim(){
+        return "dataset_all";
+    }
+
+    public static String getDatasetClaim(String datasetCode){
+        return "dataset_" + datasetCode;
+    }
+}
diff --git a/src/main/java/eu/hbp/mip/utils/CustomAccessDeniedHandler.java b/src/main/java/eu/hbp/mip/utils/CustomAccessDeniedHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..783e4a3ff68ab3384a798d9fc70f68f29c114bd6
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/utils/CustomAccessDeniedHandler.java
@@ -0,0 +1,33 @@
+package eu.hbp.mip.utils;
+
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.web.access.AccessDeniedHandler;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.sql.Timestamp;
+
+public class CustomAccessDeniedHandler implements AccessDeniedHandler {
+    @Override
+    public void handle(HttpServletRequest request, HttpServletResponse response,
+                       AccessDeniedException accessDeniedException) throws IOException, ServletException {
+        response.setContentType("application/json;charset=UTF-8");
+        response.setStatus(403);
+        try {
+            response.getWriter().write(new JSONObject()
+                    .put("timestamp", new Timestamp(System.currentTimeMillis()))
+                    .put("status", 403)
+                    .put("error", "Forbidden")
+                    .put("message", "Access Denied. Please contact the system administrator to request access.")
+                    .put("path", request.getServletPath())
+                    .toString());
+        } catch (JSONException e) {
+            response.getWriter().write("");
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/src/main/java/eu/hbp/mip/utils/JSONUtil.java b/src/main/java/eu/hbp/mip/utils/JSONUtil.java
deleted file mode 100644
index 5822a44053790772138f53a6e388bbfd4e6d888a..0000000000000000000000000000000000000000
--- a/src/main/java/eu/hbp/mip/utils/JSONUtil.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package eu.hbp.mip.utils;
-
-import com.google.gson.JsonParseException;
-import com.google.gson.JsonParser;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Created by mirco on 01.07.16.
- */
-public class JSONUtil {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(JSONUtil.class);
-
-    private JSONUtil() {
-        /* Hide implicit public constructor */
-        throw new IllegalAccessError("JSONUtil class");
-    }
-
-    public static boolean isJSONValid(String test) {
-        try {
-            new JsonParser().parse(test);
-        } catch (JsonParseException jpe)
-        {
-            LOGGER.trace("Cannot parse to json", jpe); // This is the normal behavior when the input string is not JSON-ified
-            return false;
-        }
-        return true;
-    }
-
-}
diff --git a/src/main/java/eu/hbp/mip/utils/UserActionLogging.java b/src/main/java/eu/hbp/mip/utils/UserActionLogging.java
index b4a96fc864a16063c39dede8ea0233fbfd41b981..a0ec02277d0249c92577a3fad044de506ab7b039 100644
--- a/src/main/java/eu/hbp/mip/utils/UserActionLogging.java
+++ b/src/main/java/eu/hbp/mip/utils/UserActionLogging.java
@@ -2,24 +2,21 @@ package eu.hbp.mip.utils;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.security.core.context.SecurityContextHolder;
 
 public class UserActionLogging {
 
-
     private static final Logger LOGGER = LoggerFactory.getLogger(UserActionLogging.class);
 
-    public static void LogAction(String actionName, String actionIdInfo)
-    {
-        LOGGER.info( " User : "
-                + SecurityContextHolder.getContext().getAuthentication().getName()
+    public static void LogUserAction(String userName, String actionName, String actionInfo) {
+        LOGGER.info(" User : "
+                + userName
                 + " called endpoint: " + actionName
-                + " info: " + actionIdInfo);
+                + " info: " + actionInfo);
     }
 
-    // Used from Threads because LogAction won't work.
-    public static void LogThreadAction(String actionName, String actionIdInfo)
-    {
-        LOGGER.info( "Thread -->" + actionName + " info: " + actionIdInfo);
+    // Usually, used from Threads because threads can't get userName.
+    // Also used when a user is not authorised yet
+    public static void LogAction(String actionName, String actionIdInfo) {
+        LOGGER.info("Action -->" + actionName + " info: " + actionIdInfo);
     }
 }
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
index efd7a874adcd194ee0145465dca9c08c1f3f5c5d..d4a1e4765b7d25b98ccaf68141e28784a6ff09cb 100644
--- a/src/main/resources/logback.xml
+++ b/src/main/resources/logback.xml
@@ -1,6 +1,6 @@
 <configuration>
     <appender name="FILE1" class="ch.qos.logback.core.FileAppender">
-        <file>logs/log1.txt</file>
+        <file>logs/portal-backend.txt</file>
         <append>true</append>
         <encoder>
             <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %msg%n</pattern>