or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-security.mdauthorization-flows.mdclient-authentication.mdconfiguration.mdgrant-types.mdindex.mdpassport-integration.mdprotected-resources.mdtoken-management.md

grant-types.mddocs/

0

# Grant Types

1

2

Complete implementation of OAuth 2.0 and OpenID Connect grant types including Client Credentials, Refresh Token, Device Authorization, Client-Initiated Backchannel Authentication (CIBA), and generic grant support.

3

4

## Capabilities

5

6

### Client Credentials Grant

7

8

Obtain access tokens using client credentials for machine-to-machine authentication.

9

10

```typescript { .api }

11

/**

12

* Execute Client Credentials Grant

13

* @param config - Configuration instance

14

* @param parameters - Additional parameters (scope, resource, etc.)

15

* @param options - Grant options (DPoP, etc.)

16

* @returns Promise resolving to token response with helpers

17

*/

18

function clientCredentialsGrant(

19

config: Configuration,

20

parameters?: URLSearchParams | Record<string, string>,

21

options?: DPoPOptions

22

): Promise<TokenEndpointResponse & TokenEndpointResponseHelpers>;

23

```

24

25

**Usage Examples:**

26

27

```typescript

28

import * as client from "openid-client";

29

30

// Basic client credentials grant

31

const tokens = await client.clientCredentialsGrant(config);

32

33

// With scope and resource parameters

34

const tokens = await client.clientCredentialsGrant(config, {

35

scope: "read:users write:users",

36

resource: "https://api.example.com"

37

});

38

39

// With multiple resources (resource indicators)

40

const tokens = await client.clientCredentialsGrant(config, {

41

scope: "api:access",

42

resource: ["https://api1.example.com", "https://api2.example.com"]

43

});

44

45

console.log("Access Token:", tokens.access_token);

46

console.log("Token Type:", tokens.token_type);

47

console.log("Expires In:", tokens.expiresIn(), "seconds");

48

```

49

50

### Refresh Token Grant

51

52

Exchange refresh tokens for new access tokens.

53

54

```typescript { .api }

55

/**

56

* Execute Refresh Token Grant

57

* @param config - Configuration instance

58

* @param refreshToken - Refresh token to exchange

59

* @param parameters - Additional parameters (scope, resource, etc.)

60

* @param options - Grant options (DPoP, etc.)

61

* @returns Promise resolving to token response with helpers

62

*/

63

function refreshTokenGrant(

64

config: Configuration,

65

refreshToken: string,

66

parameters?: URLSearchParams | Record<string, string>,

67

options?: DPoPOptions

68

): Promise<TokenEndpointResponse & TokenEndpointResponseHelpers>;

69

```

70

71

**Usage Examples:**

72

73

```typescript

74

import * as client from "openid-client";

75

76

// Basic refresh token grant

77

const newTokens = await client.refreshTokenGrant(

78

config,

79

existingTokens.refresh_token

80

);

81

82

// With scope parameter (potentially reducing scope)

83

const newTokens = await client.refreshTokenGrant(

84

config,

85

existingTokens.refresh_token,

86

{

87

scope: "read:profile" // reduced from original scope

88

}

89

);

90

91

// With resource indicators

92

const newTokens = await client.refreshTokenGrant(

93

config,

94

existingTokens.refresh_token,

95

{

96

resource: "https://api.example.com",

97

scope: "api:read api:write"

98

}

99

);

100

101

// Check if refresh token was rotated

102

if (newTokens.refresh_token && newTokens.refresh_token !== existingTokens.refresh_token) {

103

console.log("Refresh token was rotated");

104

// Store new refresh token

105

}

106

```

107

108

### Device Authorization Grant

109

110

Implement device flow for input-constrained devices.

111

112

```typescript { .api }

113

/**

114

* Initiate Device Authorization Grant

115

* @param config - Configuration instance

116

* @param parameters - Authorization request parameters

117

* @returns Promise resolving to device authorization response

118

*/

119

function initiateDeviceAuthorization(

120

config: Configuration,

121

parameters: URLSearchParams | Record<string, string>

122

): Promise<DeviceAuthorizationResponse>;

123

124

/**

125

* Poll for Device Authorization Grant completion

126

* @param config - Configuration instance

127

* @param deviceAuthorizationResponse - Response from initiateDeviceAuthorization

128

* @param parameters - Additional token endpoint parameters

129

* @param options - Polling options

130

* @returns Promise resolving to token response when authorized

131

*/

132

function pollDeviceAuthorizationGrant(

133

config: Configuration,

134

deviceAuthorizationResponse: DeviceAuthorizationResponse,

135

parameters?: URLSearchParams | Record<string, string>,

136

options?: DeviceAuthorizationGrantPollOptions

137

): Promise<TokenEndpointResponse & TokenEndpointResponseHelpers>;

138

```

