diff --git a/adapters/oidc/pom.xml b/adapters/oidc/pom.xml
index e26749fe89c..f6ef8753053 100755
--- a/adapters/oidc/pom.xml
+++ b/adapters/oidc/pom.xml
@@ -42,6 +42,7 @@
servlet-oauth-client
spring-boot
spring-boot2
+ spring-boot-adapter-core
spring-boot-container-bundle
spring-security
tomcat
diff --git a/adapters/oidc/spring-boot-adapter-core/pom.xml b/adapters/oidc/spring-boot-adapter-core/pom.xml
new file mode 100755
index 00000000000..56646f96da5
--- /dev/null
+++ b/adapters/oidc/spring-boot-adapter-core/pom.xml
@@ -0,0 +1,120 @@
+
+
+
+
+
+ keycloak-parent
+ org.keycloak
+ 3.3.0.CR1-SNAPSHOT
+ ../../../pom.xml
+
+ 4.0.0
+
+ keycloak-spring-boot-adapter-core
+ Keycloak Spring Boot Adapter Core
+
+
+
+ 1.3.0.RELEASE
+
+
+
+
+ org.jboss.logging
+ jboss-logging
+
+
+ org.keycloak
+ keycloak-core
+
+
+ org.keycloak
+ spring-boot-container-bundle
+ ${project.version}
+ true
+ compile
+
+
+ org.keycloak
+ keycloak-spring-security-adapter
+ ${project.version}
+ compile
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ ${spring-boot.version}
+ compile
+ true
+
+
+ io.undertow
+ undertow-servlet
+ compile
+ true
+
+
+ org.eclipse.jetty
+ jetty-server
+ ${jetty9.version}
+ compile
+ true
+
+
+
+ org.eclipse.jetty
+ jetty-security
+ ${jetty9.version}
+ compile
+ true
+
+
+
+ org.eclipse.jetty
+ jetty-webapp
+ ${jetty9.version}
+ compile
+ true
+
+
+ junit
+ junit
+ test
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+ ${spring-boot.version}
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.7
+ 1.7
+
+
+
+
+
diff --git a/adapters/oidc/spring-boot-adapter-core/src/main/java/org/keycloak/adapters/springboot/KeycloakBaseSpringBootConfiguration.java b/adapters/oidc/spring-boot-adapter-core/src/main/java/org/keycloak/adapters/springboot/KeycloakBaseSpringBootConfiguration.java
new file mode 100755
index 00000000000..8afd32b4675
--- /dev/null
+++ b/adapters/oidc/spring-boot-adapter-core/src/main/java/org/keycloak/adapters/springboot/KeycloakBaseSpringBootConfiguration.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed 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.keycloak.adapters.springboot;
+
+import io.undertow.servlet.api.DeploymentInfo;
+import io.undertow.servlet.api.WebResourceCollection;
+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.keycloak.adapters.undertow.KeycloakServletExtension;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+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;
+
+/**
+ * Keycloak authentication base integration for Spring Boot - base to be extended for particular boot versions.
+ */
+public class KeycloakBaseSpringBootConfiguration {
+
+ protected KeycloakSpringBootProperties keycloakProperties;
+
+ @Autowired
+ public void setKeycloakSpringBootProperties(KeycloakSpringBootProperties keycloakProperties) {
+ this.keycloakProperties = keycloakProperties;
+ KeycloakSpringBootConfigResolver.setAdapterConfig(keycloakProperties);
+ }
+
+
+ static class KeycloakBaseUndertowDeploymentInfoCustomizer {
+
+ protected final KeycloakSpringBootProperties keycloakProperties;
+
+ public KeycloakBaseUndertowDeploymentInfoCustomizer(KeycloakSpringBootProperties keycloakProperties) {
+ this.keycloakProperties = keycloakProperties;
+ }
+
+ public void customize(DeploymentInfo deploymentInfo) {
+
+ io.undertow.servlet.api.LoginConfig loginConfig = new io.undertow.servlet.api.LoginConfig(keycloakProperties.getRealm());
+ loginConfig.addFirstAuthMethod("KEYCLOAK");
+
+ deploymentInfo.setLoginConfig(loginConfig);
+
+ deploymentInfo.addInitParameter("keycloak.config.resolver", KeycloakSpringBootConfigResolver.class.getName());
+ deploymentInfo.addSecurityConstraints(getSecurityConstraints());
+
+ deploymentInfo.addServletExtension(new KeycloakServletExtension());
+ }
+
+ private List getSecurityConstraints() {
+
+ List undertowSecurityConstraints = new ArrayList();
+ for (KeycloakSpringBootProperties.SecurityConstraint constraintDefinition : keycloakProperties.getSecurityConstraints()) {
+
+ io.undertow.servlet.api.SecurityConstraint undertowSecurityConstraint = new io.undertow.servlet.api.SecurityConstraint();
+ undertowSecurityConstraint.addRolesAllowed(constraintDefinition.getAuthRoles());
+
+ for (KeycloakSpringBootProperties.SecurityCollection collectionDefinition : constraintDefinition.getSecurityCollections()) {
+
+ WebResourceCollection webResourceCollection = new WebResourceCollection();
+ webResourceCollection.addHttpMethods(collectionDefinition.getMethods());
+ webResourceCollection.addHttpMethodOmissions(collectionDefinition.getOmittedMethods());
+ webResourceCollection.addUrlPatterns(collectionDefinition.getPatterns());
+
+ undertowSecurityConstraint.addWebResourceCollections(webResourceCollection);
+
+ }
+
+ undertowSecurityConstraints.add(undertowSecurityConstraint);
+ }
+ return undertowSecurityConstraints;
+ }
+ }
+
+ static class KeycloakBaseJettyServerCustomizer {
+
+ protected final KeycloakSpringBootProperties keycloakProperties;
+
+ public KeycloakBaseJettyServerCustomizer(KeycloakSpringBootProperties keycloakProperties) {
+ this.keycloakProperties = keycloakProperties;
+ }
+
+ public void customize(Server server) {
+
+ KeycloakJettyAuthenticator keycloakJettyAuthenticator = new KeycloakJettyAuthenticator();
+ keycloakJettyAuthenticator.setConfigResolver(new KeycloakSpringBootConfigResolver());
+
+ /* see org.eclipse.jetty.webapp.StandardDescriptorProcessor#visitSecurityConstraint for an example
+ on how to map servlet spec to Constraints */
+
+ List jettyConstraintMappings = new ArrayList();
+ for (KeycloakSpringBootProperties.SecurityConstraint constraintDefinition : keycloakProperties.getSecurityConstraints()) {
+
+ for (KeycloakSpringBootProperties.SecurityCollection securityCollectionDefinition : constraintDefinition
+ .getSecurityCollections()) {
+ // securityCollection matches servlet spec's web-resource-collection
+ Constraint jettyConstraint = new Constraint();
+
+ if (constraintDefinition.getAuthRoles().size() > 0) {
+ jettyConstraint.setAuthenticate(true);
+ jettyConstraint.setRoles(constraintDefinition.getAuthRoles().toArray(new String[0]));
+ }
+
+ jettyConstraint.setName(securityCollectionDefinition.getName());
+
+ // according to the servlet spec each security-constraint has at least one URL pattern
+ for(String pattern : securityCollectionDefinition.getPatterns()) {
+
+ /* the following code is asymmetric as Jetty's ConstraintMapping accepts only one allowed HTTP method,
+ but multiple omitted methods. Therefore we add one ConstraintMapping for each allowed
+ mapping but only one mapping in the cases of omitted methods or no methods.
+ */
+
+ if (securityCollectionDefinition.getMethods().size() > 0) {
+ // according to the servlet spec we have either methods ...
+ for(String method : securityCollectionDefinition.getMethods()) {
+ ConstraintMapping jettyConstraintMapping = new ConstraintMapping();
+ jettyConstraintMappings.add(jettyConstraintMapping);
+
+ jettyConstraintMapping.setConstraint(jettyConstraint);
+ jettyConstraintMapping.setPathSpec(pattern);
+ jettyConstraintMapping.setMethod(method);
+ }
+ } else if (securityCollectionDefinition.getOmittedMethods().size() > 0){
+ // ... omitted methods ...
+ ConstraintMapping jettyConstraintMapping = new ConstraintMapping();
+ jettyConstraintMappings.add(jettyConstraintMapping);
+
+ jettyConstraintMapping.setConstraint(jettyConstraint);
+ jettyConstraintMapping.setPathSpec(pattern);
+ jettyConstraintMapping.setMethodOmissions(
+ securityCollectionDefinition.getOmittedMethods().toArray(new String[0]));
+ } else {
+ // ... or no methods at all
+ ConstraintMapping jettyConstraintMapping = new ConstraintMapping();
+ jettyConstraintMappings.add(jettyConstraintMapping);
+
+ jettyConstraintMapping.setConstraint(jettyConstraint);
+ jettyConstraintMapping.setPathSpec(pattern);
+ }
+
+ }
+
+ }
+ }
+
+ WebAppContext webAppContext = server.getBean(WebAppContext.class);
+ //if not found as registered bean let's try the handler
+ if(webAppContext==null){
+ webAppContext = (WebAppContext) server.getHandler();
+ }
+
+ ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
+ securityHandler.setConstraintMappings(jettyConstraintMappings);
+ securityHandler.setAuthenticator(keycloakJettyAuthenticator);
+
+ webAppContext.setSecurityHandler(securityHandler);
+ }
+ }
+
+ static class KeycloakBaseTomcatContextCustomizer {
+
+ protected final KeycloakSpringBootProperties keycloakProperties;
+
+ public KeycloakBaseTomcatContextCustomizer(KeycloakSpringBootProperties keycloakProperties) {
+ this.keycloakProperties = keycloakProperties;
+ }
+
+ 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 (String authRole : constraint.getAuthRoles()) {
+ if (!authRoles.contains(authRole)) {
+ context.addSecurityRole(authRole);
+ authRoles.add(authRole);
+ }
+ }
+ }
+
+ for (KeycloakSpringBootProperties.SecurityConstraint constraint : keycloakProperties.getSecurityConstraints()) {
+ SecurityConstraint tomcatConstraint = new SecurityConstraint();
+
+ for (String authRole : constraint.getAuthRoles()) {
+ tomcatConstraint.addAuthRole(authRole);
+ }
+
+ 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 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());
+ }
+ }
+}
diff --git a/adapters/oidc/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootConfigResolver.java b/adapters/oidc/spring-boot-adapter-core/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootConfigResolver.java
similarity index 100%
rename from adapters/oidc/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootConfigResolver.java
rename to adapters/oidc/spring-boot-adapter-core/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootConfigResolver.java
diff --git a/adapters/oidc/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootProperties.java b/adapters/oidc/spring-boot-adapter-core/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootProperties.java
similarity index 100%
rename from adapters/oidc/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootProperties.java
rename to adapters/oidc/spring-boot-adapter-core/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootProperties.java
diff --git a/adapters/oidc/spring-boot-adapter-core/src/main/resources/META-INF/spring.factories b/adapters/oidc/spring-boot-adapter-core/src/main/resources/META-INF/spring.factories
new file mode 100644
index 00000000000..0c80e3bd8b2
--- /dev/null
+++ b/adapters/oidc/spring-boot-adapter-core/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+org.keycloak.adapters.springboot.KeycloakAutoConfiguration
\ No newline at end of file
diff --git a/adapters/oidc/spring-boot/pom.xml b/adapters/oidc/spring-boot/pom.xml
index 6a720f65a5b..44a08139836 100755
--- a/adapters/oidc/spring-boot/pom.xml
+++ b/adapters/oidc/spring-boot/pom.xml
@@ -35,6 +35,12 @@
+
+
+ org.keycloak
+ keycloak-spring-boot-adapter-core
+
+
org.jboss.logging
jboss-logging
diff --git a/adapters/oidc/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakAutoConfiguration.java b/adapters/oidc/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakAutoConfiguration.java
index 679691aef68..90837f5bcb9 100755
--- a/adapters/oidc/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakAutoConfiguration.java
+++ b/adapters/oidc/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakAutoConfiguration.java
@@ -17,20 +17,7 @@
package org.keycloak.adapters.springboot;
-import io.undertow.servlet.api.DeploymentInfo;
-import io.undertow.servlet.api.WebResourceCollection;
-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.keycloak.adapters.undertow.KeycloakServletExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -47,10 +34,6 @@ 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;
/**
* Keycloak authentication integration for Spring Boot
@@ -62,7 +45,7 @@ import java.util.Set;
@ConditionalOnWebApplication
@EnableConfigurationProperties(KeycloakSpringBootProperties.class)
@ConditionalOnProperty(value = "keycloak.enabled", matchIfMissing = true)
-public class KeycloakAutoConfiguration {
+public class KeycloakAutoConfiguration extends KeycloakBaseSpringBootConfiguration {
private KeycloakSpringBootProperties keycloakProperties;
@@ -117,200 +100,27 @@ public class KeycloakAutoConfiguration {
return new KeycloakUndertowDeploymentInfoCustomizer(keycloakProperties);
}
- static class KeycloakUndertowDeploymentInfoCustomizer implements UndertowDeploymentInfoCustomizer {
-
- private final KeycloakSpringBootProperties keycloakProperties;
+ static class KeycloakUndertowDeploymentInfoCustomizer extends KeycloakBaseUndertowDeploymentInfoCustomizer implements UndertowDeploymentInfoCustomizer {
public KeycloakUndertowDeploymentInfoCustomizer(KeycloakSpringBootProperties keycloakProperties) {
- this.keycloakProperties = keycloakProperties;
+ super(keycloakProperties);
}
- @Override
- public void customize(DeploymentInfo deploymentInfo) {
-
- io.undertow.servlet.api.LoginConfig loginConfig = new io.undertow.servlet.api.LoginConfig(keycloakProperties.getRealm());
- loginConfig.addFirstAuthMethod("KEYCLOAK");
-
- deploymentInfo.setLoginConfig(loginConfig);
-
- deploymentInfo.addInitParameter("keycloak.config.resolver", KeycloakSpringBootConfigResolver.class.getName());
- deploymentInfo.addSecurityConstraints(getSecurityConstraints());
-
- deploymentInfo.addServletExtension(new KeycloakServletExtension());
- }
-
- private List getSecurityConstraints() {
-
- List undertowSecurityConstraints = new ArrayList();
- for (KeycloakSpringBootProperties.SecurityConstraint constraintDefinition : keycloakProperties.getSecurityConstraints()) {
-
- io.undertow.servlet.api.SecurityConstraint undertowSecurityConstraint = new io.undertow.servlet.api.SecurityConstraint();
- undertowSecurityConstraint.addRolesAllowed(constraintDefinition.getAuthRoles());
-
- for (KeycloakSpringBootProperties.SecurityCollection collectionDefinition : constraintDefinition.getSecurityCollections()) {
-
- WebResourceCollection webResourceCollection = new WebResourceCollection();
- webResourceCollection.addHttpMethods(collectionDefinition.getMethods());
- webResourceCollection.addHttpMethodOmissions(collectionDefinition.getOmittedMethods());
- webResourceCollection.addUrlPatterns(collectionDefinition.getPatterns());
-
- undertowSecurityConstraint.addWebResourceCollections(webResourceCollection);
-
- }
-
- undertowSecurityConstraints.add(undertowSecurityConstraint);
- }
- return undertowSecurityConstraints;
- }
}
- static class KeycloakJettyServerCustomizer implements JettyServerCustomizer {
-
- private final KeycloakSpringBootProperties keycloakProperties;
+ static class KeycloakJettyServerCustomizer extends KeycloakBaseJettyServerCustomizer implements JettyServerCustomizer {
public KeycloakJettyServerCustomizer(KeycloakSpringBootProperties keycloakProperties) {
- this.keycloakProperties = keycloakProperties;
+ super(keycloakProperties);
}
- @Override
- public void customize(Server server) {
-
- KeycloakJettyAuthenticator keycloakJettyAuthenticator = new KeycloakJettyAuthenticator();
- keycloakJettyAuthenticator.setConfigResolver(new KeycloakSpringBootConfigResolver());
-
- /* see org.eclipse.jetty.webapp.StandardDescriptorProcessor#visitSecurityConstraint for an example
- on how to map servlet spec to Constraints */
-
- List jettyConstraintMappings = new ArrayList();
- for (KeycloakSpringBootProperties.SecurityConstraint constraintDefinition : keycloakProperties.getSecurityConstraints()) {
-
- for (KeycloakSpringBootProperties.SecurityCollection securityCollectionDefinition : constraintDefinition
- .getSecurityCollections()) {
- // securityCollection matches servlet spec's web-resource-collection
- Constraint jettyConstraint = new Constraint();
-
- if (constraintDefinition.getAuthRoles().size() > 0) {
- jettyConstraint.setAuthenticate(true);
- jettyConstraint.setRoles(constraintDefinition.getAuthRoles().toArray(new String[0]));
- }
-
- jettyConstraint.setName(securityCollectionDefinition.getName());
-
- // according to the servlet spec each security-constraint has at least one URL pattern
- for(String pattern : securityCollectionDefinition.getPatterns()) {
-
- /* the following code is asymmetric as Jetty's ConstraintMapping accepts only one allowed HTTP method,
- but multiple omitted methods. Therefore we add one ConstraintMapping for each allowed
- mapping but only one mapping in the cases of omitted methods or no methods.
- */
-
- if (securityCollectionDefinition.getMethods().size() > 0) {
- // according to the servlet spec we have either methods ...
- for(String method : securityCollectionDefinition.getMethods()) {
- ConstraintMapping jettyConstraintMapping = new ConstraintMapping();
- jettyConstraintMappings.add(jettyConstraintMapping);
-
- jettyConstraintMapping.setConstraint(jettyConstraint);
- jettyConstraintMapping.setPathSpec(pattern);
- jettyConstraintMapping.setMethod(method);
- }
- } else if (securityCollectionDefinition.getOmittedMethods().size() > 0){
- // ... omitted methods ...
- ConstraintMapping jettyConstraintMapping = new ConstraintMapping();
- jettyConstraintMappings.add(jettyConstraintMapping);
-
- jettyConstraintMapping.setConstraint(jettyConstraint);
- jettyConstraintMapping.setPathSpec(pattern);
- jettyConstraintMapping.setMethodOmissions(
- securityCollectionDefinition.getOmittedMethods().toArray(new String[0]));
- } else {
- // ... or no methods at all
- ConstraintMapping jettyConstraintMapping = new ConstraintMapping();
- jettyConstraintMappings.add(jettyConstraintMapping);
-
- jettyConstraintMapping.setConstraint(jettyConstraint);
- jettyConstraintMapping.setPathSpec(pattern);
- }
-
- }
-
- }
- }
-
- WebAppContext webAppContext = server.getBean(WebAppContext.class);
- //if not found as registered bean let's try the handler
- if(webAppContext==null){
- webAppContext = (WebAppContext) server.getHandler();
- }
-
- ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
- securityHandler.setConstraintMappings(jettyConstraintMappings);
- securityHandler.setAuthenticator(keycloakJettyAuthenticator);
-
- webAppContext.setSecurityHandler(securityHandler);
- }
}
- static class KeycloakTomcatContextCustomizer implements TomcatContextCustomizer {
-
- private final KeycloakSpringBootProperties keycloakProperties;
+ static class KeycloakTomcatContextCustomizer extends KeycloakBaseTomcatContextCustomizer implements TomcatContextCustomizer {
public KeycloakTomcatContextCustomizer(KeycloakSpringBootProperties keycloakProperties) {
- this.keycloakProperties = keycloakProperties;
+ super(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 (String authRole : constraint.getAuthRoles()) {
- if (!authRoles.contains(authRole)) {
- context.addSecurityRole(authRole);
- authRoles.add(authRole);
- }
- }
- }
-
- for (KeycloakSpringBootProperties.SecurityConstraint constraint : keycloakProperties.getSecurityConstraints()) {
- SecurityConstraint tomcatConstraint = new SecurityConstraint();
-
- for (String authRole : constraint.getAuthRoles()) {
- tomcatConstraint.addAuthRole(authRole);
- }
-
- 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 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());
- }
}
}
diff --git a/adapters/oidc/spring-boot2/pom.xml b/adapters/oidc/spring-boot2/pom.xml
index 3c7a9621a70..1406254a604 100755
--- a/adapters/oidc/spring-boot2/pom.xml
+++ b/adapters/oidc/spring-boot2/pom.xml
@@ -46,6 +46,12 @@
+
+
+ org.keycloak
+ keycloak-spring-boot-adapter-core
+
+
org.jboss.logging
jboss-logging
diff --git a/adapters/oidc/spring-boot2/src/main/java/org/keycloak/adapters/springboot/KeycloakAutoConfiguration.java b/adapters/oidc/spring-boot2/src/main/java/org/keycloak/adapters/springboot/KeycloakAutoConfiguration.java
index 0cc5c4d022b..6b16541a28b 100755
--- a/adapters/oidc/spring-boot2/src/main/java/org/keycloak/adapters/springboot/KeycloakAutoConfiguration.java
+++ b/adapters/oidc/spring-boot2/src/main/java/org/keycloak/adapters/springboot/KeycloakAutoConfiguration.java
@@ -17,21 +17,7 @@
package org.keycloak.adapters.springboot;
-import io.undertow.servlet.api.DeploymentInfo;
-import io.undertow.servlet.api.WebResourceCollection;
-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.keycloak.adapters.undertow.KeycloakServletExtension;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
@@ -50,31 +36,15 @@ import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFa
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
/**
- * Keycloak authentication integration for Spring Boot
+ * Keycloak authentication integration for Spring Boot 2
*
- * @author Jimmi Dyson
- * @version $Revision: 1 $
*/
@Configuration
@ConditionalOnWebApplication
@EnableConfigurationProperties(KeycloakSpringBootProperties.class)
@ConditionalOnProperty(value = "keycloak.enabled", matchIfMissing = true)
-public class KeycloakAutoConfiguration {
-
- private KeycloakSpringBootProperties keycloakProperties;
-
- @Autowired
- public void setKeycloakSpringBootProperties(KeycloakSpringBootProperties keycloakProperties) {
- this.keycloakProperties = keycloakProperties;
- KeycloakSpringBootConfigResolver.setAdapterConfig(keycloakProperties);
- }
+public class KeycloakAutoConfiguration extends KeycloakBaseSpringBootConfiguration {
@Bean
@@ -121,200 +91,26 @@ public class KeycloakAutoConfiguration {
return new KeycloakUndertowDeploymentInfoCustomizer(keycloakProperties);
}
- static class KeycloakUndertowDeploymentInfoCustomizer implements UndertowDeploymentInfoCustomizer {
+ static class KeycloakJettyServerCustomizer extends KeycloakBaseJettyServerCustomizer implements JettyServerCustomizer {
- private final KeycloakSpringBootProperties keycloakProperties;
-
- public KeycloakUndertowDeploymentInfoCustomizer(KeycloakSpringBootProperties keycloakProperties) {
- this.keycloakProperties = keycloakProperties;
- }
-
- @Override
- public void customize(DeploymentInfo deploymentInfo) {
-
- io.undertow.servlet.api.LoginConfig loginConfig = new io.undertow.servlet.api.LoginConfig(keycloakProperties.getRealm());
- loginConfig.addFirstAuthMethod("KEYCLOAK");
-
- deploymentInfo.setLoginConfig(loginConfig);
-
- deploymentInfo.addInitParameter("keycloak.config.resolver", KeycloakSpringBootConfigResolver.class.getName());
- deploymentInfo.addSecurityConstraints(getSecurityConstraints());
-
- deploymentInfo.addServletExtension(new KeycloakServletExtension());
- }
-
- private List getSecurityConstraints() {
-
- List undertowSecurityConstraints = new ArrayList();
- for (KeycloakSpringBootProperties.SecurityConstraint constraintDefinition : keycloakProperties.getSecurityConstraints()) {
-
- io.undertow.servlet.api.SecurityConstraint undertowSecurityConstraint = new io.undertow.servlet.api.SecurityConstraint();
- undertowSecurityConstraint.addRolesAllowed(constraintDefinition.getAuthRoles());
-
- for (KeycloakSpringBootProperties.SecurityCollection collectionDefinition : constraintDefinition.getSecurityCollections()) {
-
- WebResourceCollection webResourceCollection = new WebResourceCollection();
- webResourceCollection.addHttpMethods(collectionDefinition.getMethods());
- webResourceCollection.addHttpMethodOmissions(collectionDefinition.getOmittedMethods());
- webResourceCollection.addUrlPatterns(collectionDefinition.getPatterns());
-
- undertowSecurityConstraint.addWebResourceCollections(webResourceCollection);
-
- }
-
- undertowSecurityConstraints.add(undertowSecurityConstraint);
- }
- return undertowSecurityConstraints;
- }
- }
-
- static class KeycloakJettyServerCustomizer implements JettyServerCustomizer {
-
- private final KeycloakSpringBootProperties keycloakProperties;
public KeycloakJettyServerCustomizer(KeycloakSpringBootProperties keycloakProperties) {
- this.keycloakProperties = keycloakProperties;
+ super(keycloakProperties);
}
- @Override
- public void customize(Server server) {
+ }
- KeycloakJettyAuthenticator keycloakJettyAuthenticator = new KeycloakJettyAuthenticator();
- keycloakJettyAuthenticator.setConfigResolver(new KeycloakSpringBootConfigResolver());
+ static class KeycloakTomcatContextCustomizer extends KeycloakBaseTomcatContextCustomizer implements TomcatContextCustomizer {
- /* see org.eclipse.jetty.webapp.StandardDescriptorProcessor#visitSecurityConstraint for an example
- on how to map servlet spec to Constraints */
-
- List jettyConstraintMappings = new ArrayList();
- for (KeycloakSpringBootProperties.SecurityConstraint constraintDefinition : keycloakProperties.getSecurityConstraints()) {
-
- for (KeycloakSpringBootProperties.SecurityCollection securityCollectionDefinition : constraintDefinition
- .getSecurityCollections()) {
- // securityCollection matches servlet spec's web-resource-collection
- Constraint jettyConstraint = new Constraint();
-
- if (constraintDefinition.getAuthRoles().size() > 0) {
- jettyConstraint.setAuthenticate(true);
- jettyConstraint.setRoles(constraintDefinition.getAuthRoles().toArray(new String[0]));
- }
-
- jettyConstraint.setName(securityCollectionDefinition.getName());
-
- // according to the servlet spec each security-constraint has at least one URL pattern
- for(String pattern : securityCollectionDefinition.getPatterns()) {
-
- /* the following code is asymmetric as Jetty's ConstraintMapping accepts only one allowed HTTP method,
- but multiple omitted methods. Therefore we add one ConstraintMapping for each allowed
- mapping but only one mapping in the cases of omitted methods or no methods.
- */
-
- if (securityCollectionDefinition.getMethods().size() > 0) {
- // according to the servlet spec we have either methods ...
- for(String method : securityCollectionDefinition.getMethods()) {
- ConstraintMapping jettyConstraintMapping = new ConstraintMapping();
- jettyConstraintMappings.add(jettyConstraintMapping);
-
- jettyConstraintMapping.setConstraint(jettyConstraint);
- jettyConstraintMapping.setPathSpec(pattern);
- jettyConstraintMapping.setMethod(method);
- }
- } else if (securityCollectionDefinition.getOmittedMethods().size() > 0){
- // ... omitted methods ...
- ConstraintMapping jettyConstraintMapping = new ConstraintMapping();
- jettyConstraintMappings.add(jettyConstraintMapping);
-
- jettyConstraintMapping.setConstraint(jettyConstraint);
- jettyConstraintMapping.setPathSpec(pattern);
- jettyConstraintMapping.setMethodOmissions(
- securityCollectionDefinition.getOmittedMethods().toArray(new String[0]));
- } else {
- // ... or no methods at all
- ConstraintMapping jettyConstraintMapping = new ConstraintMapping();
- jettyConstraintMappings.add(jettyConstraintMapping);
-
- jettyConstraintMapping.setConstraint(jettyConstraint);
- jettyConstraintMapping.setPathSpec(pattern);
- }
-
- }
-
- }
- }
-
- WebAppContext webAppContext = server.getBean(WebAppContext.class);
- //if not found as registered bean let's try the handler
- if(webAppContext==null){
- webAppContext = (WebAppContext) server.getHandler();
- }
-
- ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
- securityHandler.setConstraintMappings(jettyConstraintMappings);
- securityHandler.setAuthenticator(keycloakJettyAuthenticator);
-
- webAppContext.setSecurityHandler(securityHandler);
+ public KeycloakTomcatContextCustomizer(KeycloakSpringBootProperties keycloakProperties) {
+ super(keycloakProperties);
}
}
- static class KeycloakTomcatContextCustomizer implements TomcatContextCustomizer {
+ static class KeycloakUndertowDeploymentInfoCustomizer extends KeycloakBaseUndertowDeploymentInfoCustomizer implements UndertowDeploymentInfoCustomizer {
- 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 (String authRole : constraint.getAuthRoles()) {
- if (!authRoles.contains(authRole)) {
- context.addSecurityRole(authRole);
- authRoles.add(authRole);
- }
- }
- }
-
- for (KeycloakSpringBootProperties.SecurityConstraint constraint : keycloakProperties.getSecurityConstraints()) {
- SecurityConstraint tomcatConstraint = new SecurityConstraint();
-
- for (String authRole : constraint.getAuthRoles()) {
- tomcatConstraint.addAuthRole(authRole);
- }
-
- 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 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());
+ public KeycloakUndertowDeploymentInfoCustomizer(KeycloakSpringBootProperties keycloakProperties){
+ super(keycloakProperties);
}
}
}
diff --git a/adapters/oidc/spring-boot2/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootConfigResolver.java b/adapters/oidc/spring-boot2/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootConfigResolver.java
deleted file mode 100755
index 2f90402cf6f..00000000000
--- a/adapters/oidc/spring-boot2/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootConfigResolver.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed 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.keycloak.adapters.springboot;
-
-import org.keycloak.adapters.KeycloakDeployment;
-import org.keycloak.adapters.KeycloakDeploymentBuilder;
-import org.keycloak.adapters.OIDCHttpFacade;
-import org.keycloak.representations.adapters.config.AdapterConfig;
-
-public class KeycloakSpringBootConfigResolver implements org.keycloak.adapters.KeycloakConfigResolver {
-
- private KeycloakDeployment keycloakDeployment;
-
- private static AdapterConfig adapterConfig;
-
- @Override
- public KeycloakDeployment resolve(OIDCHttpFacade.Request request) {
- if (keycloakDeployment != null) {
- return keycloakDeployment;
- }
-
- keycloakDeployment = KeycloakDeploymentBuilder.build(KeycloakSpringBootConfigResolver.adapterConfig);
-
- return keycloakDeployment;
- }
-
- static void setAdapterConfig(AdapterConfig adapterConfig) {
- KeycloakSpringBootConfigResolver.adapterConfig = adapterConfig;
- }
-}
\ No newline at end of file
diff --git a/adapters/oidc/spring-boot2/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootProperties.java b/adapters/oidc/spring-boot2/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootProperties.java
deleted file mode 100644
index 9c28a9a7311..00000000000
--- a/adapters/oidc/spring-boot2/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootProperties.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed 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.keycloak.adapters.springboot;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import org.keycloak.representations.adapters.config.AdapterConfig;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-@ConfigurationProperties(prefix = "keycloak", ignoreUnknownFields = false)
-public class KeycloakSpringBootProperties extends AdapterConfig {
-
- /* this is a dummy property to avoid re-rebinding problem with property keycloak.config.resolver
- when using spring cloud - see KEYCLOAK-2977 */
- @JsonIgnore
- private Map config = new HashMap();
-
- /**
- * Allow enabling of Keycloak Spring Boot adapter by configuration.
- */
- private boolean enabled = true;
-
- public Map getConfig() {
- return config;
- }
-
- /**
- * To provide Java EE security constraints
- */
- private List securityConstraints = new ArrayList();
-
- public boolean isEnabled() {
- return enabled;
- }
-
- public void setEnabled(boolean enabled) {
- this.enabled = enabled;
- }
-
- /**
- * This matches security-constraint of the servlet spec
- */
- @ConfigurationProperties()
- public static class SecurityConstraint {
- /**
- * A list of security collections
- */
- private List securityCollections = new ArrayList();
- private List authRoles = new ArrayList();
-
- public List getAuthRoles() {
- return authRoles;
- }
-
- public List getSecurityCollections() {
- return securityCollections;
- }
-
- public void setSecurityCollections(List securityCollections) {
- this.securityCollections = securityCollections;
- }
-
- public void setAuthRoles(List authRoles) {
- this.authRoles = authRoles;
- }
-
- }
-
- /**
- * This matches web-resource-collection of the servlet spec
- */
- @ConfigurationProperties()
- public static class SecurityCollection {
- /**
- * The name of your security constraint
- */
- private String name;
- /**
- * The description of your security collection
- */
- private String description;
- /**
- * A list of URL patterns that should match to apply the security collection
- */
- private List patterns = new ArrayList();
- /**
- * A list of HTTP methods that applies for this security collection
- */
- private List methods = new ArrayList();
- /**
- * A list of HTTP methods that will be omitted for this security collection
- */
- private List omittedMethods = new ArrayList();
-
- public List getPatterns() {
- return patterns;
- }
-
- public List getMethods() {
- return methods;
- }
-
- public String getDescription() {
- return description;
- }
-
- public String getName() {
- return name;
- }
-
- public List getOmittedMethods() {
- return omittedMethods;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public void setDescription(String description) {
- this.description = description;
- }
-
- public void setPatterns(List patterns) {
- this.patterns = patterns;
- }
-
- public void setMethods(List methods) {
- this.methods = methods;
- }
-
- public void setOmittedMethods(List omittedMethods) {
- this.omittedMethods = omittedMethods;
- }
- }
-
- public List getSecurityConstraints() {
- return securityConstraints;
- }
-
- public void setSecurityConstraints(List securityConstraints) {
- this.securityConstraints = securityConstraints;
- }
-}
diff --git a/pom.xml b/pom.xml
index 0fd83b4fc01..3dbd4ccf8d3 100755
--- a/pom.xml
+++ b/pom.xml
@@ -849,6 +849,11 @@
keycloak-servlet-oauth-client
${project.version}
+
+ org.keycloak
+ keycloak-spring-boot-adapter-core
+ ${project.version}
+
org.keycloak
keycloak-spring-boot-adapter