Spring Security Crash Course with Kotlin & Spring Boot
Mastering Spring Security with Kotlin: From Zero to Secure in Minutes
Spring Security Crash Course with Kotlin & Spring Boot
Spring Boot makes building REST APIs fast. But security? That’s where Spring Security comes in — powerful, flexible, and production-ready out of the box. In this crash course, we’ll start from zero and walk through how Spring Security protects your application by default, and how to customize it to fit your needs.
⚙️ Project Setup (Kotlin + Spring Boot 3.5)
Let’s begin by setting up a Kotlin-based Spring Boot project with Spring Security.
📄 build.gradle.kts
plugins {
kotlin("jvm") version "1.9.25"
kotlin("plugin.spring") version "1.9.25"
id("org.springframework.boot") version "3.5.0"
id("io.spring.dependency-management") version "1.1.7"
}
group = "com.atomic.coding"
version = "0.0.1-SNAPSHOT"
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
testImplementation("org.springframework.security:spring-security-test")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
kotlin {
compilerOptions {
freeCompilerArgs.addAll("-Xjsr305=strict")
}
}
tasks.withType<Test> {
useJUnitPlatform()
}Spring Security is enabled by default with the spring-boot-starter-security dependency — and that’s what powers everything we're about to see.
🚀 Create a Simple REST Controller
Let’s start with a basic endpoint.
@RestController
@RequestMapping("/greeting")
class GreetingController {
@GetMapping
fun greeting(@RequestParam(value = "name", required = false) name: String?): String {
return "Hello, $name!"
}
}Try accessing:
http://localhost:8080/greeting?name=baggioWhat happens? You’re redirected to a login page! That’s Spring Security in action.
🔐 Default Form Login Behaviour
Without any custom security configuration, Spring Security automatically:
Secures all endpoints
Provides a form login page at
/loginGenerates a default user:
userOutputs a random password in the logs
📝 Sample Log Output
Using generated security password: 8a3f9b12-xxxx-xxxx-xxxx-xxxxxxxxxxxxLog in using:
Username:
userPassword: copy from logs
Once logged in, try accessing /greeting again — it works!
🛠️ Customizing Security with SecurityFilterChain
Spring Security allows fine-grained configuration using a SecurityFilterChain bean. This lets us define public and protected routes.
📄 SecurityConfig.kt
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
fun securityFilterChain(http: HttpSecurity): SecurityFilterChain = http
.authorizeHttpRequests { auth ->
auth
.requestMatchers("/api/health").permitAll() // public
.anyRequest().authenticated() // secure everything else
}
.formLogin {} // enable default login form
.build()
}✅ Explanation
authorizeHttpRequests {}: Secures endpoints based on request patterns.requestMatchers("/api/health").permitAll(): Allows open access.anyRequest().authenticated(): Secures all other endpoints.formLogin {}: Enables the default login page.
❤️ Creating a Public Health Check Endpoint
A common use case: expose an endpoint for monitoring tools like Prometheus or Kubernetes.
📄 HealthCheckController.kt
@RestController
@RequestMapping("/api/health")
class HealthCheckController {
@GetMapping
fun healthCheck(): String = "Up and Running"
}You can now access:
http://localhost:8080/api/healthNo login required ✅
🧠 Recap
In this crash course, we covered:
Spring Security’s default behaviour
How it secures endpoints automatically
Logging in with the default
userCustomizing routes using
SecurityFilterChainExposing public endpoints like health checks
📚 What’s Next?
Now that you’ve secured your app with default form login, you’re ready to go deeper:
Custom login pages with
.loginPage("/custom-login")Role-based access control with
.hasRole("ADMIN")JWT-based stateless authentication
Secure password storage using
BCryptPasswordEncoderIn-memory, JDBC, or custom
UserDetailsServicefor user management
🧵 Stay Tuned
This is the first post in a Spring Security series. Follow along as we build a fully secured Spring Boot application — from form login to tokens and roles.





