nano-pro/auth-test.php
DJP 61aa1931bb Add MSAL/Azure AD authentication with toggle support
Implemented complete Microsoft Authentication Library (MSAL) / Azure AD
Single Sign-On (SSO) system following Ferrero app pattern.

KEY FEATURE: Toggle authentication on/off via environment variable
- SSO_ENABLED=false → Mock user, no login required (local dev)
- SSO_ENABLED=true → Full Azure AD authentication (production)

NEW FILES:
- composer.json - Firebase JWT dependency
- .env.example - Environment variable template
- env_loader.php - Parse .env file
- JWTValidator.php - Validate JWT tokens from Azure AD
- AuthMiddleware.php - Core auth orchestrator with login UI
- auth.php - Authentication API (login/logout/status)
- auth-test.php - Debug authentication status
- AUTH_README.md - Complete setup documentation

UPDATED FILES:
- config.php - Load env vars, add SSO constants
- index.php - Require auth, add logout button, MSAL script
- api.php - Add authentication check
- enhance_prompt.php - Add authentication check
- .gitignore - Exclude .env and vendor/

AUTHENTICATION FLOW:
1. User visits app → Auth check
2. If SSO disabled → Mock "Local Developer" user
3. If SSO enabled → Validate JWT from cookie
4. If no token → Show MSAL login page
5. User signs in → Token validated → Cookie set → App loads

SECURITY FEATURES:
 httpOnly cookies (XSS prevention)
 SameSite=Lax (CSRF prevention)
 JWT signature validation
 Claims validation (exp, nbf, aud, iss)
 JWKS from Azure AD
 24-hour token expiration
 Secure flag for HTTPS

DEPENDENCIES INSTALLED:
- firebase/php-jwt v6.11.1

TESTING:
- Local: SSO disabled by default in .env
- Server: Set SSO_ENABLED=true with Azure AD credentials
- Cannot test MSAL locally (redirect URI bound to server)

DEPLOYMENT:
1. Install composer dependencies
2. Configure .env with Azure AD credentials
3. Set SSO_ENABLED=true when ready
4. Visit auth-test.php to verify setup

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
2025-12-16 10:08:07 -05:00

64 lines
2.2 KiB
PHP

<?php
/**
* Authentication Test & Debug Page
* Shows current authentication status and configuration
*/
header('Content-Type: text/plain');
require_once __DIR__ . '/config.php';
require_once __DIR__ . '/AuthMiddleware.php';
echo "=== MSAL Authentication Test ===\n\n";
echo "1. SSO Configuration:\n";
echo " Enabled: " . (SSO_ENABLED ? 'YES' : 'NO') . "\n";
echo " Tenant ID: " . (SSO_TENANT_ID ?: 'NOT SET') . "\n";
echo " Client ID: " . (SSO_CLIENT_ID ?: 'NOT SET') . "\n\n";
echo "2. Testing AuthMiddleware:\n";
try {
$auth = new AuthMiddleware();
echo " ✓ AuthMiddleware loaded successfully\n";
echo " SSO Enabled: " . ($auth->isSSOEnabled() ? 'YES' : 'NO') . "\n\n";
echo "3. Authentication Status:\n";
$status = $auth->isAuthenticated();
echo " Authenticated: " . ($status['authenticated'] ? 'YES' : 'NO') . "\n";
if ($status['authenticated']) {
echo " User Name: " . ($status['user']['name'] ?? 'Unknown') . "\n";
echo " User Email: " . ($status['user']['preferred_username'] ?? $status['user']['upn'] ?? 'Unknown') . "\n";
} else {
echo " Error: " . ($status['error'] ?? 'Unknown') . "\n";
}
echo "\n4. Cookie Check:\n";
echo " auth_token cookie: " . (isset($_COOKIE['auth_token']) ? 'PRESENT' : 'NOT PRESENT') . "\n";
if (isset($_COOKIE['auth_token'])) {
$tokenLength = strlen($_COOKIE['auth_token']);
echo " Token length: " . $tokenLength . " chars\n";
echo " Token preview: " . substr($_COOKIE['auth_token'], 0, 50) . "...\n";
}
echo "\n5. Environment Variables:\n";
echo " SSO_ENABLED env: " . (getenv('SSO_ENABLED') ?: 'NOT SET') . "\n";
echo " SSO_TENANT_ID env: " . (getenv('SSO_TENANT_ID') ?: 'NOT SET') . "\n";
echo " SSO_CLIENT_ID env: " . (getenv('SSO_CLIENT_ID') ?: 'NOT SET') . "\n";
echo "\n6. Session Info:\n";
if (session_status() === PHP_SESSION_ACTIVE) {
echo " Session active: YES\n";
echo " Session ID: " . session_id() . "\n";
} else {
echo " Session active: NO\n";
}
echo "\n=== Test Complete ===\n";
} catch (Exception $e) {
echo " ✗ Error: " . $e->getMessage() . "\n";
echo " Stack trace:\n";
echo $e->getTraceAsString() . "\n";
}