Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@ dependencies {
implementation("io.ktor:ktor-server-core:$ktor_version")
implementation("io.ktor:ktor-server-netty:$ktor_version")
implementation("ch.qos.logback:logback-classic:$logback_version")
testImplementation("junit:junit:$junit_version")
testImplementation("io.ktor:ktor-client-mock:$ktor_version")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.example

import io.ktor.client.HttpClient
import io.ktor.client.engine.mock.MockEngine
import io.ktor.client.engine.mock.respond
import io.ktor.client.plugins.auth.Auth
import io.ktor.client.plugins.auth.providers.BearerTokens
import io.ktor.client.plugins.auth.providers.bearer
import io.ktor.client.request.get
import io.ktor.http.HttpHeaders
import io.ktor.http.HttpStatusCode
import io.ktor.http.headersOf
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test

class ApplicationTest {
@Test
fun testSingleAuthProviderUsedDespiteDifferentAuthenticateHeader() = runBlocking {
var firstRequest = true

val engine = MockEngine { request ->
val authHeader = request.headers[HttpHeaders.Authorization]

if (firstRequest) {
firstRequest = false
respond(
content = "",
status = HttpStatusCode.Unauthorized,
headers = headersOf(
HttpHeaders.WWWAuthenticate,
"Basic realm=\"Test\""
)
)
} else {
assertEquals("Bearer valid", authHeader)
respond(
content = "OK",
status = HttpStatusCode.OK
)
}
}

val client = HttpClient(engine) {
install(Auth) {
bearer {
loadTokens {
BearerTokens("invalid", "refresh")
}

refreshTokens {
BearerTokens("valid", "refresh")
}
}
}
}
val response = client.get("https://test.example")
assertEquals(HttpStatusCode.OK, response.status)
}
}
70 changes: 44 additions & 26 deletions topics/client-auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,33 @@ Typical usage scenarios include logging in users and gaining access to specific

> On the server, Ktor provides the [`Authentication`](server-auth.md) plugin for handling authentication and
> authorization.
>
{style="tip"}

## Supported authentication types {id="supported"}

HTTP provides a [general framework](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication) for access control and authentication. The Ktor client allows you to use the following HTTP authentication schemes:
HTTP provides a [general framework](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication) for access control and authentication. The Ktor client allows you to use the
following HTTP authentication schemes:

* [Basic](client-basic-auth.md) - uses `Base64` encoding to provide a username and password. Generally is not recommended if not used in combination with HTTPS.
* [Digest](client-digest-auth.md) - an authentication method that communicates user credentials in an encrypted form by applying a hash function to the username and password.
* [Bearer](client-bearer-auth.md) - 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.
* [Basic](client-basic-auth.md) - uses `Base64` encoding to provide a username and password. Generally is not recommended if not used
in combination with HTTPS.
* [Digest](client-digest-auth.md) - an authentication method that communicates user credentials in an encrypted form by applying a hash
function to the username and password.
* [Bearer](client-bearer-auth.md) - 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, and X.

## Add dependencies {id="add_dependencies"}

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

<var name="artifact_name" value="ktor-client-auth"/>
<include from="lib.topic" element-id="add_ktor_artifact"/>
<include from="lib.topic" element-id="add_ktor_client_artifact_tip"/>


## Install Auth {id="install_plugin"}

To install the `Auth` plugin, pass it to the `install()` function inside a [client configuration block](client-create-and-configure.md#configure-client):

```kotlin
Expand All @@ -52,17 +60,16 @@ val client = HttpClient(CIO) {
}
}
```
Now you can [configure](#configure_authentication) the required authentication provider.



## Configure authentication {id="configure_authentication"}

### Step 1: Choose an authentication provider {id="choose-provider"}
### Choose an authentication provider {id="choose-provider"}

To use a specific authentication provider ([`basic`](client-basic-auth.md), [`digest`](client-digest-auth.md), or
[`bearer`](client-bearer-auth.md)), you need to call the corresponding function inside the `install {}` block. For example,
to use the `basic` authentication, call the [`basic {}`](https://api.ktor.io/ktor-client-auth/io.ktor.client.plugins.auth.providers/basic.html) function:
[`bearer`](client-bearer-auth.md)), call the corresponding function inside the `install {}` block.

For example, to configure basic authentication, use the [`basic {}`](https://api.ktor.io/ktor-client-auth/io.ktor.client.plugins.auth.providers/basic.html)
function:

```kotlin
install(Auth) {
Expand All @@ -71,10 +78,17 @@ install(Auth) {
}
}
```

Inside the block, you can configure settings specific to this provider.

> For provider-specific settings, see the corresponding topic:
> * [Basic authentication](client-basic-auth.md)
> * [Digest authentication](client-digest-auth.md)
> * [Bearer authentication](client-bearer-auth.md)
>
{style="tip"}

### Step 2: (Optional) Configure the realm {id="realm"}
### Configure the realm {id="realm"}

Optionally, you can configure the realm using the `realm` property:

Expand Down Expand Up @@ -102,21 +116,25 @@ install(Auth) {
}
```

In this case, the client chooses the necessary provider based on the `WWW-Authenticate` response header, which contains the realm.
In this case, the client chooses the necessary provider based on the `WWW-Authenticate` response header,
which contains the realm.

## Provider selection

When a server returns `401 Unauthorized`, the client selects an authentication provider based on the `WWW-Authenticate`
response header. This header specifies which authentication schemes the server accepts.

### Step 3: Configure a provider {id="configure-provider"}
If the client has only one authentication provider installed, the `Auth` plugin always attempts that provider when the
server returns `401 Unauthorized`, even if the `WWW-Authenticate` header is missing or specifies a different scheme.

To learn how to configure settings for a specific [provider](#supported), see a corresponding topic:
* [](client-basic-auth.md)
* [](client-digest-auth.md)
* [](client-bearer-auth.md)
If the client has multiple authentication providers installed, the client selects the provider based on the
`WWW-Authenticate` header.

## Token caching and cache control {id="token-caching"}

The Basic and Bearer authentication providers maintain an internal credential or token cache. This cache allows the
client to reuse previously loaded authentication data instead of reloading it for each request, improving performance
while still allowing full control when credentials change.
The [basic](client-basic-auth.md) and [bearer](client-bearer-auth.md) authentication providers maintain an internal
credential or token cache. This cache allows the client to reuse previously loaded authentication data instead of
reloading it for each request, improving performance while still allowing full control when credentials change.

### Accessing authentication providers

Expand All @@ -137,14 +155,14 @@ These utilities allow you to inspect providers or clear cached tokens programmat

### Clearing cached tokens

To clear cached credentials for a single provider, use the `clearToken()` function:
To clear cached credentials for a single provider, use the `.clearToken()` function:

```kotlin
val provider = client.authProvider<BasicAuthProvider>()
provider?.clearToken()
```

To clear cached tokens across all authentication providers that support cache clearing, use the `clearAuthTokens()`
To clear cached tokens across all authentication providers that support cache clearing, use the `.clearAuthTokens()`
function:

```kotlin
Expand All @@ -153,9 +171,9 @@ client.clearAuthTokens()

Clearing cached tokens is typically used in the following scenarios:

- When the user logs out.
- When credentials or tokens stored by your application change.
- When you need to force providers to reload the authentication state on the next request.
* When the user logs out.
* When credentials or tokens stored by your application change.
* When you need to force providers to reload the authentication state on the next request.

Here's an example for clearing cached tokens when the user logs out:

Expand Down
4 changes: 3 additions & 1 deletion topics/client-basic-auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
<include from="lib.topic" element-id="download_example"/>
</tldr>

The Basic [authentication scheme](client-auth.md) can be used for logging in users. In this scheme, user credentials are transmitted as username/password pairs encoded using Base64.
The basic [authentication scheme](client-auth.md) can be used for logging in users. In this scheme, user credentials are transmitted as username/password pairs encoded using Base64.

> On the server, Ktor provides the [Authentication](server-basic-auth.md) plugin for handling basic authentication.

<include from="client-auth.md" element-id="add_dependencies"/>

## Basic authentication flow {id="flow"}

The basic authentication flow looks as follows:
Expand Down
Loading