You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by sa...@apache.org on 2019/07/05 22:23:43 UTC

[atlas] 03/06: ATLAS-3153 :- Add Keycloak authentication method to Atlas.

This is an automated email from the ASF dual-hosted git repository.

sarath pushed a commit to branch branch-2.0
in repository https://gitbox.apache.org/repos/asf/atlas.git

commit fd2544978658fbb8c1ee1164b286727af28770e5
Author: Bolke de Bruin <bo...@xs4all.nl>
AuthorDate: Mon May 13 08:05:20 2019 +0200

    ATLAS-3153 :- Add Keycloak authentication method to Atlas.
    
    Keycloak is an open source Identity and Access Management solution aimed at modern applications and services. It makes it easy to secure applications and services with little to no code.
    This enabled Atlas to use OpenID Connect (OAUTH2) and allows integration with more services.
    
    Signed-off-by: nixonrodrigues <ni...@apache.org>
    (cherry picked from commit 645bc94e59969d08b81e7af7a5a2db78207ab3fe)
---
 docs/src/site/twiki/Atlas-Authentication.twiki     |  28 ++++
 pom.xml                                            |   4 +
 webapp/pom.xml                                     |   8 +
 .../web/security/AtlasAuthenticationProvider.java  |  32 +++-
 .../AtlasKeycloakAuthenticationProvider.java       |  76 ++++++++++
 .../atlas/web/security/AtlasSecurityConfig.java    | 165 +++++++++++++++++++--
 6 files changed, 298 insertions(+), 15 deletions(-)

diff --git a/docs/src/site/twiki/Atlas-Authentication.twiki b/docs/src/site/twiki/Atlas-Authentication.twiki
index ddaa7fe..75626ea 100644
--- a/docs/src/site/twiki/Atlas-Authentication.twiki
+++ b/docs/src/site/twiki/Atlas-Authentication.twiki
@@ -7,6 +7,7 @@ Atlas supports following authentication methods
    * *File*
    * *Kerberos*
    * *LDAP*
+   * *Keycloak (OpenID Connect / OAUTH2)*
 
 
 Following properties should be set true to enable the authentication of that type in =atlas-application.properties= file.
@@ -16,6 +17,7 @@ Following properties should be set true to enable the authentication of that typ
 atlas.authentication.method.kerberos=true|false
 atlas.authentication.method.ldap=true|false
 atlas.authentication.method.file=true|false
+atlas.authentication.method.keycloak=true|false
 </verbatim>
 
 If two or more authentication methods are set to true, then the authentication falls back to the latter method if the earlier one fails.
@@ -111,3 +113,29 @@ atlas.authentication.method.ldap.user.searchfilter=(uid={0})
 atlas.authentication.method.ldap.default.role=ROLE_USER
 </verbatim>
 
+---++++ Keycloak Method.
+
+To enable Keycloak authentication mode in Atlas, set the property =atlas.authentication.method.keycloak= to true and also set the property =atlas.authentication.method.keycloak.file= to the localtion of your =keycloak.json= in =atlas-application.properties=.
+Also set =atlas.authentication.method.keycloak.ugi-groups= to false if you want to pickup groups from Keycloak. By default the groups will be picked up from the *roles* defined in Keycloak. In case you want to use the groups
+you need to create a mapping in keycloak and define =atlas.authentication.method.keycloak.groups_claim= equal to the token claim name. Make sure *not* to use the full group path and add the information to the access token.
+
+<verbatim>
+atlas.authentication.method.keycloak=true
+atlas.authentication.method.keycloak.file=/opt/atlas/conf/keycloak.json
+atlas.authentication.method.keycloak.ugi-groups=false
+</verbatim>
+
+Setup you keycloak.json per instructions from Keycloak. Make sure to include ="principal-attribute": "preferred_username"= to ensure readable user names and ="autodetect-bearer-only": true=.
+
+<verbatim>
+{
+  "realm": "auth",
+  "auth-server-url": "http://keycloak-server/auth",
+  "ssl-required": "external",
+  "resource": "atlas",
+  "public-client": true,
+  "confidential-port": 0,
+  "principal-attribute": "preferred_username",
+  "autodetect-bearer-only": true
+}
+</verbatim>
diff --git a/pom.xml b/pom.xml
index ccbdb13..46b5e6b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -719,6 +719,10 @@
         <hppc.version>0.8.1</hppc.version>
         <!-- Storm dependencies -->
 