139

140

**Usage Examples:**

141

142

```typescript

143

import * as client from "openid-client";

144

145

// Initiate device flow

146

const deviceResponse = await client.initiateDeviceAuthorization(config, {

147

scope: "openid profile email"

148

});

149

150

// Display user instructions

151

console.log("Go to:", deviceResponse.verification_uri);

152

console.log("Enter code:", deviceResponse.user_code);

153

154

// Or use complete URI if available

155

if (deviceResponse.verification_uri_complete) {

156

console.log("Or visit:", deviceResponse.verification_uri_complete);

157

}

158

159

// Poll for completion

160

try {

161

const tokens = await client.pollDeviceAuthorizationGrant(

162

config,

163

deviceResponse

164

);

165

166

console.log("Device authorized!");

167

console.log("Access Token:", tokens.access_token);

168

console.log("ID Token Claims:", tokens.claims());

169

} catch (error) {

170

if (error.error === "access_denied") {

171

console.log("User denied the request");

172

} else if (error.error === "expired_token") {

173

console.log("Device code expired");

174

}

175

}

176

177

// Poll with timeout and additional parameters

178

const tokens = await client.pollDeviceAuthorizationGrant(

179

config,

180

deviceResponse,

181

{ resource: "https://api.example.com" }, // additional parameters

182

{

183

signal: AbortSignal.timeout(300000) // 5 minute timeout

184

}

185

);

186

```

187

188

### Client-Initiated Backchannel Authentication (CIBA)

189

190

Implement CIBA flow for authentication without user interaction on the requesting device.

191

192

```typescript { .api }

193

/**

194

* Initiate CIBA flow

195

* @param config - Configuration instance

196

* @param parameters - CIBA request parameters (must include one of login_hint, id_token_hint, or login_hint_token)

197

* @returns Promise resolving to backchannel authentication response

198

*/

199

function initiateBackchannelAuthentication(

200

config: Configuration,

201

parameters: URLSearchParams | Record<string, string>

202

): Promise<BackchannelAuthenticationResponse>;

203

204

/**

205

* Poll for CIBA completion

206

* @param config - Configuration instance

207

* @param backchannelAuthenticationResponse - Response from initiateBackchannelAuthentication

208

* @param parameters - Additional token endpoint parameters

209

* @param options - Polling options

210

* @returns Promise resolving to token response when authenticated

211

*/

212

function pollBackchannelAuthenticationGrant(

213

config: Configuration,

214

backchannelAuthenticationResponse: BackchannelAuthenticationResponse,

215

parameters?: URLSearchParams | Record<string, string>,

216

options?: BackchannelAuthenticationGrantPollOptions

217

): Promise<TokenEndpointResponse & TokenEndpointResponseHelpers>;

218

```

219

220

**Usage Examples:**

221

222

```typescript

223

import * as client from "openid-client";

224

225

// Initiate CIBA with login hint

226

const cibaResponse = await client.initiateBackchannelAuthentication(config, {

227

scope: "openid profile email",

228

login_hint: "user@example.com",

229

binding_message: "Please confirm transaction #12345"

230

});

231

232

console.log("Authentication initiated. Auth req ID:", cibaResponse.auth_req_id);

233

234

// Poll for completion (for poll mode)

235

try {

236

const tokens = await client.pollBackchannelAuthenticationGrant(

237

config,

238

cibaResponse

239

);

240

241

console.log("User authenticated!");

242

console.log("Access Token:", tokens.access_token);

243

console.log("ID Token Claims:", tokens.claims());

244

} catch (error) {

245

if (error.error === "access_denied") {

246

console.log("User denied authentication");

247

} else if (error.error === "expired_token") {

248

console.log("Authentication request expired");

249

}

250

}

251

252

// With ID token hint instead of login hint

253

const cibaResponse = await client.initiateBackchannelAuthentication(config, {

254

scope: "openid profile",

255

id_token_hint: previousIdToken,

256

user_code: "USER123" // optional user code for verification

257

});

258

```

259

260

### Generic Grant Request

261

262

Execute any OAuth 2.0 grant type including custom grants.

