or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication.mddriver-management.mderror-handling.mdgraph-types.mdindex.mdreactive-programming.mdsession-operations.mdtemporal-types.mdtransaction-management.md

authentication.mddocs/

0

# Authentication

1

2

Comprehensive authentication system supporting basic, Kerberos, bearer token, and custom authentication methods.

3

4

## Capabilities

5

6

### Authentication Token Creation

7

8

Factory functions for creating authentication tokens for different authentication schemes.

9

10

```typescript { .api }

11

declare const auth: {

12

/**

13

* Create basic authentication token

14

* @param username - Username for authentication

15

* @param password - Password for authentication

16

* @param realm - Optional authentication realm

17

* @returns AuthToken for basic authentication

18

*/

19

basic(username: string, password: string, realm?: string): AuthToken;

20

21

/**

22

* Create Kerberos authentication token

23

* @param base64EncodedTicket - Base64 encoded Kerberos ticket

24

* @returns AuthToken for Kerberos authentication

25

*/

26

kerberos(base64EncodedTicket: string): AuthToken;

27

28

/**

29

* Create bearer token authentication

30

* @param base64EncodedToken - Base64 encoded bearer token

31

* @returns AuthToken for bearer token authentication

32

*/

33

bearer(base64EncodedToken: string): AuthToken;

34

35

/**

36

* Create custom authentication token

37

* @param principal - Authentication principal (username)

38

* @param credentials - Authentication credentials (password/token)

39

* @param realm - Authentication realm

40

* @param scheme - Custom authentication scheme

41

* @param parameters - Additional authentication parameters

42

* @returns AuthToken for custom authentication

43

*/

44

custom(

45

principal: string,

46

credentials: string,

47

realm: string,

48

scheme: string,

49

parameters?: Parameters

50

): AuthToken;

51

};

52

```

53

54

**Usage Examples:**

55

56

```typescript

57

import { driver, auth } from "neo4j-driver";

58

59

// Basic authentication (most common)

60

const basicDriver = driver(

61

"neo4j://localhost:7687",

62

auth.basic("neo4j", "password")

63

);

64

65

// Basic authentication with realm

66

const realmDriver = driver(

67

"neo4j://localhost:7687",

68

auth.basic("username", "password", "my-realm")

69

);

70

71

// Kerberos authentication

72

const kerberosTicket = "YII..."; // Base64 encoded Kerberos ticket

73

const kerberosDriver = driver(

74

"neo4j://localhost:7687",

75

auth.kerberos(kerberosTicket)

76

);

77

78

// Bearer token authentication

79

const bearerToken = "eyJ..."; // Base64 encoded JWT or similar

80

const bearerDriver = driver(

81

"neo4j://localhost:7687",

82

auth.bearer(bearerToken)

83

);

84

85

// Custom authentication

86

const customDriver = driver(

87

"neo4j://localhost:7687",

88

auth.custom("principal", "credentials", "realm", "custom-scheme", {

89

applicationId: "myapp",

90

version: "1.0"

91

})

92

);

93

94

// No authentication (for testing)

95

const noAuthDriver = driver(

96

"neo4j://localhost:7687",

97

auth.basic("", "", "")

98

);

99

```

100

101

### Authentication Token Interface

102

103

Structure of authentication tokens used by the driver.

104

105

```typescript { .api }

106

interface AuthToken {

107

/** Authentication scheme (basic, kerberos, bearer, custom, etc.) */

108

scheme: string;

109

110

/** Authentication principal (username) */

111

principal: string;

112

113

/** Authentication credentials (password, token, etc.) */

114

credentials: string;

115

116

/** Optional authentication realm */

117

realm?: string;

118

119

/** Additional authentication parameters */

120

parameters?: Record<string, any>;

121

}

122

```

123

124

**Usage Examples:**

125

126

```typescript

127

// Manually creating auth tokens (usually not needed)

128

const manualAuthToken: AuthToken = {

129

scheme: "basic",

130

principal: "neo4j",

131

credentials: "password",

132

realm: "neo4j"

133

};

134

135

const manualDriver = driver("neo4j://localhost:7687", manualAuthToken);

136

137

// Inspecting auth tokens (for debugging)

138

const authToken = auth.basic("user", "pass");

139

console.log(`Scheme: ${authToken.scheme}`); // "basic"

140

console.log(`Principal: ${authToken.principal}`); // "user"

141

console.log(`Has realm: ${!!authToken.realm}`); // false

142

```

143

144

### Authentication Token Managers

145

146

Advanced authentication with token management and automatic refresh capabilities.

147

148

