or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

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

integration.mddocs/

0

# Integration

1

2

CDI injection support, JAX-RS client filter integration, and SPI interfaces for extending OIDC client functionality. Provides seamless integration with Quarkus's dependency injection system and REST client ecosystem.

3

4

## Capabilities

5

6

### CDI Integration

7

8

Dependency injection support for OIDC clients using standard CDI annotations and custom qualifiers for named clients.

9

10

```java { .api }

11

/**

12

* CDI qualifier annotation for injecting named OIDC clients

13

*/

14

@Qualifier

15

@Retention(RUNTIME)

16

@Target({FIELD, PARAMETER, METHOD})

17

public @interface NamedOidcClient {

18

/**

19

* Name of the OIDC client to inject

20

* @return Client name as configured in application properties

21

*/

22

String value();

23

}

24

```

25

26

**Usage Examples:**

27

28

```java

29

import io.quarkus.oidc.client.OidcClient;

30

import io.quarkus.oidc.client.OidcClients;

31

import io.quarkus.oidc.client.NamedOidcClient;

32

import jakarta.inject.Inject;

33

import jakarta.enterprise.context.ApplicationScoped;

34

35

@ApplicationScoped

36

public class TokenService {

37

38

// Inject default OIDC client

39

@Inject

40

OidcClient defaultClient;

41

42

// Inject OIDC clients factory

43

@Inject

44

OidcClients oidcClients;

45

46

// Inject named OIDC client using qualifier

47

@Inject

48

@NamedOidcClient("auth-provider")

49

OidcClient authProviderClient;

50

51

// Inject named OIDC client for API access

52

@Inject

53

@NamedOidcClient("api-client")

54

OidcClient apiClient;

55

56

public void useInjectedClients() {

57

// Use default client

58

Uni<Tokens> defaultTokens = defaultClient.getTokens();

59

60

// Use named clients

61

Uni<Tokens> authTokens = authProviderClient.getTokens();

62

Uni<Tokens> apiTokens = apiClient.getTokens();

63

64

// Use factory for dynamic client access

65

OidcClient dynamicClient = oidcClients.getClient("dynamic-provider");

66

Uni<Tokens> dynamicTokens = dynamicClient.getTokens();

67

}

68

}

69

```

70

71

**Configuration for Named Clients:**

72

73

```properties

74

# Default client

75

quarkus.oidc-client.auth-server-url=https://default.example.com

76

quarkus.oidc-client.client-id=default-client

77

quarkus.oidc-client.credentials.secret=default-secret

78

79

# Named client: auth-provider

80

quarkus.oidc-client.auth-provider.auth-server-url=https://auth.example.com

81

quarkus.oidc-client.auth-provider.client-id=auth-client

82

quarkus.oidc-client.auth-provider.credentials.secret=auth-secret

83

84

# Named client: api-client

85

quarkus.oidc-client.api-client.auth-server-url=https://api.example.com

86

quarkus.oidc-client.api-client.client-id=api-client

87

quarkus.oidc-client.api-client.credentials.secret=api-secret

88

quarkus.oidc-client.api-client.grant.type=client

89

```

90

91

### JAX-RS Integration

92

93

Automatic token injection for REST clients using filter annotations. Enables seamless authentication for outbound HTTP requests.

94

95

```java { .api }

96

/**

97

* Annotation for JAX-RS client filters to automatically inject OIDC tokens

98

*/

99

@Target({TYPE})

100

@Retention(RUNTIME)

101

public @interface OidcClientFilter {

102

/**

103

* Name of the OIDC client to use for token acquisition

104

* Empty string uses the default client

105

* @return OIDC client name

106

*/

107

String value() default "";

108

}

109

```

110

111

**Usage Examples:**

112

113