+        <!-- keycloak dependencies -->
+        <keycloak.version>6.0.1</keycloak.version>
+        <!-- keycloak dependencies -->
+
         <PermGen>64m</PermGen>
         <MaxPermGen>512m</MaxPermGen>
 
diff --git a/webapp/pom.xml b/webapp/pom.xml
index 4dffbd8..529d2c7 100755
--- a/webapp/pom.xml
+++ b/webapp/pom.xml
@@ -468,6 +468,14 @@
             <artifactId>hadoop-aws</artifactId>
             <version>${hadoop.version}</version>
         </dependency>
+
+        <!-- Keycloak -->
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-spring-security-adapter</artifactId>
+            <version>${keycloak.version}</version>
+        </dependency>
+
     </dependencies>
 
     <build>
diff --git a/webapp/src/main/java/org/apache/atlas/web/security/AtlasAuthenticationProvider.java b/webapp/src/main/java/org/apache/atlas/web/security/AtlasAuthenticationProvider.java
index fb21d75..dff3d8d 100644
--- a/webapp/src/main/java/org/apache/atlas/web/security/AtlasAuthenticationProvider.java
+++ b/webapp/src/main/java/org/apache/atlas/web/security/AtlasAuthenticationProvider.java
@@ -37,11 +37,14 @@ public class AtlasAuthenticationProvider extends AtlasAbstractAuthenticationProv
 
     private boolean fileAuthenticationMethodEnabled = true;
     private boolean pamAuthenticationEnabled = false;
+    private boolean keycloakAuthenticationEnabled = false;
+
     private String ldapType = "NONE";
     public static final String FILE_AUTH_METHOD = "atlas.authentication.method.file";
     public static final String LDAP_AUTH_METHOD = "atlas.authentication.method.ldap";
     public static final String LDAP_TYPE = "atlas.authentication.method.ldap.type";
     public static final String PAM_AUTH_METHOD = "atlas.authentication.method.pam";
+    public static final String KEYCLOAK_AUTH_METHOD = "atlas.authentication.method.keycloak";
 
 
 
@@ -55,15 +58,19 @@ public class AtlasAuthenticationProvider extends AtlasAbstractAuthenticationProv
 
     final AtlasPamAuthenticationProvider pamAuthenticationProvider;
 
+    final AtlasKeycloakAuthenticationProvider atlasKeycloakAuthenticationProvider;
+
     @Inject
     public AtlasAuthenticationProvider(AtlasLdapAuthenticationProvider ldapAuthenticationProvider,
                                        AtlasFileAuthenticationProvider fileAuthenticationProvider,
                                        AtlasADAuthenticationProvider adAuthenticationProvider,
-                                       AtlasPamAuthenticationProvider pamAuthenticationProvider) {
+                                       AtlasPamAuthenticationProvider pamAuthenticationProvider,
+                                       AtlasKeycloakAuthenticationProvider atlasKeycloakAuthenticationProvider) {
         this.ldapAuthenticationProvider = ldapAuthenticationProvider;
         this.fileAuthenticationProvider = fileAuthenticationProvider;
         this.adAuthenticationProvider = adAuthenticationProvider;
         this.pamAuthenticationProvider = pamAuthenticationProvider;
+        this.atlasKeycloakAuthenticationProvider = atlasKeycloakAuthenticationProvider;
     }
 
     @PostConstruct
