Skip to main content
GET
/
settings
curl -X GET "https://auth-api.yourdomain.com/settings" \
  -H "Content-Type: application/json"
{
  "external_email_enabled": true,
  "external_phone_enabled": true,
  "external_providers_enabled": true,
  "external_providers": [
    {
      "name": "google",
      "enabled": true
    },
    {
      "name": "github", 
      "enabled": true
    },
    {
      "name": "apple",
      "enabled": false
    }
  ],
  "disable_signup": false,
  "autoconfirm": false,
  "password_min_length": 8,
  "password_requirements": {
    "lowercase": true,
    "uppercase": true,
    "numbers": true,
    "symbols": false
  },
  "email_confirm_required": true,
  "phone_confirm_required": true,
  "session_timeout": 3600,
  "refresh_token_rotation_enabled": true,
  "mfa_enabled": true,
  "mfa_max_enrolled_factors": 10,
  "rate_limits": {
    "signup": {
      "requests": 5,
      "window": 300
    },
    "login": {
      "requests": 10,
      "window": 300
    },
    "recover": {
      "requests": 3,
      "window": 300
    }
  }
}

Overview

The /settings endpoint returns publicly available authentication settings that can be used by client applications to configure their authentication flows. This endpoint does not require authentication and is safe to call from public clients.

Request

curl -X GET "https://auth-api.yourdomain.com/settings" \
  -H "Content-Type: application/json"

Response

{
  "external_email_enabled": true,
  "external_phone_enabled": true,
  "external_providers_enabled": true,
  "external_providers": [
    {
      "name": "google",
      "enabled": true
    },
    {
      "name": "github", 
      "enabled": true
    },
    {
      "name": "apple",
      "enabled": false
    }
  ],
  "disable_signup": false,
  "autoconfirm": false,
  "password_min_length": 8,
  "password_requirements": {
    "lowercase": true,
    "uppercase": true,
    "numbers": true,
    "symbols": false
  },
  "email_confirm_required": true,
  "phone_confirm_required": true,
  "session_timeout": 3600,
  "refresh_token_rotation_enabled": true,
  "mfa_enabled": true,
  "mfa_max_enrolled_factors": 10,
  "rate_limits": {
    "signup": {
      "requests": 5,
      "window": 300
    },
    "login": {
      "requests": 10,
      "window": 300
    },
    "recover": {
      "requests": 3,
      "window": 300
    }
  }
}

Response Fields

FieldTypeDescription
external_email_enabledbooleanWhether email/password authentication is enabled
external_phone_enabledbooleanWhether phone/SMS authentication is enabled
external_providers_enabledbooleanWhether OAuth providers are enabled
external_providersarrayList of available OAuth providers and their status
disable_signupbooleanWhether new user registration is disabled
autoconfirmbooleanWhether users are automatically confirmed
password_min_lengthintegerMinimum password length requirement
password_requirementsobjectPassword complexity requirements
email_confirm_requiredbooleanWhether email confirmation is required
phone_confirm_requiredbooleanWhether phone confirmation is required
session_timeoutintegerSession timeout in seconds
refresh_token_rotation_enabledbooleanWhether refresh tokens are rotated
mfa_enabledbooleanWhether multi-factor authentication is enabled
mfa_max_enrolled_factorsintegerMaximum MFA factors per user
rate_limitsobjectRate limiting configuration for different endpoints

Implementation Examples

React Hook for Settings

import { useState, useEffect } from 'react';

export function useAuthSettings() {
  const [settings, setSettings] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchSettings() {
      try {
        const response = await fetch('/api/auth/settings');
        if (!response.ok) {
          throw new Error('Failed to fetch settings');
        }
        const data = await response.json();
        setSettings(data);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    }

    fetchSettings();
  }, []);

  return { settings, loading, error };
}

// Usage in component
function AuthForm() {
  const { settings, loading } = useAuthSettings();

  if (loading) return <div>Loading...</div>;

  return (
    <form>
      {settings?.external_email_enabled && (
        <input 
          type="email" 
          placeholder="Email"
          minLength={settings.password_min_length}
        />
      )}
      
      {settings?.external_phone_enabled && (
        <input 
          type="tel" 
          placeholder="Phone number"
        />
      )}

      {settings?.external_providers_enabled && (
        <div className="oauth-providers">
          {settings.external_providers
            .filter(provider => provider.enabled)
            .map(provider => (
              <button key={provider.name} type="button">
                Sign in with {provider.name}
              </button>
            ))}
        </div>
      )}
    </form>
  );
}

