Index: trunk/lib/App.inc.php
===================================================================
--- trunk/lib/App.inc.php	(revision 686)
+++ trunk/lib/App.inc.php	(revision 690)
@@ -89,8 +89,4 @@
         'redirect_home_url' => '/',
 
-        // SSL URL used when redirecting with $app->sslOn().
-        'ssl_domain' => null,
-        'ssl_enabled' => false,
-
         // Use CSRF tokens. See notes in the getCSRFToken() method.
         'csrf_token_enabled' => true,
@@ -211,4 +207,7 @@
         'tmp_dir' => '/tmp',
 
+        // Session files directory. If not defined, the default value from php.ini will be used.
+        'session_dir' => '',
+
         // A key for calculating simple cryptographic signatures. Set using as an environment variables in the httpd.conf with 'SetEnv SIGNING_KEY <key>'.
         // Existing password hashes rely on the same key/salt being used to compare encryptions.
@@ -383,4 +382,10 @@
         if ($this->getParam('php_timezone')) {
             $this->setTimezone($this->getParam('php_timezone'));
+        }
+
+        // If external request was HTTPS but internal request is HTTP, set $_SERVER['HTTPS']='on', which is used by the application to determine that TLS features should be enabled.
+        if (strtolower(getenv('HTTP_X_FORWARDED_PROTO')) == 'https' && strtolower(getenv('REQUEST_SCHEME')) == 'http') {
+            putenv('HTTPS=on'); // Available via getenv(âŠ)
+            isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] = 'on'; // Available via $_SERVER[âŠ]
         }
 
@@ -448,12 +453,24 @@
 
             // Session parameters.
+            // https://www.php.net/manual/en/session.security.ini.php
+            ini_set('session.cookie_httponly', true);
+            ini_set('session.cookie_secure', getenv('HTTPS') == 'on');
+            ini_set('session.cookie_samesite', 'Strict'); // Only PHP >= 7.3
+            // TODO: Reliance on gc_maxlifetime is not recommended. Developers should manage the lifetime of sessions with a timestamp by themselves.
+            ini_set('session.cookie_lifetime', 604800); // 7 days.
+            ini_set('session.gc_maxlifetime', 604800); // 7 days.
+            ini_set('session.gc_divisor', 1000);
             ini_set('session.gc_probability', 1);
-            ini_set('session.gc_divisor', 1000);
-            ini_set('session.gc_maxlifetime', 43200); // 12 hours
             ini_set('session.use_cookies', $this->getParam('session_use_cookies'));
+            ini_set('session.use_only_cookies', true);
             ini_set('session.use_trans_sid', false);
+            ini_set('session.use_strict_mode', true);
             ini_set('session.entropy_file', '/dev/urandom');
             ini_set('session.entropy_length', '512');
-            ini_set('session.cookie_httponly', true);
+            ini_set('session.sid_length', '48'); // Only PHP >= 7.1
+            ini_set('session.cache_limiter', 'nocache');
+            if ('' != $this->getParam('session_dir') && is_dir($this->getParam('session_dir'))) {
+                ini_set('session.save_path', $this->getParam('session_dir'));
+            }
             session_name($this->getParam('session_name'));
 
@@ -1146,5 +1163,4 @@
         $url = $parts[0];
         $anchor = isset($parts[1]) ? $parts[1] : '';
-        // $anchor =
 
         // Include the necessary SID if the following is true:
@@ -1411,4 +1427,5 @@
      * and the session is not already defined in the given $url, the SID is appended as a URI query.
      * As with all header generating functions, make sure this is called before any other output.
+     * Using relative URI with Location: header is valid as per https://tools.ietf.org/html/rfc7231#section-7.1.2
      *
      * @param   string  $url                    The URL the client will be redirected to.
@@ -1431,10 +1448,4 @@
             $url = $this->getParam('redirect_home_url');
         }
-
-        // FIXME: actually, it seems better to continue using a relative URL since we can't guess the port at the reverse proxy (e.g., port 3000 for browser-sync).
-        // if (preg_match('!^/!', $url)) {
-        //     // If relative URL is given, prepend site_url, which contains: scheme://hostname[:port]
-        //     $url = sprintf('%s%s', $this->getParam('site_url'), $url);k
-        // }
 
         $url = $this->url($url, $carry_args, $always_include_sid);
