diff --git a/lib/SimpleSAML/Module.php b/lib/SimpleSAML/Module.php
index 18a332b51415af4f96bd89c4f4c26b6dc892a19c..9d0f1fdcbb49f5f459ad9c2467db6f15f8745615 100644
--- a/lib/SimpleSAML/Module.php
+++ b/lib/SimpleSAML/Module.php
@@ -146,6 +146,37 @@ class SimpleSAML_Module {
 		return SimpleSAML_Utilities::selfURLhost() . '/' . $config->getBaseURL() . 'module.php/' . $resource;
 	}
 
+
+	/**
+	 * Call a hook in all enabled modules.
+	 *
+	 * This function iterates over all enabled modules and calls a hook in each module.
+	 *
+	 * @param string $hook  The name of the hook.
+	 * @param mixed &$data  The data which should be passed to each hook. Will be passed as a reference.
+	 */
+	public static function callHooks($hook, &$data = NULL) {
+		assert('is_string($hook)');
+
+		foreach (self::getModules() as $module) {
+			if (!self::isModuleEnabled($module)) {
+				continue;
+			}
+
+			$hookfile = self::getModuleDir($module) . '/hooks/hook_' . $hook . '.php';
+			if (!file_exists($hookfile)) {
+				continue;
+			}
+
+			require_once($hookfile);
+
+			$hookfunc = $module . '_hook_' . $hook;
+			assert('is_callable($hookfunc)');
+
+			$hookfunc($data);
+		}
+	}
+
 }
 
 ?>
\ No newline at end of file