diff --git a/lib/SimpleSAML/XHTML/Template.php b/lib/SimpleSAML/XHTML/Template.php
index d6f4d836caa7f2576281d3bec41b8fc9b6c3f5e0..9b2907fd327146fbca2a11df1c8ae4bc02006567 100644
--- a/lib/SimpleSAML/XHTML/Template.php
+++ b/lib/SimpleSAML/XHTML/Template.php
@@ -143,6 +143,29 @@ class Template extends Response
     }
 
 
+    /**
+     * Return the URL of an asset, including a cache-buster parameter that depends on the last modification time of
+     * the original file.
+     *
+     * @param string $asset
+     * @return string
+     */
+    public function asset($asset)
+    {
+        $file = $this->configuration->getBaseDir().'www/assets/'.$asset;
+        if (!file_exists($file)) {
+            // don't be too harsh if an asset is missing, just pretend it's there...
+            return $this->configuration->getBasePath().'assets/'.$asset;
+        }
+
+        $tag = $this->configuration->getVersion();
+        if ($tag === 'master') {
+            $tag = substr(hash('md5', filemtime($file)), 0, 5);
+        }
+        return $this->configuration->getBasePath().'assets/'.$asset.'?tag='.$tag;
+    }
+
+
     /**
      * Get the normalized template name.
      *
@@ -289,6 +312,9 @@ class Template extends Response
             )
         );
 
+        // add an asset() function
+        $twig->addFunction(new \Twig_SimpleFunction('asset', [$this, 'asset']));
+
         if ($this->controller) {
             $this->controller->setUpTwig($twig);
         }