@@ -75,6 +82,8 @@ public class AtlasAuthenticationProvider extends AtlasAbstractAuthenticationProv
 
             this.pamAuthenticationEnabled = configuration.getBoolean(PAM_AUTH_METHOD, false);
 
+            this.keycloakAuthenticationEnabled = configuration.getBoolean(KEYCLOAK_AUTH_METHOD, false);
+
             boolean ldapAuthenticationEnabled = configuration.getBoolean(LDAP_AUTH_METHOD, false);
 
             if (ldapAuthenticationEnabled) {
@@ -118,6 +127,12 @@ public class AtlasAuthenticationProvider extends AtlasAbstractAuthenticationProv
                 } catch (Exception ex) {
                     LOG.error("Error while PAM authentication", ex);
                 }
+            } else if (keycloakAuthenticationEnabled) {
+                try {
+                    authentication = atlasKeycloakAuthenticationProvider.authenticate(authentication);
+                } catch (Exception ex) {
+                    LOG.error("Error while Keycloak authentication", ex);
+                }
             }
         }
 
@@ -137,6 +152,21 @@ public class AtlasAuthenticationProvider extends AtlasAbstractAuthenticationProv
         throw new AtlasAuthenticationException("Authentication failed.");
     }
 
+    @Override
+    public boolean supports(Class<?> authentication) {
+        if (pamAuthenticationEnabled) {
+            return pamAuthenticationProvider.supports(authentication);
+        } else if (ldapType.equalsIgnoreCase("LDAP")) {
+            return ldapAuthenticationProvider.supports(authentication);
+        } else if (ldapType.equalsIgnoreCase("AD")) {
+            return adAuthenticationProvider.supports(authentication);
+        } else if (keycloakAuthenticationEnabled) {
+            return atlasKeycloakAuthenticationProvider.supports(authentication);
+        } else {
+            return super.supports(authentication);
+        }
+    }
+
     public boolean isSsoEnabled() {
         return ssoEnabled;
     }
diff --git a/webapp/src/main/java/org/apache/atlas/web/security/AtlasKeycloakAuthenticationProvider.java b/webapp/src/main/java/org/apache/atlas/web/security/AtlasKeycloakAuthenticationProvider.java
new file mode 100644
index 0000000..367839b
--- /dev/null
+++ b/webapp/src/main/java/org/apache/atlas/web/security/AtlasKeycloakAuthenticationProvider.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.atlas.web.security;
+
+import org.apache.atlas.ApplicationProperties;
+import org.apache.commons.configuration.Configuration;
+import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
+import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+@Component
+public class AtlasKeycloakAuthenticationProvider extends AtlasAbstractAuthenticationProvider {
+  private final boolean groupsFromUGI;
+  private final String groupsClaim;
+
+  private final KeycloakAuthenticationProvider keycloakAuthenticationProvider;
+
+  public AtlasKeycloakAuthenticationProvider() throws Exception {
+    this.keycloakAuthenticationProvider = new KeycloakAuthenticationProvider();
+
+    Configuration configuration = ApplicationProperties.get();
+    this.groupsFromUGI = configuration.getBoolean("atlas.authentication.method.keycloak.ugi-groups", true);
+    this.groupsClaim = configuration.getString("atlas.authentication.method.keycloak.groups_claim");
+  }
+
+  @Override
+  public Authentication authenticate(Authentication authentication) {
+    authentication = keycloakAuthenticationProvider.authenticate(authentication);
+
+    if (groupsFromUGI) {
+      List<GrantedAuthority> groups = getAuthoritiesFromUGI(authentication.getName());
+      KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) authentication;
+
+      authentication = new KeycloakAuthenticationToken(token.getAccount(), token.isInteractive(), groups);
+    } else if (groupsClaim != null) {
+      KeycloakAuthenticationToken token = (KeycloakAuthenticationToken)authentication;
+      Map<String, Object> claims = token.getAccount().getKeycloakSecurityContext().getToken().getOtherClaims();
+      if (claims.containsKey(groupsClaim)) {
+        List<String> membership = (List<String>)claims.get(groupsClaim);
+        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
+        for (String group : membership) {
+          grantedAuthorities.add(new SimpleGrantedAuthority(group));
+        }
+        authentication = new KeycloakAuthenticationToken(token.getAccount(), token.isInteractive(), grantedAuthorities);
+      }
+    }
+
+    return authentication;
+  }
+
+  @Override
+  public boolean supports(Class<?> aClass) {
+    return keycloakAuthenticationProvider.supports(aClass);
+  }
+}
\ No newline at end of file
diff --git a/webapp/src/main/java/org/apache/atlas/web/security/AtlasSecurityConfig.java b/webapp/src/main/java/org/apache/atlas/web/security/AtlasSecurityConfig.java
index bf6b85b..fc2855d 100644
--- a/webapp/src/main/java/org/apache/atlas/web/security/AtlasSecurityConfig.java
+++ b/webapp/src/main/java/org/apache/atlas/web/security/AtlasSecurityConfig.java
@@ -25,8 +25,31 @@ import org.apache.atlas.web.filters.AtlasKnoxSSOAuthenticationFilter;
 import org.apache.atlas.web.filters.StaleTransactionCleanupFilter;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.lang.StringUtils;
