Home Doh Ref
Dohballs
  • 📁 doh_modules
    • 📦 dataforge
    • 📦 express
    • 📁 sso
    • 📁 user

Users

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.

Key Features

  • Unified authentication across browser and server
  • JWT-based token management with refresh capability
  • Multi-device login with device tracking
  • Context-aware permission system for fine-grained access control
  • Email verification for new user accounts
  • Field validation and sanitization framework
  • Brute force protection with account lockout
  • Ready-to-use UI components for quick implementation

System Architecture

The user system consists of these interconnected components:

  • Core User Model: Manages user data, validation, and sanitization
  • Authentication Service: Handles login, refresh tokens, and session management
  • Permission System: Provides context-aware authorization
    • Programmatic contexts and groups in code modules
    • Configuration-based groups in Pod settings
  • Client Components: Offers UI elements for login, profile, and user management
  • Middleware: Connects Express/Router with the authentication system

Configuration

Basic Setup

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: { ... }
  }
});

Field Validation Configuration

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 empty
  • email: Must be valid email format
  • minLength/maxLength: Character count limits
  • unique: Must not exist in database
  • requiredCharSets: Must contain characters from specified sets
  • bannedSubstrings: Cannot contain specified strings

You can add custom validators:

Doh.addValidator('matchesField', function(value, fieldName, context) {
  return value === context[fieldName] ? true : `Must match ${fieldName}`;
});

Field Sanitization Configuration

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 whitespace
  • SanitizeEmail: Normalizes email addresses
  • SanitizePassword: Removes common issues from passwords
  • NormalizeWhitespace: Replaces multiple spaces with a single space

Authentication Flow

Registration and Email Verification

  1. User Registers: Client sends credentials to /api/register
  2. Account Created: Server creates user with verified: false
  3. Verification Email: System sends email with verification link
  4. User Verifies: User clicks link, server marks account as verified: true
  5. Login Available: User can now log in with credentials

If the verification email is lost, users can request a new one through the /api/resend-verification endpoint.

Login Process

  1. Submit Credentials: Client sends username/password to /api/login
  2. Verification Check: Server confirms email has been verified
  3. Auth Check: Server validates credentials and checks for account lockout
  4. Device Tracking: System identifies device or creates new device record
  5. Token Generation: Server issues access and refresh tokens
  6. Authentication Complete: Client stores tokens for subsequent requests

Token Management

  1. Token Storage: Client stores tokens in localStorage and cookies
  2. Request Authentication: Client includes token in subsequent requests
  3. Token Refresh: Client automatically refreshes tokens before expiration (at 80% of token lifetime)
  4. Server Validation: Client validates authentication state with server during session restoration and token refresh
  5. Automatic Synchronization: Browser state is regularly synchronized with server state to detect server-side invalidations
  6. Logout: Client calls /api/logout to invalidate tokens

Session Management

The system provides robust session management with automatic synchronization between browser and server:

  • Session Restoration: On page load, the system validates stored tokens with the server before restoring the session
  • Periodic Validation: Authentication state is validated with the server during token refresh cycles
  • Device Tracking: Each login session is associated with a specific device for enhanced security
  • Graceful Degradation: Network failures during validation don't force logout, allowing for temporary connectivity issues

Client-Side Usage

Authentication

// 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();

UI Components

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');

Server-Side Features

User Management

// 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');

Handling Email Verification

// 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);
  }
});

Password Reset

// 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');

Authentication Validation

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.

Last updated: 10/22/2025