0Pricing
Kotlin Academy · Lesson

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 in validate
  • Sessions: stateful; call.sessions.set() on login, clear() on logout
  • Use challenge to 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

  1. Ktor Project Setup: embeddedServer and Application Modules
  2. Routing and Typed Parameters
  3. Content Negotiation and kotlinx.serialization
  4. Authentication Plugins: JWT and Session
← Back to Kotlin Academy