+import org.keycloak.adapters.AdapterDeploymentContext;
+import org.keycloak.adapters.KeycloakConfigResolver;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.KeycloakDeploymentBuilder;
+import org.keycloak.adapters.spi.HttpFacade;
+import org.keycloak.adapters.springsecurity.AdapterDeploymentContextFactoryBean;
+import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
+import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationEntryPoint;
+import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
+import org.keycloak.adapters.springsecurity.authentication.KeycloakLogoutHandler;
+import org.keycloak.adapters.springsecurity.config.KeycloakSpringConfigResolverWrapper;
+import org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter;
+import org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter;
+import org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter;
+import org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter;
+import org.keycloak.adapters.springsecurity.filter.QueryParamPresenceRequestMatcher;
+import org.keycloak.adapters.springsecurity.management.HttpSessionManager;
+import org.keycloak.representations.adapters.config.AdapterConfig;
 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.context.annotation.Bean;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.core.io.Resource;
 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
 import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@@ -34,22 +57,34 @@ import org.springframework.security.config.annotation.web.builders.WebSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.core.session.SessionRegistryImpl;
 import org.springframework.security.web.AuthenticationEntryPoint;
 import org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint;
+import org.springframework.security.web.authentication.logout.LogoutFilter;
+import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
+import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
 import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
 import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
 import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+import org.springframework.security.web.util.matcher.OrRequestMatcher;
 import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;
 import org.springframework.security.web.util.matcher.RequestMatcher;
 import org.springframework.security.web.header.writers.StaticHeadersWriter;
 
 import javax.inject.Inject;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
 
 import static org.apache.atlas.AtlasConstants.ATLAS_MIGRATION_MODE_FILENAME;
 
 @EnableWebSecurity
 @EnableGlobalMethodSecurity(prePostEnabled = true)
