diff --git a/lib/SimpleSAML/Auth/Source.php b/lib/SimpleSAML/Auth/Source.php
index d42d3eef3b0617e8e6b28ab86965cf10e7e39fb4..358cd178d720be82c81bce349178dc1eb326b8e2 100644
--- a/lib/SimpleSAML/Auth/Source.php
+++ b/lib/SimpleSAML/Auth/Source.php
@@ -99,6 +99,26 @@ abstract class SimpleSAML_Auth_Source {
 	abstract public function authenticate(&$state);
 
 
+	/**
+	 * Reauthenticate an user.
+	 *
+	 * This function is called by the IdP to give the authentication source a chance to
+	 * interact with the user even in the case when the user is already authenticated.
+	 *
+	 * @param array &$state  Information about the current authentication.
+	 */
+	public function reauthenticate(array &$state) {
+		assert('isset($state["ReturnCallback"])');
+
+		/* The default implementation just copies over the previous authentication data. */
+		$session = SimpleSAML_Session::getInstance();
+		$data = $session->getAuthState($this->authId);
+		foreach ($data as $k => $v) {
+			$state[$k] = $v;
+		}
+	}
+
+
 	/**
 	 * Complete authentication.
 	 *
diff --git a/lib/SimpleSAML/IdP.php b/lib/SimpleSAML/IdP.php
index f974551946e512a27d8b02e832debf6ba86353f6..a8a2d1f6e8883b4f41e2c2c00bf2697b7d8f0640 100644
--- a/lib/SimpleSAML/IdP.php
+++ b/lib/SimpleSAML/IdP.php
@@ -326,13 +326,36 @@ class SimpleSAML_IdP {
 			throw new SimpleSAML_Error_NoPassive('Passive authentication not supported.');
 		}
 
-		$state['IdPMetadata'] = $this->getConfig()->toArray();
-		$state['ReturnCallback'] = array('SimpleSAML_IdP', 'postAuth');
-
 		$this->authSource->login($state);
 	}
 
 
+	/**
+	 * Reuthenticate the user.
+	 *
+	 * This function reauthenticates an user with an existing session. This
+	 * gives the authentication source a chance to do additional work when
+	 * reauthenticating for SSO.
+	 *
+	 * Note: This function is not used when ForceAuthn=true.
+	 *
+	 * @param array &$state  The authentication request state.
+	 */
+	private function reauthenticate(array &$state) {
+
+		$sourceImpl = $this->authSource->getAuthSource();
+		if ($sourceImpl === NULL) {
+			/* Backwards-compatibility with non-authsource IdP. */
+			foreach ($this->authSource->getAuthDataArray() as $k => $v) {
+				$state[$k] = $v;
+			}
+			return;
+		}
+
+		$sourceImpl->reauthenticate($state);
+	}
+
+
 	/**
 	 * Process authentication requests.
 	 *
@@ -362,14 +385,15 @@ class SimpleSAML_IdP {
 			$needAuth = !$this->isAuthenticated();
 		}
 
+		$state['IdPMetadata'] = $this->getConfig()->toArray();
+		$state['ReturnCallback'] = array('SimpleSAML_IdP', 'postAuth');
+
 		try {
 			if ($needAuth) {
 				$this->authenticate($state);
 				assert('FALSE');
 			} else {
-				foreach ($this->authSource->getAuthDataArray() as $k => $v) {
-					$state[$k] = $v;
-				}
+				$this->reauthenticate($state);
 			}
 			$this->postAuth($state);
 		} catch (SimpleSAML_Error_Exception $e) {