diff --git a/build.sh b/build.sh
index 5df0e1ce8b819d6e60cc939b9bf32b1ff95bad9f..84efdf7b37f26e7a7083bbb402aeced4609a152e 100755
--- a/build.sh
+++ b/build.sh
@@ -37,6 +37,7 @@ docker build --build-arg BUILD_DATE=$(date -Iseconds) \
     --tag "$IMAGE:$VERSION" \
     .
 
+
 BUGSNAG_KEY=""
 eval $(grep -e "^\\s*BUGSNAG_KEY" Dockerfile | tr '\\' ' ')
 
diff --git a/docker/config/application.tmpl b/docker/config/application.tmpl
index e3a624a13a6c1588210c0546923888956fe45a9f..e34a00c0c2d4b693fc1a4ff26d3f709b43223299 100644
--- a/docker/config/application.tmpl
+++ b/docker/config/application.tmpl
@@ -30,7 +30,8 @@ hbp:
     clientSecret: {{ .Env.CLIENT_SECRET }}
     accessTokenUri: {{ default .Env.TOKEN_URI "https://services.humanbrainproject.eu/oidc/token" }}
     userAuthorizationUri: {{ default .Env.AUTH_URI "https://services.humanbrainproject.eu/oidc/authorize" }}
-    tokenName: oauth_token
+    logoutUri: {{ .Env.LOGOUT_URI }}
+    tokenName: access_token
     authenticationScheme: query
     clientAuthenticationScheme: form
     useCurrentUri: false
@@ -46,12 +47,13 @@ frontend:
   loginUrl: {{ default .Env.FRONTEND_LOGIN_URL "http://frontend/services/login/hbp" }}
   redirectAfterLogoutUrl: {{ default .Env.FRONTEND_AFTER_LOGOUT_URL (default .Env.LOGIN_URI "http://frontend/services/login/hbp") }}
   redirectAfterLoginUrl: {{ default .Env.FRONTEND_AFTER_LOGIN_URL "http://frontend/home" }}
-
+  
 logging:
   level:
     root: {{ default .Env.LOG_LEVEL "INFO" }}
     org:
       springframework:
+        security: DEBUG
         web: {{ default .Env.LOGGING_LEVEL_WEB "WARN" }}
         web.servlet.handler.BeanNameUrlHandlerMapping: WARN
       hibernate: {{ default .Env.LOGGING_LEVEL_HIBERNATE "WARN" }}
@@ -86,4 +88,5 @@ services:
     galaxyUsername:  {{ default .Env.GALAXY_USERNAME "admin" }}
     galaxyPassword:  {{ default .Env.GALAXY_PASSWORD "password" }}
     galaxyContext:  {{ default .Env.GALAXY_CONTEXT "nativeGalaxy" }}
-
+  keycloak:
+    keycloakUrl: {{ .Env.KEYCLOAK_URL }}
diff --git a/pom.xml b/pom.xml
index 33287a67edb208121a0935c13ae7ab66d8690f7b..674ec19543bfb73623cdf88324f209ae513aa0c3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,6 +16,7 @@
         <artifactId>spring-boot-starter-parent</artifactId>
         <version>1.3.8.RELEASE</version>
         <relativePath/>
+
     </parent>
 
     <properties>
@@ -65,30 +66,15 @@
     </repositories>
 
     <dependencies>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-log4j2</artifactId>
-        </dependency>
+
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.springframework.boot</groupId>
-                    <artifactId>spring-boot-starter-logging</artifactId>
-                </exclusion>
-            </exclusions>
         </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-actuator</artifactId>
             <version>${spring-boot-starter-actuator.version}</version>
-             <exclusions>
-                <exclusion>
-                    <groupId>org.springframework.boot</groupId>
-                    <artifactId>spring-boot-starter-logging</artifactId>
-                </exclusion>
-            </exclusions>
         </dependency>
         <dependency>
             <groupId>org.springframework.data</groupId>
@@ -98,22 +84,11 @@
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-security</artifactId>
-             <exclusions>
-                <exclusion>
-                    <groupId>org.springframework.boot</groupId>
-                    <artifactId>spring-boot-starter-logging</artifactId>
-                </exclusion>
-            </exclusions>
+
         </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
-             <exclusions>
-                <exclusion>
-                    <groupId>org.springframework.boot</groupId>
-                    <artifactId>spring-boot-starter-logging</artifactId>
-                </exclusion>
-            </exclusions>
         </dependency>
         <dependency>
             <groupId>org.springframework.security.oauth</groupId>
@@ -145,12 +120,6 @@
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-test</artifactId>
-             <exclusions>
-                <exclusion>
-                    <groupId>org.springframework.boot</groupId>
-                    <artifactId>spring-boot-starter-logging</artifactId>
-                </exclusion>
-            </exclusions>
             <scope>test</scope>
         </dependency>
         <dependency>
@@ -249,6 +218,11 @@
             <artifactId>java-jwt</artifactId>
             <version>3.8.3</version>
         </dependency>
+        <dependency>
+            <groupId>com.auth0</groupId>
+            <artifactId>java-jwt</artifactId>
+            <version>3.8.3</version>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/src/main/java/eu/hbp/mip/MIPApplication.java b/src/main/java/eu/hbp/mip/MIPApplication.java
index df70ba78a5ba397676f1ad1533895e86a67c4f89..befb16ec91ee35a0bbd2c9a7631f30be9cde4b21 100644
--- a/src/main/java/eu/hbp/mip/MIPApplication.java
+++ b/src/main/java/eu/hbp/mip/MIPApplication.java
@@ -4,14 +4,23 @@
 
 package eu.hbp.mip;
 
