or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

basic-authentication.mdbearer-authentication.mddigest-authentication.mdindex.mdplugin-configuration.md

bearer-authentication.mddocs/

0

# Bearer Authentication

1

2

Bearer token authentication provider with support for automatic token refresh, access/refresh token pairs, circuit breaker functionality, and configurable token loading and refresh mechanisms for OAuth flows and API token authentication.

3

4

## Capabilities

5

6

### Bearer Authentication Provider Installation

7

8

Install the Bearer authentication provider with configuration for token management.

9

10

```kotlin { .api }

11

/**

12

* Installs the client's BearerAuthProvider

13

* @param block Configuration block for Bearer authentication

14

*/

15

fun AuthConfig.bearer(block: BearerAuthConfig.() -> Unit)

16

```

17

18

**Usage Example:**

19

20

```kotlin

21

import io.ktor.client.*

22

import io.ktor.client.plugins.auth.*

23

import io.ktor.client.plugins.auth.providers.*

24

25

val client = HttpClient {

26

Auth {

27

bearer {

28

loadTokens {

29

BearerTokens("access_token", "refresh_token")

30

}

31

refreshTokens { params ->

32

// Refresh token logic

33

refreshAccessToken(params.oldTokens?.refreshToken)

34

}

35

}

36

}

37

}

38

```

39

40

### Bearer Authentication Configuration

41

42

Configuration class for BearerAuthProvider with token loading, refreshing, and sending behavior control.

43

44

```kotlin { .api }

45

/**

46

* Configuration for BearerAuthProvider

47

*/

48

class BearerAuthConfig {

49

/**

50

* Optional realm specification for Bearer authentication

51

*/

52

var realm: String?

53

54

/**

55

* Configures a callback that refreshes a token when the 401 status code is received

56

* @param block Suspend function that handles token refresh with refresh parameters

57

*/

58

fun refreshTokens(block: suspend RefreshTokensParams.() -> BearerTokens?)

59

60

/**

61

* Configures a callback that loads a cached token from a local storage

62

* Note: Using the same client instance here to make a request will result in a deadlock

63

* @param block Suspend function that returns cached tokens or null

64

*/

65

fun loadTokens(block: suspend () -> BearerTokens?)

66

67

/**

68

* Configures when to send credentials without waiting for HttpStatusCode.Unauthorized

69

* @param block Function that determines based on request whether to send credentials proactively

70

*/

71

fun sendWithoutRequest(block: (HttpRequestBuilder) -> Boolean)

72

}

73

```

74

75

**Usage Examples:**

76

77

```kotlin

78

bearer {

79

// Load tokens from storage

80

loadTokens {

81

loadTokensFromSecureStorage()

82

}

83

84

// Refresh token logic

85

refreshTokens { params ->

86

val oldRefreshToken = params.oldTokens?.refreshToken

87

if (oldRefreshToken != null) {

88

// Use a different client instance to avoid deadlock

89

val refreshClient = HttpClient()

90

91

// Mark as refresh request to prevent infinite loops

92

val response = refreshClient.post("/oauth/refresh") {

93

markAsRefreshTokenRequest()

94

setBody(RefreshTokenRequest(oldRefreshToken))

95

}

96

97

if (response.status.isSuccess()) {

98

val tokenResponse = response.body<TokenResponse>()

99

BearerTokens(tokenResponse.accessToken, tokenResponse.refreshToken)

100

} else null

101

} else null

102

}

103

104

// Send tokens proactively for API calls

105

sendWithoutRequest { request ->

106

request.url.host == "api.example.com"

107

}

108

109

realm = "api"

110

}

111

```

112

113

### Bearer Tokens

114

115

Container class for Bearer authentication tokens supporting access/refresh token pairs.

116

117

```kotlin { .api }

118

/**

119

* Container for bearer tokens

120

* @param accessToken The access token used for authentication

121

* @param refreshToken Optional refresh token used to obtain new access tokens

122

*/

123

class BearerTokens(

124

val accessToken: String,

125

val refreshToken: String?

126

)

127

```

128

129

### Refresh Token Parameters

130

131

Parameters passed to the token refresh callback providing context for the refresh operation.

132

133

```kotlin { .api }

134

/**

135

* Parameters passed to refreshTokens lambda

136

* @param client HttpClient instance for making refresh requests

137

* @param response HttpResponse that triggered the token refresh

138

* @param oldTokens Previously cached tokens, may be null

139

*/

140

class RefreshTokensParams(

141

val client: HttpClient,

142

val response: HttpResponse,

143

val oldTokens: BearerTokens?

144

) {

145

/**

146

* Marks that this request is for refreshing auth tokens, resulting in special handling

147

* This prevents the request from triggering additional authentication flows

148

*/

149

fun HttpRequestBuilder.markAsRefreshTokenRequest()

150

}

151

```