```typescript { .api }

149

interface AuthTokenManager {

150

/**

151

* Get authentication token (called by driver as needed)

152

* @returns Promise resolving to auth token with optional expiration

153

*/

154

getToken(): Promise<AuthTokenAndExpiration>;

155

156

/**

157

* Handle security exceptions (e.g., token expired)

158

* @param authToken - The token that caused the security exception

159

* @param securityException - The security exception that occurred

160

* @returns true if the token was handled and retry should occur

161

*/

162

handleSecurityException(

163

authToken: AuthToken,

164

securityException: any

165

): Promise<boolean>;

166

}

167

168

interface AuthTokenAndExpiration {

169

/** The authentication token */

170

authToken: AuthToken;

171

172

/** Optional expiration time in milliseconds since epoch */

173

expiration?: number;

174

}

175

176

interface AuthTokenManagers {

177

/** Create a static auth token manager (no refresh) */

178

static(config: { authToken: AuthToken }): AuthTokenManager;

179

180

/** Create a bearer auth token manager with refresh capability */

181

bearer(config: BearerAuthTokenManagerConfig): AuthTokenManager;

182

183

/** Create a basic auth token manager */

184

basic(config: BasicAuthTokenManagerConfig): AuthTokenManager;

185

}

186

187

declare const authTokenManagers: AuthTokenManagers;

188

```

189

190

**Usage Examples:**

191

192

```typescript

193

import { driver, authTokenManagers, auth } from "neo4j-driver";

194

195

// Static auth token manager (simple wrapper)

196

const staticManager = authTokenManagers.static({

197

authToken: auth.basic("neo4j", "password")

198

});

199

200

const staticDriver = driver("neo4j://localhost:7687", staticManager);

201

202

// Bearer token manager with refresh

203

const bearerManager = authTokenManagers.bearer({

204

tokenProvider: async () => {

205

// Fetch fresh token from your auth service

206

const response = await fetch("/api/auth/token", {

207

method: "POST",

208

headers: { "Content-Type": "application/json" },

209

body: JSON.stringify({ userId: "current-user" })

210

});

211

212

const data = await response.json();

213

return {

214

authToken: auth.bearer(data.token),

215

expiration: Date.now() + (data.expiresIn * 1000)

216

};

217

}

218

});

219

220

const bearerDriver = driver("neo4j://localhost:7687", bearerManager);

221

222

// Custom auth token manager

223

class CustomAuthTokenManager implements AuthTokenManager {

224

private currentToken?: AuthToken;

225

private expiration?: number;

226

227

async getToken(): Promise<AuthTokenAndExpiration> {

228

// Check if current token is still valid

229

if (this.currentToken && this.expiration && Date.now() < this.expiration) {

230

return {

231

authToken: this.currentToken,

232

expiration: this.expiration

233

};

234

}

235

236

// Refresh token

237

const newToken = await this.refreshToken();

238

this.currentToken = newToken.authToken;

239

this.expiration = newToken.expiration;

240

241

return newToken;

242

}

243

244

async handleSecurityException(authToken: AuthToken, exception: any): Promise<boolean> {

245

console.log("Security exception occurred:", exception.message);

246

247

// Clear cached token to force refresh on next getToken call

248

this.currentToken = undefined;

249

this.expiration = undefined;

250

251

// Return true to indicate the driver should retry with a new token

252

return true;

253

}

254

255

private async refreshToken(): Promise<AuthTokenAndExpiration> {

256

// Your token refresh logic here

257

const response = await fetch("/api/auth/refresh", { method: "POST" });

258

const data = await response.json();

259

260

return {

261

authToken: auth.bearer(data.accessToken),

262

expiration: Date.now() + (data.expiresIn * 1000)

263

};

264

}

265

}

266

267

const customManager = new CustomAuthTokenManager();

268

const customDriver = driver("neo4j://localhost:7687", customManager);

269

```

270

271

### Static Auth Token Manager

272

273

Utility for creating static auth token managers.

274

275

```typescript { .api }

276

/**

277

* Create a static auth token manager from an auth token

278

* @param config - Configuration containing the auth token

279

* @returns AuthTokenManager that always returns the same token

280

*/

281

function staticAuthTokenManager(config: { authToken: AuthToken }): AuthTokenManager;

282

```

283

284

**Usage Examples:**

285

286

```typescript

287

import { driver, auth, staticAuthTokenManager } from "neo4j-driver";

288

289

// Create static manager directly

290

const manager = staticAuthTokenManager({

291

authToken: auth.basic("neo4j", "password")

292

});

293

294

const driverWithManager = driver("neo4j://localhost:7687", manager);

295

296

// Equivalent to using auth token directly

297

const directDriver = driver(

298

"neo4j://localhost:7687",

299

auth.basic("neo4j", "password")

300

);

301

302

// Static manager is useful when you need to pass an AuthTokenManager interface

303

function createDriverWithManager(authManager: AuthTokenManager) {

304

return driver("neo4j://localhost:7687", authManager);

305

}

306

307

const driver1 = createDriverWithManager(

308

staticAuthTokenManager({ authToken: auth.basic("user1", "pass1") })

309

);

310

311

const driver2 = createDriverWithManager(

312

staticAuthTokenManager({ authToken: auth.bearer("token123") })

313

);

314

```

315

316

### Session-Level Authentication

317

318

Override authentication at the session level for impersonation or multi-tenant scenarios.