Password Validation

function validatePassword(password, settings) {
  const errors = [];
  
  if (password.length < settings.password_min_length) {
    errors.push(`Password must be at least ${settings.password_min_length} characters`);
  }
  
  const requirements = settings.password_requirements;
  
  if (requirements.lowercase && !/[a-z]/.test(password)) {
    errors.push('Password must contain lowercase letters');
  }
  
  if (requirements.uppercase && !/[A-Z]/.test(password)) {
    errors.push('Password must contain uppercase letters');
  }
  
  if (requirements.numbers && !/\d/.test(password)) {
    errors.push('Password must contain numbers');
  }
  
  if (requirements.symbols && !/[!@#$%^&*(),.?":{}|<>]/.test(password)) {
    errors.push('Password must contain symbols');
  }
  
  return {
    isValid: errors.length === 0,
    errors
  };
}

Node.js Middleware

const express = require('express');
const app = express();

// Cache settings to avoid repeated API calls
let cachedSettings = null;
let settingsLastFetched = 0;
const SETTINGS_CACHE_TTL = 5 * 60 * 1000; // 5 minutes

async function getAuthSettings() {
  const now = Date.now();
  
  if (cachedSettings && (now - settingsLastFetched) < SETTINGS_CACHE_TTL) {
    return cachedSettings;
  }
  
  try {
    const response = await fetch('https://auth-api.yourdomain.com/settings');
    const settings = await response.json();
    
    cachedSettings = settings;
    settingsLastFetched = now;
    
    return settings;
  } catch (error) {
    console.error('Failed to fetch auth settings:', error);
    return cachedSettings || {}; // Return cached settings or empty object
  }
}

// Middleware to inject settings into requests
app.use(async (req, res, next) => {
  req.authSettings = await getAuthSettings();
  next();
});

// Route that uses settings
app.post('/validate-signup', (req, res) => {
  const { email, password } = req.body;
  const settings = req.authSettings;
  
  if (settings.disable_signup) {
    return res.status(403).json({
      error: 'User registration is currently disabled'
    });
  }
  
  const passwordValidation = validatePassword(password, settings);
  if (!passwordValidation.isValid) {
    return res.status(400).json({
      error: 'Invalid password',
      details: passwordValidation.errors
    });
  }
  
  // Continue with signup logic...
  res.json({ message: 'Validation passed' });
});

Use Cases

Dynamic Form Configuration

Use the settings to dynamically configure your authentication forms:
  • Show/hide email vs phone authentication options
  • Display available OAuth providers
  • Configure password requirements
  • Show appropriate confirmation messages

Client-Side Validation

Implement client-side validation that matches server-side requirements:
  • Password complexity validation
  • Rate limiting awareness
  • Feature availability checks

Progressive Enhancement

Gracefully handle different authentication capabilities:
  • Fallback to email if phone is disabled
  • Hide MFA options if not enabled
  • Adjust UI based on confirmation requirements

Security Considerations

  • Public Endpoint: This endpoint is intentionally public and doesn’t expose sensitive configuration
  • Rate Limiting: Consider caching settings on the client side to avoid excessive requests
  • Feature Detection: Use settings to enable/disable features rather than hardcoding capabilities
  • Validation Sync: Ensure client-side validation matches the server-side requirements

Testing

// Jest test example
describe('Auth Settings', () => {
  test('should fetch public settings', async () => {
    const response = await fetch('/settings');
    const settings = await response.json();
    
    expect(response.status).toBe(200);
    expect(settings).toHaveProperty('external_email_enabled');
    expect(settings).toHaveProperty('password_min_length');
    expect(typeof settings.disable_signup).toBe('boolean');
  });
  
  test('should validate password requirements', () => {
    const settings = {
      password_min_length: 8,
      password_requirements: {
        lowercase: true,
        uppercase: true,
        numbers: true,
        symbols: false
      }
    };
    
    const validation = validatePassword('Password123', settings);
    expect(validation.isValid).toBe(true);
    
    const weakValidation = validatePassword('weak', settings);
    expect(weakValidation.isValid).toBe(false);
    expect(weakValidation.errors.length).toBeGreaterThan(0);
  });
});
I