Ktor 3.0.0 Help

Session authentication

Sessions provide a mechanism to persist data between different HTTP requests. Typical use cases include storing a logged-in user's ID, the contents of a shopping basket, or keeping user preferences on the client.

In Ktor, a user that already has an associated session can be authenticated using the session provider. For example, when a user logs in using a web form for the first time, you can save a username to a cookie session and authorize this user on subsequent requests using the session provider.

Add dependencies

To enable session authentication, you need to include the following artifacts in the build script:

  • Add the ktor-server-sessions dependency for using sessions:

    implementation("io.ktor:ktor-server-sessions:$ktor_version")
    implementation "io.ktor:ktor-server-sessions:$ktor_version"
    <dependency> <groupId>io.ktor</groupId> <artifactId>ktor-server-sessions-jvm</artifactId> <version>${ktor_version}</version> </dependency>
  • Add the ktor-server-auth dependency for authentication:

    implementation("io.ktor:ktor-server-auth:$ktor_version")
    implementation "io.ktor:ktor-server-auth:$ktor_version"
    <dependency> <groupId>io.ktor</groupId> <artifactId>ktor-server-auth-jvm</artifactId> <version>${ktor_version}</version> </dependency>

Session authentication flow

The authentication flow with sessions might vary and depends on how users are authenticated in your application. Let's see how it might look with the form-based authentication:

  1. A client makes a request containing web form data (which includes the username and password) to a server.

  2. A server validates credentials sent by a client, saves a username to a cookie session, and responds with the requested content and a cookie containing a username.

  3. A client makes a subsequent request with a cookie to the protected resource.

  4. Based on received cookie data, Ktor checks that a cookie session exists for this user and, optionally, performs additional validations on received session data. In a case of successful validation, a server responds with the requested content.

Install session authentication

To install the session authentication provider, call the session function with the required session type inside the install block:

import io.ktor.server.application.* import io.ktor.server.auth.* import io.ktor.server.sessions.* //... install(Authentication) { session<UserSession> { // Configure session authentication } }

Configure session authentication

This section demonstrates how to authenticate a user with a form-based authentication, save information about this user to a cookie session, and then authorize this user on subsequent requests using the session provider. You can find the complete example here: auth-form-session.

Step 1: Create a data class

First, you need to create a data class for storing session data. Note that this class should inherit Principal since the validate function should return a Principal in the case of successful authentication.

@Serializable data class UserSession(val name: String, val count: Int) : Principal

Step 2: Install and configure a session

After creating a data class, you need to install and configure the Sessions plugin. A code snippet below shows how to install and configure a cookie session with the specified cookie path and expiration time.

cookie<UserSession>("user_session") { cookie.path = "/" cookie.maxAgeInSeconds = 60 } }

You can learn more about configuring sessions from Session configuration overview.

Step 3: Configure session authentication

The session authentication provider exposes its settings via the SessionAuthenticationProvider.Config class. In the example below, the following settings are specified:

  • The validate function checks the session instance and returns Principal in the case of successful authentication.

  • The challenge function specifies an action performed if authentication fails. For instance, you can redirect back to a login page or send UnauthorizedResponse.

install(Authentication) { session<UserSession>("auth-session") { validate { session -> if(session.name.startsWith("jet")) { session } else { null } } challenge { call.respondRedirect("/login") } } }

Step 4: Save user data in a session

To save information about a logged-in user to a session, use the call.sessions.set function.

authenticate("auth-form") { post("/login") { val userName = call.principal<UserIdPrincipal>()?.name.toString() call.sessions.set(UserSession(name = userName, count = 1)) call.respondRedirect("/hello") } }

Step 5: Protect specific resources

After configuring the session provider, you can protect specific resources in our application using the authenticate function. In the case of successful authentication, you can retrieve an authenticated Principal (the UserSession instance) inside a route handler using the call.principal function and information about a user.

authenticate("auth-session") { get("/hello") { val userSession = call.principal<UserSession>() call.sessions.set(userSession?.copy(count = userSession.count + 1)) call.respondText("Hello, ${userSession?.name}! Visit count is ${userSession?.count}.") } }

You can find the full example here: auth-form-session.

Last modified: 22 August 2024