152

153

**Usage Example:**

154

155

```kotlin

156

refreshTokens { params ->

157

val refreshToken = params.oldTokens?.refreshToken

158

if (refreshToken != null) {

159

try {

160

// Create separate client for refresh to avoid deadlock

161

val refreshClient = HttpClient()

162

163

val response = refreshClient.post("/auth/refresh") {

164

// Important: mark as refresh request

165

markAsRefreshTokenRequest()

166

167

header("Authorization", "Bearer $refreshToken")

168

contentType(ContentType.Application.Json)

169

setBody(mapOf("refresh_token" to refreshToken))

170

}

171

172

if (response.status.isSuccess()) {

173

val newTokens = response.body<TokenResponse>()

174

BearerTokens(newTokens.access_token, newTokens.refresh_token)

175

} else {

176

null // Refresh failed

177

}

178

} catch (e: Exception) {

179

null // Handle refresh errors

180

}

181

} else {

182

null // No refresh token available

183

}

184

}

185

```

186

187

### Bearer Authentication Provider

188

189

Authentication provider implementation for the Bearer HTTP authentication scheme supporting OAuth flows and API token authentication.

190

191

```kotlin { .api }

192

/**

193

* Authentication provider for the Bearer HTTP authentication scheme

194

* Bearer authentication involves security tokens called bearer tokens

195

* These tokens can be used as part of OAuth flow to authorize users of your application

196

* by using external providers, such as Google, Facebook, Twitter, and so on

197

*/

198

class BearerAuthProvider(

199

private val refreshTokens: suspend RefreshTokensParams.() -> BearerTokens?,

200

loadTokens: suspend () -> BearerTokens?,

201

private val sendWithoutRequestCallback: (HttpRequestBuilder) -> Boolean = { true },

202

private val realm: String?

203

) : AuthProvider {

204

205

// Note: clearToken() method is available but marked as @InternalAPI

206

207

override fun sendWithoutRequest(request: HttpRequestBuilder): Boolean

208

override fun isApplicable(auth: HttpAuthHeader): Boolean

209

override suspend fun addRequestHeaders(request: HttpRequestBuilder, authHeader: HttpAuthHeader?)

210

override suspend fun refreshToken(response: HttpResponse): Boolean

211

}

212

```

213

214

**Usage Examples:**

215

216

```kotlin

217

import io.ktor.client.*

218

import io.ktor.client.plugins.auth.*

219

import io.ktor.client.plugins.auth.providers.*

220

221

// Simple bearer token setup

222

val client = HttpClient {

223

Auth {

224

bearer {

225

loadTokens {

226

BearerTokens("my-access-token", null)

227

}

228

}

229

}

230

}

231

232

// OAuth flow with refresh tokens

233

val oauthClient = HttpClient {

234

Auth {

235

bearer {

236

loadTokens {

237

// Load from secure storage

238

val tokens = secureStorage.getTokens()

239

if (tokens != null) {

240

BearerTokens(tokens.accessToken, tokens.refreshToken)

241

} else null

242

}

243

244

refreshTokens { params ->

245

val refreshToken = params.oldTokens?.refreshToken

246

if (refreshToken != null) {

247

val refreshClient = HttpClient()

248

249

val response = refreshClient.post("https://oauth.provider.com/token") {

250

markAsRefreshTokenRequest()

251

parameter("grant_type", "refresh_token")

252

parameter("refresh_token", refreshToken)

253

parameter("client_id", "my-client-id")

254

}

255

256

if (response.status.isSuccess()) {

257

val tokenData = response.body<OAuthTokenResponse>()

258

// Cache new tokens

259

secureStorage.saveTokens(tokenData)

260

BearerTokens(tokenData.access_token, tokenData.refresh_token)

261

} else null

262

} else null

263

}

264

265

sendWithoutRequest { request ->

266

// Always send for API requests

267

request.url.host.contains("api.")

268

}

269

}

270

}

271

}

272

273

// Note: clearToken() is available as internal API for clearing cached tokens

274

```

275

276

## Authentication Flow

277

278

1. **Token Loading**: `loadTokens()` is called to retrieve cached tokens

279

2. **Proactive Sending**: If `sendWithoutRequest` returns `true`, Bearer header is added immediately

280

3. **401 Response**: When server responds with 401, provider checks `isApplicable()` for Bearer scheme

281

4. **Realm Matching**: Provider validates realm from WWW-Authenticate header if specified

282

5. **Token Refresh**: `refreshTokens()` is called with refresh parameters

283

6. **Cache Update**: New tokens are cached automatically after successful refresh

284

7. **Retry Request**: Request is retried with new Bearer token

285

8. **Circuit Breaker**: Refresh requests marked with `markAsRefreshTokenRequest()` skip authentication