319

320

```typescript { .api }

321

interface SessionConfig {

322

/** Session-level authentication override */

323

auth?: AuthToken | AuthTokenManager;

324

325

/** User to impersonate for this session */

326

impersonatedUser?: string;

327

328

// ... other session config properties

329

}

330

```

331

332

**Usage Examples:**

333

334

```typescript

335

// Driver with default authentication

336

const mainDriver = driver(

337

"neo4j://localhost:7687",

338

auth.basic("admin", "admin-password")

339

);

340

341

// Session with different authentication

342

const userSession = mainDriver.session({

343

auth: auth.basic("regular-user", "user-password"),

344

database: "userdata"

345

});

346

347

// Session with impersonation (requires Neo4j Enterprise)

348

const impersonatedSession = mainDriver.session({

349

impersonatedUser: "john.doe@company.com",

350

database: "analytics"

351

});

352

353

// Session with token manager override

354

const tokenManager = authTokenManagers.bearer({

355

tokenProvider: async () => ({

356

authToken: auth.bearer(await getUserToken("session-user")),

357

expiration: Date.now() + 3600000 // 1 hour

358

})

359

});

360

361

const tokenSession = mainDriver.session({

362

auth: tokenManager,

363

database: "reporting"

364

});

365

366

try {

367

// Use sessions with different authentication contexts

368

const userResult = await userSession.run("MATCH (n:UserData) RETURN count(n) AS count");

369

const impersonatedResult = await impersonatedSession.run("MATCH (n:Analytics) RETURN count(n) AS count");

370

const tokenResult = await tokenSession.run("MATCH (n:Report) RETURN count(n) AS count");

371

372

console.log(`User data: ${userResult.records[0].get("count")}`);

373

console.log(`Analytics: ${impersonatedResult.records[0].get("count")}`);

374

console.log(`Reports: ${tokenResult.records[0].get("count")}`);

375

} finally {

376

await userSession.close();

377

await impersonatedSession.close();

378

await tokenSession.close();

379

}

380

```

381

382

### Authentication Best Practices

383

384

**Security Considerations:**

385

386

```typescript

387

// Good: Use environment variables for credentials

388

const driver = driver(

389

process.env.NEO4J_URI || "neo4j://localhost:7687",

390

auth.basic(

391

process.env.NEO4J_USERNAME || "neo4j",

392

process.env.NEO4J_PASSWORD || ""

393

)

394

);

395

396

// Good: Use token managers for rotating credentials

397

const refreshingManager = authTokenManagers.bearer({

398

tokenProvider: async () => {

399

const token = await getTokenFromSecureStorage();

400

return {

401

authToken: auth.bearer(token.value),

402

expiration: token.expiresAt

403

};

404

}

405

});

406

407

// Good: Handle authentication errors gracefully

408

try {

409

const session = driver.session();

410

const result = await session.run("RETURN 1");

411

await session.close();

412

} catch (error) {

413

if (error.code === "Neo.ClientError.Security.Unauthorized") {

414

console.error("Authentication failed - check credentials");

415

// Trigger credential refresh or user re-authentication

416

} else {

417

console.error("Other error:", error.message);

418

}

419

}

420

421

// Avoid: Hardcoding credentials in source code

422

const badDriver = driver(

423

"neo4j://localhost:7687",

424

auth.basic("neo4j", "hardcoded-password") // Don't do this!

425

);

426

427

// Avoid: Logging authentication tokens

428

const authToken = auth.basic("user", "password");

429

console.log(authToken); // This logs the password!

430

```

431

432

**Token Refresh Patterns:**

433

434

```typescript

435

// Proactive token refresh

436

class ProactiveTokenManager implements AuthTokenManager {

437

private token?: AuthTokenAndExpiration;

438

private refreshPromise?: Promise<AuthTokenAndExpiration>;

439

440

async getToken(): Promise<AuthTokenAndExpiration> {

441

// If token expires in less than 5 minutes, refresh it

442

const refreshThreshold = 5 * 60 * 1000; // 5 minutes

443

444

if (!this.token ||

445

(this.token.expiration && this.token.expiration - Date.now() < refreshThreshold)) {

446

447

// Ensure only one refresh happens at a time

448

if (!this.refreshPromise) {

449

this.refreshPromise = this.refreshToken();

450

}

451

452

this.token = await this.refreshPromise;

453

this.refreshPromise = undefined;

454

}

455

456

return this.token;

457

}

458

459

async handleSecurityException(): Promise<boolean> {

460

// Force immediate refresh on security exception

461

this.token = undefined;

462

this.refreshPromise = undefined;

463

return true;

464

}

465

466

private async refreshToken(): Promise<AuthTokenAndExpiration> {

467

// Your token refresh implementation

468

const response = await fetch("/api/token/refresh", { method: "POST" });

469

const data = await response.json();

470

471

return {

472

authToken: auth.bearer(data.token),

473

expiration: Date.now() + (data.expiresIn * 1000)

474

};

475

}

476

}

477

```