Authentication Plugins: JWT and Session
Secure Ktor routes using JWT bearer tokens and session-based authentication.
Authentication Plugins: JWT and Session is a free Kotlin Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Kotlin Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Ktor Authentication Overview
Ktor's Authentication plugin provides a unified API for protecting routes. You configure one or more providers (JWT, Session, Basic, OAuth, etc.) and then wrap routes in an authenticate("providerName") { } block.
Adding Auth Dependencies
Add the auth and JWT libraries to your build:
dependencies {
implementation("io.ktor:ktor-server-auth:2.3.12")
implementation("io.ktor:ktor-server-auth-jwt:2.3.12")
implementation("io.ktor:ktor-server-sessions:2.3.12")
}Configuring JWT Authentication
Install the Authentication plugin and configure a JWT provider. The verifier validates the token signature; validate extracts the principal from the payload:
install(Authentication) {
jwt("auth-jwt") {
realm = "ktor app"
verifier(
JWT.require(Algorithm.HMAC256(secret))
.withAudience(audience)
.withIssuer(issuer)
.build()
)
validate { credential ->
if (credential.payload.getClaim("username").asString() != null)
JWTPrincipal(credential.payload)
else null
}
}
}Protecting Routes with JWT
Wrap any route group in authenticate("auth-jwt") { }. Unauthenticated requests receive a 401 automatically:
routing {
authenticate("auth-jwt") {
get("/protected") {
val principal = call.principal<JWTPrincipal>()!!
val username = principal.payload.getClaim("username").asString()
call.respondText("Hello, $username")
}
}
}Issuing a JWT Token
Generate and sign a JWT on the login endpoint using the java-jwt library:
post("/login") {
val user = call.receive<LoginRequest>()
// validate credentials ...
val token = JWT.create()
.withAudience(audience)
.withIssuer(issuer)
.withClaim("username", user.username)
.withExpiresAt(Date(System.currentTimeMillis() + 3_600_000))
.sign(Algorithm.HMAC256(secret))
call.respond(mapOf("token" to token))
}Session Authentication
Sessions store user state server-side (or client-side as signed cookies). Install the Sessions plugin and define a session data class:
data class UserSession(val userId: Long, val username: String)
install(Sessions) {
cookie<UserSession>("user_session") {
cookie.path = "/"
cookie.httpOnly = true
}
}Configuring Session Auth Provider
Create a session authentication provider that reads the session and returns a principal:
install(Authentication) {
session<UserSession>("auth-session") {
validate { session -> session }
challenge { call.respond(HttpStatusCode.Unauthorized) }
}
}Setting and Clearing Sessions
Set a session after login with call.sessions.set() and clear it on logout with call.sessions.clear:
post("/login") {
val creds = call.receive<LoginRequest>()
// validate ...
call.sessions.set(UserSession(userId = 1L, username = creds.username))
call.respond(HttpStatusCode.OK)
}
post("/logout") {
call.sessions.clear<UserSession>()
call.respond(HttpStatusCode.OK)
}JWT vs Session: When to Use Each
JWT: stateless, good for APIs consumed by mobile/SPA clients. Token carries all claims; server needs no session store. Sessions: stateful, good for server-rendered web apps. Session ID in cookie; server holds the data (memory, Redis, DB).
Combining Multiple Auth Providers
You can define multiple providers and require any of them using authenticate("jwt", "session") { }. Ktor tries each in order and accepts the request if any provider validates successfully.
Custom Challenge Responses
Each provider has a challenge block that defines what to do when authentication fails. Return a 401 with a JSON error body instead of the default WWW-Authenticate header:
jwt("auth-jwt") {
// ...
challenge { _, _ ->
call.respond(HttpStatusCode.Unauthorized, mapOf("error" to "Token expired or invalid"))
}
}Quick Check
What does the validate block in a Ktor JWT provider do?
Recap: Authentication Plugins — JWT and Session
Key takeaways:
- Install
Authentication; configure providers (jwt, session, basic, oauth) - Protect routes with
authenticate("providerName") { } - JWT: stateless tokens; sign on login, verify with
verifier, read claims invalidate - Sessions: stateful;
call.sessions.set()on login,clear()on logout - Use
challengeto customize the 401 response format
Frequently asked questions
Is the “Authentication Plugins: JWT and Session” lesson free?
Yes — the full text of “Authentication Plugins: JWT and Session” is free to read here on the web, and the Kotlin Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Kotlin Academy course, upgrade to CoddyKit PRO.
What will I learn in “Authentication Plugins: JWT and Session”?
Secure Ktor routes using JWT bearer tokens and session-based authentication. You practise Kotlin Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Kotlin Academy?
No prior experience is required. Kotlin Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Authentication Plugins: JWT and Session” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Kotlin Academy lesson?
Yes. Every Kotlin Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Ktor Project Setup: embeddedServer and Application Modules
- Routing and Typed Parameters
- Content Negotiation and kotlinx.serialization
- Authentication Plugins: JWT and Session