or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

client-interface.mdconfiguration.mdindex.mdintegration.mdtoken-management.md

token-management.mddocs/

0

# Token Management

1

2

Token container and management functionality providing access to tokens, expiration tracking, and automatic refresh capabilities. The `Tokens` class encapsulates access and refresh tokens along with metadata for intelligent token lifecycle management.

3

4

## Capabilities

5

6

### Tokens Class

7

8

Container class for access and refresh tokens returned from OIDC token grant requests. Provides comprehensive token metadata and expiration tracking capabilities.

9

10

```java { .api }

11

/**

12

* Container for access and refresh tokens with metadata

13

*/

14

public class Tokens {

15

/**

16

* Construct a Tokens instance with full token information

17

* @param accessToken The access token string

18

* @param accessTokenExpiresAt Timestamp when access token expires (epoch seconds)

19

* @param refreshTokenTimeSkewDuration Time skew duration for refresh token operations

20

* @param refreshToken The refresh token string (may be null)

21

* @param refreshTokenExpiresAt Timestamp when refresh token expires (epoch seconds, may be null)

22

* @param grantResponse The complete JSON response from the token grant

23

* @param clientId The client ID used for the token request

24

*/

25

public Tokens(String accessToken, Long accessTokenExpiresAt, Duration refreshTokenTimeSkewDuration,

26

String refreshToken, Long refreshTokenExpiresAt, JsonObject grantResponse, String clientId);

27

28

/**

29

* Get the access token string

30

* @return The access token

31

*/

32

public String getAccessToken();

33

34

/**

35

* Get the refresh token string

36

* @return The refresh token, or null if not available

37

*/

38

public String getRefreshToken();

39

40

/**

41

* Get the client ID used for token acquisition

42

* @return The client ID

43

*/

44

public String getClientId();

45

46

/**

47

* Get a property from the original grant response

48

* @param propertyName Name of the property to retrieve

49

* @return The property value as a String, or null if not found

50

*/

51

public String get(String propertyName);

52

53

/**

54

* Get the access token expiration timestamp

55

* @return Epoch seconds when access token expires, or null if not specified

56

*/

57

public Long getAccessTokenExpiresAt();

58

59

/**

60

* Get the refresh token time skew in seconds

61

* @return Time skew in seconds, or null if not specified

62

*/

63

public Long getRefreshTokenTimeSkew();

64

65

/**

66

* Check if the access token has expired

67

* @return true if access token is expired, false otherwise

68

*/

69

public boolean isAccessTokenExpired();

70

71

/**

72

* Check if the refresh token has expired

73

* @return true if refresh token is expired, false otherwise

74

*/

75

public boolean isRefreshTokenExpired();

76

77

/**

78

* Check if access token should be proactively refreshed

79

* Considers the refresh interval and time skew to determine if token

80

* should be refreshed before it actually expires

81

* @return true if token should be refreshed, false otherwise

82

*/

83

public boolean isAccessTokenWithinRefreshInterval();

84

}

85

```

86

87

**Usage Examples:**

88

89

```java

90

import io.quarkus.oidc.client.Tokens;

91

import io.quarkus.oidc.client.OidcClient;

92

import io.smallrye.mutiny.Uni;

93

import jakarta.enterprise.context.ApplicationScoped;

94

import jakarta.inject.Inject;

95

import java.time.Instant;

96

97

@ApplicationScoped

98

public class TokenManager {

99

100

@Inject

101

OidcClient oidcClient;

102

103

public void manageTokens() {

104

// Get initial tokens

105

Uni<Tokens> tokensUni = oidcClient.getTokens();

106

107

tokensUni.subscribe().with(tokens -> {

108

// Access token information

109

String accessToken = tokens.getAccessToken();

110

Long expiresAt = tokens.getAccessTokenExpiresAt();

111

112

System.out.println("Access token: " + accessToken);

113

System.out.println("Expires at: " +

114

(expiresAt != null ? Instant.ofEpochSecond(expiresAt) : "Never"));

115

116

// Check token status

117

if (tokens.isAccessTokenExpired()) {

118

System.out.println("Access token has expired");

119

} else if (tokens.isAccessTokenWithinRefreshInterval()) {

120

System.out.println("Access token should be refreshed soon");

121

122

// Refresh token if available

123

String refreshToken = tokens.getRefreshToken();

124

if (refreshToken != null && !tokens.isRefreshTokenExpired()) {

125

Uni<Tokens> refreshedTokens = oidcClient.refreshTokens(refreshToken);

126

// Handle refreshed tokens...

127

}

128

}

129

130

// Access additional properties from grant response

131

String scope = tokens.get("scope");

132

String tokenType = tokens.get("token_type");

133

System.out.println("Scope: " + scope);

134

System.out.println("Token type: " + tokenType);

135

});

136

}

137

}

138

```

139

140

### Token Lifecycle Management

141

142

Comprehensive example showing token lifecycle management with automatic refresh and error handling.

143

144

