Ktor 1.6.7 Help

Authentication and authorization

Ktor provides the Auth plugin (previously known as feature) to handle authentication and authorization in your client application. Typical usage scenarios include logging in users and gaining access to specific resources.

Supported authentication types

HTTP provides a general framework for access control and authentication. The Ktor client allows you to use the following HTTP authentication schemes:

  • Basic- uses Base64 encoding to provide a username and password. Generally is not recommended if not used in combination with HTTPS.

  • Digest- an authentication method that communicates user credentials in an encrypted form by applying a hash function to the username and password.

  • Bearer- an authentication scheme that involves security tokens called bearer tokens. For example, you can use this scheme as a part of OAuth flow to authorize users of your application by using external providers, such as Google, Facebook, Twitter, and so on.

Add dependencies

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

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

Install Auth

To install the Auth plugin, pass it to the install function inside a client configuration block:

val client = HttpClient(CIO) { install(Auth) { // Configure authentication } }

Now you can configure the required authentication provider.

Configure authentication

Basic

The Basic authentication scheme can be used for logging in users. In this scheme, user credentials are transmitted as username/password pairs encoded using Base64. You can learn how the basic authentication flow might look from the Basic authentication flow section for a Ktor server.

To send user credentials in the Authorization header using the Basic scheme, you need to configure the basic authentication provider as follows:

  1. Call the basic function inside the install block.

  2. Provide the required credentials using BasicAuthCredentials and pass this object to the credentials function.

  3. Optionally, configure the realm using the realm property.

val client = HttpClient(CIO) { install(Auth) { basic { credentials { BasicAuthCredentials(username = "jetbrains", password = "foobar") } realm = "Access to the '/' path" } } }

You can find the full example here: client-auth-basic.

The client also allows you to send credentials in the initial request without waiting for a 401 (Unauthorized) response with the WWW-Authenticate header. You need to call the sendWithoutRequest function returning boolean and check the request parameters.

install(Auth) { basic { // ... sendWithoutRequest { request -> request.url.host == "0.0.0.0" } } }

Digest

In the Digest authentication scheme, a hash function is applied to a username and password before sending them over the network. You can learn how the digest authentication flow might look from the Digest authentication flow section for a Ktor server.

To send user credentials in the Authorization header using the Digest scheme, you need to configure the digest authentication provider as follows:

  1. Call the digest function inside the install block.

  2. Provide the required credentials using DigestAuthCredentials and pass this object to the credentials function.

  3. Optionally, configure the realm using the realm property.

val client = HttpClient(CIO) { install(Auth) { digest { credentials { DigestAuthCredentials(username = "jetbrains", password = "foobar") } realm = "Access to the '/' path" } } }

You can find the full example here: client-auth-digest.

Bearer

Bearer authentication involves security tokens called bearer tokens. As an example, these tokens can be used as a part of OAuth flow to authorize users of your application by using external providers, such as Google, Facebook, Twitter, and so on.

A Ktor client allows you to configure a token to be sent in the Authorization header using the Bearer scheme. You can also specify logic for refreshing a token if the old one is invalid. To configure the bearer provider, follow the steps below:

  1. Call the bearer function inside the install block.

  2. Specify how to get an initial token using loadTokens. A code snippet below shows how to make a POST request to get the access and refresh tokens for accessing Google APIs.

    install(Auth) { lateinit var tokenInfo: TokenInfo var refreshTokenInfo: TokenInfo bearer { loadTokens { tokenInfo = tokenClient.submitForm( url = "https://accounts.google.com/o/oauth2/token", formParameters = Parameters.build { append("grant_type", "authorization_code") append("code", authorizationCode) append("client_id", clientId) append("redirect_uri", redirectUri) } ) BearerTokens( accessToken = tokenInfo.accessToken, refreshToken = tokenInfo.refreshToken!! ) } } } }
  3. Specify how to obtain a new token if the old one is invalid using refreshTokens. Note that this block will be called after receiving a 401 (Unauthorized) response with the WWW-Authenticate header. The example below shows how to get a new access token using a refresh token.

    install(Auth) { lateinit var tokenInfo: TokenInfo var refreshTokenInfo: TokenInfo bearer { refreshTokens { unauthorizedResponse: HttpResponse -> refreshTokenInfo = tokenClient.submitForm( url = "https://accounts.google.com/o/oauth2/token", formParameters = Parameters.build { append("grant_type", "refresh_token") append("client_id", clientId) append("refresh_token", tokenInfo.refreshToken!!) } ) BearerTokens( accessToken = refreshTokenInfo.accessToken, refreshToken = tokenInfo.refreshToken!! ) } } } }

After configuring the bearer provider, you can make requests to the protected API.

val userInfo: UserInfo = apiClient.get("https://www.googleapis.com/oauth2/v2/userinfo") println("Hello, ${userInfo.name}!")

You can find the full example here: client-auth-oauth-google.

Last modified: 02 December 2021