Ktor 1.6.8 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</artifactId> <version>${ktor_version}</version> </dependency>

  • Add the ktor-auth dependency for authentication:

    implementation "io.ktor:ktor-auth:$ktor_version"
    implementation("io.ktor:ktor-auth:$ktor_version")
    <dependency> <groupId>io.ktor</groupId> <artifactId>ktor-auth</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:

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 a case of successful authentication.

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.

install(Sessions) { 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/Configuration class. In the example below, the following settings are specified:

  • The validate function checks the session instance and returns Principal in a 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: Define authorization scope

After configuring the session provider, you can define the authorization for the different resources in our application using the authenticate function. In a 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: 11 May 2022