263

264

```typescript { .api }

265

/**

266

* Execute generic grant request

267

* @param config - Configuration instance

268

* @param grantType - Grant type identifier

269

* @param parameters - Grant-specific parameters

270

* @param options - Grant options (DPoP, etc.)

271

* @returns Promise resolving to token response with helpers

272

*/

273

function genericGrantRequest(

274

config: Configuration,

275

grantType: string,

276

parameters: URLSearchParams | Record<string, string>,

277

options?: DPoPOptions

278

): Promise<TokenEndpointResponse & TokenEndpointResponseHelpers>;

279

```

280

281

**Usage Examples:**

282

283

```typescript

284

import * as client from "openid-client";

285

286

// JWT Bearer Token Grant (RFC 7523)

287

const tokens = await client.genericGrantRequest(

288

config,

289

"urn:ietf:params:oauth:grant-type:jwt-bearer",

290

{

291

assertion: jwtAssertion,

292

scope: "api:access",

293

resource: "https://api.example.com"

294

}

295

);

296

297

// SAML 2.0 Bearer Assertion Grant (RFC 7522)

298

const tokens = await client.genericGrantRequest(

299

config,

300

"urn:ietf:params:oauth:grant-type:saml2-bearer",

301

{

302

assertion: samlAssertion,

303

scope: "read write"

304

}

305

);

306

307

// Token Exchange Grant (RFC 8693)

308

const tokens = await client.genericGrantRequest(

309

config,

310

"urn:ietf:params:oauth:grant-type:token-exchange",

311

{

312

subject_token: accessToken,

313

subject_token_type: "urn:ietf:params:oauth:token-type:access_token",

314

resource: "https://api.example.com",

315

audience: "https://api.example.com"

316

}

317

);

318

319

// Custom grant type

320

const tokens = await client.genericGrantRequest(

321

config,

322

"urn:example:custom-grant",

323

{

324

custom_parameter: "value",

325

scope: "custom:access"

326

}

327

);

328

```

329

330

## Grant Response Types

331

332

```typescript { .api }

333

interface DeviceAuthorizationResponse {

334

device_code: string;

335

user_code: string;

336

verification_uri: string;

337

verification_uri_complete?: string;

338

expires_in: number;

339

interval?: number;

340

}

341

342

interface BackchannelAuthenticationResponse {

343

auth_req_id: string;

344

expires_in: number;

345

interval?: number;

346

}

347

348

interface DeviceAuthorizationGrantPollOptions extends DPoPOptions {

349

/** AbortSignal to stop polling */

350

signal?: AbortSignal;

351

}

352

353

interface BackchannelAuthenticationGrantPollOptions extends DPoPOptions {

354

/** AbortSignal to stop polling */

355

signal?: AbortSignal;

356

}

357

```

358

359

## Token Response Helpers

360

361

```typescript { .api }

362

interface TokenEndpointResponse {

363

access_token: string;

364

token_type: string;

365

expires_in?: number;

366

refresh_token?: string;

367

scope?: string;

368

id_token?: string;

369

// Additional server-specific properties may be present

370

}

371

372

interface TokenEndpointResponseHelpers {

373

/**

374

* Parse ID Token claims (if present)

375

* @returns ID Token claims or undefined

376

*/

377

claims(): IDToken | undefined;

378

379

/**

380

* Calculate seconds until token expiration

381

* @returns Seconds until expiration or undefined

382

*/

383

expiresIn(): number | undefined;

384

}

385

```

386

387

## DPoP Support

388

389

All grant types support DPoP (Demonstrating Proof-of-Possession) for sender-constrained tokens:

390

391

```typescript { .api }

392

interface DPoPOptions {

393

/** DPoP handle for proof-of-possession */

394

DPoP?: DPoPHandle;

395

}

396

```

397

398

**Usage with DPoP:**

399

400

```typescript

401

import * as client from "openid-client";

402

403

// Create DPoP key pair

404

const dpopKeyPair = await client.randomDPoPKeyPair();

405

const dpopHandle = client.getDPoPHandle(config, dpopKeyPair);

406

407

// Use with any grant

408

const tokens = await client.clientCredentialsGrant(

409

config,

410

{ scope: "api:access" },

411

{ DPoP: dpopHandle }

412

);

413

414

// Token will be sender-constrained if server supports DPoP

415

if (tokens.token_type === "dpop") {

416

console.log("Token is sender-constrained with DPoP");

417

}

418

```