+
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
 
 @SpringBootApplication
 public class MIPApplication {
 
+	private static final Logger LOGGER = LoggerFactory.getLogger(MIPApplication.class);
+	
     public static void main(String[] args) {
         SpringApplication.run(MIPApplication.class, args);
     }
 
+
+
+	
 }
diff --git a/src/main/java/eu/hbp/mip/configuration/SecurityConfiguration.java b/src/main/java/eu/hbp/mip/configuration/SecurityConfiguration.java
index d8ec1acfbc932f8cb5faa1a42199904ffc88a092..a92879577926739b703e4d015a1a64caa1ed5b87 100644
--- a/src/main/java/eu/hbp/mip/configuration/SecurityConfiguration.java
+++ b/src/main/java/eu/hbp/mip/configuration/SecurityConfiguration.java
@@ -4,10 +4,12 @@ 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 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.security.oauth2.resource.AuthoritiesExtractor;
 import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties;
 import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices;
 import org.springframework.boot.context.embedded.FilterRegistrationBean;
@@ -34,6 +36,10 @@ import org.springframework.security.web.csrf.CsrfTokenRepository;
 import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
 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.servlet.Filter;
 import javax.servlet.FilterChain;
@@ -42,179 +48,324 @@ import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
+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
 
-/**
- * Configuration for security.
- */
 @Configuration
 @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 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 {
-        // @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()
-                    .anyRequest().authenticated()
-                    .and().exceptionHandling().authenticationEntryPoint(new CustomLoginUrlAuthenticationEntryPoint(loginUrl))
-                    .and().logout().addLogoutHandler(new CustomLogoutHandler()).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;
+   
+   
+
+//    @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 {
             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;
-    }
+   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
+   public FilterRegistrationBean oauth2ClientFilterRegistration(
+           OAuth2ClientContextFilter filter) {
+       FilterRegistrationBean registration = new FilterRegistrationBean();
+       registration.setFilter(filter);
+       registration.setOrder(-100);
+       return registration;
+   }
 
-    @Bean(name="hbp")
-    @ConfigurationProperties("hbp.client")
-    public OAuth2ProtectedResourceDetails hbp() {
-        return new AuthorizationCodeResourceDetails();
-    }
+   @Bean(name="hbp")
+   @ConfigurationProperties("hbp.client")
+   public BaseOAuth2ProtectedResourceDetails hbp() {
+       return new AuthorizationCodeResourceDetails();
+   }
 
-    @Bean(name="hbpResource")
-    @ConfigurationProperties("hbp.resource")
-    public ResourceServerProperties hbpResource() {
-        return new ResourceServerProperties();
-    }
+   @Bean(name="hbpResource")
+   @ConfigurationProperties("hbp.resource")
+   public ResourceServerProperties hbpResource() {
+       return new ResourceServerProperties();
+   }
 
-    public boolean isAuthentication() {
-        return authentication;
-    }
+   public boolean isAuthentication() {
+       return authentication;
+   }
 
-    public String getFrontendRedirectAfterLogin() {
-        return frontendRedirectAfterLogin;
-    }
+   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 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);
+           }
 
-    private CsrfTokenRepository csrfTokenRepository() {
-        HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
-        repository.setHeaderName("X-XSRF-TOKEN");
-        return repository;
+           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();
     }
 
-    private class CustomLogoutHandler implements LogoutHandler {
+
+    public class KeycloakAuthoritiesExtractor
+            implements AuthoritiesExtractor {
+
         @Override
-        public void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) {
+        public List<GrantedAuthority> extractAuthorities
+                (Map<String, Object> map) {
+            return AuthorityUtils
+                    .commaSeparatedStringToAuthorityList(asAuthorities(map));
+        }
 
-            // Hackish way of accessing to this information...
-            final UserInfo userInfo = (UserInfo) httpServletRequest.getSession().getAttribute("userInfo");
-            if (userInfo != null) {
-                userInfo.setFakeAuth(false);
+        private String asAuthorities(Map<String, Object> map) {
+            List<String> authorities = new ArrayList<>();
+//            authorities.add("BAELDUNG_USER");
+            List<LinkedHashMap<String, String>> authz;
+            authz = (List<LinkedHashMap<String, String>>) map.get("authorities");
+            for (LinkedHashMap<String, String> entry : authz) {
+                authorities.add(entry.get("authority"));
             }
+            return String.join(",", authorities);
+        }
+    }
+	
+	
+	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());
+        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リクエスト送信(ログアウト実行)
 
-            if (oauth2ClientContext == null || oauth2ClientContext.getAccessToken() == null)
-            {
-                return;
-            }
+		ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class);
+    }
+   
+   @Value("#{'${services.keycloak.keycloakUrl}'}")
+   private String keycloakUrl;
+   
+    // static {
+        // disableCertificateValidation();
+    // }
 
-            String idToken = oauth2ClientContext.getAccessToken().getAdditionalInformation().get("id_token").toString();
+    public void disableCertificateValidation() {
+		LOGGER.info("disabling certificate validation host : " + keycloakUrl);
+        // Create a trust manager that does not validate certificate chains
+        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) {}
+                } };
 
-            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)
+        // 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))
                 {
-                    LOGGER.warn("Cannot send request to OIDC server for revocation ! ");
+                    return true;
                 }
