diff --git a/kotlin-spring-security-dsl/.gitignore b/kotlin-spring-security-dsl/.gitignore
new file mode 100644
index 0000000000..a2a3040aa8
--- /dev/null
+++ b/kotlin-spring-security-dsl/.gitignore
@@ -0,0 +1,31 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**
+!**/src/test/**
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+
+### VS Code ###
+.vscode/
diff --git a/kotlin-spring-security-dsl/.mvn/wrapper/MavenWrapperDownloader.java b/kotlin-spring-security-dsl/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000000..a45eb6ba26
--- /dev/null
+++ b/kotlin-spring-security-dsl/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2007-present the original author or authors.
+ *
+ * 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
+ *
+ * https://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.
+ */
+
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ private static final String WRAPPER_VERSION = "0.5.6";
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if (mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if (mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if (!outputFile.getParentFile().exists()) {
+ if (!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+ String username = System.getenv("MVNW_USERNAME");
+ char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+ Authenticator.setDefault(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password);
+ }
+ });
+ }
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/kotlin-spring-security-dsl/.mvn/wrapper/maven-wrapper.jar b/kotlin-spring-security-dsl/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000000..2cc7d4a55c
Binary files /dev/null and b/kotlin-spring-security-dsl/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/kotlin-spring-security-dsl/.mvn/wrapper/maven-wrapper.properties b/kotlin-spring-security-dsl/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000000..642d572ce9
--- /dev/null
+++ b/kotlin-spring-security-dsl/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
diff --git a/kotlin-spring-security-dsl/pom.xml b/kotlin-spring-security-dsl/pom.xml
new file mode 100644
index 0000000000..6e1fc02954
--- /dev/null
+++ b/kotlin-spring-security-dsl/pom.xml
@@ -0,0 +1,98 @@
+
+
+ 4.0.0
+
+ com.baeldung
+ parent-kotlin
+ 1.0.0-SNAPSHOT
+ ../parent-kotlin
+
+
+ com.baeldung.spring.security.dsl
+ kotlin-spring-security-dsl
+ 1.0
+ kotlin-spring-security-dsl
+ Spring Security Kotlin DSL
+
+
+ 11
+ 1.3.72
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ com.fasterxml.jackson.module
+ jackson-module-kotlin
+
+
+ org.jetbrains.kotlin
+ kotlin-reflect
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib-jdk8
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.springframework.security
+ spring-security-test
+ test
+
+
+
+
+ ${project.basedir}/src/main/kotlin
+ ${project.basedir}/src/test/kotlin
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-plugin
+
+
+ -Xjsr305=strict
+
+
+ spring
+
+
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-allopen
+ ${kotlin.version}
+
+
+
+
+
+
+
diff --git a/kotlin-spring-security-dsl/src/main/kotlin/com/spring/security/kotlin/dsl/SpringSecurityKotlinApplication.kt b/kotlin-spring-security-dsl/src/main/kotlin/com/spring/security/kotlin/dsl/SpringSecurityKotlinApplication.kt
new file mode 100644
index 0000000000..368bb5978e
--- /dev/null
+++ b/kotlin-spring-security-dsl/src/main/kotlin/com/spring/security/kotlin/dsl/SpringSecurityKotlinApplication.kt
@@ -0,0 +1,71 @@
+package com.spring.security.kotlin.dsl
+
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import org.springframework.boot.runApplication
+import org.springframework.context.annotation.Configuration
+import org.springframework.context.support.beans
+import org.springframework.core.annotation.Order
+import org.springframework.security.config.annotation.web.builders.HttpSecurity
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
+import org.springframework.security.config.web.servlet.invoke
+import org.springframework.security.core.userdetails.User
+import org.springframework.security.provisioning.InMemoryUserDetailsManager
+import org.springframework.web.servlet.function.ServerResponse
+import org.springframework.web.servlet.function.router
+
+@EnableWebSecurity
+@SpringBootApplication
+class SpringSecurityKotlinApplication
+
+@Order(1)
+@Configuration
+class AdminSecurityConfiguration : WebSecurityConfigurerAdapter() {
+ override fun configure(http: HttpSecurity?) {
+ http {
+ authorizeRequests {
+ authorize("/greetings/**", hasAuthority("ROLE_ADMIN"))
+ }
+ httpBasic {}
+ }
+ }
+}
+
+@Configuration
+class BasicSecurityConfiguration : WebSecurityConfigurerAdapter() {
+ override fun configure(http: HttpSecurity?) {
+ http {
+ authorizeRequests {
+ authorize("/**", permitAll)
+ }
+ httpBasic {}
+ }
+ }
+}
+
+fun main(args: Array) {
+ runApplication(*args) {
+ addInitializers( beans {
+ bean {
+ fun user(user: String, password: String, vararg roles: String) =
+ User
+ .withDefaultPasswordEncoder()
+ .username(user)
+ .password(password)
+ .roles(*roles)
+ .build()
+
+ InMemoryUserDetailsManager(user("user", "password", "USER")
+ , user("admin", "password", "USER", "ADMIN"))
+ }
+
+ bean {
+ router {
+ GET("/greetings") {
+ request -> request.principal().map { it.name }.map { ServerResponse.ok().body(mapOf("greeting" to "Hello $it")) }.orElseGet { ServerResponse.badRequest().build() }
+ }
+ }
+ }
+ })
+ }
+}
diff --git a/kotlin-spring-security-dsl/src/main/resources/application.properties b/kotlin-spring-security-dsl/src/main/resources/application.properties
new file mode 100644
index 0000000000..5ff028510d
--- /dev/null
+++ b/kotlin-spring-security-dsl/src/main/resources/application.properties
@@ -0,0 +1 @@
+server.port=9090
\ No newline at end of file
diff --git a/kotlin-spring-security-dsl/src/test/kotlin/com/spring/security/kotlin/dsl/SpringSecurityKotlinApplicationTests.kt b/kotlin-spring-security-dsl/src/test/kotlin/com/spring/security/kotlin/dsl/SpringSecurityKotlinApplicationTests.kt
new file mode 100644
index 0000000000..3da8110feb
--- /dev/null
+++ b/kotlin-spring-security-dsl/src/test/kotlin/com/spring/security/kotlin/dsl/SpringSecurityKotlinApplicationTests.kt
@@ -0,0 +1,35 @@
+package com.spring.security.kotlin.dsl
+
+import org.junit.jupiter.api.Test
+import org.junit.runner.RunWith
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.security.test.context.support.WithMockUser
+import org.springframework.test.context.junit4.SpringRunner
+import org.springframework.test.web.servlet.MockMvc
+import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.*
+import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user
+import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic
+import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated
+import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated
+import org.springframework.test.web.servlet.get
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
+
+@RunWith(SpringRunner::class)
+@SpringBootTest
+@AutoConfigureMockMvc
+class SpringSecurityKotlinApplicationTests {
+
+ @Autowired
+ private lateinit var mockMvc: MockMvc
+
+ @Test
+ fun `ordinary user not permitted to access the endpoint`() {
+ this.mockMvc
+ .perform(get("/greetings")
+ .with(httpBasic("user", "password")))
+ .andExpect(unauthenticated())
+ }
+}