REMOTE USER Authentication

From VoIPmonitor.org


REMOTE_USER Authentication

REMOTE_USER authentication allows VoIPmonitor GUI to integrate with external Single Sign-On (SSO) systems like Shibboleth, CAS, Kerberos, or any web server authentication module that sets the REMOTE_USER environment variable.

How It Works

  1. User accesses VoIPmonitor GUI
  2. Web server intercepts and redirects to Identity Provider
  3. User authenticates with IdP (Shibboleth, AD, LDAP, etc.)
  4. Web server sets $_SERVER['REMOTE_USER'] with authenticated username
  5. VoIPmonitor's custom_login.php script reads this value and maps to GUI user

Configuration

Step 1: Configure Web Server Authentication

Configure your web server to protect the VoIPmonitor directory and set REMOTE_USER. Example for Apache with Shibboleth:

<Location /voipmonitor>
    AuthType shibboleth
    ShibRequestSetting requireSession 1
    Require valid-user
</Location>

Example for Apache with Kerberos:

<Location /voipmonitor>
    AuthType Kerberos
    AuthName "VoIPmonitor SSO"
    KrbAuthRealms EXAMPLE.COM
    KrbServiceName HTTP/voipmonitor.example.com@EXAMPLE.COM
    Krb5Keytab /etc/httpd/http.keytab
    KrbMethodNegotiate on
    KrbMethodK5Passwd off
    Require valid-user
</Location>

Step 2: Create custom_login.php Script

Create the custom login script at /var/www/html/scripts/custom_login.php:

<?php
/**
 * REMOTE_USER Authentication for VoIPmonitor
 *
 * This script is called by VoIPmonitor GUI when custom authentication is enabled.
 * It must return a JSON array with user details.
 */