-                else{
-                    LOGGER.info("Should be logged out");
+                else
+                {
+                    return false;
                 }
-            } catch (IOException e) {
-                LOGGER.warn("Cannot notify logout to OIDC server !");
-                LOGGER.trace("Cannot notify logout", e);
             }
+        };
+
+        // Install the all-trusting trust manager
+        try {
+            SSLContext sc = SSLContext.getInstance("SSL");
+            sc.init(null, trustAllCerts, new SecureRandom());
+            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
+            HttpsURLConnection.setDefaultHostnameVerifier(hv);
+        } catch (Exception e) {}
+
+    } 
 
-        }
-    }
 }
diff --git a/src/main/java/eu/hbp/mip/controllers/ArticlesApi.java b/src/main/java/eu/hbp/mip/controllers/ArticlesApi.java
index 3b567b102c182f529006f055a11112efd5c749a7..963b181576f0626620d76b3a0370dcb840767778 100644
--- a/src/main/java/eu/hbp/mip/controllers/ArticlesApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/ArticlesApi.java
@@ -10,6 +10,7 @@ import eu.hbp.mip.model.Article;
 import eu.hbp.mip.model.User;
 import eu.hbp.mip.model.UserInfo;
 import eu.hbp.mip.repositories.ArticleRepository;
+import eu.hbp.mip.utils.UserActionLogging;
 import io.swagger.annotations.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -30,8 +31,6 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 @Api(value = "/articles", description = "the articles API")
 public class ArticlesApi {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(ArticlesApi.class);
-
     @Autowired
     private UserInfo userInfo;
 
@@ -44,8 +43,6 @@ public class ArticlesApi {
             @ApiParam(value = "Only ask own articles") @RequestParam(value = "own", required = false) Boolean own,
             @ApiParam(value = "Only ask results matching status", allowableValues = "draft, published") @RequestParam(value = "status", required = false) String status
     ) {
-        LOGGER.info("Get articles");
-
         User user = userInfo.getUser();
         Iterable<Article> articles;
 
@@ -69,7 +66,8 @@ public class ArticlesApi {
                 }
             }
         }
-
+		UserActionLogging.LogAction("Get articles", "id : Get All articles");
+        
         return ResponseEntity.ok(articles);
     }
 
