diff --git a/lib/SimpleSAML/Utils/System.php b/lib/SimpleSAML/Utils/System.php
index 6769ae9b6d83597d8e8078856e93560c38d75213..e0e93fab83055f2bd6f0198b96a5cd1f36e691be 100644
--- a/lib/SimpleSAML/Utils/System.php
+++ b/lib/SimpleSAML/Utils/System.php
@@ -107,7 +107,9 @@ class System
     /**
      * Resolve a (possibly) relative path from the given base path.
      *
-     * A path which starts with a '/' is assumed to be absolute, all others are assumed to be
+     * A path which starts with a stream wrapper pattern (e.g. s3://) will not be touched
+     * and returned as is - regardles of the value given as base path.
+     * If it starts with a '/' it is assumed to be absolute, all others are assumed to be
      * relative. The default base path is the root of the SimpleSAMLphp installation.
      *
      * @param string      $path The path we should resolve.
@@ -144,17 +146,21 @@ class System
             $ret = $base;
         }
 
-        $path = explode('/', $path);
-        foreach ($path as $d) {
-            if ($d === '.') {
-                continue;
-            } elseif ($d === '..') {
-                $ret = dirname($ret);
-            } else {
-                if ($ret && substr($ret, -1) !== '/') {
-                    $ret .= '/';
+        if (static::pathContainsStreamWrapper($path)){
+            $ret = $path;
+        } else {
+            $path = explode('/', $path);
+            foreach ($path as $d) {
+                if ($d === '.') {
+                    continue;
+                } elseif ($d === '..') {
+                    $ret = dirname($ret);
+                } else {
+                    if ($ret && substr($ret, -1) !== '/') {
+                        $ret .= '/';
+                    }
+                    $ret .= $d;
                 }
-                $ret .= $d;
             }
         }
 
@@ -239,4 +245,14 @@ class System
         return substr($path, 1, 1) === ':'
                 && $letterAsciiValue >= 65 && $letterAsciiValue <= 90;
     }
+
+    /**
+     * Check if the supplied path contains a stream wrapper
+     * @param string $path
+     * @return bool
+     */
+    private static function pathContainsStreamWrapper($path)
+    {
+        return preg_match('/^[\w\d]*:\/{2}/', $path) === 1;
+    }
 }
diff --git a/tests/lib/SimpleSAML/Utils/SystemTest.php b/tests/lib/SimpleSAML/Utils/SystemTest.php
index 99a77ebe08a0890f345b26583cbac427e79fb182..6b2c49b28e91105a413bf08a576a8926452d08e1 100644
--- a/tests/lib/SimpleSAML/Utils/SystemTest.php
+++ b/tests/lib/SimpleSAML/Utils/SystemTest.php
@@ -99,6 +99,36 @@ class SystemTest extends TestCase
         $this->assertEquals($expected, $res);
     }
 
+    /**
+     * @covers \SimpleSAML\Utils\System::resolvePath
+     * @test
+     */
+    public function testResolvePathAllowsStreamWrappers()
+    {
+        $base = '/base/';
+        $path = 'vfs://simplesaml';
+
+        $res = System::resolvePath($path, $base);
+        $expected = $path;
+
+        $this->assertEquals($expected, $res);
+    }
+
+    /**
+     * @covers \SimpleSAML\Utils\System::resolvePath
+     * @test
+     */
+    public function testResolvePathAllowsAwsS3StreamWrappers()
+    {
+        $base = '/base/';
+        $path = 's3://bucket-name/key-name';
+
+        $res = System::resolvePath($path, $base);
+        $expected = $path;
+
+        $this->assertEquals($expected, $res);
+    }
+
     /**
      * @covers \SimpleSAML\Utils\System::writeFile
      * @test
@@ -230,7 +260,6 @@ class SystemTest extends TestCase
 
         $this->clearInstance($config, '\SimpleSAML\Configuration');
     }
-
     private function setConfigurationTempDir($directory)
     {
         $config = Configuration::loadFromArray([