@archie/auth0-user-security
v0.1.7
Published
Enterprise-grade Auth0 user security library for Node.js applications
Readme
@archie/auth0-user-security
A framework-agnostic TypeScript library for managing Auth0 user security operations including session management, authentication methods, and account linking.
Features
- Session Management: List, revoke, and manage user sessions
- Authentication Methods: List and manage connected authentication providers
- Account Linking: Connect and disconnect secondary authentication methods
- Password Management: Generate secure password change tickets
- Framework Agnostic: Core service works with any Node.js framework
- TypeScript Support: Fully typed with comprehensive type definitions
- Enterprise Ready: Built with enterprise-grade patterns and error handling
Installation
npm install @archie/auth0-user-security
# or
yarn add @archie/auth0-user-security
# or
pnpm add @archie/auth0-user-securityPrerequisites
Auth0 Configuration
Before using this library, you need to configure your Auth0 tenant with the following:
Create a Machine to Machine Application:
- Go to Auth0 Dashboard > Applications > Create Application
- Choose "Machine to Machine Applications"
- Select your API and grant the following scopes:
read:usersupdate:usersdelete:usersread:user_idp_tokenscreate:user_tickets
Configure Social Connections (optional):
- Go to Auth0 Dashboard > Authentication > Social
- Enable the providers you want to support (Google, GitHub, Microsoft, Apple)
Basic Usage
import { Auth0UserSecurityService } from "@archie/auth0-user-security";
// Initialize the service
const userSecurityService = new Auth0UserSecurityService({
domain: "your-tenant.auth0.com",
clientId: "your-client-id",
clientSecret: "your-client-secret",
audience: "your-api-audience",
});
// List user sessions
const sessions = await userSecurityService.findUserSessions("user123");
// Revoke a specific session
await userSecurityService.revokeUserSession("user123", "sessionId");
// Generate password change ticket
const ticket =
await userSecurityService.generatePasswordChangeTicket("user123");Usage Examples
Complete Session Management
import {
Auth0UserSecurityService,
UserAuthenticationMethodProvider,
SessionNotFoundError,
UserNotFoundError,
Auth0ApiError,
type IUser,
type UserSession,
type UserSessionRevokeInput,
} from "@archie/auth0-user-security";
const userSecurityService = new Auth0UserSecurityService({
domain: process.env.AUTH0_DOMAIN!,
clientId: process.env.AUTH0_CLIENT_ID!,
clientSecret: process.env.AUTH0_CLIENT_SECRET!,
});
// 1. Find User Sessions - Get all active sessions for a user
async function getUserSessionsWithDetails(userEmail: string) {
try {
const user: IUser = { email: userEmail };
const sessions = await userSecurityService.findUserSessions(user);
console.log(`User ${userEmail} has ${sessions.length} active sessions:`);
sessions.forEach((session, index) => {
console.log(`Session ${index + 1}:`);
console.log(` - ID: ${session.id}`);
console.log(` - Platform: ${session.platform}`);
console.log(` - Name: ${session.name}`);
console.log(` - Address: ${session.address}`);
console.log(` - Last Activity: ${session.lastActivityAt || "Unknown"}`);
});
return sessions;
} catch (error) {
if (error instanceof UserNotFoundError) {
console.error(`User not found: ${userEmail}`);
} else if (error instanceof Auth0ApiError) {
console.error(`Auth0 API error: ${error.message}`);
} else {
console.error("Error fetching user sessions:", error.message);
}
throw error;
}
}
// 2. Revoke User Session - Revoke a specific session
async function revokeSpecificSession(userEmail: string, sessionId: string) {
try {
const user: IUser = { email: userEmail };
const sessionInput: UserSessionRevokeInput = { id: sessionId };
const success = await userSecurityService.revokeUserSession(
user,
sessionInput,
);
if (success) {
console.log(`✅ Session ${sessionId} revoked successfully`);
} else {
console.log(`❌ Failed to revoke session ${sessionId}`);
}
return success;
} catch (error) {
if (error instanceof SessionNotFoundError) {
console.log("Session not found or does not belong to user");
} else if (error instanceof UserNotFoundError) {
console.log("User not found");
} else {
console.error("Error revoking session:", error.message);
}
throw error;
}
}
// 3. Revoke All User Sessions - Revoke all sessions for a user
async function revokeAllUserSessions(userEmail: string) {
try {
const user: IUser = { email: userEmail };
const success = await userSecurityService.revokeAllUserSessions(user);
if (success) {
console.log(`✅ All sessions revoked for user: ${userEmail}`);
} else {
console.log(`❌ Failed to revoke all sessions for user: ${userEmail}`);
}
return success;
} catch (error) {
if (error instanceof UserNotFoundError) {
console.error(`User not found: ${userEmail}`);
} else {
console.error("Error revoking all sessions:", error.message);
}
throw error;
}
}
// 4. Smart Session Management - Revoke all sessions except current
async function revokeAllOtherSessions(
userEmail: string,
currentSessionId?: string,
) {
try {
const user: IUser = { email: userEmail };
const sessions = await userSecurityService.findUserSessions(user);
// If no current session specified, revoke all
const sessionsToRevoke = currentSessionId
? sessions.filter((session) => session.id !== currentSessionId)
: sessions;
let revokedCount = 0;
for (const session of sessionsToRevoke) {
try {
const sessionInput: UserSessionRevokeInput = { id: session.id };
const success = await userSecurityService.revokeUserSession(
user,
sessionInput,
);
if (success) {
console.log(
`Revoked session: ${session.name} on ${session.platform}`,
);
revokedCount++;
}
} catch (error) {
console.warn(`Failed to revoke session ${session.id}:`, error.message);
}
}
console.log(
`✅ Revoked ${revokedCount} out of ${sessionsToRevoke.length} sessions`,
);
return revokedCount;
} catch (error) {
console.error("Error revoking sessions:", error.message);
throw error;
}
}Authentication Methods Management
import {
type UserAuthenticationMethod,
type UserAuthenticationMethodDisconnectInput,
} from "@archie/auth0-user-security";
// 5. Find User Authentication Methods - Get all connected auth methods
async function displayUserAuthMethods(userEmail: string) {
try {
const user: IUser = { email: userEmail };
const methods =
await userSecurityService.findUserAuthenticationMethods(user);
console.log(
`User ${userEmail} has ${methods.length} authentication methods:`,
);
methods.forEach((method, index) => {
console.log(`Method ${index + 1}:`);
console.log(` - ID: ${method.id}`);
console.log(` - Provider: ${method.provider}`);
console.log(` - Username: ${method.username}`);
});
return methods;
} catch (error) {
if (error instanceof UserNotFoundError) {
console.error(`User not found: ${userEmail}`);
} else {
console.error("Error fetching authentication methods:", error.message);
}
throw error;
}
}
// 6. Connect Secondary Account - Link additional auth method
async function connectSecondaryAccount(
userEmail: string,
redirectUri: string,
authorizationCode: string,
) {
try {
const user: IUser = { email: userEmail };
console.log(`Connecting secondary account for user: ${userEmail}`);
const updatedMethods = await userSecurityService.connectSecondaryAccount(
user,
redirectUri,
authorizationCode,
);
console.log("✅ Secondary account connected successfully!");
console.log(
`User now has ${updatedMethods.length} authentication methods:`,
);
updatedMethods.forEach((method, i) => {
console.log(` ${i + 1}. ${method.provider} (${method.username})`);
});
return updatedMethods;
} catch (error) {
if (error instanceof UserNotFoundError) {
console.error(`User not found: ${userEmail}`);
} else {
console.error("Error connecting secondary account:", error.message);
}
throw error;
}
}
// 7. Disconnect Secondary Account - Remove linked auth method
async function disconnectSecondaryAccount(
userEmail: string,
methodId: string,
provider: UserAuthenticationMethodProvider,
) {
try {
const user: IUser = { email: userEmail };
const methodInput: UserAuthenticationMethodDisconnectInput = {
id: methodId,
provider: provider,
};
console.log(`Disconnecting ${provider} account (${methodId})...`);
const updatedMethods = await userSecurityService.disconnectSecondaryAccount(
user,
methodInput,
);
console.log(`✅ ${provider} account disconnected successfully!`);
console.log(`User now has ${updatedMethods.length} authentication methods`);
return updatedMethods;
} catch (error) {
if (error instanceof UserNotFoundError) {
console.error(`User not found: ${userEmail}`);
} else {
console.error(`Error disconnecting ${provider} account:`, error.message);
}
throw error;
}
}
// Helper: Check if user has specific auth method
async function hasAuthenticationMethod(
userEmail: string,
provider: UserAuthenticationMethodProvider,
): Promise<boolean> {
try {
const user: IUser = { email: userEmail };
const methods =
await userSecurityService.findUserAuthenticationMethods(user);
return methods.some((method) => method.provider === provider);
} catch (error) {
console.error("Error checking authentication method:", error.message);
return false;
}
}Password Management
import {
type UserAccountChangePasswordTicket,
type UserAccountConnectionTicket,
ConfigurationError,
} from "@archie/auth0-user-security";
// 8. Generate Password Change Ticket - Create secure password reset URL
async function initiatePasswordChange(userEmail: string, redirectUrl: string) {
try {
const user: IUser = { email: userEmail };
console.log(`Generating password change ticket for user: ${userEmail}`);
const ticket: UserAccountChangePasswordTicket =
await userSecurityService.generatePasswordChangeTicket(user, redirectUrl);
// Send email to user (pseudo-code)
await sendPasswordChangeEmail(userEmail, ticket.redirect);
console.log("✅ Password change ticket generated and sent to user");
console.log(`Ticket URL: ${ticket.redirect}`);
return ticket;
} catch (error) {
if (error instanceof UserNotFoundError) {
console.error(`User not found: ${userEmail}`);
} else if (error instanceof ConfigurationError) {
console.error(`Configuration error: ${error.message}`);
} else {
console.error("Error generating password change ticket:", error.message);
}
throw error;
}
}
// Helper function to send email (implement with your email service)
async function sendPasswordChangeEmail(email: string, ticketUrl: string) {
// Implementation depends on your email service (SendGrid, AWS SES, etc.)
console.log(`📧 Sending password change email to: ${email}`);
console.log(`🔗 Ticket URL: ${ticketUrl}`);
// Example with a generic email service
// await emailService.send({
// to: email,
// subject: 'Password Reset Request',
// html: `
// <h2>Password Reset</h2>
// <p>Click the link below to reset your password:</p>
// <a href="${ticketUrl}">Reset Password</a>
// <p>This link will expire in 24 hours.</p>
// `
// });
}Account Connection URL Generation
// 9. Generate Account Connection URL - Create OAuth connection URL
function generateAccountConnectionUrl(
provider: UserAuthenticationMethodProvider,
redirectUrl: string,
) {
try {
console.log(`Generating connection URL for ${provider}...`);
const ticket: UserAccountConnectionTicket =
userSecurityService.generateAccountConnectionUrl(provider, redirectUrl);
console.log(`✅ Connection URL generated for ${provider}`);
console.log(`🔗 Redirect URL: ${ticket.redirect}`);
console.log(`📱 Provider: ${ticket.provider}`);
return ticket;
} catch (error) {
if (error instanceof ConfigurationError) {
console.error(`Configuration error: ${error.message}`);
} else {
console.error(
`Error generating connection URL for ${provider}:`,
error.message,
);
}
throw error;
}
}
// Complete OAuth flow example
async function completeOAuthFlow(
userEmail: string,
provider: UserAuthenticationMethodProvider,
callbackUrl: string,
) {
try {
// Step 1: Generate connection URL
const ticket = generateAccountConnectionUrl(provider, callbackUrl);
console.log(`\n🚀 Step 1: Visit this URL to connect ${provider}:`);
console.log(ticket.redirect);
// Step 2: After user completes OAuth, you'll receive authorization code in your callback
// This would typically be handled by your web server callback endpoint
console.log(`\n⏳ Step 2: Waiting for OAuth callback...`);
console.log(
`Your callback endpoint should receive: ${callbackUrl}?code=AUTHORIZATION_CODE`,
);
// Step 3: Use the authorization code to link accounts (this would be in your callback handler)
// const authCode = 'received-from-callback';
// const methods = await connectSecondaryAccount(userEmail, callbackUrl, authCode);
return ticket;
} catch (error) {
console.error("Error in OAuth flow:", error.message);
throw error;
}
}Complete User Security Dashboard
// 10. Complete Security Dashboard - Get all user security info
async function getUserSecurityDashboard(userEmail: string) {
try {
const user: IUser = { email: userEmail };
console.log("=== User Security Dashboard ===");
console.log(`👤 User: ${userEmail}`);
// Get sessions
const sessions = await userSecurityService.findUserSessions(user);
console.log(`\n📱 Active Sessions: ${sessions.length}`);
if (sessions.length > 0) {
sessions.forEach((session, i) => {
console.log(` ${i + 1}. ${session.name} on ${session.platform}`);
console.log(` IP: ${session.address}`);
console.log(
` Last Activity: ${session.lastActivityAt || "Unknown"}`,
);
});
} else {
console.log(" No active sessions found");
}
// Get authentication methods
const methods =
await userSecurityService.findUserAuthenticationMethods(user);
console.log(`\n🔐 Authentication Methods: ${methods.length}`);
if (methods.length > 0) {
methods.forEach((method, i) => {
console.log(` ${i + 1}. ${method.provider} (${method.username})`);
});
} else {
console.log(" No authentication methods found");
}
// Security summary
console.log(`\n📊 Security Summary:`);
console.log(` - Total Sessions: ${sessions.length}`);
console.log(` - Total Auth Methods: ${methods.length}`);
console.log(
` - Has Social Auth: ${methods.some((m) => m.provider !== "email-password") ? "Yes" : "No"}`,
);
console.log(
` - Primary Auth: ${methods.find((m) => m.provider === "email-password") ? "Email/Password" : "Social Only"}`,
);
return {
user: userEmail,
sessions,
methods,
summary: {
totalSessions: sessions.length,
totalAuthMethods: methods.length,
hasSocialAuth: methods.some((m) => m.provider !== "email-password"),
hasPrimaryAuth: methods.some((m) => m.provider === "email-password"),
},
};
} catch (error) {
if (error instanceof UserNotFoundError) {
console.error(`User not found: ${userEmail}`);
} else {
console.error("Error fetching user security dashboard:", error.message);
}
throw error;
}
}Bulk Operations and Advanced Examples
// Bulk session management for multiple users
async function bulkRevokeUserSessions(userEmails: string[]) {
const results = [];
console.log(
`🔄 Processing ${userEmails.length} users for session revocation...`,
);
for (const userEmail of userEmails) {
try {
const user: IUser = { email: userEmail };
const success = await userSecurityService.revokeAllUserSessions(user);
results.push({
userEmail,
status: success ? "success" : "failed",
timestamp: new Date().toISOString(),
});
console.log(`✅ Revoked all sessions for user: ${userEmail}`);
} catch (error) {
results.push({
userEmail,
status: "error",
error: error.message,
timestamp: new Date().toISOString(),
});
console.log(
`❌ Failed to revoke sessions for user: ${userEmail} - ${error.message}`,
);
}
}
const successCount = results.filter((r) => r.status === "success").length;
console.log(`\n📊 Bulk Operation Summary:`);
console.log(` - Total Users: ${userEmails.length}`);
console.log(` - Successful: ${successCount}`);
console.log(` - Failed: ${userEmails.length - successCount}`);
return results;
}
// Security audit report with detailed analysis
async function generateSecurityAuditReport(userEmails: string[]) {
const report = {
generatedAt: new Date().toISOString(),
totalUsers: userEmails.length,
totalSessions: 0,
totalAuthMethods: 0,
userDetails: [],
statistics: {
usersWithMultipleSessions: 0,
usersWithSocialAuth: 0,
usersWithEmailPasswordOnly: 0,
averageSessionsPerUser: 0,
averageAuthMethodsPerUser: 0,
mostCommonProviders: {},
},
};
console.log(`🔍 Generating security audit for ${userEmails.length} users...`);
for (const userEmail of userEmails) {
try {
const user: IUser = { email: userEmail };
const [sessions, methods] = await Promise.all([
userSecurityService.findUserSessions(user),
userSecurityService.findUserAuthenticationMethods(user),
]);
report.totalSessions += sessions.length;
report.totalAuthMethods += methods.length;
// Update statistics
if (sessions.length > 1) report.statistics.usersWithMultipleSessions++;
if (methods.some((m) => m.provider !== "email-password"))
report.statistics.usersWithSocialAuth++;
if (methods.every((m) => m.provider === "email-password"))
report.statistics.usersWithEmailPasswordOnly++;
// Count providers
methods.forEach((method) => {
report.statistics.mostCommonProviders[method.provider] =
(report.statistics.mostCommonProviders[method.provider] || 0) + 1;
});
report.userDetails.push({
userEmail,
sessionsCount: sessions.length,
authMethodsCount: methods.length,
providers: methods.map((m) => m.provider),
hasSocialAuth: methods.some((m) => m.provider !== "email-password"),
lastActivity: sessions.length > 0 ? sessions[0].lastActivityAt : null,
riskLevel: calculateRiskLevel(sessions, methods),
});
console.log(`✅ Processed user: ${userEmail}`);
} catch (error) {
console.error(`❌ Error processing user ${userEmail}:`, error.message);
report.userDetails.push({
userEmail,
error: error.message,
riskLevel: "unknown",
});
}
}
// Calculate averages
report.statistics.averageSessionsPerUser =
report.totalSessions / report.totalUsers;
report.statistics.averageAuthMethodsPerUser =
report.totalAuthMethods / report.totalUsers;
// Print report
console.log("\n=== 🔒 SECURITY AUDIT REPORT ===");
console.log(`📅 Generated: ${report.generatedAt}`);
console.log(`👥 Total Users Analyzed: ${report.totalUsers}`);
console.log(`📱 Total Active Sessions: ${report.totalSessions}`);
console.log(`🔐 Total Auth Methods: ${report.totalAuthMethods}`);
console.log(`\n📊 Statistics:`);
console.log(
` - Users with Multiple Sessions: ${report.statistics.usersWithMultipleSessions}`,
);
console.log(
` - Users with Social Auth: ${report.statistics.usersWithSocialAuth}`,
);
console.log(
` - Users with Email/Password Only: ${report.statistics.usersWithEmailPasswordOnly}`,
);
console.log(
` - Average Sessions per User: ${report.statistics.averageSessionsPerUser.toFixed(2)}`,
);
console.log(
` - Average Auth Methods per User: ${report.statistics.averageAuthMethodsPerUser.toFixed(2)}`,
);
console.log(`\n🔝 Most Common Providers:`);
Object.entries(report.statistics.mostCommonProviders)
.sort(([, a], [, b]) => b - a)
.forEach(([provider, count]) => {
console.log(` - ${provider}: ${count} users`);
});
return report;
}
// Helper function to calculate risk level
function calculateRiskLevel(
sessions: UserSession[],
methods: UserAuthenticationMethod[],
): "low" | "medium" | "high" {
let riskScore = 0;
// Multiple sessions increase risk
if (sessions.length > 3) riskScore += 2;
else if (sessions.length > 1) riskScore += 1;
// Only social auth (no email/password) increases risk
if (!methods.some((m) => m.provider === "email-password")) riskScore += 2;
// Many auth methods might indicate account compromise
if (methods.length > 3) riskScore += 1;
if (riskScore >= 4) return "high";
if (riskScore >= 2) return "medium";
return "low";
}
// Emergency security response - revoke all sessions for high-risk users
async function emergencySecurityResponse(userEmails: string[]) {
console.log("🚨 EMERGENCY SECURITY RESPONSE INITIATED");
const results = [];
for (const userEmail of userEmails) {
try {
const user: IUser = { email: userEmail };
// Get current security status
const [sessions, methods] = await Promise.all([
userSecurityService.findUserSessions(user),
userSecurityService.findUserAuthenticationMethods(user),
]);
const riskLevel = calculateRiskLevel(sessions, methods);
if (riskLevel === "high") {
// Revoke all sessions for high-risk users
const success = await userSecurityService.revokeAllUserSessions(user);
// Generate password reset ticket
const ticket = await userSecurityService.generatePasswordChangeTicket(
user,
"https://yourapp.com/password-reset-complete",
);
results.push({
userEmail,
action: "sessions_revoked_password_reset_sent",
riskLevel,
sessionsRevoked: success,
passwordResetUrl: ticket.redirect,
timestamp: new Date().toISOString(),
});
console.log(
`🔒 HIGH RISK - Revoked sessions and sent password reset for: ${userEmail}`,
);
} else {
results.push({
userEmail,
action: "no_action_required",
riskLevel,
timestamp: new Date().toISOString(),
});
console.log(
`✅ LOW/MEDIUM RISK - No action required for: ${userEmail}`,
);
}
} catch (error) {
results.push({
userEmail,
action: "error",
error: error.message,
timestamp: new Date().toISOString(),
});
console.log(`❌ Error processing ${userEmail}:`, error.message);
}
}
const actionsCount = results.filter(
(r) => r.action === "sessions_revoked_password_reset_sent",
).length;
console.log(`\n🚨 Emergency Response Summary:`);
console.log(` - Users Processed: ${userEmails.length}`);
console.log(` - High-Risk Actions Taken: ${actionsCount}`);
console.log(` - Users Requiring Immediate Attention: ${actionsCount}`);
return results;
}API Reference
Auth0UserSecurityService
The main service class providing all user security operations.
Constructor
constructor(config: Auth0Config, logger?: ILogger)Parameters:
config: Auth0 configuration objectlogger: Optional logger instance (defaults to console)
Methods
findUserSessions(userId: string): Promise<UserSession[]>
Retrieves all active sessions for a user.
Parameters:
userId: The Auth0 user ID
Returns: Array of user sessions with device and browser information
Example:
const sessions = await userSecurityService.findUserSessions("auth0|user123");
console.log(sessions[0].device); // "Desktop"
console.log(sessions[0].browser); // "Chrome 120.0.0"findUserAuthenticationMethods(userId: string): Promise<UserAuthenticationMethod[]>
Retrieves all authentication methods connected to a user account.
Parameters:
userId: The Auth0 user ID
Returns: Array of authentication methods
Example:
const methods =
await userSecurityService.findUserAuthenticationMethods("auth0|user123");
console.log(methods[0].provider); // "google-oauth2"
console.log(methods[0].connection); // "google-oauth2"revokeUserSession(userId: string, sessionId: string): Promise<void>
Revokes a specific user session.
Parameters:
userId: The Auth0 user IDsessionId: The session ID to revoke
Throws:
SessionNotFoundError: If session doesn't exist or doesn't belong to user
revokeAllUserSessions(userId: string): Promise<void>
Revokes all sessions for a user.
Parameters:
userId: The Auth0 user ID
generatePasswordChangeTicket(userId: string): Promise<string>
Generates a secure password change ticket URL.
Parameters:
userId: The Auth0 user ID
Returns: Password change ticket URL
generateAccountConnectionUrl(userId: string, provider: UserAuthenticationMethodProvider): Promise<string>
Generates a URL for connecting a new authentication method.
Parameters:
userId: The Auth0 user IDprovider: The authentication provider to connect
Returns: Connection URL
connectSecondaryAccount(userId: string, provider: UserAuthenticationMethodProvider, accessToken: string): Promise<UserAuthenticationMethod[]>
Connects a secondary authentication method to a user account.
Parameters:
userId: The Auth0 user IDprovider: The authentication provideraccessToken: The access token from the provider
Returns: Updated list of authentication methods
disconnectSecondaryAccount(userId: string, provider: UserAuthenticationMethodProvider, secondaryUserId: string): Promise<UserAuthenticationMethod[]>
Disconnects a secondary authentication method from a user account.
Parameters:
userId: The Auth0 user IDprovider: The authentication providersecondaryUserId: The secondary user ID to disconnect
Returns: Updated list of authentication methods
Types
UserSession
interface UserSession {
id: string;
userId: string;
clientId: string;
createdAt: Date;
updatedAt: Date;
device: string;
browser: string;
os: string;
country?: string;
city?: string;
current: boolean;
}UserAuthenticationMethod
interface UserAuthenticationMethod {
userId: string;
provider: UserAuthenticationMethodProvider;
connection: string;
isSocial: boolean;
profileData: Record<string, any>;
}UserAuthenticationMethodProvider
enum UserAuthenticationMethodProvider {
GOOGLE = "google-oauth2",
GITHUB = "github",
MICROSOFT = "windowslive",
APPLE = "apple",
EMAIL_PASSWORD = "email-password",
}Framework Integration
NestJS Example
import { Injectable } from "@nestjs/common";
import { Auth0UserSecurityService } from "@archie/auth0-user-security";
@Injectable()
export class UserSecurityService {
private readonly auth0Service: Auth0UserSecurityService;
constructor() {
this.auth0Service = new Auth0UserSecurityService({
domain: process.env.AUTH0_DOMAIN!,
clientId: process.env.AUTH0_CLIENT_ID!,
clientSecret: process.env.AUTH0_CLIENT_SECRET!,
audience: process.env.AUTH0_AUDIENCE!,
});
}
async getUserSessions(userId: string) {
return this.auth0Service.findUserSessions(userId);
}
async revokeSession(userId: string, sessionId: string) {
return this.auth0Service.revokeUserSession(userId, sessionId);
}
}Express Example
import express from "express";
import { Auth0UserSecurityService } from "@archie/auth0-user-security";
const app = express();
const userSecurityService = new Auth0UserSecurityService({
domain: process.env.AUTH0_DOMAIN!,
clientId: process.env.AUTH0_CLIENT_ID!,
clientSecret: process.env.AUTH0_CLIENT_SECRET!,
audience: process.env.AUTH0_AUDIENCE!,
});
app.get("/users/:userId/sessions", async (req, res) => {
try {
const sessions = await userSecurityService.findUserSessions(
req.params.userId,
);
res.json(sessions);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.delete("/users/:userId/sessions/:sessionId", async (req, res) => {
try {
await userSecurityService.revokeUserSession(
req.params.userId,
req.params.sessionId,
);
res.status(204).send();
} catch (error) {
res.status(500).json({ error: error.message });
}
});Error Handling
The library provides specific error classes for different scenarios:
import {
UserNotFoundError,
SessionNotFoundError,
Auth0ApiError,
ConfigurationError,
} from "@archie/auth0-user-security";
try {
await userSecurityService.revokeUserSession("user123", "session123");
} catch (error) {
if (error instanceof UserNotFoundError) {
console.log("User not found in Auth0");
} else if (error instanceof SessionNotFoundError) {
console.log("Session not found or does not belong to user");
} else if (error instanceof Auth0ApiError) {
console.log("Auth0 API error:", error.message);
} else if (error instanceof ConfigurationError) {
console.log("Configuration error:", error.message);
}
}Environment Variables
Set these environment variables for your application:
AUTH0_DOMAIN=your-tenant.auth0.com
AUTH0_CLIENT_ID=your-client-id
AUTH0_CLIENT_SECRET=your-client-secret
AUTH0_AUDIENCE=your-api-audienceSecurity Considerations
- Store credentials securely: Never commit Auth0 credentials to version control
- Use environment variables: Store sensitive configuration in environment variables
- Validate user ownership: Always verify that the user making the request owns the resource
- Rate limiting: Implement rate limiting to prevent abuse
- Audit logging: Log security-related operations for compliance
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Run the test suite
- Submit a pull request
License
MIT License - see LICENSE file for details
Support
For support, please open an issue on the GitHub repository or contact the maintainers.
Changelog
See CHANGELOG.md for version history and changes.
