The Doh User System provides a comprehensive solution for authentication, authorization, and user management across both client and server environments. It combines secure authentication flows with a powerful contextual permission system, making it adaptable for both simple and complex authorization requirements.
The user system consists of these interconnected components:
Configure the user system through your pod.yaml
or directly in code:
Doh.Pod('user_config', {
browser_pod: {
Users: {
// Token settings
tokenExpirationTime: '24h',
refreshTokenExpirationTime: '30d',
// Login UI behavior
loginAction: 'dialog', // 'dialog' or 'redirect'
registration: true, // Enable/disable registration
// Field validation rules (see Validation section)
validators: { ... },
// Field sanitization rules (see Sanitization section)
sanitizers: { ... }
}
},
// Server-side settings
Users: {
// Required JWT secrets
JWT_SECRET: 'your-secret-key',
REFRESH_SECRET: 'your-refresh-secret',
// Email verification & password reset
passwordResetHost: 'https://example.com',
passwordResetTokenExpirationTime: '1h',
// Brute force protection
maxLoginAttempts: 5,
lockoutDuration: 900000, // 15 minutes
// Email configuration
send_email: {
host: 'smtp.example.com',
port: 587,
from: 'noreply@example.com',
auth: {
user: 'username',
pass: 'password'
}
},
// Authentication debugging (for development)
auth_debug: false,
// Permission groups (see Permission Groups section)
groups: { ... }
}
});
The validation system ensures user data meets your requirements:
Doh.Pod('user_config', {
browser_pod: {
Users: {
validators: {
username: {
required: true,
email: true,
unique: true,
minLength: 5,
maxLength: 32
},
password: {
required: true,
minLength: 8,
maxLength: 32,
requiredCharSets: ['letter', 'number', 'special'],
bannedSubstrings: ['password', '12345', 'qwerty']
},
firstName: {
required: true,
minLength: 2
}
}
}
}
});
Built-in validators include:
required
: Field cannot be emptyemail
: Must be valid email formatminLength
/maxLength
: Character count limitsunique
: Must not exist in databaserequiredCharSets
: Must contain characters from specified setsbannedSubstrings
: Cannot contain specified stringsYou can add custom validators:
Doh.addValidator('matchesField', function(value, fieldName, context) {
return value === context[fieldName] ? true : `Must match ${fieldName}`;
});
Sanitizers clean user input before storage:
Doh.Pod('user_config', {
browser_pod: {
Users: {
sanitizers: {
username: ['SanitizeEmail'],
password: ['SanitizePassword'],
firstName: ['Trim', 'NormalizeWhitespace']
}
}
}
});
Built-in sanitizers:
Trim
: Removes leading/trailing whitespaceSanitizeEmail
: Normalizes email addressesSanitizePassword
: Removes common issues from passwordsNormalizeWhitespace
: Replaces multiple spaces with a single space/api/register
verified: false
verified: true
If the verification email is lost, users can request a new one through the /api/resend-verification
endpoint.
/api/login
/api/logout
to invalidate tokensThe system provides robust session management with automatic synchronization between browser and server:
// Login a user
await Doh.user.authenticate('username@example.com', 'password');
// Check if user is authenticated
if (Doh.user.isAuthenticated) {
// User is logged in
}
// Get current user info
const username = Doh.user.currentUser.username;
// Validate authentication state with server
const authState = await Doh.user.validateAuthState();
if (authState.valid) {
console.log('Authentication is valid');
} else {
console.log('Authentication invalid:', authState.reason);
}
// Logout
await Doh.user.logout();
The system provides ready-to-use UI components:
// Create a login form
New('UserLogin', {
inDialog: true, // Show in modal dialog
onLogin: async (user) => {
console.log('User logged in:', user);
}
});
// Create a user icon (typically for navigation)
New('UserIcon');
// Create a user profile dashboard
New('UserProfile');
// Create a user
const user = await Users.createUser('username@example.com', 'password', {
firstName: 'John',
lastName: 'Doe'
});
// Update user
await Users.updateUser('username@example.com', {
firstName: 'Jane'
});
// Delete user
await Users.deleteUser('username@example.com');
// Resend verification email
Router.AddRoute('/api/resend-verification', [], async function(data, req, res, callback) {
const { username } = data;
try {
await Users.sendVerificationEmail(username, newVerificationToken);
Router.SendJSON(res, { success: true }, callback);
} catch (error) {
Router.SendJSON(res, { success: false, error: error.message }, callback);
}
});
// Verify email endpoint
Router.AddRoute('/api/verify-email', [], async function(data, req, res, callback) {
const { token } = data;
try {
// Find user with token and verify
const user = findUserByVerificationToken(token);
await Users.updateUser(user.username, { verified: true });
Router.SendJSON(res, { success: true }, callback);
} catch (error) {
Router.SendJSON(res, { success: false, error: error.message }, callback);
}
});
// Generate reset token
const resetToken = await Users.generateResetToken('username@example.com');
// Send password reset email
await Users.sendPasswordResetEmail('username@example.com', resetToken);
// Reset password with token
await Users.resetPassword(resetToken, 'newPassword');
The system provides endpoints for validating authentication state:
// Validate current authentication state
Router.AddRoute('/api/validate-auth', [], async function(data, req, res, callback) {
// Assumes global parseToken middleware - req.user will be set if valid
if (!req.user) {
return Router.SendJSON(res, {
success: false,
authenticated: false,
error: 'Not authenticated'
}, callback);
}
Router.SendJSON(res, {
success: true,
authenticated: true,
user: {
username: req.user.username,
deviceId: req.user.currentDeviceId
}
}, callback);
});
This endpoint allows clients to validate their authentication state without requiring token refresh, useful for checking if a session is still valid on the server side.