diff --git a/docs/simplesamlphp-sp-api.txt b/docs/simplesamlphp-sp-api.txt
index 54cd65a895db1c8bdf7af068e8a88b5c494c4524..07c5a35c364913e0efa79e19f3262fc0239c00c5 100644
--- a/docs/simplesamlphp-sp-api.txt
+++ b/docs/simplesamlphp-sp-api.txt
@@ -117,22 +117,55 @@ The [`saml:SP`](./saml:sp) authentication source also defines some parameters.
 `logout`
 --------
 
-    void logout(string $url = NULL)
+    void logout(mixed $params = NULL)
 
-Log the user out, and return to the given URL.
-If the user isn't authenticated, the user will be redirected to the URL.
-If the user is authenticated with an IdP, the user will be sent to the IdP for logout.
+Log the user out.
+After logging out, the user will either be redirected to another page, or a function will be called.
 This function never returns.
 
 ### Parameters
 
-`$url`
-:   The URL the user should be sent to after logout.
-    The default is the URL of the current page.
+`$params`
+:   Parameters for the logout operation.
+    This can either be a simple string, in which case it is interpreted as the URL the user should be redirected to after logout, or an associative array with logout parameters.
+    If this parameter isn't specified, we will redirect the user to the current URL after logout.
 
-### Example
+    If the parameter is an an array, it can have the following options:
+
+    - `ReturnTo`: The URL the user should be returned to after logout.
+    - `ReturnCallback`: The function that should be called after logout.
+    - `ReturnStateParam`: The parameter we should return the state in when redirecting.
+    - `ReturnStateStage`: The stage the state array should be saved with.
+
+    The `ReturnState` parameters allow access to the result of the logout operation after it completes.
+
+### Example 1
+
+Logout, and redirect to the specified URL.
+
+    $auth->logout('https://sp.example.org/logged_out.php');
 
-    $auth->logout('https://sp.example.org/');
+### Example 2
+
+Same as the previous, but check the result of the logout operation afterwards.
+
+    $auth->logout(array(
+        'ReturnTo' => 'https://sp.example.org/logged_out.php',
+        'ReturnStateParam' => 'LogoutState',
+        'ReturnStateStage' => 'MyLogoutState',
+    ));
+
+And in logged_out.php:
+
+    $state = SimpleSAML_Auth_State::loadState((string)$_REQUEST['LogoutState'], 'MyLogoutState');
+    $ls = $state['saml:sp:LogoutStatus']; /* Only works for SAML SP */
+    if ($ls['Code'] === 'urn:oasis:names:tc:SAML:2.0:status:Success' && !isset($ls['SubCode'])) {
+        /* Successful logout. */
+        echo("You have been logged out.");
+    } else {
+        /* Logout failed. Tell the user to close the browser. */
+        echo("We were unable to log you out of all your sessions. To be completely sure that you are logged out, you need to close your web browser.");
+    }
 
 
 `getAttributes`
diff --git a/lib/SimpleSAML/Auth/Simple.php b/lib/SimpleSAML/Auth/Simple.php
index f5d36fb4c9e5139e362cd17355e1c1f62ca8444c..ec08f29d680386ae9e54c4ac3c794844d18acdab 100644
--- a/lib/SimpleSAML/Auth/Simple.php
+++ b/lib/SimpleSAML/Auth/Simple.php
@@ -134,26 +134,83 @@ class SimpleSAML_Auth_Simple {
 	 *
 	 * This function logs the user out. It will never return. By default,
 	 * it will cause a redirect to the current page after logging the user
-	 * out, but a different URL can be given with the $url parameter.
+	 * out, but a different URL can be given with the $params parameter.
 	 *
-	 * @param string|NULL $url  The url the user should be redirected to after logging out.
-	 *                          Defaults to the current page.
+	 * Generic parameters are:
+	 *  - 'ReturnTo': The URL the user should be returned to after logout.
+	 *  - 'ReturnCallback': The function that should be called after logout.
+	 *  - 'ReturnStateParam': The parameter we should return the state in when redirecting.
+	 *  - 'ReturnStateStage': The stage the state array should be saved with.
+	 *
+	 * @param string|array|NULL $params  Either the url the user should be redirected to after logging out,
+	 *                                   or an array with parameters for the logout. If this parameter is
+	 *                                   NULL, we will return to the current page.
 	 */
-	public function logout($url = NULL) {
-		assert('is_string($url) || is_null($url)');
+	public function logout($params = NULL) {
+		assert('is_array($params) || is_string($params) || is_null($params)');
+
+		if ($params === NULL) {
+			$params = SimpleSAML_Utilities::selfURL();
+		}
+
+		if (is_string($params)) {
+			$params = array(
+				'ReturnTo' => $params,
+			);
+		}
+
+		assert('is_array($params)');
+		assert('isset($params["ReturnTo"]) || isset($params["ReturnCallback"])');
 
-		if ($url === NULL) {
-			$url = SimpleSAML_Utilities::selfURL();
+		if (isset($params['ReturnStateParam']) || isset($params['ReturnStateStage'])) {
+			assert('isset($params["ReturnStateParam"]) && isset($params["ReturnStateStage"])');
 		}
 
 		$session = SimpleSAML_Session::getInstance();
-		if (!$session->isValid($this->authSource)) {
-			/* Not authenticated to this authentication source. */
-			SimpleSAML_Utilities::redirect($url);
-			assert('FALSE');
+		if ($session->isValid($this->authSource)) {
+			$state = $session->getAuthData($this->authSource, 'LogoutState');
+			if ($state !== NULL) {
+				$params = array_merge($state, $params);
+			}
+
+			$session->doLogout($this->authSource);
+
+			$params['LogoutCompletedHandler'] = array(get_class(), 'logoutCompleted');
+
+			$as = SimpleSAML_Auth_Source::getById($this->authSource);
+			if ($as !== NULL) {
+				$as->logout($params);
+			}
 		}
 
-		SimpleSAML_Auth_Default::initLogout($url, $this->authSource);
+		self::logoutCompleted($params);
+	}
+
+
+	/**
+	 * Called when logout operation completes.
+	 *
+	 * This function never returns.
+	 *
+	 * @param array $state  The state after the logout.
+	 */
+	public static function logoutCompleted($state) {
+		assert('is_array($state)');
+		assert('isset($state["ReturnTo"]) || isset($state["ReturnCallback"])');
+
+		if (isset($state['ReturnCallback'])) {
+			call_user_func($state['ReturnCallback'], $state);
+			assert('FALSE');
+		} else {
+			$params = array();
+			if (isset($state['ReturnStateParam']) || isset($state['ReturnStateStage'])) {
+				assert('isset($state["ReturnStateParam"]) && isset($state["ReturnStateStage"])');
+				$stateID = SimpleSAML_Auth_State::saveState($state, $state['ReturnStateStage']);
+				$params[$state['ReturnStateParam']] = $stateID;
+			}
+
+			SimpleSAML_Utilities::redirect($state['ReturnTo'], $params);
+		}
 	}