diff --git a/modules/authYubiKey/lib/Auth/Source/YubiKey.php b/modules/authYubiKey/lib/Auth/Source/YubiKey.php
index 71b8a3cdf500999eae7c706ef62e68b04b5cf8da..9262ac680a9204f130d6c495bc3f2b5c738faf4c 100644
--- a/modules/authYubiKey/lib/Auth/Source/YubiKey.php
+++ b/modules/authYubiKey/lib/Auth/Source/YubiKey.php
@@ -40,13 +40,29 @@
  * @package simpleSAMLphp
  * @version $Id$
  */
-class sspmod_authYubiKey_Auth_Source_YubiKey extends sspmod_core_Auth_UserPassBase {
+class sspmod_authYubiKey_Auth_Source_YubiKey extends SimpleSAML_Auth_Source {
 
-      /**
-       * The client id/key for use with the Auth_Yubico PHP module.
-       */
-      private $yubi_id;
-      private $yubi_key;
+	/**
+	 * The string used to identify our states.
+	 */
+	const STAGEID = 'sspmod_authYubiKey_Auth_Source_YubiKey.state';
+
+	/**
+	 * The number of characters of the OTP that is the secure token.
+	 * The rest is the user id.
+	 */
+	const TOKENSIZE = 32;
+
+	/**
+	 * The key of the AuthId field in the state.
+	 */
+	const AUTHID = 'sspmod_authYubiKey_Auth_Source_YubiKey.AuthId';
+
+	/**
+	 * The client id/key for use with the Auth_Yubico PHP module.
+	 */
+	private $yubi_id;
+	private $yubi_key;
 
 	/**
 	 * Constructor for this authentication source.
@@ -71,6 +87,84 @@ class sspmod_authYubiKey_Auth_Source_YubiKey extends sspmod_core_Auth_UserPassBa
 	}
 
 
+	/**
+	 * Initialize login.
+	 *
+	 * This function saves the information about the login, and redirects to a
+	 * login page.
+	 *
+	 * @param array &$state  Information about the current authentication.
+	 */
+	public function authenticate(&$state) {
+		assert('is_array($state)');
+
+		/* We are going to need the authId in order to retrieve this authentication source later. */
+		$state[self::AUTHID] = $this->authId;
+
+		$id = SimpleSAML_Auth_State::saveState($state, self::STAGEID);
+
+		$url = SimpleSAML_Module::getModuleURL('authYubiKey/yubikeylogin.php');
+		SimpleSAML_Utilities::redirect($url, array('AuthState' => $id));
+	}
+	
+	
+	/**
+	 * Handle login request.
+	 *
+	 * This function is used by the login form (core/www/loginuserpass.php) when the user
+	 * enters a username and password. On success, it will not return. On wrong
+	 * username/password failure, it will return the error code. Other failures will throw an
+	 * exception.
+	 *
+	 * @param string $authStateId  The identifier of the authentication state.
+	 * @param string $otp  The one time password entered-
+	 * @return string  Error code in the case of an error.
+	 */
+	public static function handleLogin($authStateId, $otp) {
+		assert('is_string($authStateId)');
+		assert('is_string($otp)');
+
+		/* Retrieve the authentication state. */
+		$state = SimpleSAML_Auth_State::loadState($authStateId, self::STAGEID);
+
+		/* Find authentication source. */
+		assert('array_key_exists(self::AUTHID, $state)');
+		$source = SimpleSAML_Auth_Source::getById($state[self::AUTHID]);
+		if ($source === NULL) {
+			throw new Exception('Could not find authentication source with id ' . $state[self::AUTHID]);
+		}
+
+
+		try {
+			/* Attempt to log in. */
+			$attributes = $source->login($otp);
+		} catch (SimpleSAML_Error_Error $e) {
+			/* An error occured during login. Check if it is because of the wrong
+			 * username/password - if it is, we pass that error up to the login form,
+			 * if not, we let the generic error handler deal with it.
+			 */
+			if ($e->getErrorCode() === 'WRONGUSERPASS') {
+				return 'WRONGUSERPASS';
+			}
+
+			/* Some other error occured. Rethrow exception and let the generic error
+			 * handler deal with it.
+			 */
+			throw $e;
+		}
+
+		$state['Attributes'] = $attributes;
+		SimpleSAML_Auth_Source::completeAuth($state);
+	}
+	
+	/**
+	 * Return the user id part of a one time passord
+	 */
+	public static function getYubiKeyPrefix($otp) {
+		$uid = substr ($otp, 0, strlen ($otp) - self::TOKENSIZE);
+		return $uid;
+	}
+
 	/**
 	 * Attempt to log in using the given username and password.
 	 *
@@ -84,9 +178,8 @@ class sspmod_authYubiKey_Auth_Source_YubiKey extends sspmod_core_Auth_UserPassBa
 	 * @param string $password  The password the user wrote.
 	 * @return array  Associative array with the users attributes.
 	 */
-	protected function login($username, $password) {
-		assert('is_string($username)');
-		assert('is_string($password)');
+	protected function login($otp) {
+		assert('is_string($otp)');
 
 		require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/libextinc/Yubico.php';
 
@@ -94,16 +187,16 @@ class sspmod_authYubiKey_Auth_Source_YubiKey extends sspmod_core_Auth_UserPassBa
 
 		try {
 			$yubi = &new Auth_Yubico($this->yubi_id, $this->yubi_key);
-			$auth = $yubi->verify($password);
-			
-			$attributes = array('uid' => array($username), 'otp' => array($password));
+			$auth = $yubi->verify($otp);
+			$uid = self::getYubiKeyPrefix($otp);
+			$attributes = array('uid' => array($uid));
 		} catch (Exception $e) {
-		  	SimpleSAML_Logger::info('YubiKey:' . $this->authId . ': Validation error (user ' . $username . ' otp ' . $password . '), debug output: ' . $yubi->getLastResponse());
+		  	SimpleSAML_Logger::info('YubiKey:' . $this->authId . ': Validation error (otp ' . $otp . '), debug output: ' . $yubi->getLastResponse());
 
 			throw new SimpleSAML_Error_Error('WRONGUSERPASS', $e);
 		}
 
-		SimpleSAML_Logger::info('YubiKey:' . $this->authId . ': YubiKey otp ' . $password . ' for user ' . $username . ' validated successfully: ' . $yubi->getLastResponse());
+		SimpleSAML_Logger::info('YubiKey:' . $this->authId . ': YubiKey otp ' . $password . ' validated successfully: ' . $yubi->getLastResponse());
 
 		return $attributes;
 	}
diff --git a/modules/authYubiKey/templates/default/yubikeylogin.php b/modules/authYubiKey/templates/default/yubikeylogin.php
new file mode 100644
index 0000000000000000000000000000000000000000..6632a19b621eacf95e351e7c7211c4e79e360ef4
--- /dev/null
+++ b/modules/authYubiKey/templates/default/yubikeylogin.php
@@ -0,0 +1,50 @@
+<?php
+$this->data['icon'] = 'lock.png';
+$this->data['header'] = $this->t('{authYubiKey:yubikey:header}');
+$this->data['autofocus'] = 'otp';
+
+$this->includeAtTemplateBase('includes/header.php');
+
+?>
+<div id="content">
+
+<?php
+if ($this->data['errorcode'] !== NULL) {
+?>
+	<div style="border-left: 1px solid #e8e8e8; border-bottom: 1px solid #e8e8e8; background: #f5f5f5">
+		<img src="/<?php echo $this->data['baseurlpath']; ?>resources/icons/bomb.png" style="float: left; margin: 15px " />
+		<h2><?php echo $this->t('{login:error_header}'); ?></h2>
+		<p><b><?php echo $this->t('{errors:title_' . $this->data['errorcode'] . '}'); ?></b></p>
+		<p><?php echo $this->t('{errors:descr_' . $this->data['errorcode'] . '}'); ?></p>
+	</div>
+<?php
+}
+?>
+
+	<img style="float: right" src="<?php echo(SimpleSAML_Module::getModuleURL('authYubiKey/resources/logo.jpg')); ?>" />
+	<img style="clear: right; float: right" src="<?php echo(SimpleSAML_Module::getModuleURL('authYubiKey/resources/yubikey.jpg')); ?>" />
+
+
+	<h2 style=""><?php echo $this->t('{authYubiKey:yubikey:header}'); ?></h2>
+
+	<form action="?" method="post" name="f">
+
+		<p><?php echo $this->t('{authYubiKey:yubikey:intro}'); ?></p>
+	
+		<p><input id="otp" style="border: 1px solid #ccc; background: #eee; padding: .5em; font-size: medium; width: 70%; color: #aaa" type="text" tabindex="2" name="otp" /></p>
+
+
+
+
+<?php
+foreach ($this->data['stateparams'] as $name => $value) {
+	echo('<input type="hidden" name="' . htmlspecialchars($name) . '" value="' . htmlspecialchars($value) . '" />');
+}
+?>
+
+	</form>
+
+<?php
+
+$this->includeAtTemplateBase('includes/footer.php');
+?>
\ No newline at end of file
diff --git a/modules/authYubiKey/www/resources/logo.jpg b/modules/authYubiKey/www/resources/logo.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..3b7e7f360ddb176fd383a8bea0d6b500fff95cf5
Binary files /dev/null and b/modules/authYubiKey/www/resources/logo.jpg differ
diff --git a/modules/authYubiKey/www/resources/yubikey.jpg b/modules/authYubiKey/www/resources/yubikey.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..f3c8d0bd96f6752de7f5dbaa22be933e261da6cc
Binary files /dev/null and b/modules/authYubiKey/www/resources/yubikey.jpg differ
diff --git a/modules/authYubiKey/www/yubikeylogin.php b/modules/authYubiKey/www/yubikeylogin.php
new file mode 100644
index 0000000000000000000000000000000000000000..3c281507feca9296e5e37ce20ab0f8184e3e7682
--- /dev/null
+++ b/modules/authYubiKey/www/yubikeylogin.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * This page shows a username/password login form, and passes information from it
+ * to the sspmod_core_Auth_UserPassBase class, which is a generic class for
+ * username/password authentication.
+ *
+ * @author Olav Morken, UNINETT AS.
+ * @package simpleSAMLphp
+ * @version $Id$
+ */
+
+if (!array_key_exists('AuthState', $_REQUEST)) {
+	throw new SimpleSAML_Error_BadRequest('Missing AuthState parameter.');
+}
+$authStateId = $_REQUEST['AuthState'];
+
+if (array_key_exists('otp', $_REQUEST)) {
+	$otp = $_REQUEST['otp'];
+} else {
+	$otp = '';
+}
+
+if (!empty($otp)) {
+	/*  attempt to log in. */
+	$errorCode = sspmod_authYubiKey_Auth_Source_YubiKey::handleLogin($authStateId, $otp);
+} else {
+	$errorCode = NULL;
+}
+
+$globalConfig = SimpleSAML_Configuration::getInstance();
+$t = new SimpleSAML_XHTML_Template($globalConfig, 'authYubiKey:yubikeylogin.php');
+$t->data['stateparams'] = array('AuthState' => $authStateId);
+$t->data['errorcode'] = $errorCode;
+$t->show();
+exit();
+
+
+?>
\ No newline at end of file