function custom_login($username, $password) {
    // Get REMOTE_USER from web server
    $remote_user = isset($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'] : null;

    // For SSO, password is not used - user is already authenticated
    if (empty($remote_user)) {
        return array('error' => 'Not authenticated via SSO');
    }

    // Extract username (remove domain if present: user@domain.com -> user)
    $clean_username = preg_replace('/@.*$/', '', $remote_user);

    // Map to VoIPmonitor user
    // Option A: Direct mapping (SSO username = VoIPmonitor username)
    return array(
        'id'       => crc32($clean_username),  // MUST be unique numeric ID per user
        'username' => $clean_username,
        'name'     => $clean_username,
        'is_admin' => false,                   // Set true for admin users
        'id_group' => 1,                       // Group ID for permissions
    );

    // Option B: LDAP lookup for additional attributes
    // $ldap_info = ldap_lookup($remote_user);
    // return array(
    //     'id'       => $ldap_info['uidnumber'],
    //     'username' => $ldap_info['uid'],
    //     'name'     => $ldap_info['cn'],
    //     'is_admin' => in_array('VoIP-Admins', $ldap_info['groups']),
    //     'id_group' => determine_group($ldap_info),
    // );
}
?>

⚠️ Warning: The id field MUST return a unique numeric ID for each user. Using the same ID for multiple users causes them to share settings and permissions. Use LDAP uidnumber or crc32() of username.

Step 3: Enable Custom Login in GUI

  1. Navigate to Settings > System Configuration > Authentication
  2. Set Custom login script to: /var/www/html/scripts/custom_login.php
  3. Optionally set Don't display local login form to Yes (SSO only)

User Mapping Options

Method Description When to Use
Direct SSO username maps directly to VoIPmonitor username Simple setups, usernames match
LDAP Lookup Query LDAP/AD for user attributes Need groups, full name, or permissions from directory
Database Lookup Query external database for mapping Custom user management systems
Hybrid Check VoIPmonitor DB first, then create from SSO Auto-provisioning new users

Auto-Provisioning Users

To automatically create GUI users on first SSO login, extend custom_login.php to check if user exists and insert if not:

function custom_login($username, $password) {
    $remote_user = $_SERVER['REMOTE_USER'] ?? null;
    if (!$remote_user) return array('error' => 'SSO required');

    $clean_username = preg_replace('/@.*$/', '', $remote_user);

    // Check if user exists in VoIPmonitor
    $mysqli = new mysqli('localhost', 'voipmonitor', 'password', 'voipmonitor');
    $stmt = $mysqli->prepare("SELECT id, id_group FROM users WHERE username = ?");
    $stmt->bind_param('s', $clean_username);
    $stmt->execute();
    $result = $stmt->get_result();

    if ($row = $result->fetch_assoc()) {
        // Existing user
        return array(
            'id'       => (int)$row['id'],
            'username' => $clean_username,
            'id_group' => (int)$row['id_group'],
        );
    } else {
        // Create new user (auto-provision)
        $stmt = $mysqli->prepare("INSERT INTO users (username, id_group) VALUES (?, 2)");
        $stmt->bind_param('s', $clean_username);
        $stmt->execute();

        return array(
            'id'       => (int)$mysqli->insert_id,
            'username' => $clean_username,
            'id_group' => 2,  // Default group for new users
        );
    }
}

Troubleshooting

Problem Cause Solution
SSO works but "Access denied" custom_login.php not configured Enable custom login in GUI Settings
All users share settings Same id returned for all users Return unique numeric ID per user (use uidnumber or crc32(username))
REMOTE_USER is empty Web server auth not reaching PHP Check CGIPassAuth On (Apache 2.4.13+) or proxy headers
SSO bypass possible Local login form still visible Set "Don't display local login form" = Yes
Headers not passed through proxy Reverse proxy strips auth headers Configure RequestHeader set REMOTE_USER %{REMOTE_USER}e

Debugging

Create a test script to verify REMOTE_USER is being passed:

<?php
// /var/www/html/test_sso.php - DELETE after testing!
echo "REMOTE_USER: " . ($_SERVER['REMOTE_USER'] ?? 'NOT SET') . "\n";
echo "All auth headers:\n";
foreach ($_SERVER as $key => $value) {
    if (strpos($key, 'AUTH') !== false || strpos($key, 'REMOTE') !== false) {
        echo "  $key: $value\n";
    }
}
?>

ℹ️ Note: For Nginx with PHP-FPM, pass REMOTE_USER via: fastcgi_param REMOTE_USER $remote_user;

See Also

AI Summary for RAG

Summary: REMOTE_USER authentication enables VoIPmonitor GUI integration with enterprise SSO systems (Shibboleth, Kerberos, CAS) via web server authentication modules. Configuration requires: (1) Web server setup (Apache/Nginx) with auth module to set REMOTE_USER, (2) custom_login.php script that reads $_SERVER['REMOTE_USER'] and returns user mapping with UNIQUE numeric ID, (3) Enable custom login in GUI Settings. Critical requirement: each user MUST have unique numeric 'id' field to prevent shared settings. Supports auto-provisioning via database insertion on first login. For reverse proxies, configure header passthrough (CGIPassAuth On, RequestHeader set). Debugging: check $_SERVER['REMOTE_USER'] value with test script.

Keywords: REMOTE_USER, SSO, Single Sign-On, Shibboleth, Kerberos, CAS, SAML, custom_login.php, Apache mod_shib, mod_auth_kerb, enterprise authentication, auto-provision, LDAP, uidnumber, unique user ID, CGIPassAuth, reverse proxy authentication, PHP-FPM REMOTE_USER

Key Questions:

  • How do I configure VoIPmonitor for Shibboleth SSO?
  • How do I integrate VoIPmonitor with Kerberos authentication?
  • What is custom_login.php and how do I use it for SSO?
  • Why do all my SSO users share the same settings?
  • How do I auto-provision VoIPmonitor users from SSO?
  • Why is REMOTE_USER empty in my custom_login.php script?
  • How do I pass REMOTE_USER through Nginx reverse proxy?
  • How do I disable local login when using SSO?
  • What unique ID should I return for each SSO user?
  • How do I debug REMOTE_USER authentication issues?