Ktor 1.5.3 Help

Authentication and Authorization

Ktor supports authentication out of the box as a standard pluggable feature. It supports mechanisms to read credentials, and to authenticate principals.

It can be used in some cases along with the sessions feature to keep the login information between requests.

Add Dependencies

To enable authentication, you need to include the ktor-auth artifact in the build script:

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>

Note that some authentication features (for example JWT/JWK and LDAP) might require additional artifacts.

Basic usage

Ktor defines two concepts: credentials and principals.

  • A principal is something that can be authenticated: a user, a computer, a group, etc.

  • A credential is an object that represents a set of properties for the server to authenticate a principal: a user/password, an API key or an authenticated payload signature, etc.

To install it, you have to call to application.install(Authentication). You have to install this feature directly to the application and it won't work in another ApplicationCallPipeline like Route.

Using its DSL, it allows you to configure the authentication providers available:

install(Authentication) { basic(name = "myauth1") { realm = "Ktor Server" validate { credentials -> if (credentials.name == credentials.password) { UserIdPrincipal(credentials.name) } else { null } } } }

After defining one or more authentication providers (named or unnamed), with the routing feature you can create a route group, that will apply that authentication to all the routes defined in that group:

routing { authenticate("myauth1") { get("/authenticated/route1") { // ... } get("/other/route2") { // ... } } get("/") { // ... } }

You can specify several names to apply several authentication providers, or none or null to use the unnamed one.

You can get the generated Principal instance inside your handler with:

val principal: UserIdPrincipal? = call.authentication.principal<UserIdPrincipal>()

Naming the AuthenticationProvider

It is possible to give arbitrary names to the authentication providers you specify, or to not provide a name at all (unnamed provider) by not setting the name argument or passing a null.

You cannot repeat authentication provider names, and you can define just one provider without a name.

In the case you repeat a name for the provider or try to define two unnamed providers, an exception will be thrown:

java.lang.IllegalArgumentException: Provider with the name `authName` is already registered

Summarizing:

install(Authentication) { basic { // Unamed `basic` provider // ... } form { // Unamed `form` provider (exception, already defined a provider with name = null) // ... } basic("name1") { // "name1" provider // ... } basic("name1") { // "name1" provider (exception, already defined a provider with name = "name1") // ... } }

Skipping/Omitting Authentication providers

You can also skip an authentication based on a criteria.

/** * Authentication filters specifying if authentication is required for particular [ApplicationCall] * If there is no filters, authentication is required. If any filter returns true, authentication is not required. */ fun AuthenticationProvider.skipWhen(predicate: (ApplicationCall) -> Boolean)

For example, to skip a basic authentication if there is already a session, you could write:

authentication { basic { skipWhen { call -> call.sessions.get<UserSession>() != null } } }

Advanced

Last modified: 24 February 2021