The official Neo4j driver for JavaScript applications, enabling connection to and interaction with Neo4j graph databases.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Comprehensive authentication system supporting basic, Kerberos, bearer token, and custom authentication methods.
Factory functions for creating authentication tokens for different authentication schemes.
declare const auth: {
/**
* Create basic authentication token
* @param username - Username for authentication
* @param password - Password for authentication
* @param realm - Optional authentication realm
* @returns AuthToken for basic authentication
*/
basic(username: string, password: string, realm?: string): AuthToken;
/**
* Create Kerberos authentication token
* @param base64EncodedTicket - Base64 encoded Kerberos ticket
* @returns AuthToken for Kerberos authentication
*/
kerberos(base64EncodedTicket: string): AuthToken;
/**
* Create bearer token authentication
* @param base64EncodedToken - Base64 encoded bearer token
* @returns AuthToken for bearer token authentication
*/
bearer(base64EncodedToken: string): AuthToken;
/**
* Create custom authentication token
* @param principal - Authentication principal (username)
* @param credentials - Authentication credentials (password/token)
* @param realm - Authentication realm
* @param scheme - Custom authentication scheme
* @param parameters - Additional authentication parameters
* @returns AuthToken for custom authentication
*/
custom(
principal: string,
credentials: string,
realm: string,
scheme: string,
parameters?: Parameters
): AuthToken;
};Usage Examples:
import { driver, auth } from "neo4j-driver";
// Basic authentication (most common)
const basicDriver = driver(
"neo4j://localhost:7687",
auth.basic("neo4j", "password")
);
// Basic authentication with realm
const realmDriver = driver(
"neo4j://localhost:7687",
auth.basic("username", "password", "my-realm")
);
// Kerberos authentication
const kerberosTicket = "YII..."; // Base64 encoded Kerberos ticket
const kerberosDriver = driver(
"neo4j://localhost:7687",
auth.kerberos(kerberosTicket)
);
// Bearer token authentication
const bearerToken = "eyJ..."; // Base64 encoded JWT or similar
const bearerDriver = driver(
"neo4j://localhost:7687",
auth.bearer(bearerToken)
);
// Custom authentication
const customDriver = driver(
"neo4j://localhost:7687",
auth.custom("principal", "credentials", "realm", "custom-scheme", {
applicationId: "myapp",
version: "1.0"
})
);
// No authentication (for testing)
const noAuthDriver = driver(
"neo4j://localhost:7687",
auth.basic("", "", "")
);Structure of authentication tokens used by the driver.
interface AuthToken {
/** Authentication scheme (basic, kerberos, bearer, custom, etc.) */
scheme: string;
/** Authentication principal (username) */
principal: string;
/** Authentication credentials (password, token, etc.) */
credentials: string;
/** Optional authentication realm */
realm?: string;
/** Additional authentication parameters */
parameters?: Record<string, any>;
}Usage Examples:
// Manually creating auth tokens (usually not needed)
const manualAuthToken: AuthToken = {
scheme: "basic",
principal: "neo4j",
credentials: "password",
realm: "neo4j"
};
const manualDriver = driver("neo4j://localhost:7687", manualAuthToken);
// Inspecting auth tokens (for debugging)
const authToken = auth.basic("user", "pass");
console.log(`Scheme: ${authToken.scheme}`); // "basic"
console.log(`Principal: ${authToken.principal}`); // "user"
console.log(`Has realm: ${!!authToken.realm}`); // falseAdvanced authentication with token management and automatic refresh capabilities.
interface AuthTokenManager {
/**
* Get authentication token (called by driver as needed)
* @returns Promise resolving to auth token with optional expiration
*/
getToken(): Promise<AuthTokenAndExpiration>;
/**
* Handle security exceptions (e.g., token expired)
* @param authToken - The token that caused the security exception
* @param securityException - The security exception that occurred
* @returns true if the token was handled and retry should occur
*/
handleSecurityException(
authToken: AuthToken,
securityException: any
): Promise<boolean>;
}
interface AuthTokenAndExpiration {
/** The authentication token */
authToken: AuthToken;
/** Optional expiration time in milliseconds since epoch */
expiration?: number;
}
interface AuthTokenManagers {
/** Create a static auth token manager (no refresh) */
static(config: { authToken: AuthToken }): AuthTokenManager;
/** Create a bearer auth token manager with refresh capability */
bearer(config: BearerAuthTokenManagerConfig): AuthTokenManager;
/** Create a basic auth token manager */
basic(config: BasicAuthTokenManagerConfig): AuthTokenManager;
}
declare const authTokenManagers: AuthTokenManagers;Usage Examples:
import { driver, authTokenManagers, auth } from "neo4j-driver";
// Static auth token manager (simple wrapper)
const staticManager = authTokenManagers.static({
authToken: auth.basic("neo4j", "password")
});
const staticDriver = driver("neo4j://localhost:7687", staticManager);
// Bearer token manager with refresh
const bearerManager = authTokenManagers.bearer({
tokenProvider: async () => {
// Fetch fresh token from your auth service
const response = await fetch("/api/auth/token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ userId: "current-user" })
});
const data = await response.json();
return {
authToken: auth.bearer(data.token),
expiration: Date.now() + (data.expiresIn * 1000)
};
}
});
const bearerDriver = driver("neo4j://localhost:7687", bearerManager);
// Custom auth token manager
class CustomAuthTokenManager implements AuthTokenManager {
private currentToken?: AuthToken;
private expiration?: number;
async getToken(): Promise<AuthTokenAndExpiration> {
// Check if current token is still valid
if (this.currentToken && this.expiration && Date.now() < this.expiration) {
return {
authToken: this.currentToken,
expiration: this.expiration
};
}
// Refresh token
const newToken = await this.refreshToken();
this.currentToken = newToken.authToken;
this.expiration = newToken.expiration;
return newToken;
}
async handleSecurityException(authToken: AuthToken, exception: any): Promise<boolean> {
console.log("Security exception occurred:", exception.message);
// Clear cached token to force refresh on next getToken call
this.currentToken = undefined;
this.expiration = undefined;
// Return true to indicate the driver should retry with a new token
return true;
}
private async refreshToken(): Promise<AuthTokenAndExpiration> {
// Your token refresh logic here
const response = await fetch("/api/auth/refresh", { method: "POST" });
const data = await response.json();
return {
authToken: auth.bearer(data.accessToken),
expiration: Date.now() + (data.expiresIn * 1000)
};
}
}
const customManager = new CustomAuthTokenManager();
const customDriver = driver("neo4j://localhost:7687", customManager);Utility for creating static auth token managers.
/**
* Create a static auth token manager from an auth token
* @param config - Configuration containing the auth token
* @returns AuthTokenManager that always returns the same token
*/
function staticAuthTokenManager(config: { authToken: AuthToken }): AuthTokenManager;Usage Examples:
import { driver, auth, staticAuthTokenManager } from "neo4j-driver";
// Create static manager directly
const manager = staticAuthTokenManager({
authToken: auth.basic("neo4j", "password")
});
const driverWithManager = driver("neo4j://localhost:7687", manager);
// Equivalent to using auth token directly
const directDriver = driver(
"neo4j://localhost:7687",
auth.basic("neo4j", "password")
);
// Static manager is useful when you need to pass an AuthTokenManager interface
function createDriverWithManager(authManager: AuthTokenManager) {
return driver("neo4j://localhost:7687", authManager);
}
const driver1 = createDriverWithManager(
staticAuthTokenManager({ authToken: auth.basic("user1", "pass1") })
);
const driver2 = createDriverWithManager(
staticAuthTokenManager({ authToken: auth.bearer("token123") })
);Override authentication at the session level for impersonation or multi-tenant scenarios.
interface SessionConfig {
/** Session-level authentication override */
auth?: AuthToken | AuthTokenManager;
/** User to impersonate for this session */
impersonatedUser?: string;
// ... other session config properties
}Usage Examples:
// Driver with default authentication
const mainDriver = driver(
"neo4j://localhost:7687",
auth.basic("admin", "admin-password")
);
// Session with different authentication
const userSession = mainDriver.session({
auth: auth.basic("regular-user", "user-password"),
database: "userdata"
});
// Session with impersonation (requires Neo4j Enterprise)
const impersonatedSession = mainDriver.session({
impersonatedUser: "john.doe@company.com",
database: "analytics"
});
// Session with token manager override
const tokenManager = authTokenManagers.bearer({
tokenProvider: async () => ({
authToken: auth.bearer(await getUserToken("session-user")),
expiration: Date.now() + 3600000 // 1 hour
})
});
const tokenSession = mainDriver.session({
auth: tokenManager,
database: "reporting"
});
try {
// Use sessions with different authentication contexts
const userResult = await userSession.run("MATCH (n:UserData) RETURN count(n) AS count");
const impersonatedResult = await impersonatedSession.run("MATCH (n:Analytics) RETURN count(n) AS count");
const tokenResult = await tokenSession.run("MATCH (n:Report) RETURN count(n) AS count");
console.log(`User data: ${userResult.records[0].get("count")}`);
console.log(`Analytics: ${impersonatedResult.records[0].get("count")}`);
console.log(`Reports: ${tokenResult.records[0].get("count")}`);
} finally {
await userSession.close();
await impersonatedSession.close();
await tokenSession.close();
}Security Considerations:
// Good: Use environment variables for credentials
const driver = driver(
process.env.NEO4J_URI || "neo4j://localhost:7687",
auth.basic(
process.env.NEO4J_USERNAME || "neo4j",
process.env.NEO4J_PASSWORD || ""
)
);
// Good: Use token managers for rotating credentials
const refreshingManager = authTokenManagers.bearer({
tokenProvider: async () => {
const token = await getTokenFromSecureStorage();
return {
authToken: auth.bearer(token.value),
expiration: token.expiresAt
};
}
});
// Good: Handle authentication errors gracefully
try {
const session = driver.session();
const result = await session.run("RETURN 1");
await session.close();
} catch (error) {
if (error.code === "Neo.ClientError.Security.Unauthorized") {
console.error("Authentication failed - check credentials");
// Trigger credential refresh or user re-authentication
} else {
console.error("Other error:", error.message);
}
}
// Avoid: Hardcoding credentials in source code
const badDriver = driver(
"neo4j://localhost:7687",
auth.basic("neo4j", "hardcoded-password") // Don't do this!
);
// Avoid: Logging authentication tokens
const authToken = auth.basic("user", "password");
console.log(authToken); // This logs the password!Token Refresh Patterns:
// Proactive token refresh
class ProactiveTokenManager implements AuthTokenManager {
private token?: AuthTokenAndExpiration;
private refreshPromise?: Promise<AuthTokenAndExpiration>;
async getToken(): Promise<AuthTokenAndExpiration> {
// If token expires in less than 5 minutes, refresh it
const refreshThreshold = 5 * 60 * 1000; // 5 minutes
if (!this.token ||
(this.token.expiration && this.token.expiration - Date.now() < refreshThreshold)) {
// Ensure only one refresh happens at a time
if (!this.refreshPromise) {
this.refreshPromise = this.refreshToken();
}
this.token = await this.refreshPromise;
this.refreshPromise = undefined;
}
return this.token;
}
async handleSecurityException(): Promise<boolean> {
// Force immediate refresh on security exception
this.token = undefined;
this.refreshPromise = undefined;
return true;
}
private async refreshToken(): Promise<AuthTokenAndExpiration> {
// Your token refresh implementation
const response = await fetch("/api/token/refresh", { method: "POST" });
const data = await response.json();
return {
authToken: auth.bearer(data.token),
expiration: Date.now() + (data.expiresIn * 1000)
};
}
}