Skip to content

Authentication Service

The Authentication service provides comprehensive user authentication and authorization capabilities for your Basefloor application.

Overview

The Auth module includes user registration, login, password management, email verification, and JWT token-based authentication. It provides secure authentication flows with built-in email integration and comprehensive route protection.

Configuration

Enable authentication in your basefloor.config.js:

javascript
module.exports = (API) => {
  return {
    auth: {
      enabled: true,
    },
    project: {
      app: {
        secret: process.env.APP_SECRET, // Required for JWT signing
        name: 'Your App Name',
        author: {
          name: 'Your Company',
          email: 'support@yourapp.com',
        },
        urls: {
          verify: 'https://yourapp.com/verify/:token', // Email verification URL
        },
      },
    },
    // Email service required for auth features
    emails: {
      enabled: true,
      provider: '@postmark/emails',
    },
    providers: {
      '@postmark/emails': {
        serverToken: process.env.POSTMARK_SERVER_TOKEN,
      },
    },
  }
}

Authentication Routes

User Registration

Register a new user account.

Endpoint: POST /register

Request Body:

javascript
{
  "email": "user@example.com",
  "password": "securepassword",
  "first_name": "John",
  "last_name": "Doe"
  // ... any additional user fields
}

Response:

javascript
{
  "message": "user registered!"
}

Example:

javascript
const response = await fetch('/api/register', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    email: 'john@example.com',
    password: 'mypassword123',
    first_name: 'John',
    last_name: 'Doe'
  })
});

User Login

Authenticate a user and receive a JWT token.

Endpoint: POST /login

Request Body:

javascript
{
  "email": "user@example.com",
  "password": "securepassword"
}

Response:

javascript
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "message": "logged in!"
}

Example:

javascript
const response = await fetch('/api/login', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    email: 'john@example.com',
    password: 'mypassword123'
  })
});

const { token } = await response.json();
// Store token for subsequent requests
localStorage.setItem('authToken', token);

Get User Information

Retrieve the authenticated user's information.

Endpoint: GET /user

Headers: Authorization: Bearer <token>

Response:

javascript
{
  "_id": "user_id",
  "email": "user@example.com",
  "first_name": "John",
  "last_name": "Doe",
  "email_verified": true,
  // ... other user fields
}

Example:

javascript
const response = await fetch('/api/user', {
  headers: {
    'Authorization': `Bearer ${token}`
  }
});

Update User Information

Update the authenticated user's profile.

Endpoint: PUT /user

Headers: Authorization: Bearer <token>

Request Body:

javascript
{
  "first_name": "Jane",
  "last_name": "Smith"
  // ... any updatable fields
}

Response:

javascript
{
  "message": "updated user!"
}

Delete User Account

Delete the authenticated user's account.

Endpoint: DELETE /user

Headers: Authorization: Bearer <token>

Response:

javascript
{
  "message": "deleted user!"
}

Password Reset Flow

Request Password Reset

Send a password reset code to the user's email.

Endpoint: POST /user/reset/password

Request Body:

javascript
{
  "email": "user@example.com"
}

Response:

javascript
{
  "token": "reset_token_here",
  "message": "emailed code!"
}

Verify Reset Code

Verify the emailed reset code.

Endpoint: GET /user/reset/password/:code

Headers: Authorization: Bearer <reset_token>

Response:

javascript
{
  "token": "verified_reset_token",
  "validated": true
}

Complete Password Reset

Set a new password after verification.

Endpoint: PUT /user/reset/password

Headers: Authorization: Bearer <verified_reset_token>

Request Body:

javascript
{
  "password": "newpassword123"
}

Response:

javascript
{
  "token": "new_auth_token",
  "message": "password changed and logged in!"
}

Email Verification

Request Email Verification

Send an email verification link to the user.

Endpoint: POST /user/verify/email

Headers: Authorization: Bearer <token>

Response:

javascript
{
  "message": "sending verification!",
  "token": "verification_token"
}

Check Verification Status

Check if the user's email is verified.

Endpoint: GET /user/verify

Headers: Authorization: Bearer <verification_token>

Response:

javascript
{
  "status": true,
  "message": "user email is verified!"
}

Complete Email Verification

Mark the user's email as verified (typically called from email link).

Endpoint: PUT /user/verify

Headers: Authorization: Bearer <verification_token>

Response:

javascript
{
  "message": "user email verified!"
}

Authentication Utilities

The auth module provides several utility functions accessible via API.Auth:

Password Hashing

javascript
// Hash a password
const hashedPassword = await API.Auth.hashPassword('plaintext_password');

// Compare password with hash
const isValid = await API.Auth.comparePasswordWithHashed('plaintext_password', hashedPassword);

Cryptographic Functions

javascript
// Generate MD5 hash
const md5Hash = API.Auth.md5('data_to_hash');

// Generate SHA1 hash
const sha1Hash = API.Auth.sha1('data_to_hash');

// Parse email parts
const parts = API.Auth.emailParts('user@example.com');
// Returns: { username: 'user', domain: 'example.com' }

File Operations

javascript
// Remove a file (async)
await API.Auth.removeFile('/path/to/file');

Middleware

Authentication Middleware

Protect routes with authentication middleware:

javascript
// Require authentication
app.get('/protected-route', [
  API.requireAuthentication,
  API.postAuthentication,
], (req, res) => {
  // req.user contains the authenticated user
  res.json({ user: req.user });
});

Custom Route Protection

javascript
// Custom middleware example
app.get('/admin-only', [
  API.requireAuthentication,
  API.postAuthentication,
  (req, res, next) => {
    if (req.user.role !== 'admin') {
      return res.status(403).json({ error: 'Admin access required' });
    }
    next();
  }
], (req, res) => {
  res.json({ message: 'Admin area' });
});

Email Templates

The auth module includes built-in email templates:

Password Reset Email

javascript
// Located at: auth/emails/resetPasswordWithCode.js
const emailArgs = require('./auth/emails/resetPasswordWithCode')(email, {
  code: '123456',
  durationText: '15 minutes',
  appName: 'Your App',
  appAuthor: 'Your Company',
  appAuthorEmail: 'support@yourapp.com',
});

Email Verification

javascript
// Located at: auth/emails/verifyEmail.js
const emailArgs = require('./auth/emails/verifyEmail')(email, {
  url: 'https://yourapp.com/verify?token=abc123',
  appName: 'Your App',
  appAuthor: 'Your Company',
});

Password Changed Confirmation

javascript
// Located at: auth/emails/changedPassword.js
const emailArgs = require('./auth/emails/changedPassword')(email, {
  appName: 'Your App',
  appAuthor: 'Your Company',
  appAuthorEmail: 'support@yourapp.com',
});

Database Requirements

The auth module expects a Users model with the following fields:

javascript
// Minimum required fields
{
  email: String, // Unique
  password_hash: String,
  email_verified: Boolean,
  // Optional fields
  first_name: String,
  last_name: String,
  sms: String,
  sms_verified: Boolean,
  // ... any additional user fields
}

Security Features

JWT Token Management

  • Tokens are signed with your app secret
  • Different token types for different purposes (auth, reset, verify)
  • Automatic token expiration
  • Secure token validation

Password Security

  • Passwords are hashed using bcrypt with salt rounds
  • Plain text passwords are never stored
  • Secure password comparison

Rate Limiting

Consider implementing rate limiting for auth endpoints:

javascript
// Example with express-rate-limit
const rateLimit = require('express-rate-limit');

const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 5, // Limit each IP to 5 requests per windowMs
  message: 'Too many authentication attempts, please try again later.',
});

app.use('/api/login', authLimiter);
app.use('/api/register', authLimiter);

Environment Variables

Required environment variables:

bash
# Required
APP_SECRET=your_very_secure_secret_key_here

# Email service (required for auth features)
POSTMARK_SERVER_TOKEN=your_postmark_token

# Optional: Custom token expiration times
JWT_EXPIRATION=7d
RESET_TOKEN_EXPIRATION=15m
VERIFY_TOKEN_EXPIRATION=24h

Error Handling

The auth module includes comprehensive error handling:

javascript
// Common error responses
{
  "error": "user not found!",
  "code": 404
}

{
  "error": "incorrect login information!",
  "code": 401
}

{
  "error": "email@example.com is already registered!",
  "code": 400
}

Testing Integration

The auth module includes built-in API checks for testing:

javascript
// Automatically registered checks include:
// - User registration
// - User login
// - Get user information
// - Password reset flow
// - Email verification flow

// Run checks
await API.Checks.run();

Best Practices

  1. Secure Secrets: Use strong, unique secrets for JWT signing
  2. HTTPS Only: Always use HTTPS in production for auth endpoints
  3. Token Storage: Store tokens securely on the client side
  4. Password Requirements: Implement strong password requirements
  5. Rate Limiting: Implement rate limiting on auth endpoints
  6. Email Verification: Require email verification for sensitive operations
  7. Session Management: Implement proper session management and logout
  8. Audit Logging: Log authentication events for security monitoring

Frontend Integration

React Example

javascript
// Auth context
const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null);
  const [token, setToken] = useState(localStorage.getItem('authToken'));

  const login = async (email, password) => {
    const response = await fetch('/api/login', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email, password }),
    });
    
    const data = await response.json();
    if (data.token) {
      setToken(data.token);
      localStorage.setItem('authToken', data.token);
      // Fetch user data
      fetchUser();
    }
  };

  const fetchUser = async () => {
    if (!token) return;
    
    const response = await fetch('/api/user', {
      headers: { 'Authorization': `Bearer ${token}` },
    });
    
    if (response.ok) {
      const userData = await response.json();
      setUser(userData);
    }
  };

  return (
    <AuthContext.Provider value={{ user, login, token }}>
      {children}
    </AuthContext.Provider>
  );
};

Troubleshooting

Common Issues

  1. Invalid Token: Check token format and expiration
  2. Email Not Sending: Verify email service configuration
  3. Password Hash Errors: Ensure bcrypt is properly installed
  4. Database Errors: Verify Users model exists and has required fields
  5. CORS Issues: Configure CORS for your frontend domain

Debug Mode

Enable debug logging:

javascript
// In your route handlers
API.Log('Auth debug info', { user: req.user, token: req.headers.authorization });

Released under the MIT License.