diff --git a/adapters/oidc/spring-boot/pom.xml b/adapters/oidc/spring-boot/pom.xml
index c7f322722d..a60441d26e 100755
--- a/adapters/oidc/spring-boot/pom.xml
+++ b/adapters/oidc/spring-boot/pom.xml
@@ -67,6 +67,27 @@
provided
+
+ org.eclipse.jetty
+ jetty-server
+ ${jetty9.version}
+ provided
+
+
+
+ org.eclipse.jetty
+ jetty-security
+ ${jetty9.version}
+ provided
+
+
+
+ org.eclipse.jetty
+ jetty-webapp
+ ${jetty9.version}
+ provided
+
+
junit
junit
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 ec847c019a..68c750c973 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;
-
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 authRoles = new HashSet();
- 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);
- }
- }
- }
- }
-
- 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);
- }
-
- for (String method : collection.getMethods()) {
- tomcatSecCollection.addMethod(method);
- }
-
- for (String method : collection.getOmittedMethods()) {
- tomcatSecCollection.addOmittedMethod(method);
- }
-
- tomcatConstraint.addCollection(tomcatSecCollection);
- }
-
- context.addConstraint(tomcatConstraint);
- }
-
- context.addParameter("keycloak.config.resolver", KeycloakSpringBootConfigResolver.class.getName());
- }
- };
+ @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 jettyConstraintMappings = new ArrayList();
+ 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);
+ }
+ }
+
+ WebAppContext webAppContext = server.getBean(WebAppContext.class);
+
+ ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
+ securityHandler.setConstraintMappings(jettyConstraintMappings);
+ securityHandler.setAuthenticator(keycloakJettyAuthenticator);
+
+ webAppContext.setHandler(securityHandler);
+ }
+ }
+
+ static class KeycloakTomcatContextCustomizer implements TomcatContextCustomizer {
+
+ private final KeycloakSpringBootProperties keycloakProperties;
+
+ public KeycloakTomcatContextCustomizer(KeycloakSpringBootProperties keycloakProperties) {
+ this.keycloakProperties = keycloakProperties;
+ }
+
+ @Override
+ public void customize(Context context) {
+ LoginConfig loginConfig = new LoginConfig();
+ loginConfig.setAuthMethod("KEYCLOAK");
+ context.setLoginConfig(loginConfig);
+
+ Set authRoles = new HashSet();
+ 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);
+ }
+ }
+ }
+ }
+
+ 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);
+ }
+
+ for (String method : collection.getMethods()) {
+ tomcatSecCollection.addMethod(method);
+ }
+
+ for (String method : collection.getOmittedMethods()) {
+ tomcatSecCollection.addOmittedMethod(method);
+ }
+
+ tomcatConstraint.addCollection(tomcatSecCollection);
+ }
+
+ context.addConstraint(tomcatConstraint);
+ }
+
+ context.addParameter("keycloak.config.resolver", KeycloakSpringBootConfigResolver.class.getName());
+ }
+ }
}