Overview
We've encountered significant challenges when deploying SimpleSAMLphp behind Nginx Unit, particularly with session persistence and SAML authentication flows. While SimpleSAMLphp functions correctly with Apache, we're consistently seeing session data loss when using Nginx Unit, primarily manifesting as "The POST data we should restore was lost" errors during SAML authentication.
Symptoms
-
Session and POST Data Loss
- SAML responses from IdP to SP through the ACS endpoint fail to maintain POST data
- Session data doesn't persist between authentication requests
- SAML authentication flow breaks with "The POST data we should restore was lost"
-
Nginx Unit-Specific Challenges
- Inability to modify incoming request headers in Nginx Unit
- No straightforward method to inject
X-Forwarded-Proto: https header
- Routing configuration in Nginx Unit significantly impacts SimpleSAMLphp's behavior
Root Cause Analysis
-
isHTTPS() Implementation Limitations
The current implementation in SimpleSAMLphp:
public function isHTTPS(): bool
{
return strpos($this->getSelfURL(), 'https://') === 0;
}
This approach is too simplistic as it only checks the URL scheme without considering proxy headers or the specific requirements of SAML ACS endpoints.
-
Session Cookie Handling
- Mismatch between
session.cookie.secure settings and actual protocol
- Cross-domain POST request issues with
SameSite cookie attribute
- Improper
session.cookie.path configurations leading to session data loss
-
Lack of POST Data Recovery
No robust mechanism exists to recover POST data when session failures occur
Implemented Solutions
-
Enhanced isHTTPS() Method
We've improved the HTTPS detection to handle various proxy configurations and edge cases:
public function isHTTPS(): bool
{
// Special handling for SAML ACS endpoint
$currentUrl = $_SERVER['REQUEST_URI'] ?? '';
if (strpos($currentUrl, '/module.php/saml/sp/saml2-acs.php/') !== false) {
// Force HTTPS for SAML ACS to maintain session integrity
Logger::debug('isHTTPS: Treating SAML ACS endpoint as HTTPS for session handling');
return true;
}
// Support for common proxy headers
if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])
&& strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https') {
return true;
}
// Standard HTTPS check
if (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') {
return true;
}
// Fallback to original URL-based check
return strpos($this->getSelfURL(), 'https://') === 0;
}
-
Persistent POST Data Storage
Added a fallback mechanism to store POST data in temporary files:
private function savePOSTData(Session $session, string $destination, array $data): string
{
// ... existing code ...
// Store POST data in temp file as fallback
$tempDir = sys_get_temp_dir() . '/simplesaml';
if (!is_dir($tempDir)) {
mkdir($tempDir, 0700, true);
}
$tempFile = $tempDir . '/post_' . $id . '.tmp';
file_put_contents($tempFile, json_encode($postData), LOCK_EX);
Logger::debug("Backed up POST data to temporary file: " . basename($tempFile));
return $id;
}
-
Robust POST Data Recovery
Implemented a recovery mechanism for session data loss scenarios:
public function postredirect(Request $request): Response
{
// ... existing code ...
$postData = $session->getData('core_postdatalink', $postId);
if ($postData === null) {
$tempFile = sys_get_temp_dir() . "/simplesaml/post_{$postId}.tmp";
if (file_exists($tempFile)) {
$content = file_get_contents($tempFile);
if ($content !== false) {
$postData = json_decode($content, true);
unlink($tempFile);
if (json_last_error() === JSON_ERROR_NONE) {
Logger::info("Recovered POST data from temp file for ID: {$postId}");
} else {
Logger::error("Failed to decode POST data from temp file: " . json_last_error_msg());
throw new \RuntimeException('The POST data we should restore was corrupted.');
}
}
}
if ($postData === null) {
Logger::error("Failed to recover POST data for ID: {$postId}");
throw new \RuntimeException('The POST data we should restore was lost.');
}
}
// ... rest of the implementation ...
}
Recommended Improvements for SimpleSAMLphp
-
Enhanced isHTTPS() Method
- Add comprehensive proxy header support (
X-Forwarded-Proto, X-Forwarded-SSL)
- Implement configurable URL patterns that should always be treated as HTTPS
- Document proxy configuration requirements and best practices
-
Robust POST Data Handling
- Implement built-in fallback storage mechanisms for POST data
- Add session recovery capabilities with configurable storage backends
- Include detailed logging for troubleshooting session issues
-
Improved Web Server Compatibility
- Create dedicated documentation for Nginx Unit configuration
- Add automated tests for different web server configurations
- Document common pitfalls and solutions for various deployment scenarios
Conclusion
While our current workarounds address the immediate issues with Nginx Unit, we strongly recommend incorporating these improvements into the main SimpleSAMLphp codebase. This would significantly enhance compatibility across different web servers and deployment scenarios, particularly in environments with complex proxy configurations or mixed HTTP/HTTPS requirements. The proposed changes would make SimpleSAMLphp more robust and easier to maintain in enterprise environments.
Overview
We've encountered significant challenges when deploying SimpleSAMLphp behind Nginx Unit, particularly with session persistence and SAML authentication flows. While SimpleSAMLphp functions correctly with Apache, we're consistently seeing session data loss when using Nginx Unit, primarily manifesting as "The POST data we should restore was lost" errors during SAML authentication.
Symptoms
Session and POST Data Loss
Nginx Unit-Specific Challenges
X-Forwarded-Proto: httpsheaderRoot Cause Analysis
isHTTPS()Implementation LimitationsThe current implementation in SimpleSAMLphp:
This approach is too simplistic as it only checks the URL scheme without considering proxy headers or the specific requirements of SAML ACS endpoints.
Session Cookie Handling
session.cookie.securesettings and actual protocolSameSitecookie attributesession.cookie.pathconfigurations leading to session data lossLack of POST Data Recovery
No robust mechanism exists to recover POST data when session failures occur
Implemented Solutions
Enhanced
isHTTPS()MethodWe've improved the HTTPS detection to handle various proxy configurations and edge cases:
Persistent POST Data Storage
Added a fallback mechanism to store POST data in temporary files:
Robust POST Data Recovery
Implemented a recovery mechanism for session data loss scenarios:
Recommended Improvements for SimpleSAMLphp
Enhanced
isHTTPS()MethodX-Forwarded-Proto,X-Forwarded-SSL)Robust POST Data Handling
Improved Web Server Compatibility
Conclusion
While our current workarounds address the immediate issues with Nginx Unit, we strongly recommend incorporating these improvements into the main SimpleSAMLphp codebase. This would significantly enhance compatibility across different web servers and deployment scenarios, particularly in environments with complex proxy configurations or mixed HTTP/HTTPS requirements. The proposed changes would make SimpleSAMLphp more robust and easier to maintain in enterprise environments.