```java

114

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

115

import io.quarkus.oidc.client.filter.OidcClientFilter;

116

import jakarta.ws.rs.GET;

117

import jakarta.ws.rs.Path;

118

import jakarta.ws.rs.Produces;

119

import jakarta.ws.rs.core.MediaType;

120

121

// REST client using default OIDC client

122

@RegisterRestClient(configKey = "api-service")

123

@OidcClientFilter

124

@Path("/api")

125

public interface ApiServiceClient {

126

127

@GET

128

@Path("/users")

129

@Produces(MediaType.APPLICATION_JSON)

130

List<User> getUsers();

131

132

@GET

133

@Path("/protected-resource")

134

@Produces(MediaType.APPLICATION_JSON)

135

ProtectedData getProtectedData();

136

}

137

138

// REST client using named OIDC client

139

@RegisterRestClient(configKey = "admin-service")

140

@OidcClientFilter("admin-client")

141

@Path("/admin")

142

public interface AdminServiceClient {

143

144

@GET

145

@Path("/config")

146

@Produces(MediaType.APPLICATION_JSON)

147

AdminConfig getConfig();

148

149

@POST

150

@Path("/users")

151

@Consumes(MediaType.APPLICATION_JSON)

152

void createUser(User user);

153

}

154

```

155

156

**Service Usage:**

157

158

```java

159

import org.eclipse.microprofile.rest.client.inject.RestClient;

160

import jakarta.inject.Inject;

161

import jakarta.enterprise.context.ApplicationScoped;

162

163

@ApplicationScoped

164

public class BusinessService {

165

166

@Inject

167

@RestClient

168

ApiServiceClient apiClient;

169

170

@Inject

171

@RestClient

172

AdminServiceClient adminClient;

173

174

public void performBusinessOperations() {

175

// These calls will automatically include OIDC tokens

176

List<User> users = apiClient.getUsers(); // Uses default client

177

AdminConfig config = adminClient.getConfig(); // Uses admin-client

178

179

// Process data...

180

}

181

}

182

```

183

184

**REST Client Configuration:**

185

186

```properties

187

# API service client configuration

188

quarkus.rest-client.api-service.url=https://api.example.com

189

quarkus.rest-client.api-service.connection-timeout=5000

190

quarkus.rest-client.api-service.read-timeout=10000

191

192

# Admin service client configuration

193

quarkus.rest-client.admin-service.url=https://admin.example.com

194

quarkus.rest-client.admin-service.connection-timeout=3000

195

quarkus.rest-client.admin-service.read-timeout=15000

196

197

# OIDC clients for the filters

198

quarkus.oidc-client.auth-server-url=https://auth.example.com

199

quarkus.oidc-client.client-id=api-client

200

quarkus.oidc-client.credentials.secret=api-secret

201

202

quarkus.oidc-client.admin-client.auth-server-url=https://admin-auth.example.com

203

quarkus.oidc-client.admin-client.client-id=admin-client

204

quarkus.oidc-client.admin-client.credentials.secret=admin-secret

205

```

206

207

### SPI Integration

208

209

Service Provider Interface for custom token providers and OIDC client extensions.

210

211

```java { .api }

212

/**

213

* SPI interface for OIDC clients that can acquire and refresh access tokens automatically

214

*/

215

public interface TokenProvider {

216

/**

217

* Get a valid access token

218

* Implementations should handle token refresh automatically if needed

219

* @return Uni<String> containing a valid access token

220

*/

221

Uni<String> getAccessToken();

222

}

223

```

224

225

**Usage Examples:**

226

227

```java

228

import io.quarkus.oidc.client.spi.TokenProvider;

229

import io.quarkus.oidc.client.OidcClient;

230

import io.smallrye.mutiny.Uni;

231

import jakarta.enterprise.context.ApplicationScoped;

232

import jakarta.inject.Inject;

233

234

/**

235

* Custom token provider implementation

236

*/

237

@ApplicationScoped

238

public class CustomTokenProvider implements TokenProvider {

239

240

@Inject

241

OidcClient oidcClient;

242

243

private volatile String cachedToken;

244

private volatile long tokenExpiresAt;

245

246

@Override

247

public Uni<String> getAccessToken() {

248

// Check if cached token is still valid

249

if (cachedToken != null && System.currentTimeMillis() < tokenExpiresAt) {

250

return Uni.createFrom().item(cachedToken);

251

}

252

253

// Get new token

254

return oidcClient.getTokens()

255

.onItem().invoke(tokens -> {

256

cachedToken = tokens.getAccessToken();

257

258

// Cache for 90% of the token lifetime

259

Long expiresAt = tokens.getAccessTokenExpiresAt();

260

if (expiresAt != null) {

261

long now = System.currentTimeMillis() / 1000;

262

long lifetime = expiresAt - now;

263

tokenExpiresAt = (now + (long)(lifetime * 0.9)) * 1000;

264

} else {

265

// Default to 1 hour if no expiration provided

266

tokenExpiresAt = System.currentTimeMillis() + 3600000;

267

}

268

})

269

.map(tokens -> tokens.getAccessToken());

270

}

271

}

272

273

/**

274

* Service using custom token provider

275

*/

276

@ApplicationScoped

277

public class SecureService {

278

279

@Inject

280

TokenProvider tokenProvider;

281

282

public Uni<String> callProtectedApi() {

283

return tokenProvider.getAccessToken()

284

.flatMap(token -> {

285

// Use token to call protected API

286

return callApiWithToken(token);

287

});

288

}

289

290

private Uni<String> callApiWithToken(String token) {

291

// Implementation for calling API with token

292

// ...

293

return Uni.createFrom().item("API response");

294

}

295

}

296

```