```java

145

import io.quarkus.oidc.client.Tokens;

146

import io.quarkus.oidc.client.OidcClient;

147

import io.quarkus.oidc.client.OidcClientException;

148

import io.smallrye.mutiny.Uni;

149

import jakarta.enterprise.context.ApplicationScoped;

150

import jakarta.inject.Inject;

151

import java.time.Instant;

152

import java.util.concurrent.atomic.AtomicReference;

153

154

@ApplicationScoped

155

public class TokenLifecycleManager {

156

157

@Inject

158

OidcClient oidcClient;

159

160

private final AtomicReference<Tokens> currentTokens = new AtomicReference<>();

161

162

/**

163

* Get a valid access token, refreshing if necessary

164

*/

165

public Uni<String> getValidAccessToken() {

166

Tokens tokens = currentTokens.get();

167

168

if (tokens == null) {

169

// No tokens yet, get initial tokens

170

return obtainInitialTokens();

171

} else if (tokens.isAccessTokenExpired()) {

172

// Token expired, must refresh

173

return refreshTokens(tokens);

174

} else if (tokens.isAccessTokenWithinRefreshInterval()) {

175

// Token should be refreshed proactively

176

return refreshTokensProactively(tokens);

177

} else {

178

// Token is still valid

179

return Uni.createFrom().item(tokens.getAccessToken());

180

}

181

}

182

183

private Uni<String> obtainInitialTokens() {

184

return oidcClient.getTokens()

185

.onItem().invoke(tokens -> {

186

currentTokens.set(tokens);

187

logTokenInfo("Obtained initial tokens", tokens);

188

})

189

.map(Tokens::getAccessToken)

190

.onFailure().invoke(throwable ->

191

System.err.println("Failed to obtain initial tokens: " + throwable.getMessage())

192

);

193

}

194

195

private Uni<String> refreshTokens(Tokens expiredTokens) {

196

String refreshToken = expiredTokens.getRefreshToken();

197

198

if (refreshToken == null || expiredTokens.isRefreshTokenExpired()) {

199

// No refresh token or refresh token expired, get new tokens

200

return obtainInitialTokens();

201

}

202

203

return oidcClient.refreshTokens(refreshToken)

204

.onItem().invoke(tokens -> {

205

currentTokens.set(tokens);

206

logTokenInfo("Refreshed expired tokens", tokens);

207

})

208

.map(Tokens::getAccessToken)

209

.onFailure().recoverWithUni(throwable -> {

210

System.err.println("Token refresh failed: " + throwable.getMessage());

211

// Fall back to getting new tokens

212

return obtainInitialTokens();

213

});

214

}

215

216

private Uni<String> refreshTokensProactively(Tokens currentTokens) {

217

String refreshToken = currentTokens.getRefreshToken();

218

219

if (refreshToken != null && !currentTokens.isRefreshTokenExpired()) {

220

return oidcClient.refreshTokens(refreshToken)

221

.onItem().invoke(tokens -> {

222

this.currentTokens.set(tokens);

223

logTokenInfo("Proactively refreshed tokens", tokens);

224

})

225

.map(Tokens::getAccessToken)

226

.onFailure().recoverWithItem(throwable -> {

227

System.err.println("Proactive refresh failed, using current token: " +

228

throwable.getMessage());

229

// Fall back to current token if proactive refresh fails

230

return currentTokens.getAccessToken();

231

});

232

} else {

233

// No refresh token available, use current access token

234

return Uni.createFrom().item(currentTokens.getAccessToken());

235

}

236

}

237

238

private void logTokenInfo(String action, Tokens tokens) {

239

Long expiresAt = tokens.getAccessTokenExpiresAt();

240

String expirationInfo = expiresAt != null ?

241

Instant.ofEpochSecond(expiresAt).toString() : "Never";

242

243

System.out.println(String.format(

244

"%s - Client: %s, Expires: %s, Has refresh: %s",

245

action,

246

tokens.getClientId(),

247

expirationInfo,

248

tokens.getRefreshToken() != null

249

));

250

}

251

252

/**

253

* Revoke current tokens and clear cache

254

*/

255

public Uni<Void> revokeAndClearTokens() {

256

Tokens tokens = currentTokens.getAndSet(null);

257

258

if (tokens != null) {

259

return oidcClient.revokeAccessToken(tokens.getAccessToken())

260

.onItem().invoke(revoked -> {

261

if (revoked) {

262

System.out.println("Tokens revoked and cleared");

263

} else {

264

System.out.println("Token revocation may need to be retried");

265

}

266

})

267

.onFailure().invoke(throwable ->

268

System.err.println("Failed to revoke tokens: " + throwable.getMessage())

269

)

270

.replaceWithVoid();

271

} else {

272

return Uni.createFrom().voidItem();

273

}

274

}

275

}

276

```

277

278

### Token Expiration Strategies

279

280

Different strategies for handling token expiration based on application requirements.

281

282

```java

283

/**

284

* Conservative strategy - refresh tokens well before expiration

285

*/

286

public boolean shouldRefreshConservative(Tokens tokens) {

287

if (tokens.isAccessTokenExpired()) {

288

return true; // Must refresh

289

}

290

291

Long expiresAt = tokens.getAccessTokenExpiresAt();

292

if (expiresAt != null) {

293

long now = Instant.now().getEpochSecond();

294

long timeToExpiry = expiresAt - now;

295

296

// Refresh if less than 5 minutes remaining

297

return timeToExpiry < 300;

298

}

299

300

return false;

301

}

302

303

/**

304

* Aggressive strategy - refresh tokens just before expiration

305

*/

306

public boolean shouldRefreshAggressive(Tokens tokens) {

307

if (tokens.isAccessTokenExpired()) {

308

return true; // Must refresh

309

}

310

311

Long expiresAt = tokens.getAccessTokenExpiresAt();

312

if (expiresAt != null) {

313

long now = Instant.now().getEpochSecond();

314

long timeToExpiry = expiresAt - now;

315

316

// Refresh if less than 30 seconds remaining

317

return timeToExpiry < 30;

318

}

319

320

return false;

321

}

322

323

/**

324

* Use built-in strategy with configured time skew

325

*/

326

public boolean shouldRefreshBuiltIn(Tokens tokens) {

327

return tokens.isAccessTokenWithinRefreshInterval();

328

}

329

```