@@ -1638,7 +1649,7 @@
         }
 
-        if ($url == absoluteMe()) {
+        if ($url == absoluteMe() || $url == getenv('REQUEST_URI')) {
             // The URL we are directing to is the current page.
-            $this->logMsg(sprintf('validBoomerangURL(%s) not valid, same as absoluteMe: %s', $id, $url), LOG_DEBUG, __FILE__, __LINE__);
+            $this->logMsg(sprintf('validBoomerangURL(%s) not valid, same as absoluteMe or REQUEST_URI: %s', $id, $url), LOG_DEBUG, __FILE__, __LINE__);
             return false;
         }
@@ -1711,5 +1722,5 @@
         // Defaults.
         $expire = (is_numeric($expire) ? $expire : (is_string($expire) ? strtotime($expire) : $expire));
-        $secure = $secure ?: (getenv('HTTPS') && $this->getParam('ssl_enabled'));
+        $secure = $secure ?: getenv('HTTPS') == 'on';
         $httponly = $httponly ?: true;
 
Index: trunk/lib/Auth_File.inc.php
===================================================================
--- trunk/lib/Auth_File.inc.php	(revision 686)
+++ trunk/lib/Auth_File.inc.php	(revision 690)
@@ -324,5 +324,5 @@
 
             // Login scripts must have the same 'login' tag for boomerangURL verification/manipulation.
-            $app->setBoomerangURL(absoluteMe(), 'login');
+            $app->setBoomerangURL(getenv('REQUEST_URI'), 'login');
             $app->dieURL($this->_params['login_url']);
         }
Index: trunk/lib/Auth_SQL.inc.php
===================================================================
--- trunk/lib/Auth_SQL.inc.php	(revision 686)
+++ trunk/lib/Auth_SQL.inc.php	(revision 690)
@@ -610,4 +610,6 @@
      *  - remote address is the same as the login remote address
      *
+     * TODO: implement persisten sessions as per https://paragonie.com/blog/2015/04/secure-authentication-php-with-long-term-persistence
+     *
      * @access public
      */
@@ -771,5 +773,5 @@
 
             // Login scripts must have the same 'login' tag for boomerangURL verification/manipulation.
-            $app->setBoomerangURL(absoluteMe(), 'login');
+            $app->setBoomerangURL(getenv('REQUEST_URI'), 'login');
             $app->dieURL($this->_params['login_url']);
         }
Index: trunk/lib/Auth_Simple.inc.php
===================================================================
--- trunk/lib/Auth_Simple.inc.php	(revision 686)
+++ trunk/lib/Auth_Simple.inc.php	(revision 690)
@@ -261,5 +261,5 @@
 
             // Login scripts must have the same 'login' tag for boomerangURL verification/manipulation.
-            $app->setBoomerangURL(absoluteMe(), 'login');
+            $app->setBoomerangURL(getenv('REQUEST_URI'), 'login');
             $app->dieURL($this->_params['login_url']);
         }
Index: trunk/lib/Lock.inc.php
===================================================================
--- trunk/lib/Lock.inc.php	(revision 686)
+++ trunk/lib/Lock.inc.php	(revision 690)
@@ -389,5 +389,5 @@
         $app =& App::getInstance();
 
-        $app->dieURL($this->getParam('error_url'), array('lock_id' => $this->data['lock_id'], 'boomerang' => urlencode(absoluteMe())));
+        $app->dieURL($this->getParam('error_url'), array('lock_id' => $this->data['lock_id'], 'boomerang' => urlencode(getenv('REQUEST_URI'))));
     }
 
Index: trunk/lib/Utilities.inc.php
===================================================================
--- trunk/lib/Utilities.inc.php	(revision 686)
+++ trunk/lib/Utilities.inc.php	(revision 690)
@@ -1399,5 +1399,5 @@
 
 /**
- * Returns a fully qualified URL to the current script, including the query.
+ * Returns a fully qualified URL to the current script, including the query. If you don't need the scheme://, use REQUEST_URI instead.
  *
  * @return string    a full url to the current script
