diff --git a/docs/simplesamlphp-authproc.txt b/docs/simplesamlphp-authproc.txt
index d8122894b40979ebbe9ff568dad4657a493849f5..d6b556ef94915068c6875f1966d59f74e09d0659 100644
--- a/docs/simplesamlphp-authproc.txt
+++ b/docs/simplesamlphp-authproc.txt
@@ -143,6 +143,7 @@ The following filters are included in the simpleSAMLphp distribution:
 - [`core:WarnShortSSOInterval`](./core:authproc_warnshortssointerval): Give a warning if the user logs into the same SP twice within a few seconds.
 - [`preprodwarning:Warning`](./preprodwarning:warning): Warn the user about accessing a test IdP.
 - [`saml:AttributeNameID`](./saml:nameid): Generate custom NameID with the value of an attribute.
+- [`saml:NameIDAttribute`](./saml:nameidattribute): Create an attribute based on the NameID we receive from the IdP.
 - [`saml:PersistentNameID`](./saml:nameid): Generate persistent NameID from an attribute.
 - [`saml:TransientNameID`](./saml:nameid): Generate transient NameID.
 
diff --git a/modules/saml/docs/nameidattribute.txt b/modules/saml/docs/nameidattribute.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5bc440985cb8fa02d4d12f8ceba790217308fe40
--- /dev/null
+++ b/modules/saml/docs/nameidattribute.txt
@@ -0,0 +1,67 @@
+`saml:NameIDAttribute`
+======================
+
+Filter that extracts the NameID we received in the authentication response and adds it as an attribute.
+
+Parameters
+----------
+
+`attribute`
+:   The name of the attribute we should create.
+    The default is `nameid`.
+
+`format`
+:   The format string for the attribute.
+    The default is `%I!%S!%V`.
+
+:   The format string accepts the following replacements:
+
+    * `%I`: The IdP that issued the NameID.
+            This will be the `NameQualifier` element of the NameID if it is present, or the entity ID of the IdP we received the response from if not.
+    * `%S`: The SP the NameID was issued to.
+            This will be the `SPNameQualifier` element of the NameID if it is present, or the entity ID of this SP otherwise.
+    * `%V`: The value of the NameID.
+    * `%F`: The format of the NameID.
+    * `%%`: Will be replaced with a single `%`.
+
+Examples
+--------
+
+Minimal configuration:
+
+    'default-sp' => array(
+        'saml:SP',
+        'authproc' => array(
+            20 => 'saml:NameIDAttribute',
+        ),
+    ),
+
+Custom attribute name:
+
+    'default-sp' => array(
+        'saml:SP',
+        'authproc' => array(
+            20 => array(
+                'class' => 'saml:NameIDAttribute',
+                'attribute' => 'someattributename',
+            ),
+        ),
+    ),
+
+Only extract the value of the NameID.
+
+    'default-sp' => array(
+        'saml:SP',
+        'authproc' => array(
+            20 => array(
+                'class' => 'saml:NameIDAttribute',
+                'format' => '%V',
+            ),
+        ),
+    ),
+
+See also
+--------
+
+ * [The description of the `saml:SP` authentication source.](./saml:sp)
+ * [How to generate various NameIDs on the IdP.](./saml:nameid)
diff --git a/modules/saml/lib/Auth/Process/NameIDAttribute.php b/modules/saml/lib/Auth/Process/NameIDAttribute.php
new file mode 100644
index 0000000000000000000000000000000000000000..26640e257d557bed0cb3859ad3bd14227b2ec06c
--- /dev/null
+++ b/modules/saml/lib/Auth/Process/NameIDAttribute.php
@@ -0,0 +1,138 @@
+<?php
+
+/**
+ * Authproc filter to create an attribute from a NameID.
+ *
+ * @package simpleSAMLphp
+ * @version $Id$
+ */
+class sspmod_saml_Auth_Process_NameIDAttribute extends SimpleSAML_Auth_ProcessingFilter {
+
+	/**
+	 * The attribute we should save the NameID in.
+	 *
+	 * @var string
+	 */
+	private $attribute;
+
+
+	/**
+	 * The format of the NameID in the attribute.
+	 *
+	 * @var array
+	 */
+	private $format;
+
+
+	/**
+	 * Initialize this filter, parse configuration.
+	 *
+	 * @param array $config  Configuration information about this filter.
+	 * @param mixed $reserved  For future use.
+	 */
+	public function __construct($config, $reserved) {
+		parent::__construct($config, $reserved);
+		assert('is_array($config)');
+
+		if (isset($config['attribute'])) {
+			$this->attribute = (string)$config['attribute'];
+		} else {
+			$this->attribute = 'nameid';
+		}
+
+		if (isset($config['format'])) {
+			$format = (string)$config['format'];
+		} else {
+			$format = '%I!%S!%V';
+		}
+
+		$this->format = self::parseFormat($format);
+	}
+
+
+	/**
+	 * Parse a NameID format string into an array.
+	 *
+	 * @param string $format  The format string.
+	 * @return array  The format string broken into its individual components.
+	 */
+	private static function parseFormat($format) {
+		assert('is_string($format)');
+
+		$ret = array();
+		$pos = 0;
+		while ( ($next = strpos($format, '%', $pos)) !== FALSE) {
+			$ret[] = substr($format, $pos, $next - $pos);
+
+			$replacement = $format[$next + 1];
+			switch ($replacement) {
+			case 'F':
+				$ret[] = 'Format';
+				break;
+			case 'I':
+				$ret[] = 'NameQualifier';
+				break;
+			case 'S':
+				$ret[] = 'SPNameQualifier';
+				break;
+			case 'V':
+				$ret[] = 'Value';
+				break;
+			case '%':
+				$ret[] = '%';
+				break;
+			default:
+				throw new SimpleSAML_Error_Exception('NameIDAttribute: Invalid replacement: "%' . $replacement . '"');
+			}
+
+			$pos = $next + 2;
+		}
+		$ret[] = substr($format, $pos);
+
+		return $ret;
+	}
+
+
+	/**
+	 * Convert NameID to attribute.
+	 *
+	 * @param array &$state  The request state.
+	 */
+	public function process(&$state) {
+		assert('is_array($state)');
+		assert('isset($state["Source"]["entityid"])');
+		assert('isset($state["Destination"]["entityid"])');
+
+		if (!isset($state['saml:sp:State']['LogoutState']['saml:logout:NameID'])) {
+			return;
+		}
+
+		$rep = $state['saml:sp:State']['LogoutState']['saml:logout:NameID'];
+		assert('isset($rep["Value"])');
+
+		$rep['%'] = '%';
+		if (!isset($rep['Format'])) {
+			$rep['Format'] = SAML2_Const::NAMEID_UNSPECIFIED;
+		}
+		if (!isset($rep['NameQualifier'])) {
+			$rep['NameQualifier'] = $state['Source']['entityid'];
+		}
+		if (!isset($rep['SPNameQualifier'])) {
+			$rep['SPNameQualifier'] = $state['Destination']['entityid'];
+		}
+
+		$value = '';
+		$isString = TRUE;
+		foreach ($this->format as $element) {
+			if ($isString) {
+				$value .= $element;
+			} else {
+				$value .= $rep[$element];
+			}
+			$isString = !$isString;
+		}
+
+		$state['Attributes'][$this->attribute] = array($value);
+	}
+
+}