keycloak-memoizeit

KEYCLOAK-3300 Add support for jetty in spring-boot-adapter This

7/11/2016 8:44:54 PM

Details

diff --git a/adapters/oidc/spring-boot/pom.xml b/adapters/oidc/spring-boot/pom.xml
index c7f3227..a60441d 100755
--- a/adapters/oidc/spring-boot/pom.xml
+++ b/adapters/oidc/spring-boot/pom.xml
@@ -68,6 +68,27 @@
     </dependency>
 
     <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-server</artifactId>
+      <version>${jetty9.version}</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-security</artifactId>
+      <version>${jetty9.version}</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-webapp</artifactId>
+      <version>${jetty9.version}</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <scope>test</scope>
diff --git a/adapters/oidc/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootConfiguration.java b/adapters/oidc/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootConfiguration.java
index ec847c0..68c750c 100755
--- a/adapters/oidc/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootConfiguration.java
+++ b/adapters/oidc/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootConfiguration.java
@@ -21,20 +21,31 @@ import org.apache.catalina.Context;
 import org.apache.tomcat.util.descriptor.web.LoginConfig;
 import org.apache.tomcat.util.descriptor.web.SecurityCollection;
 import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
+import org.eclipse.jetty.security.ConstraintMapping;
+import org.eclipse.jetty.security.ConstraintSecurityHandler;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.util.security.Constraint;
+import org.eclipse.jetty.webapp.WebAppContext;
+import org.keycloak.adapters.jetty.KeycloakJettyAuthenticator;
 import org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
 import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
 import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
 import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
+import org.springframework.boot.context.embedded.jetty.JettyServerCustomizer;
 import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
 import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
+import org.springframework.boot.context.embedded.undertow.UndertowDeploymentInfoCustomizer;
 import org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 
+import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -61,80 +72,166 @@ public class KeycloakSpringBootConfiguration {
         return new EmbeddedServletContainerCustomizer() {
             @Override
             public void customize(ConfigurableEmbeddedServletContainer configurableEmbeddedServletContainer) {
+
                 if (configurableEmbeddedServletContainer instanceof TomcatEmbeddedServletContainerFactory) {
-                    TomcatEmbeddedServletContainerFactory container = (TomcatEmbeddedServletContainerFactory) configurableEmbeddedServletContainer;
 
+                    TomcatEmbeddedServletContainerFactory container = (TomcatEmbeddedServletContainerFactory) configurableEmbeddedServletContainer;
                     container.addContextValves(new KeycloakAuthenticatorValve());
+                    container.addContextCustomizers(tomcatKeycloakContextCustomizer());
 
-                    container.addContextCustomizers(getTomcatKeycloakContextCustomizer());
                 } else if (configurableEmbeddedServletContainer instanceof UndertowEmbeddedServletContainerFactory) {
-                    throw new IllegalArgumentException("Undertow Keycloak integration is not yet implemented");
+
+                    UndertowEmbeddedServletContainerFactory container = (UndertowEmbeddedServletContainerFactory) configurableEmbeddedServletContainer;
+                    container.addDeploymentInfoCustomizers(undertowKeycloakContextCustomizer());
+
                 } else if (configurableEmbeddedServletContainer instanceof JettyEmbeddedServletContainerFactory) {
-                    throw new IllegalArgumentException("Jetty Keycloak integration is not yet implemented");
+
+                    JettyEmbeddedServletContainerFactory container = (JettyEmbeddedServletContainerFactory) configurableEmbeddedServletContainer;
+                    container.addServerCustomizers(jettyKeycloakServerCustomizer());
                 }
             }
         };
     }
 
     @Bean