@@ -80,8 +78,7 @@ public class ArticlesApi {
     public ResponseEntity<Void> addAnArticle(
             @RequestBody @ApiParam(value = "Article to create", required = true) @Valid Article article
     ) {
-        LOGGER.info("Create an article");
-
+        
         User user = userInfo.getUser();
 
         article.setCreatedAt(new Date());
@@ -111,7 +108,7 @@ public class ArticlesApi {
             slug = new Slugify().slugify(article.getTitle());
         } catch (IOException e) {
             slug = "";
-            LOGGER.trace("Cannot slugify title", e);
+            //LOGGER.trace("Cannot slugify title", e);
         }
 
         boolean alreadyExists = true;
@@ -130,8 +127,7 @@ public class ArticlesApi {
         }
         articleRepository.save(article);
 
-        LOGGER.info("Article saved");
-
+		UserActionLogging.LogAction("Created article", "id : " + article.getSlug());
         return new ResponseEntity<>(HttpStatus.CREATED);
     }
 
@@ -141,7 +137,7 @@ public class ArticlesApi {
     public ResponseEntity<Article> getAnArticle(
             @ApiParam(value = "slug", required = true) @PathVariable("slug") String slug
     ) {
-        LOGGER.info("Get an article");
+		UserActionLogging.LogAction("Getting an article", "id : " + slug);
 
         User user = userInfo.getUser();
         Article article;
@@ -149,7 +145,7 @@ public class ArticlesApi {
 
         if(article == null)
         {
-            LOGGER.warn("Cannot find article : " + slug);
+            //LOGGER.warn("Cannot find article : " + slug);
             return ResponseEntity.badRequest().body(null);
         }
 
@@ -169,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
     ) {
-        LOGGER.info("Update an article");
+        UserActionLogging.LogAction("Update an article", "id : " + slug);
 
         User user = userInfo.getUser();
 
@@ -201,8 +197,7 @@ public class ArticlesApi {
 
         articleRepository.save(article);
 
-        LOGGER.info("Article updated");
-
+        
         return new ResponseEntity<>(HttpStatus.NO_CONTENT);
     }
 
diff --git a/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java b/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java
index 9f4fee480c37b7b0b0ac8d3fad50ed8e7bf79e59..deef20f755c0fd961e09a238eb662a671a9532e2 100644
--- a/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/ExperimentApi.java
@@ -20,6 +20,7 @@ import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
 import eu.hbp.mip.utils.JWTUtil;
+import eu.hbp.mip.utils.UserActionLogging;
 
 import java.io.IOException;
 import java.util.*;
@@ -33,7 +34,7 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 @Api(value = "/experiments", description = "the experiments API")
 public class ExperimentApi {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(ExperimentApi.class);
+    //private static final Logger LOGGER = LoggerFactory.getLogger(ExperimentApi.class);
 
     private static final Gson gson = new Gson();
 
@@ -61,7 +62,7 @@ public class ExperimentApi {
     @ApiOperation(value = "Create an experiment on Exareme", response = Experiment.class)
     @RequestMapping(value = "/exareme", method = RequestMethod.POST)
     public ResponseEntity<String> runExaremeExperiment(@RequestBody ExperimentQuery expQuery) {
-        LOGGER.info("send ExaremeExperiment");
+        //LOGGER.info("send ExaremeExperiment");
 
         Experiment experiment = saveExperiment(expQuery);
 
@@ -87,23 +88,24 @@ public class ExperimentApi {
                 experiment.setHasError(code >= 400);
                 experiment.setHasServerError(code >= 500);
             } catch (IOException e) {
-                LOGGER.trace("Invalid UUID", e);
-                LOGGER.warn("Exareme experiment failed to run properly !");
+                //LOGGER.trace("Invalid UUID", e);
+                //LOGGER.warn("Exareme experiment failed to run properly !");
                 experiment.setHasError(true);
                 experiment.setHasServerError(true);
                 experiment.setResult(e.getMessage());
             }
             finishExperiment(experiment);
         }).start();
-
+		
+		UserActionLogging.LogAction("create ExaremeExperiment", "no info");
+		
         return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
     }
 
     @ApiOperation(value = "Create a workflow", response = Experiment.class)
     @RequestMapping(value = "/workflow", method = RequestMethod.POST)
     public ResponseEntity<String> runWorkflow(@RequestBody ExperimentQuery expQuery) {
-        LOGGER.info("send Workflow");
-
+        
         Experiment experiment = saveExperiment(expQuery);
 
         String algoCode = expQuery.getAlgorithms().get(0).getCode();
@@ -132,7 +134,7 @@ public class ExperimentApi {
                 experiment.setHasError(code >= 400);
                 experiment.setHasServerError(code >= 500);
             } catch (IOException e) {
-                LOGGER.trace("Invalid UUID", e);
+                //LOGGER.trace("Invalid UUID", e);
                 experiment.setHasError(true);
                 experiment.setHasServerError(true);
                 experiment.setResult(e.getMessage());
@@ -140,6 +142,8 @@ public class ExperimentApi {
             finishExperiment(experiment);
         }).start();
 
+		UserActionLogging.LogAction("create workflow", "no info");
+		
         return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
     }
 
@@ -147,15 +151,14 @@ public class ExperimentApi {
     @RequestMapping(value = "/{uuid}", method = RequestMethod.GET)
     public ResponseEntity<String> getExperiment(
             @ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
-        LOGGER.info("Get an experiment");
 
         Experiment experiment;
         UUID experimentUuid;
         try {
             experimentUuid = UUID.fromString(uuid);
         } catch (IllegalArgumentException iae) {
-            LOGGER.trace("Invalid UUID", iae);
-            LOGGER.warn("An invalid Experiment UUID was received ! " + uuid);
+            //LOGGER.trace("Invalid UUID", iae);
+            //LOGGER.warn("An invalid Experiment UUID was received ! " + uuid);
             return ResponseEntity.badRequest().body("Invalid Experiment UUID");
         }
 
@@ -164,7 +167,9 @@ public class ExperimentApi {
         if (experiment == null) {
             return new ResponseEntity<>("Not found", HttpStatus.NOT_FOUND);
         }
-
+		
+		UserActionLogging.LogAction("Get an experiment ", " uuid : "+ uuid);
+		
         return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
     }
 
@@ -172,8 +177,9 @@ public class ExperimentApi {
     @RequestMapping(value = "/workflow/status/{historyId}", method = RequestMethod.GET)
     public ResponseEntity<String> getWorkflowStatus(
             @ApiParam(value = "historyId", required = true) @PathVariable("historyId") String historyId) {
-        LOGGER.info("Get a workflow status");
-
+       
+		UserActionLogging.LogAction("Get a workflow status", " historyId : "+ historyId);
+		
         String url = workflowUrl + "/getWorkflowStatus/" + historyId;
         try {
             User user = userInfo.getUser();
@@ -186,6 +192,7 @@ public class ExperimentApi {
         } catch (IOException e) {
             return ResponseEntity.status(500).body(e.getMessage());
         }
+		
     }
 
     // TODO: factorize workflow results
@@ -193,8 +200,8 @@ public class ExperimentApi {
     @RequestMapping(value = "/workflow/results/{historyId}", method = RequestMethod.GET)
     public ResponseEntity<String> getWorkflowResults(
             @ApiParam(value = "historyId", required = true) @PathVariable("historyId") String historyId) {
-        LOGGER.info("Get a workflow results");
-
+        UserActionLogging.LogAction("Get workflow results", " historyId : "+ historyId);
+		
         String url = workflowUrl + "/getWorkflowResults/" + historyId;
         try {
             StringBuilder response = new StringBuilder();
@@ -214,8 +221,9 @@ public class ExperimentApi {
     public ResponseEntity<String> getWorkflowResultBody(
             @ApiParam(value = "historyId", required = true) @PathVariable("historyId") String historyId,
             @ApiParam(value = "resultId", required = true) @PathVariable("resultId") String resultId) {
-        LOGGER.info("Get a workflow result content");
 
+		UserActionLogging.LogAction("Get workflow result content", " historyId : "+ historyId + " resultId : "+ resultId);
+		
         String url = workflowUrl + "/getWorkflowResultsBody/" + historyId + "/contents/" + resultId;
         try {
             StringBuilder response = new StringBuilder();
@@ -235,7 +243,7 @@ public class ExperimentApi {
     public ResponseEntity<String> getWorkflowResultsDetails(
             @ApiParam(value = "historyId", required = true) @PathVariable("historyId") String historyId,
             @ApiParam(value = "resultId", required = true) @PathVariable("resultId") String resultId) {
-        LOGGER.info("Get a workflow result content");
+		UserActionLogging.LogAction("Get workflow result details", " historyId : "+ historyId + " resultId : "+ resultId);
 
         String url = workflowUrl + "/getWorkflowResultsDetails/" + historyId + "/contents/" + resultId;
         try {
@@ -255,7 +263,8 @@ public class ExperimentApi {
     @RequestMapping(value = "/{uuid}/markAsViewed", method = RequestMethod.GET)
     public ResponseEntity<String> markExperimentAsViewed(
             @ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
-        LOGGER.info("Mark an experiment as viewed");
+
+		UserActionLogging.LogAction("Mark an experiment as viewed", " uuid : "+ uuid);
 
         Experiment experiment;
         UUID experimentUuid;
@@ -263,8 +272,8 @@ public class ExperimentApi {
         try {
             experimentUuid = UUID.fromString(uuid);
         } catch (IllegalArgumentException iae) {
-            LOGGER.trace("Invalid UUID", iae);
-            LOGGER.warn("An invalid Experiment UUID was received !");
+            //LOGGER.trace("Invalid UUID", iae);
+            //LOGGER.warn("An invalid Experiment UUID was received !");
             return ResponseEntity.badRequest().body("Invalid Experiment UUID");
         }
 
@@ -274,7 +283,7 @@ public class ExperimentApi {
         experiment.setResultsViewed(true);
         experimentRepository.save(experiment);
 
-        LOGGER.info("Experiment updated (marked as viewed)");
+		UserActionLogging.LogAction("Experiment updated (marked as viewed)", " ");
 
         return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
     }
@@ -283,8 +292,9 @@ public class ExperimentApi {
     @RequestMapping(value = "/{uuid}/markAsShared", method = RequestMethod.GET)
     public ResponseEntity<String> markExperimentAsShared(
             @ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
-        LOGGER.info("Mark an experiment as shared");
 
+		UserActionLogging.LogAction("Mark an experiment as shared", " uuid : "+ uuid);
+		
         return doMarkExperimentAsShared(uuid, true);
     }
 
@@ -292,8 +302,8 @@ public class ExperimentApi {
     @RequestMapping(value = "/{uuid}/markAsUnshared", method = RequestMethod.GET)
     public ResponseEntity<String> markExperimentAsUnshared(
             @ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
-        LOGGER.info("Mark an experiment as unshared");
-
+		UserActionLogging.LogAction("Mark an experiment as unshared", " uuid : "+ uuid);
+		
         return doMarkExperimentAsShared(uuid, false);
     }
 
@@ -301,8 +311,9 @@ public class ExperimentApi {
     @RequestMapping(method = RequestMethod.GET, params = { "maxResultCount" })
     public ResponseEntity<String> listExperiments(
             @ApiParam(value = "maxResultCount") @RequestParam int maxResultCount) {
-        LOGGER.info("List experiments");
 
+		UserActionLogging.LogAction("List experiments", " maxResultCount : "+ maxResultCount);
+		
         return doListExperiments(false, null);
     }
 
@@ -310,7 +321,8 @@ public class ExperimentApi {
     @RequestMapping(method = RequestMethod.GET, params = { "slug", "maxResultCount" })
     public ResponseEntity<String> listExperiments(@ApiParam(value = "slug") @RequestParam("slug") String modelSlug,
             @ApiParam(value = "maxResultCount") @RequestParam("maxResultCount") int maxResultCount) {
-        LOGGER.info("List experiments");
+
+		UserActionLogging.LogAction("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",
@@ -323,7 +335,7 @@ 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) {
-        LOGGER.info("List my experiments");
+        UserActionLogging.LogAction("List my experiments", " mine : "+ mine);
 
         return doListExperiments(true, null);
     }
@@ -361,8 +373,8 @@ public class ExperimentApi {
         try {
             experimentUuid = UUID.fromString(uuid);
         } catch (IllegalArgumentException iae) {
-            LOGGER.trace("Invalid UUID", iae);
-            LOGGER.warn("An invalid Experiment UUID was received !");
+            //LOGGER.trace("Invalid UUID", iae);
+            //LOGGER.warn("An invalid Experiment UUID was received !");
             return ResponseEntity.badRequest().body("Invalid Experiment UUID");
         }
 
@@ -373,8 +385,8 @@ public class ExperimentApi {
 
         experiment.setShared(shared);
         experimentRepository.save(experiment);
-
-        LOGGER.info("Experiment updated (marked as shared)");
+		
+		UserActionLogging.LogAction("Experiment updated (marked as shared)", "");
 
         return new ResponseEntity<>(gsonOnlyExposed.toJson(experiment.jsonify()), HttpStatus.OK);
     }
@@ -383,7 +395,7 @@ public class ExperimentApi {
         experiment.setFinished(new Date());
         experimentRepository.save(experiment);
 
-        LOGGER.info("Experiment updated (finished)");
+        UserActionLogging.LogAction("Experiment updated (finished)","");
     }
 
     private HashMap<String, String> makeObject(String name, String value) {
@@ -395,7 +407,6 @@ public class ExperimentApi {
     }
 
     private Experiment saveExperiment(ExperimentQuery expQuery) {
-        LOGGER.info("saveExperiment");
 
         Experiment experiment = new Experiment();
         experiment.setUuid(UUID.randomUUID());
@@ -408,7 +419,7 @@ public class ExperimentApi {
         experiment.setModel(modelRepository.findOne(expQuery.getModel()));
         experimentRepository.save(experiment);
 
-        LOGGER.info("Experiment saved");
+        UserActionLogging.LogAction("Saved an experiment", " id : "+experiment.getUuid());
 
         return experiment;
     }
diff --git a/src/main/java/eu/hbp/mip/controllers/FilesAPI.java b/src/main/java/eu/hbp/mip/controllers/FilesAPI.java
index d79717062874418824d305a908926f1c61075255..5acdb38ca88a851cb96a3c375c51165b1e157531 100644
--- a/src/main/java/eu/hbp/mip/controllers/FilesAPI.java
+++ b/src/main/java/eu/hbp/mip/controllers/FilesAPI.java
@@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RestController;
+import eu.hbp.mip.utils.UserActionLogging;
 
 import java.time.LocalDateTime;
 
@@ -26,8 +27,7 @@ import java.time.LocalDateTime;
 @Api(value = "/protected", description = "the protected files API")
 public class FilesAPI {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(FilesAPI.class);
-
+    
     @Autowired
     private UserInfo userInfo;
 
@@ -36,12 +36,12 @@ public class FilesAPI {
     public ResponseEntity<Void> getProtectedFile(
             @ApiParam(value = "filename", required = true) @PathVariable("filename") String filename
     ) {
-        LOGGER.info("Get protected file");
+        UserActionLogging.LogAction("Get protected file", " filename : " + filename);
 
         String filepath = "/protected/" + filename;
         String user = userInfo.getUser().getUsername();
         String time = LocalDateTime.now().toString();
-        LOGGER.info("User " + user + " downloaded " + filepath + " at "+ time);
+        UserActionLogging.LogAction("User " + user + " downloaded " + filepath, "");
 
         HttpHeaders headers = new HttpHeaders();
         headers.add("X-Accel-Redirect", filepath);
diff --git a/src/main/java/eu/hbp/mip/controllers/JWTApi.java b/src/main/java/eu/hbp/mip/controllers/JWTApi.java
index a3d939bbba3eb5c5a8666497be9f5c6d6414e446..a1cb6afd55431bb859170b52c9daa7007ca69c42 100644
--- a/src/main/java/eu/hbp/mip/controllers/JWTApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/JWTApi.java
@@ -13,14 +13,13 @@ import org.springframework.web.bind.annotation.*;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import eu.hbp.mip.utils.JWTUtil;
+import eu.hbp.mip.utils.UserActionLogging;
 
 @RestController
 @RequestMapping(value = "/jwt", produces = { TEXT_PLAIN_VALUE })
 @Api(value = "/jwt", description = "the jwt API")
 public class JWTApi {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(JWTApi.class);
-
     @Autowired
     private UserInfo userInfo;
 
@@ -31,7 +30,7 @@ public class JWTApi {
     @RequestMapping(method = RequestMethod.POST)
     public ResponseEntity<String> createJWT() {
 
-        LOGGER.info("Create a JSON Web Token");
+        UserActionLogging.LogAction("Create a JSON Web Token", "");
 
         User user = userInfo.getUser();
         String token = JWTUtil.getJWT(jwtSecret, user.getEmail());
diff --git a/src/main/java/eu/hbp/mip/controllers/MethodsApi.java b/src/main/java/eu/hbp/mip/controllers/MethodsApi.java
index fe7e8cd4535ac8af92603be12d40fad2bd264a74..f88f6795156f566b4b4e6e70288a5e4d535a67da 100644
--- a/src/main/java/eu/hbp/mip/controllers/MethodsApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/MethodsApi.java
@@ -15,14 +15,14 @@ import java.io.IOException;
 import eu.hbp.mip.utils.JWTUtil;
 import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 import org.springframework.beans.factory.annotation.Autowired;
+import eu.hbp.mip.utils.UserActionLogging;
 
 @RestController
 @RequestMapping(value = "/methods", produces = { APPLICATION_JSON_VALUE })
 @Api(value = "/methods", description = "the methods API")
 public class MethodsApi {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(MethodsApi.class);
-
+    
     private static final Gson gson = new Gson();
 
     @Value("#{'${services.exareme.algorithmsUrl:http://localhost:9090/mining/algorithms.json}'}")
@@ -40,7 +40,7 @@ public class MethodsApi {
     @ApiOperation(value = "List Exareme algorithms and validations", response = String.class)
     @RequestMapping(value = "/exareme", method = RequestMethod.GET)
     public ResponseEntity<Object> getExaremeAlgorithms() {
-        LOGGER.info("List Exareme algorithms and validations");
+        UserActionLogging.LogAction("List Exareme algorithms and validations", "");
 
         try {
             StringBuilder response = new StringBuilder();
@@ -57,7 +57,7 @@ public class MethodsApi {
     @ApiOperation(value = "List Galaxy workflows", response = String.class)
     @RequestMapping(value = "/workflows", method = RequestMethod.GET)
     public ResponseEntity<Object> getWorkflows() {
-        LOGGER.info("List Galaxy workflows");
+        UserActionLogging.LogAction("List Galaxy workflows", "");
 
         try {
             User user = userInfo.getUser();
diff --git a/src/main/java/eu/hbp/mip/controllers/MiningApi.java b/src/main/java/eu/hbp/mip/controllers/MiningApi.java
index e34b317d48e37cdea220bc447c1b1a853b2ee8ed..13272fc7355ed509e5b030429409a98b83ac55e1 100644
--- a/src/main/java/eu/hbp/mip/controllers/MiningApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/MiningApi.java
@@ -21,6 +21,9 @@ import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RestController;
+
+import eu.hbp.mip.utils.UserActionLogging;
+
 import org.springframework.web.bind.annotation.*;
 
 
@@ -37,7 +40,6 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 @Api(value = "/mining", description = "the mining API")
 public class MiningApi {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(MiningApi.class);
     private static final Gson gson = new Gson();
 
     @Autowired
@@ -49,7 +51,7 @@ public class MiningApi {
     @ApiOperation(value = "Create an histogram on Exareme", response = String.class)
     @RequestMapping(value = "/exareme", method = RequestMethod.POST)
     public ResponseEntity runExaremeMining(@RequestBody List<HashMap<String, String>> queryList) {
-        LOGGER.info("Run an histogram");
+        UserActionLogging.LogAction("Run an histogram", "");
 
         String query = gson.toJson(queryList);
         String url = miningExaremeQueryUrl + "/" + "HISTOGRAMS";
@@ -67,7 +69,7 @@ public class MiningApi {
     @ApiOperation(value = "Create an descriptive statistic on Exareme", response = String.class)
     @RequestMapping(value = "/exareme-stats", method = RequestMethod.POST)
     public ResponseEntity runExaremeDescriptiveStats(@RequestBody List<HashMap<String, String>> queryList) {
-        LOGGER.info("Run descriptive stats");
+        UserActionLogging.LogAction("Run descriptive stats", "");
 
         String query = gson.toJson(queryList);
         String url = miningExaremeQueryUrl + "/" + "DESCRIPTIVE_STATS";
@@ -88,7 +90,7 @@ public class MiningApi {
         @RequestBody List<HashMap<String, String>> queryList,
         @ApiParam(value = "algorithmName", required = true) @PathVariable("algorithmName") String algorithmName
         ) {
-        LOGGER.info("Run algo");
+        UserActionLogging.LogAction("Run algo", "");
 
         String query = gson.toJson(queryList);
         String url = miningExaremeQueryUrl + "/" + algorithmName;
diff --git a/src/main/java/eu/hbp/mip/controllers/ModelsApi.java b/src/main/java/eu/hbp/mip/controllers/ModelsApi.java
index 56bc1ce10bf5c4f322349720b69d48f6b14f61fe..02ee9ac6b25b353876566a7261a7e6deba962574 100644
--- a/src/main/java/eu/hbp/mip/controllers/ModelsApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/ModelsApi.java
@@ -17,6 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
+import eu.hbp.mip.utils.UserActionLogging;
 
 import java.io.IOException;
 import java.util.*;
@@ -28,7 +29,6 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 @Api(value = "/models", description = "the models API")
 public class ModelsApi {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(ModelsApi.class);
 
     @Autowired
     private UserInfo userInfo;
@@ -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
     )  {
-        LOGGER.info("Get models");
+        UserActionLogging.LogAction("Get models","");
 
         User user = userInfo.getUser();
 
@@ -98,7 +98,7 @@ public class ModelsApi {
             @RequestBody @ApiParam(value = "Model to create", required = true) Model model
     )  {
 
-        LOGGER.info("Create a model");
+        UserActionLogging.LogAction("Create a model","");
 
         User user = userInfo.getUser();
 
@@ -129,7 +129,7 @@ public class ModelsApi {
         }
         modelRepository.save(model);
 
-        LOGGER.info("Model saved (also saved model.config and model.query)");
+        UserActionLogging.LogAction("Model saved (also saved model.config and model.query)"," id : " + model.getSlug());
 
         return ResponseEntity.status(HttpStatus.CREATED).body(model);
     }
@@ -165,7 +165,7 @@ public class ModelsApi {
             slug = new Slugify().slugify(title);
         } catch (IOException e) {
             slug = "";  // Should never happen
-            LOGGER.trace("Cannot slugify title", e);
+            //LOGGER.trace("Cannot slugify title", e);
         }
         return slug;
     }
@@ -192,7 +192,7 @@ public class ModelsApi {
     public ResponseEntity<Model> getAModel(
             @ApiParam(value = "slug", required = true) @PathVariable("slug") String slug
     )  {
-        LOGGER.info("Get a model");
+        UserActionLogging.LogAction("Get a model", " id : " + slug);
 
         User user = userInfo.getUser();
 
@@ -200,7 +200,7 @@ public class ModelsApi {
 
         if(model == null)
         {
-            LOGGER.warn("Cannot find model : " + slug);
+            //LOGGER.warn("Cannot find model : " + slug);
             return ResponseEntity.badRequest().body(null);
         }
 
@@ -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
     )  {
-        LOGGER.info("Update a model");
+        UserActionLogging.LogAction("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);
 
-        LOGGER.info("Model updated (also saved/updated model.config and model.query)");
+        UserActionLogging.LogAction("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 59511de85016213a66eb576e8ea7f8410d5d6b0f..27f635d3278e9a2990489b4a3c01bd0d9851c34a 100644
--- a/src/main/java/eu/hbp/mip/controllers/PathologiesApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/PathologiesApi.java
@@ -18,6 +18,7 @@ import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
+import eu.hbp.mip.utils.UserActionLogging;
 
 import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 
@@ -28,6 +29,8 @@ public class PathologiesApi {
 
     @RequestMapping(name = "/pathologies", method = RequestMethod.GET)
     public String getPathologies() {
+		UserActionLogging.LogAction("load the pathologies", "");
+		
         return loadPathologies();
     }
 
diff --git a/src/main/java/eu/hbp/mip/controllers/SecurityApi.java b/src/main/java/eu/hbp/mip/controllers/SecurityApi.java
index cfddbd334d3070cb433672b93b3bc0d205339e10..0f93c437ea8477000e1881815cce984eca36f3f8 100644
--- a/src/main/java/eu/hbp/mip/controllers/SecurityApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/SecurityApi.java
@@ -17,6 +17,8 @@ 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.prepost.PreAuthorize;
+import eu.hbp.mip.utils.UserActionLogging;
 
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletResponse;
@@ -29,8 +31,6 @@ import java.util.Base64;
 @RestController
 public class SecurityApi {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(SecurityApi.class);
-
     private static final Gson gson = new Gson();
 
     @Autowired
@@ -45,7 +45,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","");
         try {
             String userJSON = mapper.writeValueAsString(userInfo.getUser());
             Cookie cookie = new Cookie("user", URLEncoder.encode(userJSON, "UTF-8"));
@@ -53,7 +54,7 @@ public class SecurityApi {
             cookie.setPath("/");
             response.addCookie(cookie);
         } catch (JsonProcessingException | UnsupportedEncodingException e) {
-            LOGGER.trace("Cannot read user json", e);
+            //LOGGER.trace("Cannot read user json", e);
         }
 
         if (!securityConfiguration.isAuthentication()) {
@@ -76,6 +77,9 @@ public class SecurityApi {
             user.setAgreeNDA(agreeNDA);
             userRepository.save(user);
         }
+		
+		UserActionLogging.LogAction("user agreeNDA","");
+		
         return new ResponseEntity<>(HttpStatus.NO_CONTENT);
     }
 
@@ -102,13 +106,15 @@ public class SecurityApi {
      */
 
     @RequestMapping(path = "/galaxy", method = RequestMethod.GET, produces = "application/json")
+	@PreAuthorize("hasRole('Data Manager')")
     @ResponseStatus(value = HttpStatus.OK)
     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","");
+		
         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 d09c032bc75659c18100a4f58ca3965c2e4b4933..a92adecde01cb383ce4c677b2476b27afa862437 100644
--- a/src/main/java/eu/hbp/mip/controllers/StatsApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/StatsApi.java
@@ -3,7 +3,7 @@
  */
 
 package eu.hbp.mip.controllers;
-
+import eu.hbp.mip.utils.UserActionLogging;
 import eu.hbp.mip.model.GeneralStats;
 import eu.hbp.mip.repositories.ArticleRepository;
 import eu.hbp.mip.repositories.UserRepository;
@@ -25,8 +25,7 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 @Api(value = "/stats", description = "the stats API")
 public class StatsApi {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(StatsApi.class);
-
+    
     @Autowired
     private UserRepository userRepository;
 
@@ -37,7 +36,7 @@ public class StatsApi {
     @ApiOperation(value = "Get general statistics", response = GeneralStats.class)
     @RequestMapping(method = RequestMethod.GET)
     public ResponseEntity<GeneralStats> getGeneralStatistics()  {
-        LOGGER.info("Get statistics (count on users, articles and variables)");
+        UserActionLogging.LogAction("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 89767017e0557b231e200006f8e330d9ca44ee9c..ed3104eb807ab844c25f20df69fac2c200ed0bf2 100644
--- a/src/main/java/eu/hbp/mip/controllers/UsersApi.java
+++ b/src/main/java/eu/hbp/mip/controllers/UsersApi.java
@@ -4,6 +4,7 @@
 
 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.repositories.UserRepository;
@@ -23,8 +24,6 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 @Api(value = "/users", description = "the users API")
 public class UsersApi {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(UsersApi.class);
-
     @Autowired
     private UserRepository userRepository;
 
@@ -33,7 +32,7 @@ public class UsersApi {
     public ResponseEntity<User> getAUser(
             @ApiParam(value = "username", required = true) @PathVariable("username") String username
     )  {
-        LOGGER.info("Get a user");
+        UserActionLogging.LogAction("Get a user","");
 
         return ResponseEntity.ok(userRepository.findOne(username));
     }
diff --git a/src/main/java/eu/hbp/mip/utils/UserActionLogging.java b/src/main/java/eu/hbp/mip/utils/UserActionLogging.java
new file mode 100644
index 0000000000000000000000000000000000000000..745fc24a6ca53951c1f43cd9db2f6fa5965a73d4
--- /dev/null
+++ b/src/main/java/eu/hbp/mip/utils/UserActionLogging.java
@@ -0,0 +1,23 @@
+package eu.hbp.mip.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+import java.time.LocalTime;
+
+public class UserActionLogging {
+
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(UserActionLogging.class);
+
+    public static void LogAction(String actionName, String actionIdInfo)
+    {
+        LOGGER.info( LocalTime.now()+" User : "
+                + SecurityContextHolder.getContext().getAuthentication().getName()
+                + " called enpoint " + actionName
+                + " info "
+                + actionIdInfo);
+    }
+
+}
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
new file mode 100644
index 0000000000000000000000000000000000000000..efd7a874adcd194ee0145465dca9c08c1f3f5c5d
--- /dev/null
+++ b/src/main/resources/logback.xml
@@ -0,0 +1,19 @@
+<configuration>
+    <appender name="FILE1" class="ch.qos.logback.core.FileAppender">
+        <file>logs/log1.txt</file>
+        <append>true</append>
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %msg%n</pattern>
+        </encoder>
+    </appender>
+
+	<logger name="eu.hbp.mip">
+		<appender-ref ref="FILE1" />
+	</logger>
+	<logger name="org.springframework">
+		<appender-ref ref="FILE1" />
+	</logger>
+    <logger name="eu.hbp.mip.utils" level="INFO" additivity="false">
+        <appender-ref ref="FILE1" />
+    </logger>
+</configuration>
\ No newline at end of file