297

298

### Advanced Integration Patterns

299

300

Complex integration scenarios combining multiple OIDC clients and advanced token management.

301

302

```java

303

import io.quarkus.oidc.client.OidcClient;

304

import io.quarkus.oidc.client.OidcClients;

305

import io.quarkus.oidc.client.NamedOidcClient;

306

import io.quarkus.oidc.client.spi.TokenProvider;

307

import jakarta.enterprise.context.ApplicationScoped;

308

import jakarta.inject.Inject;

309

import java.util.Map;

310

import java.util.concurrent.ConcurrentHashMap;

311

312

/**

313

* Multi-tenant token provider supporting different OIDC providers per tenant

314

*/

315

@ApplicationScoped

316

public class MultiTenantTokenProvider implements TokenProvider {

317

318

@Inject

319

OidcClients oidcClients;

320

321

private final Map<String, String> tenantTokens = new ConcurrentHashMap<>();

322

323

public Uni<String> getAccessTokenForTenant(String tenantId) {

324

// Get tenant-specific OIDC client

325

OidcClient tenantClient = oidcClients.getClient(tenantId);

326

327

return tenantClient.getTokens()

328

.onItem().invoke(tokens -> {

329

tenantTokens.put(tenantId, tokens.getAccessToken());

330

})

331

.map(tokens -> tokens.getAccessToken());

332

}

333

334

@Override

335

public Uni<String> getAccessToken() {

336

// Default implementation for single-tenant scenarios

337

return oidcClients.getClient().getTokens()

338

.map(tokens -> tokens.getAccessToken());

339

}

340

}

341

342

/**

343

* Token refresh service with circuit breaker pattern

344

*/

345

@ApplicationScoped

346

public class RobustTokenService {

347

348

@Inject

349

@NamedOidcClient("primary")

350

OidcClient primaryClient;

351

352

@Inject

353

@NamedOidcClient("fallback")

354

OidcClient fallbackClient;

355

356

private volatile boolean primaryHealthy = true;

357

private volatile long lastFailureTime = 0;

358

private static final long CIRCUIT_BREAKER_TIMEOUT = 60000; // 1 minute

359

360

public Uni<String> getAccessTokenWithFallback() {

361

if (primaryHealthy || shouldTryPrimary()) {

362

return primaryClient.getTokens()

363

.onItem().invoke(() -> {

364

primaryHealthy = true;

365

})

366

.onFailure().invoke(throwable -> {

367

primaryHealthy = false;

368

lastFailureTime = System.currentTimeMillis();

369

})

370

.onFailure().recoverWithUni(throwable -> {

371

System.err.println("Primary client failed, using fallback: " +

372

throwable.getMessage());

373

return fallbackClient.getTokens();

374

})

375

.map(tokens -> tokens.getAccessToken());

376

} else {

377

return fallbackClient.getTokens()

378

.map(tokens -> tokens.getAccessToken());

379

}

380

}

381

382

private boolean shouldTryPrimary() {

383

return System.currentTimeMillis() - lastFailureTime > CIRCUIT_BREAKER_TIMEOUT;

384

}

385

}

386

```