Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/emmanueljarquin-sys/GrupoMecsaCMS/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Grupo Mecsa CMS implements comprehensive security measures to protect sensitive data and ensure only authorized staff can access administrative functions.

Security Architecture

The CMS uses a multi-layered security approach:
  1. Session-based Authentication - Secure token storage in PHP sessions
  2. Role-based Access Control (RBAC) - Fine-grained permissions by user role
  3. Supabase Row Level Security - Database-level access control
  4. Security Audit Logging - Track unauthorized access attempts

Access Control

Security Check Implementation

Every protected page must include config/security_check.php to enforce authentication and authorization
Location: config/security_check.php The security check runs on every page load and performs:
  • Session validation
  • Token verification
  • Role authorization
  • Access denial for non-staff users

Usage in Pages

Include at the top of every protected PHP file:
<?php
require_once __DIR__ . '/config/security_check.php';
// Rest of your page code
?>

Staff Roles

The system recognizes four staff roles:
RoleVariablePermissions
Admin$isAdminFull system access, user management
Comercial$isComercialClient and project management
Proyecto$isProyectoProject management and tracking
RRHH$isRRHHEmployee and department management
Users without any staff role are immediately blocked and logged out, even if they have valid credentials

Role Detection Logic

$user = $_SESSION['user'] ?? null;

// Check Admin role
$isAdmin = !empty($user['admin']) && 
           ($user['admin'] === true || $user['admin'] === 't' || 
            $user['admin'] === 1 || $user['admin'] === '1');

// Check other roles similarly
$isComercial = !empty($user['comercial']) && (/* boolean checks */);
$isProyecto = !empty($user['proyecto']) && (/* boolean checks */);
$isRRHH = !empty($user['rrhh']) && (/* boolean checks */);

// User must have at least one role
$isStaff = $isAdmin || $isComercial || $isProyecto || $isRRHH;
The system handles multiple boolean representations (true, ‘t’, 1, ‘1’) to accommodate different data sources and database types

Session Management

Session Initialization

if (session_status() === PHP_SESSION_NONE) {
    session_start();
}
The security check safely starts sessions only if not already active.

Required Session Variables

VariableTypeDescription
$_SESSION['token']stringSupabase authentication JWT token
$_SESSION['user']arrayUser profile with role flags
$_SESSION['uid']stringUnique user identifier

Token Validation

If no token is found in the session, users are immediately redirected to login (except from login.php itself)
if (!isset($_SESSION['token'])) {
    if (basename($_SERVER['PHP_SELF']) !== 'login.php') {
        header("Location: ../../login.php?error=session_expired");
        exit;
    }
}

Session Expiration

Users are redirected with specific error codes:
  • session_expired - No valid token found
  • unauthorized_staff_only - Valid user but no staff role
  • unauthorized - Generic access denial

API Key Protection

Development vs Production Keys

CRITICAL: Never commit API keys to version control!

Development Environment

Store keys in local.supabase.php (add to .gitignore):
local.supabase.php
<?php
$supabase_url = 'https://xxxxx.supabase.co';
$supabase_key = 'your-development-anon-key';
$supabase_service_role = 'your-development-service-role-key';
?>

Production Environment

Use environment variables:
# Set in server environment
export SUPABASE_URL="https://production.supabase.co"
export SUPABASE_KEY="production-anon-key"
export SUPABASE_SERVICE_ROLE="production-service-role-key"
Or configure in .htaccess:
SetEnv SUPABASE_URL "https://production.supabase.co"
SetEnv SUPABASE_KEY "production-anon-key"
SetEnv SUPABASE_SERVICE_ROLE "production-service-role-key"

Key Types and Security Levels

Understand the difference between key types to use them appropriately

Anon/Public Key ($supabase_key)

  • Security Level: Standard
  • RLS: Enforced (respects Row Level Security policies)
  • Usage: Normal CRUD operations, user-level authentication
  • Exposure: Can be exposed in client-side code

Service Role Key ($supabase_service_role)

  • Security Level: Administrative
  • RLS: Bypassed (full database access)
  • Usage: User management, password resets, admin operations
  • Exposure: Must NEVER be exposed to clients
