Authorization and Authentication in Kotlin: Complete Guide
In modern web development with Kotlin, application security begins with proper implementation of authentication (verifying user identity) and authorization (checking access rights). In this article, we will review the main approaches, libraries, and tools for implementing these mechanisms on Spring Boot and Ktor platforms.
Basic Concepts
Before moving to code, let's clarify the terms:
- Authentication — the process of verifying that a user is who they claim to be (usually via login/password, token, or biometrics).
- Authorization — determining the access rights of an authenticated user (e.g., access to specific routes or data).
- JWT (JSON Web Token) — a compact and self-contained token for transferring data between parties.
- BCrypt — a password hashing algorithm with salt, resistant to brute-force attacks.
Authentication with JWT in Spring Boot
Spring Security provides a powerful infrastructure for authentication. Let's look at implementing JWT authentication using the io.jsonwebtoken:jjwt library.
// build.gradle.ktsdependencies { implementation("org.springframework.boot:spring-boot-starter-security") implementation("io.jsonwebtoken:jjwt-api:0.12.3") runtimeOnly("io.jsonwebtoken:jjwt-impl:0.12.3") runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.12.3")}Let's create a utility class for working with JWT:
import io.jsonwebtoken.*import io.jsonwebtoken.security.Keysimport org.springframework.stereotype.Componentimport java.security.Keyimport java.util.*
@Componentclass JwtUtil { private val secretKey: Key = Keys.secretKeyFor(SignatureAlgorithm.HS256) private val expirationMs: Long = 3600000 // 1 hour
fun generateToken(username: String): String { return Jwts.builder() .subject(username) .issuedAt(Date()) .expiration(Date(System.currentTimeMillis() + expirationMs)) .signWith(secretKey) .compact() }
fun extractUsername(token: String): String? { return try { Jwts.parser().verifyWith(secretKey).build() .parseSignedClaims(token).payload.subject } catch (e: Exception) { null } }
fun validateToken(token: String): Boolean { return try { Jwts.parser().verifyWith(secretKey).build() .parseSignedClaims(token) true } catch (e: JwtException) { false } }}Authentication Filter for Spring Security
Now let's create a filter that will intercept requests and check the JWT token:
import jakarta.servlet.FilterChainimport jakarta.servlet.http.HttpServletRequestimport jakarta.servlet.http.HttpServletResponseimport org.springframework.security.authentication.UsernamePasswordAuthenticationTokenimport org.springframework.security.core.context.SecurityContextHolderimport org.springframework.security.web.authentication.WebAuthenticationDetailsSourceimport org.springframework.stereotype.Componentimport org.springframework.web.filter.OncePerRequestFilter
@Componentclass JwtAuthFilter( private val jwtUtil: JwtUtil, private val userDetailsService: org.springframework.security.core.userdetails.UserDetailsService) : OncePerRequestFilter() {
override fun doFilterInternal( request: HttpServletRequest, response: HttpServletResponse, chain: FilterChain ) { val authHeader = request.getHeader("Authorization") if (authHeader == null || !authHeader.startsWith("Bearer ")) { chain.doFilter(request, re