diff --git a/modules/openidProvider/config-template/module_openidProvider.php b/modules/openidProvider/config-template/module_openidProvider.php
new file mode 100644
index 0000000000000000000000000000000000000000..ce391ebe985a063f6eabca88f6a1b07bd72ac753
--- /dev/null
+++ b/modules/openidProvider/config-template/module_openidProvider.php
@@ -0,0 +1,17 @@
+<?php
+/**
+ * Configuration file for the OpenID provider.
+ */
+
+$config = array(
+
+	/* The authentication source that should be used. */
+	'auth' => 'default-sp',
+
+	/* The name of the attribute which contains the username of the user. */
+	'username_attribute' => 'uid',
+
+	/* The directory where OpenID data is stored. */
+	'filestore' => '/tmp/ssp-openid-provider',
+
+);
diff --git a/modules/openidProvider/default-disable b/modules/openidProvider/default-disable
new file mode 100644
index 0000000000000000000000000000000000000000..fa0bd82e2df7bd79d57593d35bc53c1f9d3ef71f
--- /dev/null
+++ b/modules/openidProvider/default-disable
@@ -0,0 +1,3 @@
+This file indicates that the default state of this module
+is disabled. To enable, create a file named enable in the
+same directory as this file.
diff --git a/modules/openidProvider/dictionaries/op.php b/modules/openidProvider/dictionaries/op.php
new file mode 100644
index 0000000000000000000000000000000000000000..3154cabf5e0f1f26734329a6ea06ea9ee26405a6
--- /dev/null
+++ b/modules/openidProvider/dictionaries/op.php
@@ -0,0 +1,138 @@
+<?php
+
+/*
+ * DO NOT EDIT THIS FILE MANUALLY.
+ * If you want to contribute to translation, you must instead use the 
+ * SimpleSAMLphp translation portal:
+ * https://translation.rnd.feide.no/index.php?aid=simplesamlphp
+ *
+ * This file is automatically generated from the translation portal.
+ */
+
+$lang = array(
+	'title_no_user' => array (
+		'no' => 'OpenID tilbyder',
+		'en' => 'OpenID provider',
+	),
+	'title_user' => array (
+		'no' => 'OpenID for %USERID%',
+		'en' => 'OpenID for %USERID%',
+	),
+	'user_page_for' => array (
+		'no' => 'Dette er OpenID brukersiden for <code>%USERID%</code>.',
+		'en' => 'This is the OpenID user page for <code>%USERID%</code>.',
+	),
+	'view_own_page' => array (
+		'no' => 'Se pĂĄ din egen OpenID side.',
+		'en' => 'View your own OpenID page.',
+	),
+	'login_view_own_page' => array (
+		'no' => 'Logg pĂĄ for ĂĄ se pĂĄ din egen OpenID side.',
+		'en' => 'Log in to view your own OpenID page.',
+	),
+	'your_identifier' => array (
+		'en' => 'To log in with your OpenID identifier, use the following identifier:',
+	),
+	'howto_delegate' => array (
+		'en' => 'You can also delegate a different identifier to use this OpenID provider. To do that, you need to add the following to the <code>&lt;head&gt;</code>-element on the webpage of that identifier:',
+	),
+	'logout_title' => array (
+		'no' => 'Logg av',
+		'en' => 'Log out',
+	),
+	'logout' => array (
+		'no' => 'Trykk her for ĂĄ logge ut av din OpenID bruker.',
+		'en' => 'Click here to log out of your OpenID user.',
+	),
+	'confirm_question' => array (
+		'no' => 'Ønsker du å logge på %SITEURL%?',
+		'en' => 'Do you wish to log on to %SITEURL%?',
+	),
+	'remember' => array (
+		'no' => 'Husk dette valget',
+		'nn' => 'Hugs denne avgjerda',
+		'da' => 'Husk dette',
+		'en' => 'Remember this decision',
+		'de' => 'Diese Entscheidung merken',
+		'sv' => 'Spara detta beslut',
+		'es' => 'Recordar esta decisiĂłn',
+		'nl' => 'Onthoud deze keuze',
+		'sl' => 'Zapomni si to odloÄŤitev',
+		'hr' => 'Zapamti ovu odluku',
+		'hu' => 'Emlékezzen erre a választásra',
+		'pl' => 'Zapamiętaj tą decyzję',
+		'pt' => 'Lembrar esta decisĂŁo',
+		'pt-BR' => 'Lembrar desta decisĂŁo',
+		'tr' => 'Kararımı hatırla',
+	),
+	'confirm' => array (
+		'no' => 'Bekreft',
+		'nn' => 'Stadfest',
+		'da' => 'Bekræft',
+		'en' => 'Confirm',
+		'de' => 'Bestätigen',
+		'sv' => 'Bekräfta',
+		'es' => 'Confirmar',
+		'nl' => 'Bevestig',
+		'sl' => 'Potrdi',
+		'hr' => 'Potvrdi',
+		'hu' => 'Megerősít',
+		'pl' => 'PotwierdĹş',
+		'pt' => 'Confirmar',
+		'pt-BR' => 'Confirmar',
+		'tr' => 'DoÄźrula',
+	),
+	'notconfirm' => array (
+		'no' => 'Ikke bekreft',
+		'nn' => 'Treng ikkje stadfesting',
+		'da' => 'Bekræft ikke',
+		'en' => 'Do not confirm',
+		'de' => 'Nicht Bestätigen',
+		'sv' => 'Bekräfta inte',
+		'es' => 'No confirmar',
+		'nl' => 'Weiger',
+		'sl' => 'Ne potrdi',
+		'hr' => 'Nemoj potvrditi',
+		'hu' => 'Nem erősíti meg',
+		'pl' => 'Nie potwierdzaj',
+		'pt' => 'NĂŁo confirmar',
+		'pt-BR' => 'NĂŁo confirmar',
+		'tr' => 'DoÄźrulama',
+	),
+	'trustlist_trustedsites' => array (
+		'no' => 'Klarerte websider',
+		'nn' => 'Tiltrudde partnarar',
+		'da' => 'Hjemmesider du har tillid til',
+		'en' => 'Trusted Sites',
+		'de' => 'Vertraute Seiten',
+		'sv' => 'Godkända sajter',
+		'es' => 'Sitios de confianza',
+		'nl' => 'Trusted Sites',
+		'sl' => 'Zaupanja vredne strani',
+		'hr' => 'Sjedišta kojima vjerujete',
+		'hu' => 'MegbĂ­zhatĂł oldalak',
+		'pl' => 'Zaufane strony',
+		'pt' => 'Sites confiáveis',
+		'pt-BR' => 'Sites Confiáveis',
+		'tr' => 'GĂĽvenilir Siteler',
+	),
+	'trustlist_remove' => array (
+		'no' => 'Fjern',
+		'nn' => 'Ta vekk',
+		'da' => 'Fjern',
+		'en' => 'Remove',
+		'de' => 'Ausgewählte löschen',
+		'sv' => 'Ta bort',
+	),
+	'trustlist_nosites' => array (
+		'no' => 'Ingen sites er husket. NĂĄr du autentiserer deg hos en site, kan du velge ĂĄ legge den til denne listen ved ĂĄ velge <q>Husk dette valget</q>.',
+		'nn' => 'Ingen tenester er lagra.  NĂĄr du logger inn pĂĄ ei teneste, kan du velja ĂĄ leggja ho inn pĂĄ lista over tiltrudde partnarar ved ĂĄ velja <q>Hugs denne avgjerda</q>.',
+		'da' => 'Der er ikke gemt nogle sites. Når authenticater mod et site kan du vælge at gemme sitet i denne liste ved at vælge <q>Gem mit valg</q>',
+		'en' => 'No sites are trusted. When you authenticate with a site, you can choose to add it to this list by choosing <q>Remember this decision</q>.',
+		'sv' => 'Inga sajter är sparade. När du loggar in på en sajt kan du välja om du ska lägga den i listan genom att välja <q>Spara detta beslut</q>.',
+	),
+
+);
+
+
+?>
\ No newline at end of file
diff --git a/modules/openidProvider/docs/provider.txt b/modules/openidProvider/docs/provider.txt
new file mode 100644
index 0000000000000000000000000000000000000000..53dac6415aadc74d39f7b85a27be7ee9279ea038
--- /dev/null
+++ b/modules/openidProvider/docs/provider.txt
@@ -0,0 +1,56 @@
+OpenID provider support
+=======================
+
+simpleSAMLphp can act as an OpenID provider.
+This allows you to integrate OpenID into an existing IdP, or to add a bridge between OpenID and SAML 2.0.
+
+To use it, you need to enable the OpenID provider module:
+
+    touch modules/openidProvider/enable
+
+You must also edit the configuration file:
+
+    cp modules/openidProvider/config-template/module_openidProvider.php config/
+    "$EDITOR" config/module_openidProvider.php
+
+
+Options
+-------
+
+The following options must be set in the configuration file:
+
+`auth`
+:   The authentication source that should be used to authenticate users who access the OpenID endpoint.
+    This can be any authentication source configured in `config/authsources.php`.
+
+:   To configure this as a bridge, set up a `saml` authentication source, and use that one.
+
+`username_attribute`
+:   The name of the attribute that contains the username of the user.
+
+
+`filestore`
+:   A path to a directory where the OpenID provider can save data.
+    This directory must be writeable by the web server.
+
+
+Testing
+-------
+
+To test your provider, go to the authentication tab on the frontpage.
+There you will find a link to the OpenID provider.
+Click that link and log in.
+
+Once you are logged in, the OpenID identifier for your user will be displayed.
+Use that identifier with an OpenID consumer to test authentication.
+
+
+Delegation
+----------
+
+The OpenID identifier created by the simpleSAMLphp OpenID provider is quite long and hard to type.
+To use a simpler identifier, you can delegate accesses from the simple identifier to the OpenID provider.
+Your OpenID page will list two `<link>`-elements that you can add to any web page in order to turn it into your OpenID identifier.
+
+For example, to use `myid.example.org` as your OpeNID identifier, add the `<link>`-elements to the web page which handles `http://myid.example.org/`.
+
diff --git a/modules/openidProvider/lib/Server.php b/modules/openidProvider/lib/Server.php
new file mode 100644
index 0000000000000000000000000000000000000000..e930b2d8ea2ef69b1afab205bbcf7c5171fb917f
--- /dev/null
+++ b/modules/openidProvider/lib/Server.php
@@ -0,0 +1,430 @@
+<?php
+
+/**
+ * Helper class for the OpenID provider code.
+ *
+ * @package simpleSAMLphp
+ * @version $Id$
+ */
+class sspmod_openidProvider_Server {
+
+	/**
+	 * The authencication source for this provider.
+	 *
+	 * @var SimpleSAML_Auth_Simple
+	 */
+	private $authSource;
+
+
+	/**
+	 * The attribute name where the username is stored.
+	 *
+	 * @var string
+	 */
+	private $usernameAttribute;
+
+
+	/**
+	 * The OpenID server.
+	 *
+	 * @var Auth_OpenID_Server
+	 */
+	private $server;
+
+
+	/**
+	 * The directory which contains the trust roots for the users.
+	 *
+	 * @var string
+	 */
+	private $trustStoreDir;
+
+
+	/**
+	 * The instance of the OpenID provider class.
+	 *
+	 * @var sspmod_openidProvider_Server
+	 */
+	private static $instance;
+
+
+	/**
+	 * Retrieve the OpenID provider class.
+	 *
+	 * @return sspmod_openidProvider_Server  The OpenID Provider class.
+	 */
+	public static function getInstance() {
+
+		if (self::$instance === NULL) {
+			self::$instance = new sspmod_openidProvider_Server();
+		}
+		return self::$instance;
+	}
+
+
+	/**
+	 * The constructor for the OpenID provider class.
+	 *
+	 * Initializes and validates the configuration.
+	 */
+	private function __construct() {
+
+		$config = SimpleSAML_Configuration::getConfig('module_openidProvider.php');
+
+		$this->authSource = new SimpleSAML_Auth_Simple($config->getString('auth'));
+		$this->usernameAttribute = $config->getString('username_attribute');
+		$this->delegationPrefix = $config->getString('delegation_prefix');
+
+		SimpleSAML_Utilities::maskErrors(E_WARNING | E_STRICT);
+		try {
+			$store = new Auth_OpenID_FileStore($config->getString('filestore'));
+			$this->server = new Auth_OpenID_Server($store);
+		} catch (Exception $e) {
+			SimpleSAML_Utilities::popErrorMask();
+			throw $e;
+		}
+		SimpleSAML_Utilities::popErrorMask();
+
+		$this->trustStoreDir = realpath($config->getString('filestore')) . '/truststore';
+		if (!is_dir($this->trustStoreDir)) {
+			$res = mkdir($this->trustStoreDir, 0777, TRUE);
+			if (!$res) {
+				throw new SimpleSAML_Error_Exception('Failed to create directory: ' . $this->trustStoreDir);
+			}
+		}
+
+	}
+
+
+	/**
+	 * Retrieve the authentication source used by the OpenID Provider.
+	 *
+	 * @return SimpleSAML_Auth_Simple  The authentication source.
+	 */
+	public function getAuthSource() {
+
+		return $this->authSource;
+	}
+
+
+	/**
+	 * Retrieve the current user ID.
+	 *
+	 * @return string  The current user ID, or NULL if the user isn't authenticated.
+	 */
+	public function getUserId() {
+
+		if (!$this->authSource->isAuthenticated()) {
+			return NULL;
+		}
+
+		$attributes = $this->authSource->getAttributes();
+		if (!array_key_exists($this->usernameAttribute, $attributes)) {
+			throw new SimpleSAML_Error_Exception('Missing username attribute ' .
+				var_export($this->usernameAttribute, TRUE) . ' in the attributes of the user.');
+		}
+
+		$values = array_values($attributes[$this->usernameAttribute]);
+		if (empty($values)) {
+			throw new SimpleSAML_Error_Exception('Username attribute was empty.');
+		}
+		if (count($values) > 1) {
+			throw new SimpleSAML_Error_Exception('More than one attribute value in username.');
+		}
+
+		$userId = $values[0];
+		return $userId;
+	}
+
+
+	/**
+	 * Retrieve the current identity.
+	 *
+	 * @return string  The current identity, or NULL if the user isn't authenticated.
+	 */
+	public function getIdentity() {
+
+		$userId = $this->getUserId();
+		if ($userId === NULL) {
+			return NULL;
+		}
+
+		$identity = SimpleSAML_Module::getModuleURL('openidProvider/user.php/' . $userId);
+		return $identity;
+	}
+
+
+	/**
+	 * Retrieve the URL of the server.
+	 *
+	 * @return string  The URL of the OpenID server.
+	 */
+	public function getServerURL() {
+
+		return SimpleSAML_Module::getModuleURL('openidProvider/server.php');
+	}
+
+
+	/**
+	 * Get the file that contains the trust roots for the user.
+	 *
+	 * @param string $identity  The identity of the user.
+	 * @return string  The file name.
+	 */
+	private function getTrustFile($identity) {
+		assert('is_string($identity)');
+
+		$path = $this->trustStoreDir . '/' . sha1($identity) . '.serialized';
+		return $path;
+	}
+
+
+	/**
+	 * Get the sites the user trusts.
+	 *
+	 * @param string $identity  The identity of the user.
+	 * @param array $trustRoots  The trust roots the user trusts.
+	 */
+	public function saveTrustRoots($identity, array $trustRoots) {
+		assert('is_string($identity)');
+
+		$file = $this->getTrustFile($identity);
+		$tmpFile = $file . '.new.' . getmypid();
+
+		$data = serialize($trustRoots);
+
+		$ok = file_put_contents($tmpFile, $data);
+		if ($ok === FALSE) {
+			throw new SimpleSAML_Error_Exception('Failed to save file ' . var_export($tmpFile, TRUE));
+		}
+
+		$ok = rename($tmpFile, $file);
+		if ($ok === FALSE) {
+			throw new SimpleSAML_Error_Exception('Failed rename ' . var_export($tmpFile, TRUE) .
+				' to ' . var_export($file, TRUE) . '.');
+		}
+	}
+
+
+	/**
+	 * Get the sites the user trusts.
+	 *
+	 * @param string $identity  The identity of the user.
+	 * @return array  The trust roots the user trusts.
+	 */
+	public function getTrustRoots($identity) {
+		assert('is_string($identity)');
+
+		$file = $this->getTrustFile($identity);
+
+		if (!file_exists($file)) {
+			return array();
+		}
+
+		$data = file_get_contents($file);
+		if ($data === FALSE) {
+			throw new SimpleSAML_Error_Exception('Failed to load file ' .
+				var_export($file, TRUE). '.');
+		}
+
+		$data = unserialize($data);
+		if ($data === FALSE) {
+			throw new SimpleSAML_Error_Exception('Error unserializing trust roots from file ' .
+				var_export($file, TRUE) . '.');
+		}
+
+		return $data;
+	}
+
+
+	/**
+	 * Add the given trust root to the user.
+	 *
+	 * @param string $identity  The identity of the user.
+	 * @param string $trustRoot  The trust root.
+	 */
+	public function addTrustRoot($identity, $trustRoot) {
+		assert('is_string($identity)');
+		assert('is_string($trustRoot)');
+
+		$trs = $this->getTrustRoots($identity);
+		if (!in_array($trustRoot, $trs, TRUE)) {
+			$trs[] = $trustRoot;
+		}
+
+		$this->saveTrustRoots($identity, $trs);
+	}
+
+
+	/**
+	 * Remove the given trust root from the trust list of the user.
+	 *
+	 * @param string $identity  The identity of the user.
+	 * @param string $trustRoot  The trust root.
+	 */
+	public function removeTrustRoot($identity, $trustRoot) {
+		assert('is_string($identity)');
+		assert('is_string($trustRoot)');
+
+		$trs = $this->getTrustRoots($identity);
+
+		$i = array_search($trustRoot, $trs, TRUE);
+		if ($i === FALSE) {
+			return;
+		}
+		array_splice($trs, $i, 1, array());
+		$this->saveTrustRoots($identity, $trs);
+	}
+
+
+	/**
+	 * Is the given trust root trusted by the user?
+	 *
+	 * @param string $identity  The identity of the user.
+	 * @param string $trustRoot  The trust root.
+	 * @return TRUE if it is trusted, FALSE if not.
+	 */
+	private function isTrusted($identity, $trustRoot) {
+		assert('is_string($identity)');
+		assert('is_string($trustRoot)');
+
+		$trs = $this->getTrustRoots($identity);
+		return in_array($trustRoot, $trs, TRUE);
+	}
+
+
+	/**
+	 * Save the state, and return an URL that can contain a reference to the state.
+	 *
+	 * @param string $page  The name of the page.
+	 * @param array $state  The state array.
+	 * @return string  An URL with the state ID as a parameter.
+	 */
+	private function getStateURL($page, array $state) {
+		assert('is_string($page)');
+
+		$stateId = SimpleSAML_Auth_State::saveState($state, 'openidProvider:resumeState');
+		$stateURL = SimpleSAML_Module::getModuleURL('openidProvider/' . $page);
+		$stateURL = SimpleSAML_Utilities::addURLparameter($stateURL, array('StateID' => $stateId));
+
+		return $stateURL;
+	}
+
+
+	/**
+	 * Retrieve state by ID.
+	 *
+	 * @param string $stateId  The state ID.
+	 * @return array  The state array.
+	 */
+	public function loadState($stateId) {
+		assert('is_string($stateId)');
+
+		return SimpleSAML_Auth_State::loadState($stateId, 'openidProvider:resumeState');
+	}
+
+
+	/**
+	 * Send an OpenID response.
+	 *
+	 * This function never returns.
+	 *
+	 * @param Auth_OpenID_ServerResponse $response  The response.
+	 */
+	private function sendResponse(Auth_OpenID_ServerResponse $response) {
+
+		SimpleSAML_Logger::debug('openidProvider::sendResponse');
+
+		$webresponse = $this->server->encodeResponse($response);
+
+		if ($webresponse->code !== 200) {
+			header('HTTP/1.1 ' . $webresponse->code, TRUE, $webresponse->code);
+		}
+
+		foreach ($webresponse->headers as $k => $v) {
+			header($k . ': ' . $v);
+		}
+		header('Connection: Close');
+
+		print($webresponse->body);
+		exit(0);
+	}
+
+
+	/**
+	 * Process a request.
+	 *
+	 * This function never returns.
+	 *
+	 * @param Auth_OpenID_Request $request  The request we are processing.
+	 */
+	public function processRequest(array $state) {
+		assert('isset($state["request"])');
+
+		SimpleSAML_Utilities::maskErrors(E_NOTICE | E_STRICT);
+
+		$request = $state['request'];
+
+		if (!$this->authSource->isAuthenticated()) {
+			if ($request->immediate) {
+				/* Not logged in, and we cannot show a login form. */
+				$this->sendResponse($request->answer(FALSE));
+			}
+
+			$resumeURL = $this->getStateURL('resume.php', $state);
+			$this->authSource->requireAuth(array('ReturnTo' => $resumeURL));
+		}
+
+		$identity = $this->getIdentity();
+		if ($identity !== $request->identity) {
+			/* The identity in the request doesn't match the one of the logged in user. */
+			throw new SimpleSAML_Error_Exception('Logged in as different user than the one requested.');
+		}
+
+		if ($this->isTrusted($identity, $request->trust_root)) {
+			$trusted = TRUE;
+		} elseif (isset($state['TrustResponse'])) {
+			$trusted = (bool)$state['TrustResponse'];
+		} else {
+			if ($request->immediate) {
+				/* Not trusted, and we cannot show a trust-form. */
+				$this->sendResponse($request->answer(FALSE));
+			}
+
+			$trustURL = $this->getStateURL('trust.php', $state);
+			SimpleSAML_Utilities::redirect($trustURL);
+		}
+
+		if (!$trusted) {
+			/* The user doesn't trust this site. */
+			$this->sendResponse($request->answer(FALSE));
+		}
+
+		/* The user is authenticated, and trusts this site. */
+		$this->sendResponse($request->answer(TRUE));
+	}
+
+
+	/**
+	 * Receive an incoming request.
+	 *
+	 * This function never returns.
+	 */
+	public function receiveRequest() {
+
+		SimpleSAML_Utilities::maskErrors(E_NOTICE | E_STRICT);
+
+		$request = $this->server->decodeRequest();
+
+		if (!in_array($request->mode, array('checkid_immediate', 'checkid_setup'), TRUE)) {
+			$this->sendResponse($this->server->handleRequest($request));
+		}
+
+		$state = array(
+			'request' => $request,
+		);
+
+		$this->processRequest($state);
+	}
+
+}
diff --git a/modules/openidProvider/templates/trust.tpl.php b/modules/openidProvider/templates/trust.tpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..12787f7e0727dd30b95274453a523b93cd1212cd
--- /dev/null
+++ b/modules/openidProvider/templates/trust.tpl.php
@@ -0,0 +1,27 @@
+<?php
+$this->includeAtTemplateBase('includes/header.php');
+?>
+
+<div class="form">
+<?php
+$params = array(
+	'%SITEURL%' => '<code>' . htmlspecialchars($this->data['trustRoot']) . '</code>',
+	);
+echo('<p>' . $this->t('{openidProvider:op:confirm_question}', $params) . '</p>');
+?>
+<form method="post" action="?">
+<input type="hidden" name="StateID" value="<?php echo $this->data['StateID']; ?>" />
+
+<input type="checkbox" name="TrustRemember" value="on" id="remember" />
+<label for="TrustRemember"><?php echo($this->t('{openidProvider:op:remember}')); ?></label>
+<br />
+
+<input type="submit" name="TrustYes" value="<?php echo($this->t('{openidProvider:op:confirm}')); ?>" />
+<input type="submit" name="TrustNo" value="<?php echo($this->t('{openidProvider:op:notconfirm}')); ?>" />
+
+</form>
+</div>
+
+<?php
+$this->includeAtTemplateBase('includes/footer.php');
+?>
\ No newline at end of file
diff --git a/modules/openidProvider/templates/user.tpl.php b/modules/openidProvider/templates/user.tpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..36de2ab93e7098055ba9688b4de27e82e09777f3
--- /dev/null
+++ b/modules/openidProvider/templates/user.tpl.php
@@ -0,0 +1,76 @@
+<?php
+$identity = $this->data['identity'];
+$loggedInAs = $this->data['loggedInAs'];
+$loginURL = $this->data['loginURL'];
+$logoutURL = $this->data['logoutURL'];
+$ownPage = $this->data['ownPage'];
+$serverURL = $this->data['serverURL'];
+$trustedSites = $this->data['trustedSites'];
+$userId = $this->data['userId'];
+$userIdURL = $this->data['userIdURL'];
+
+if ($userId !== FALSE) {
+	$title = $this->t('{openidProvider:op:title_user}', array('%USERID%' => htmlspecialchars($userId)));
+} else {
+	$title = $this->t('{openidProvider:op:title_no_user}');
+}
+
+$serverLink = '<link rel="openid.server" href="' . htmlspecialchars($serverURL) . '" />';
+$delegateLink = '<link rel="openid.delegate" href="' . htmlspecialchars($userIdURL) . '" />';
+
+$this->data['header'] = $title;
+$this->data['head'] = $serverLink;
+$this->includeAtTemplateBase('includes/header.php');
+
+echo('<h2>' . $title . '</h2>');
+
+if ($userId !== FALSE) {
+	echo('<p>' . $this->t('{openidProvider:op:user_page_for}', array('%USERID%' => htmlspecialchars($userId))) . '</p>');
+}
+
+if ($loggedInAs === NULL) {
+	echo('<p><a href="' . htmlspecialchars($loginURL) . '">' . $this->t('{openidProvider:op:login_view_own_page}') . '</a></p>');
+} elseif (!$ownPage) {
+	echo('<p><a href="' . htmlspecialchars($identity) . '">' . $this->t('{openidProvider:op:view_own_page}') . '</a></p>');
+}
+
+if ($ownPage) {
+
+
+	echo('<h3>Using your OpenID</h3>');
+	echo('<p>');
+	echo($this->t('{openidProvider:op:your_identifier}') . '<br />');
+	echo('<code>' . htmlspecialchars($userIdURL) . '</code>');
+	echo('</p>');
+	echo('<p>');
+	echo($this->t('{openidProvider:op:howto_delegate}'));
+	echo('<br />');
+	echo('<pre>' . htmlspecialchars($serverLink) . "\n" . htmlspecialchars($delegateLink) . '</pre>');
+	echo('</p>');
+
+	echo('<h3>' . $this->t('{openidProvider:op:trustlist_trustedsites}') . '</h3>');
+	if (count($trustedSites) > 0) {
+		echo('<div class="form">');
+		echo('<form method="post" action="?">');
+		echo('<ul>');
+
+		foreach ($trustedSites as $site) {
+			echo '<li>';
+			echo '<input type="submit" name="remove_' . bin2hex($site) .
+				'" value="' . $this->t('{openidProvider:op:trustlist_remove}') . '" />';
+			echo ' <code>' . htmlspecialchars($site) . '</code>';
+			echo '</li>';
+		}
+		echo('</ul>');
+		echo('</form>');
+		echo('</div>');
+	} else {
+		echo('<p>' . $this->t('{openidProvider:op:trustlist_nosites}') . '</p>');
+	}
+
+	echo('<h3>' . $this->t('{openidProvider:op:logout_title}') . '</h3>');
+	echo('<p><a href="' . htmlspecialchars($logoutURL) . '">' . $this->t('{openidProvider:op:logout}') . '</a></p>');
+}
+
+$this->includeAtTemplateBase('includes/footer.php');
+?>
\ No newline at end of file
diff --git a/modules/openidProvider/www/resume.php b/modules/openidProvider/www/resume.php
new file mode 100644
index 0000000000000000000000000000000000000000..7d09be588d27a9c0e6833a0d703357934b9542da
--- /dev/null
+++ b/modules/openidProvider/www/resume.php
@@ -0,0 +1,9 @@
+<?php
+
+if (!is_string($_REQUEST['StateID'])) {
+	throw new SimpleSAML_Error_BadRequest('Missing StateID-parameter');
+}
+
+$server = sspmod_openidProvider_Server::getInstance();
+$state = $server->loadState($_REQUEST['StateID']);
+$server->processRequest($state);
diff --git a/modules/openidProvider/www/server.php b/modules/openidProvider/www/server.php
new file mode 100644
index 0000000000000000000000000000000000000000..4d06c1ae69f9d1abe874c4d7b71ac29a41d63695
--- /dev/null
+++ b/modules/openidProvider/www/server.php
@@ -0,0 +1,6 @@
+<?php
+
+SimpleSAML_Logger::info('OpenID - Provider: Accessing OpenID Provider endpoint');
+
+$server = sspmod_openidProvider_Server::getInstance();
+$server->receiveRequest();
diff --git a/modules/openidProvider/www/trust.php b/modules/openidProvider/www/trust.php
new file mode 100644
index 0000000000000000000000000000000000000000..a48d05ab3361819948f53c80792578623d04ab6f
--- /dev/null
+++ b/modules/openidProvider/www/trust.php
@@ -0,0 +1,36 @@
+<?php
+
+if (!is_string($_REQUEST['StateID'])) {
+	throw new SimpleSAML_Error_BadRequest('Missing StateID-parameter.');
+}
+$StateID = $_REQUEST['StateID'];
+
+$server = sspmod_openidProvider_Server::getInstance();
+$state = $server->loadState($_REQUEST['StateID']);
+
+$trustRoot = $state['request']->trust_root;
+$identity = $server->getIdentity();
+if ($identity === NULL) {
+	$server->processRequest($state);
+}
+
+
+if (isset($_REQUEST['TrustYes'])) {
+	if (isset($_REQUEST['TrustRemember'])) {
+		$server->addTrustRoot($identity, $trustRoot);
+	}
+
+	$state['TrustResponse'] = TRUE;
+	$server->processRequest($state);
+}
+
+if (isset($_REQUEST['TrustNo'])) {
+	$state['TrustResponse'] = FALSE;
+	$server->processRequest($state);
+}
+
+$globalConfig = SimpleSAML_Configuration::getInstance();
+$t = new SimpleSAML_XHTML_Template($globalConfig, 'openidProvider:trust.tpl.php');
+$t->data['StateID'] = $_REQUEST['StateID'];
+$t->data['trustRoot'] = $trustRoot;
+$t->show();
diff --git a/modules/openidProvider/www/user.php b/modules/openidProvider/www/user.php
new file mode 100644
index 0000000000000000000000000000000000000000..2ae930b4475064d5dbeb82a239e5b2d1c4dfa5b1
--- /dev/null
+++ b/modules/openidProvider/www/user.php
@@ -0,0 +1,65 @@
+<?php
+
+if (isset($_SERVER['PATH_INFO'])) {
+	$userId = substr($_SERVER['PATH_INFO'], 1);
+} else {
+	$userId = FALSE;
+}
+
+$globalConfig = SimpleSAML_Configuration::getInstance();
+$server = sspmod_openidProvider_Server::getInstance();
+$identity = $server->getIdentity();
+
+if (!$userId && $identity) {
+	/*
+	 * We are accessing the front-page, but are logged in.
+	 * Redirect to the correct page.
+	 */
+	SimpleSAML_Utilities::redirect($identity);
+}
+
+/* Determine whether we are at the users own page. */
+if ($userId && $userId === $server->getUserId()) {
+	$ownPage = TRUE;
+} else {
+	$ownPage = FALSE;
+}
+
+if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+	if ($ownPage) {
+		foreach ($_POST as $k => $v) {
+			$op = explode('_', $k, 2);
+			if (count($op) == 1 || $op[0] !== 'remove') {
+				continue;
+			}
+
+			$site = $op[1];
+			$site = pack("H*" , $site);
+			$server->removeTrustRoot($identity, $site);
+		}
+	}
+
+	SimpleSAML_Utilities::redirect($identity);
+}
+
+if ($ownPage) {
+	$trustedSites = $server->getTrustRoots($identity);
+} else {
+	$trustedSites = array();
+}
+
+$userBase = SimpleSAML_Module::getModuleURL('openidProvider/user.php');
+
+$as = $server->getAuthSource();
+$t = new SimpleSAML_XHTML_Template($globalConfig, 'openidProvider:user.tpl.php');
+$t->data['identity'] = $identity;
+$t->data['loggedInAs'] = $server->getUserId();
+$t->data['loginURL'] = $as->getLoginURL($userBase);
+$t->data['logoutURL'] = $as->getLogoutURL();
+$t->data['ownPage'] = $ownPage;
+$t->data['serverURL'] = $server->getServerURL();
+$t->data['trustedSites'] = $trustedSites;
+$t->data['userId'] = $userId;
+$t->data['userIdURL'] = $userBase . '/' . $userId;
+$t->show();
+exit(0);