-    public TomcatContextCustomizer getTomcatKeycloakContextCustomizer() {
-        return new TomcatContextCustomizer() {
-            @Override
-            public void customize(Context context) {
-                LoginConfig loginConfig = new LoginConfig();
-                loginConfig.setAuthMethod("KEYCLOAK");
-                context.setLoginConfig(loginConfig);
-
-                Set<String> authRoles = new HashSet<String>();
-                for (KeycloakSpringBootProperties.SecurityConstraint constraint : keycloakProperties.getSecurityConstraints()) {
-                    for (KeycloakSpringBootProperties.SecurityCollection collection : constraint.getSecurityCollections()) {
-                        for (String authRole : collection.getAuthRoles()) {
-                            if (!authRoles.contains(authRole)) {
-                                context.addSecurityRole(authRole);
-                                authRoles.add(authRole);
-                            }
-                        }
+    @ConditionalOnClass(name = {"org.eclipse.jetty.webapp.WebAppContext"})
+    public JettyServerCustomizer jettyKeycloakServerCustomizer() {
+        return new KeycloakJettyServerCustomizer(keycloakProperties);
+    }
+
+    @Bean
+    @ConditionalOnClass(name = {"org.apache.catalina.startup.Tomcat"})
+    public TomcatContextCustomizer tomcatKeycloakContextCustomizer() {
+        return new KeycloakTomcatContextCustomizer(keycloakProperties);
+    }
+
+    @Bean
+    @ConditionalOnClass(name = {"io.undertow.Undertow"})
+    public UndertowDeploymentInfoCustomizer undertowKeycloakContextCustomizer() {
+        throw new IllegalArgumentException("Undertow Keycloak integration is not yet implemented");
+    }
+
+    static class KeycloakJettyServerCustomizer implements JettyServerCustomizer {
+
+        private final KeycloakSpringBootProperties keycloakProperties;
+
+        public KeycloakJettyServerCustomizer(KeycloakSpringBootProperties keycloakProperties) {
+            this.keycloakProperties = keycloakProperties;
+        }
+
+        @Override
+        public void customize(Server server) {
+
+            KeycloakJettyAuthenticator keycloakJettyAuthenticator = new KeycloakJettyAuthenticator();
+            keycloakJettyAuthenticator.setConfigResolver(new KeycloakSpringBootConfigResolver());
+
+            List<ConstraintMapping> jettyConstraintMappings = new ArrayList<ConstraintMapping>();
+            for (KeycloakSpringBootProperties.SecurityConstraint constraintDefinition : keycloakProperties.getSecurityConstraints()) {
+
+                for (KeycloakSpringBootProperties.SecurityCollection securityCollectionDefinition : constraintDefinition
+                        .getSecurityCollections()) {
+
+                    Constraint jettyConstraint = new Constraint();
+                    jettyConstraint.setName(securityCollectionDefinition.getName());
+                    jettyConstraint.setAuthenticate(true);
+
+                    if (securityCollectionDefinition.getName() != null) {
+                        jettyConstraint.setName(securityCollectionDefinition.getName());
+                    }
+
+                    jettyConstraint.setRoles(securityCollectionDefinition.getAuthRoles().toArray(new String[0]));
+
+                    ConstraintMapping jettyConstraintMapping = new ConstraintMapping();
+                    if (securityCollectionDefinition.getPatterns().size() > 0) {
+                        //First pattern wins
+                        jettyConstraintMapping.setPathSpec(securityCollectionDefinition.getPatterns().get(0));
+                        jettyConstraintMapping.setConstraint(jettyConstraint);
+                    }
+
+                    if (securityCollectionDefinition.getMethods().size() > 0) {
+                        //First method wins
+                        jettyConstraintMapping.setMethod(securityCollectionDefinition.getMethods().get(0));
                     }
+
+                    jettyConstraintMapping.setMethodOmissions(
+                            securityCollectionDefinition.getOmittedMethods().toArray(new String[0]));
+
+                    jettyConstraintMappings.add(jettyConstraintMapping);
                 }
+            }
 
-                for (KeycloakSpringBootProperties.SecurityConstraint constraint : keycloakProperties.getSecurityConstraints()) {
-                    SecurityConstraint tomcatConstraint = new SecurityConstraint();
+            WebAppContext webAppContext = server.getBean(WebAppContext.class);
 
-                    for (KeycloakSpringBootProperties.SecurityCollection collection : constraint.getSecurityCollections()) {
-                        SecurityCollection tomcatSecCollection = new SecurityCollection();
+            ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
+            securityHandler.setConstraintMappings(jettyConstraintMappings);
+            securityHandler.setAuthenticator(keycloakJettyAuthenticator);
 
-                        if (collection.getName() != null) {
-                            tomcatSecCollection.setName(collection.getName());
-                        }
-                        if (collection.getDescription() != null) {
-                            tomcatSecCollection.setDescription(collection.getDescription());
-                        }
+            webAppContext.setHandler(securityHandler);
+        }
+    }
 
-                        for (String authRole : collection.getAuthRoles()) {
-                            tomcatConstraint.addAuthRole(authRole);
-                        }
+    static class KeycloakTomcatContextCustomizer implements TomcatContextCustomizer {
 
-                        for (String pattern : collection.getPatterns()) {
-                            tomcatSecCollection.addPattern(pattern);
-                        }
+        private final KeycloakSpringBootProperties keycloakProperties;
 
-                        for (String method : collection.getMethods()) {
-                            tomcatSecCollection.addMethod(method);
-                        }
+        public KeycloakTomcatContextCustomizer(KeycloakSpringBootProperties keycloakProperties) {
+            this.keycloakProperties = keycloakProperties;
+        }
+
+        @Override
+        public void customize(Context context) {
+            LoginConfig loginConfig = new LoginConfig();
+            loginConfig.setAuthMethod("KEYCLOAK");
+            context.setLoginConfig(loginConfig);
 
-                        for (String method : collection.getOmittedMethods()) {
-                            tomcatSecCollection.addOmittedMethod(method);
+            Set<String> authRoles = new HashSet<String>();
+            for (KeycloakSpringBootProperties.SecurityConstraint constraint : keycloakProperties.getSecurityConstraints()) {
+                for (KeycloakSpringBootProperties.SecurityCollection collection : constraint.getSecurityCollections()) {
+                    for (String authRole : collection.getAuthRoles()) {
+                        if (!authRoles.contains(authRole)) {
+                            context.addSecurityRole(authRole);
+                            authRoles.add(authRole);
                         }
+                    }
+                }
+            }
 
-                        tomcatConstraint.addCollection(tomcatSecCollection);
+            for (KeycloakSpringBootProperties.SecurityConstraint constraint : keycloakProperties.getSecurityConstraints()) {
+                SecurityConstraint tomcatConstraint = new SecurityConstraint();
+
+                for (KeycloakSpringBootProperties.SecurityCollection collection : constraint.getSecurityCollections()) {
+                    SecurityCollection tomcatSecCollection = new SecurityCollection();
+
+                    if (collection.getName() != null) {
+                        tomcatSecCollection.setName(collection.getName());
+                    }
+                    if (collection.getDescription() != null) {
+                        tomcatSecCollection.setDescription(collection.getDescription());
+                    }
+
+                    for (String authRole : collection.getAuthRoles()) {
+                        tomcatConstraint.addAuthRole(authRole);
+                    }
+
+                    for (String pattern : collection.getPatterns()) {
+                        tomcatSecCollection.addPattern(pattern);
                     }
 
-                    context.addConstraint(tomcatConstraint);
+                    for (String method : collection.getMethods()) {
+                        tomcatSecCollection.addMethod(method);
+                    }
+
+                    for (String method : collection.getOmittedMethods()) {
+                        tomcatSecCollection.addOmittedMethod(method);
+                    }
+
+                    tomcatConstraint.addCollection(tomcatSecCollection);
                 }
 
-                context.addParameter("keycloak.config.resolver", KeycloakSpringBootConfigResolver.class.getName());
+                context.addConstraint(tomcatConstraint);
             }
-        };
-    }
 
+            context.addParameter("keycloak.config.resolver", KeycloakSpringBootConfigResolver.class.getName());
+        }
+    }
 }