From 918a1fb4b4616c4d1b1713f6ec531a660f0b8845 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jaime=20Pe=CC=81rez=20Crespo?= <jaime.perez@uninett.no>
Date: Thu, 7 Sep 2017 15:48:07 +0200
Subject: [PATCH] Add a new method SimpleSAML\Auth\getProcessedURL().

This method allows us to parse a URL and "rebase" it based on the $config['application']['baseURL'] configuration option. Thanks to this, applications will be able to configure a canonical base URL for the application, effectively translating any URL that might be built incorrectly (e.g. not using HTTPS because that is offloaded to a reverse proxy).
---
 lib/SimpleSAML/Auth/Simple.php | 55 ++++++++++++++++++++++++++++++++--
 lib/SimpleSAML/Utils/HTTP.php  |  4 +--
 2 files changed, 55 insertions(+), 4 deletions(-)

diff --git a/lib/SimpleSAML/Auth/Simple.php b/lib/SimpleSAML/Auth/Simple.php
index 16e8c32e6..b95a0d4c9 100644
--- a/lib/SimpleSAML/Auth/Simple.php
+++ b/lib/SimpleSAML/Auth/Simple.php
@@ -4,6 +4,8 @@ namespace SimpleSAML\Auth;
 
 use \SimpleSAML_Auth_Source as Source;
 use \SimpleSAML_Auth_State as State;
+use \SimpleSAML_Configuration as Configuration;
+use \SimpleSAML_Error_AuthSource as AuthSourceError;
 use \SimpleSAML\Module;
 use \SimpleSAML_Session as Session;
 use \SimpleSAML\Utils\HTTP;
@@ -21,8 +23,12 @@ class Simple
      *
      * @var string
      */
-    private $authSource;
+    protected $authSource;
 
+    /**
+     * @var \SimpleSAML_Configuration|null
+     */
+    protected $app_config;
 
     /**
      * Create an instance with the specified authsource.
@@ -34,6 +40,7 @@ class Simple
         assert('is_string($authSource)');
 
         $this->authSource = $authSource;
+        $this->app_config = Configuration::getInstance()->getConfigItem('application', null);
     }
 
 
@@ -48,7 +55,7 @@ class Simple
     {
         $as = Source::getById($this->authSource);
         if ($as === null) {
-            throw new \SimpleSAML_Error_AuthSource($this->authSource, 'Unknown authentication source.');
+            throw new AuthSourceError($this->authSource, 'Unknown authentication source.');
         }
         return $as;
     }
@@ -347,4 +354,48 @@ class Simple
 
         return $logout;
     }
+
+
+    /**
+     * Process a URL and modify it according to the application/baseURL configuration option, if present.
+     *
+     * @param string|null $url The URL to process, or null if we want to use the current URL. Both partial and full
+     * URLs can be used as a parameter. The maximum precedence is given to the application/baseURL configuration option,
+     * then the URL specified (if it specifies scheme, host and port) and finally the environment observed in the
+     * server.
+     *
+     * @return string The URL modified according to the precedence rules.
+     */
+    protected function getProcessedURL($url = null)
+    {
+        if ($url === null) {
+            $url = HTTP::getSelfURL();
+        }
+
+        $scheme = parse_url($url, PHP_URL_SCHEME);
+        $host = parse_url($url, PHP_URL_HOST) ?: HTTP::getSelfHost();
+        $port = parse_url($url, PHP_URL_PORT) ?: (
+            $scheme ? '' : trim(HTTP::getServerPort(), ':')
+        );
+        $scheme = $scheme ?: (HTTP::getServerHTTPS() ? 'https' : 'http');
+        $path = parse_url($url, PHP_URL_PATH) ?: '/';
+        $query = parse_url($url, PHP_URL_QUERY) ?: '';
+        $fragment = parse_url($url, PHP_URL_FRAGMENT) ?: '';
+
+        $port = !empty($port) ? ':'.$port : '';
+        if (($scheme === 'http' && $port === ':80') || ($scheme === 'https' && $port === ':443')) {
+            $port = '';
+        }
+
+        if (is_null($this->app_config)) {
+            // nothing more we can do here
+            return $scheme.'://'.$host.$port.$path.($query ? '?'.$query : '').($fragment ? '#'.$fragment : '');
+        }
+
+        $base =  trim($this->app_config->getString(
+            'baseURL',
+            $scheme.'://'.$host.$port
+        ), '/');
+        return $base.$path.($query ? '?'.$query : '').($fragment ? '#'.$fragment : '');
+    }
 }
diff --git a/lib/SimpleSAML/Utils/HTTP.php b/lib/SimpleSAML/Utils/HTTP.php
index 1f6e50cdb..a05753827 100644
--- a/lib/SimpleSAML/Utils/HTTP.php
+++ b/lib/SimpleSAML/Utils/HTTP.php
@@ -81,7 +81,7 @@ class HTTP
      *
      * @author Olav Morken, UNINETT AS <olav.morken@uninett.no>
      */
-    private static function getServerHTTPS()
+    public static function getServerHTTPS()
     {
         if (!array_key_exists('HTTPS', $_SERVER)) {
             // not an https-request
@@ -106,7 +106,7 @@ class HTTP
      *
      * @author Olav Morken, UNINETT AS <olav.morken@uninett.no>
      */
-    private static function getServerPort()
+    public static function getServerPort()
     {
         $port = (isset($_SERVER['SERVER_PORT'])) ? $_SERVER['SERVER_PORT'] : '80';
         if (self::getServerHTTPS()) {
-- 
GitLab