The service role key grants unrestricted database access. Only use it server-side for administrative operations.

Security Audit Logging

Audit Log Location

Unauthorized access attempts are logged to:
security_audit.log

Log Format

[2026-03-05 14:23:45] CMS_BLOCK: Page=dashboard.php UID=user123
[2026-03-05 14:24:12] CMS_BLOCK: Page=usuarios.php UID=N/A
Each entry includes:
  • Timestamp
  • Event type (CMS_BLOCK)
  • Page that was blocked
  • User ID (if available)

Log Implementation

@file_put_contents(
    __DIR__ . '/../../security_audit.log',
    date('[Y-m-d H:i:s] ') . 
    "CMS_BLOCK: Page=" . basename($_SERVER['PHP_SELF']) . 
    " UID=" . ($_SESSION['uid'] ?? 'N/A') . "\n",
    FILE_APPEND
);
Regularly review the audit log to detect potential security issues or brute force attempts

Best Practices

1. Credential Management

1

Never Commit Secrets

Add sensitive files to .gitignore:
local.supabase.php
.env
*.key
security_audit.log
2

Use Environment Variables

Store production credentials in environment variables, not in code
3

Rotate Keys Regularly

Periodically regenerate API keys in the Supabase dashboard
4

Separate Dev and Prod

Use different Supabase projects for development and production

2. Session Security

// Configure secure session settings
ini_set('session.cookie_httponly', 1);
ini_set('session.cookie_secure', 1);  // HTTPS only
ini_set('session.cookie_samesite', 'Strict');
Always use HTTPS in production to protect session tokens from interception

3. Password Security

  • Enforce strong password requirements
  • Use Supabase’s built-in password hashing
  • Implement password reset flows with time-limited tokens
  • Support multi-factor authentication (MFA)

4. Database Security

Leverage Supabase Row Level Security (RLS) for defense in depth
Example RLS policy:
-- Users can only see their own data
CREATE POLICY "Users view own data"
ON cms.users
FOR SELECT
USING (auth.uid() = id);

-- Admins can see everything
CREATE POLICY "Admins view all"
ON cms.users
FOR SELECT
USING (auth.jwt() ->> 'admin' = 'true');

5. Input Validation

// Sanitize user input
$email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
$name = htmlspecialchars($_POST['name'], ENT_QUOTES, 'UTF-8');

// Validate before processing
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    die('Invalid email');
}

6. CSRF Protection

Implement CSRF tokens for state-changing operations:
// Generate token
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));

// Validate on form submission
if (!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
    die('CSRF validation failed');
}

Monitoring and Maintenance

Regular Tasks

1

Review Audit Logs

Check security_audit.log weekly for suspicious activity
2

Monitor Sessions

Track active sessions and unusual login patterns
3

Update Dependencies

Keep Composer packages updated:
composer update
4

Security Audits

Perform periodic security reviews of code and configurations

Security Incident Response

If you detect unauthorized access:
  1. Immediate Actions:
    • Revoke compromised API keys in Supabase
    • Force logout all sessions
    • Change admin passwords
  2. Investigation:
    • Review audit logs
    • Check database access logs in Supabase
    • Identify the attack vector
  3. Remediation:
    • Patch the vulnerability
    • Update security policies
    • Notify affected users if necessary

Security Checklist

Ensure all items are checked before deploying to production
  • All sensitive files added to .gitignore
  • Production API keys stored in environment variables
  • HTTPS enabled on production server
  • Secure session settings configured
  • security_check.php included on all protected pages
  • Row Level Security policies configured in Supabase
  • Regular audit log reviews scheduled
  • Strong password policy enforced
  • CSRF protection implemented on forms
  • Input validation on all user inputs
  • Error messages don’t reveal sensitive information
  • Security headers configured (HSTS, CSP, X-Frame-Options)

Next Steps

Supabase Configuration

Configure database connection and credentials

Deployment

Deploy securely to production

Build docs developers (and LLMs) love