+@KeycloakConfiguration
 public class AtlasSecurityConfig extends WebSecurityConfigurerAdapter {
     private static final Logger LOG = LoggerFactory.getLogger(AtlasSecurityConfig.class);
 
@@ -66,6 +101,15 @@ public class AtlasSecurityConfig extends WebSecurityConfigurerAdapter {
     private final StaleTransactionCleanupFilter staleTransactionCleanupFilter;
     private final ActiveServerFilter activeServerFilter;
 
+    public static final RequestMatcher KEYCLOAK_REQUEST_MATCHER = new OrRequestMatcher(new RequestMatcher[]{new AntPathRequestMatcher("/login.jsp"), new RequestHeaderRequestMatcher("Authorization"), new QueryParamPresenceRequestMatcher("access_token")});
+
+    @Value("${keycloak.configurationFile:WEB-INF/keycloak.json}")
+    private Resource keycloakConfigFileResource;
+    @Autowired(required = false)
+    private KeycloakConfigResolver keycloakConfigResolver;
+
+    private final boolean keycloakEnabled;
+
     @Inject
     public AtlasSecurityConfig(AtlasKnoxSSOAuthenticationFilter ssoAuthenticationFilter,
                                AtlasCSRFPreventionFilter atlasCSRFPreventionFilter,
@@ -87,15 +131,27 @@ public class AtlasSecurityConfig extends WebSecurityConfigurerAdapter {
         this.configuration = configuration;
         this.staleTransactionCleanupFilter = staleTransactionCleanupFilter;
         this.activeServerFilter = activeServerFilter;
+
+        this.keycloakEnabled = configuration.getBoolean(AtlasAuthenticationProvider.KEYCLOAK_AUTH_METHOD, false);
     }
 
-    public BasicAuthenticationEntryPoint getAuthenticationEntryPoint() {
-        BasicAuthenticationEntryPoint basicAuthenticationEntryPoint = new BasicAuthenticationEntryPoint();
-        basicAuthenticationEntryPoint.setRealmName("atlas.com");
-        return basicAuthenticationEntryPoint;
+    public AuthenticationEntryPoint getAuthenticationEntryPoint() throws Exception {
+        AuthenticationEntryPoint authenticationEntryPoint;
+
+        if (keycloakEnabled) {
+            KeycloakAuthenticationEntryPoint keycloakAuthenticationEntryPoint = new KeycloakAuthenticationEntryPoint(adapterDeploymentContext());
+            keycloakAuthenticationEntryPoint.setRealm("atlas.com");
+            keycloakAuthenticationEntryPoint.setLoginUri("/login.jsp");
+            authenticationEntryPoint = keycloakAuthenticationEntryPoint;
+        } else {
+            BasicAuthenticationEntryPoint basicAuthenticationEntryPoint = new BasicAuthenticationEntryPoint();
+            basicAuthenticationEntryPoint.setRealmName("atlas.com");
+            authenticationEntryPoint = basicAuthenticationEntryPoint;
+        }
+        return authenticationEntryPoint;
     }
 
-    public DelegatingAuthenticationEntryPoint getDelegatingAuthenticationEntryPoint() {
+    public DelegatingAuthenticationEntryPoint getDelegatingAuthenticationEntryPoint() throws Exception {
         LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPointMap = new LinkedHashMap<>();
         entryPointMap.put(new RequestHeaderRequestMatcher("User-Agent", "Mozilla"), atlasAuthenticationEntryPoint);
         DelegatingAuthenticationEntryPoint entryPoint = new DelegatingAuthenticationEntryPoint(entryPointMap);
@@ -110,19 +166,24 @@ public class AtlasSecurityConfig extends WebSecurityConfigurerAdapter {
 
     @Override
     public void configure(WebSecurity web) throws Exception {
+        List<String> matchers = new ArrayList<>(
+          Arrays.asList("/css/**",
+            "/img/**",
+            "/libs/**",
+            "/js/**",
+            "/ieerror.html",
+            "/api/atlas/admin/status",
+            "/api/atlas/admin/metrics"));
+
+        if (!keycloakEnabled) {
+            matchers.add("/login.jsp");
+        }
+
         web.ignoring()
-                .antMatchers("/login.jsp",
-                        "/css/**",
-                        "/img/**",
-                        "/libs/**",
-                        "/js/**",
-                        "/ieerror.html",
-                        "/api/atlas/admin/status",
-                        "/api/atlas/admin/metrics");
+                .antMatchers(matchers.toArray(new String[matchers.size()]));
     }
 
     protected void configure(HttpSecurity httpSecurity) throws Exception {
-
         //@formatter:off
         httpSecurity
                 .authorizeRequests().anyRequest().authenticated()
@@ -173,5 +234,81 @@ public class AtlasSecurityConfig extends WebSecurityConfigurerAdapter {
                 .addFilterBefore(ssoAuthenticationFilter, BasicAuthenticationFilter.class)
                 .addFilterAfter(atlasAuthenticationFilter, SecurityContextHolderAwareRequestFilter.class)
                 .addFilterAfter(csrfPreventionFilter, AtlasAuthenticationFilter.class);
+
+        if (keycloakEnabled) {
+            httpSecurity
+              .logout().addLogoutHandler(keycloakLogoutHandler()).and()
+              .addFilterBefore(keycloakAuthenticationProcessingFilter(), BasicAuthenticationFilter.class)
+              .addFilterBefore(keycloakPreAuthActionsFilter(), LogoutFilter.class)
+              .addFilterAfter(keycloakSecurityContextRequestFilter(), SecurityContextHolderAwareRequestFilter.class)
+              .addFilterAfter(keycloakAuthenticatedActionsRequestFilter(), KeycloakSecurityContextRequestFilter.class);
+        }
+    }
+
+
+    @Bean
+    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
+        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
+    }
+
+    @Bean
+    protected AdapterDeploymentContext adapterDeploymentContext() throws Exception {
+        AdapterDeploymentContextFactoryBean factoryBean;
+        String fileName = configuration.getString("atlas.authentication.method.keycloak.file");
+        if (fileName != null && !fileName.isEmpty()) {
+            keycloakConfigFileResource = new FileSystemResource(fileName);
+            factoryBean = new AdapterDeploymentContextFactoryBean(keycloakConfigFileResource);
+        } else {
+            Configuration conf = configuration.subset("atlas.authentication.method.keycloak");
+            AdapterConfig cfg = new AdapterConfig();
+            cfg.setRealm(conf.getString("realm", "atlas.com"));
+            cfg.setAuthServerUrl(conf.getString("auth-server-url", "https://localhost/auth"));
+            cfg.setResource(conf.getString("resource", "none"));
+
+            Map<String,Object> credentials = new HashMap<>();
+            credentials.put("secret", conf.getString("credentials-secret", "nosecret"));
+            cfg.setCredentials(credentials);
+            KeycloakDeployment dep = KeycloakDeploymentBuilder.build(cfg);
+            factoryBean = new AdapterDeploymentContextFactoryBean(new KeycloakConfigResolver() {
+                @Override
+                public KeycloakDeployment resolve(HttpFacade.Request request) {
+                    return dep;
+                }
+            });
+        }
+
+        factoryBean.afterPropertiesSet();
+        return factoryBean.getObject();
+    }
+
+    @Bean
+    protected KeycloakPreAuthActionsFilter keycloakPreAuthActionsFilter() {
+        return new KeycloakPreAuthActionsFilter(httpSessionManager());
+    }
+
+    @Bean
+    protected HttpSessionManager httpSessionManager() {
+        return new HttpSessionManager();
+    }
+
+    protected KeycloakLogoutHandler keycloakLogoutHandler() throws Exception {
+        return new KeycloakLogoutHandler(adapterDeploymentContext());
+    }
+
+    @Bean
+    protected KeycloakSecurityContextRequestFilter keycloakSecurityContextRequestFilter() {
+        return new KeycloakSecurityContextRequestFilter();
+    }
+
+    @Bean
+    protected KeycloakAuthenticatedActionsFilter keycloakAuthenticatedActionsRequestFilter() {
+        return new KeycloakAuthenticatedActionsFilter();
+    }
+
+    @Bean
+    protected KeycloakAuthenticationProcessingFilter keycloakAuthenticationProcessingFilter() throws Exception {
+        KeycloakAuthenticationProcessingFilter filter = new KeycloakAuthenticationProcessingFilter(authenticationManagerBean(), KEYCLOAK_REQUEST_MATCHER);
+        filter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy());
+        return filter;
     }
 }