diff --git a/attributemap/linkedin2name.php b/attributemap/linkedin2name.php
new file mode 100644
index 0000000000000000000000000000000000000000..0d3a43303daff05ad18b6334b4ab11c7b4fad1b4
--- /dev/null
+++ b/attributemap/linkedin2name.php
@@ -0,0 +1,19 @@
+<?php
+$attributemap = array(
+
+	// See http://developer.linkedin.com/docs/DOC-1061 for LinkedIn Profile fields.
+	// NB: JSON response requires the conversion of field names from hyphened to camelCase.
+	// For instance, first-name becomes firstName.
+
+	// Generated LinkedIn Attributes
+	'linkedin_user'			=>	'eduPersonPrincipalName', // id  @ linkedin.com
+	'linkedin_targetedID'		=>	'eduPersonTargetedID', // http://linkedin.com!id
+
+	// Attributes Returned by LinkedIn
+	'linkedin.firstName'		=>	'givenName',
+	'linkedin.lastName'		=>	'sn',
+	'linkedin.id'			=>	'uid', // alpha + mixed case user id
+	//'linkedin.pictureUrl'		=>	'jpegPhoto', // URL not image data
+	'linkedin.headline'		=>	'title',
+	'linkedin.summary'		=>	'description',
+);
diff --git a/config-templates/authsources.php b/config-templates/authsources.php
index 8c870901d8b7c2408250c7a16585c0e9691b47eb..89a86a4de55de59ca6c79f6c3dcdd8079c0e60f5 100644
--- a/config-templates/authsources.php
+++ b/config-templates/authsources.php
@@ -134,6 +134,17 @@ $config = array(
 	),
 	*/
 
+	/*
+	// LinkedIn OAuth Authentication API.
+	// Register your application to get an API key here:
+	//  https://www.linkedin.com/secure/developer
+	'linkedin' => array(
+		'authlinkedin:LinkedIn',
+		'key' => 'xxxxxxxxxxxxxxxx',
+		'secret' => 'xxxxxxxxxxxxxxxx',
+	),
+	*/
+
 	/*
 	// Twitter OAuth Authentication API.
 	// Register your application to get an API key here:
diff --git a/modules/authlinkedin/default-disable b/modules/authlinkedin/default-disable
new file mode 100644
index 0000000000000000000000000000000000000000..fa0bd82e2df7bd79d57593d35bc53c1f9d3ef71f
--- /dev/null
+++ b/modules/authlinkedin/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/authlinkedin/docs/oauthlinkedin.txt b/modules/authlinkedin/docs/oauthlinkedin.txt
new file mode 100644
index 0000000000000000000000000000000000000000..61937284e5817fe70ed6164e3da90a86d99db584
--- /dev/null
+++ b/modules/authlinkedin/docs/oauthlinkedin.txt
@@ -0,0 +1,26 @@
+Using the LinkedIn authentication source with simpleSAMLphp
+===========================================================
+
+Remember to configure `authsources.php`, with both Consumer key and secret.
+
+To get an API key and a secret, register the application at:
+
+ * <https://www.linkedin.com/secure/developer>
+
+Set the callback URL to be:
+
+ * `http://sp.example.org/simplesaml/module.php/authlinkedin/linkback.php`
+
+Replace `sp.example.org` with your hostname.
+
+## Testing authentication
+
+On the SimpleSAMLphp frontpage, go to the *Authentication* tab, and use the link:
+
+  * *Test configured authentication sources*
+
+Then choose the *linkedin* authentication source.
+
+Expected behaviour would then be that you are sent to LinkedIn and asked to login.
+There is no consent screen for attribute release.
+
diff --git a/modules/authlinkedin/lib/Auth/Source/LinkedIn.php b/modules/authlinkedin/lib/Auth/Source/LinkedIn.php
new file mode 100644
index 0000000000000000000000000000000000000000..228e02c4af4a4fb88632e39eb9e96c07f41d85c6
--- /dev/null
+++ b/modules/authlinkedin/lib/Auth/Source/LinkedIn.php
@@ -0,0 +1,122 @@
+<?php
+
+require_once(dirname(dirname(dirname(dirname(dirname(__FILE__))))) . '/oauth/libextinc/OAuth.php');
+
+/**
+ * Authenticate using LinkedIn.
+ *
+ * @author Brook Schofield, TERENA.
+ * @package simpleSAMLphp
+ * @version $Id$
+ */
+class sspmod_authlinkedin_Auth_Source_LinkedIn extends SimpleSAML_Auth_Source {
+
+	/**
+	 * The string used to identify our states.
+	 */
+	const STAGE_INIT = 'authlinkedin:init';
+
+	/**
+	 * The key of the AuthId field in the state.
+	 */
+	const AUTHID = 'authlinkedin:AuthId';
+
+	private $key;
+	private $secret;
+
+
+	/**
+	 * Constructor for this authentication source.
+	 *
+	 * @param array $info  Information about this authentication source.
+	 * @param array $config  Configuration.
+	 */
+	public function __construct($info, $config) {
+		assert('is_array($info)');
+		assert('is_array($config)');
+
+		/* Call the parent constructor first, as required by the interface. */
+		parent::__construct($info, $config);
+
+		if (!array_key_exists('key', $config))
+			throw new Exception('LinkedIn authentication source is not properly configured: missing [key]');
+
+		$this->key = $config['key'];
+
+		if (!array_key_exists('secret', $config))
+			throw new Exception('LinkedIn authentication source is not properly configured: missing [secret]');
+
+		$this->secret = $config['secret'];
+	}
+
+
+	/**
+	 * Log-in using LinkedIn platform
+	 * Documentation at: http://developer.linkedin.com/docs/DOC-1008
+	 *
+	 * @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;
+
+		$stateID = SimpleSAML_Auth_State::getStateId($state);
+		SimpleSAML_Logger::debug('authlinkedin auth state id = ' . $stateID);
+
+		$consumer = new sspmod_oauth_Consumer($this->key, $this->secret);
+
+		// Get the request token
+		$requestToken = $consumer->getRequestToken('https://api.linkedin.com/uas/oauth/requestToken', array('oauth_callback' => SimpleSAML_Module::getModuleUrl('authlinkedin') . '/linkback.php?stateid=' . $stateID));
+
+		SimpleSAML_Logger::debug("Got a request token from the OAuth service provider [" .
+			$requestToken->key . "] with the secret [" . $requestToken->secret . "]");
+
+		$state['authlinkedin:requestToken'] = $requestToken;
+
+		// Update the state
+		SimpleSAML_Auth_State::saveState($state, self::STAGE_INIT);
+
+		// Authorize the request token
+		$consumer->getAuthorizeRequest('https://www.linkedin.com/uas/oauth/authenticate', $requestToken);
+	}
+
+
+	public function finalStep(&$state) {
+		$requestToken = $state['authlinkedin:requestToken'];
+
+		$consumer = new sspmod_oauth_Consumer($this->key, $this->secret);
+
+		SimpleSAML_Logger::debug("oauth: Using this request token [" .
+			$requestToken->key . "] with the secret [" . $requestToken->secret . "]");
+
+		// Replace the request token with an access token (via GET method)
+		$accessToken = $consumer->getAccessToken('https://api.linkedin.com/uas/oauth/accessToken', $requestToken,
+			array('oauth_verifier' => $state['authlinkedin:oauth_verifier']));
+
+		SimpleSAML_Logger::debug("Got an access token from the OAuth service provider [" .
+			$accessToken->key . "] with the secret [" . $accessToken->secret . "]");
+
+		// TODO: configure attributes (http://developer.linkedin.com/docs/DOC-1061) from config? Limited options via LinkedIn.
+		$userdata = $consumer->getUserInfo('https://api.linkedin.com/v1/people/~:(id,first-name,last-name,headline,summary,specialties,picture-url)', $accessToken, array('http' => array('header' => 'x-li-format: json')));
+
+		$attributes = array();
+		foreach($userdata AS $key => $value) {
+			if (is_string($value))
+				$attributes['linkedin.' . $key] = array((string)$value);
+
+		}
+
+		// TODO: pass accessToken: key, secret + expiry as attributes?
+
+		if (array_key_exists('id', $userdata) ) {
+			$attributes['linkedin_targetedID'] = array('http://linkedin.com!' . $userdata['id']);
+			$attributes['linkedin_user'] = array($userdata['id'] . '@linkedin.com');
+		}
+
+		SimpleSAML_Logger::debug('LinkedIn Returned Attributes: '. implode(", ",array_keys($attributes)));
+
+		$state['Attributes'] = $attributes;
+	}
+}
diff --git a/modules/authlinkedin/www/linkback.php b/modules/authlinkedin/www/linkback.php
new file mode 100644
index 0000000000000000000000000000000000000000..961eaa6bf423e56b8719f152c4976be1b95a7ac2
--- /dev/null
+++ b/modules/authlinkedin/www/linkback.php
@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * Handle linkback() response from LinkedIn.
+ */
+
+if (array_key_exists('stateid', $_REQUEST)) {
+        $stateId = $_REQUEST['stateid'];
+} else {
+        throw new Exception('Lost OAuth Client State');
+}
+
+$state = SimpleSAML_Auth_State::loadState($stateId, sspmod_authlinkedin_Auth_Source_LinkedIn::STAGE_INIT);
+
+// http://developer.linkedin.com/docs/DOC-1008#2_Redirect_the_User_to_our_Authorization_Server
+if (array_key_exists('oauth_verifier', $_REQUEST)) {
+	$state['authlinkedin:oauth_verifier'] = $_REQUEST['oauth_verifier'];
+} else {
+	throw new Exception('OAuth verifier not returned.');;
+}
+
+/* Find authentication source. */
+assert('array_key_exists(sspmod_authlinkedin_Auth_Source_LinkedIn::AUTHID, $state)');
+$sourceId = $state[sspmod_authlinkedin_Auth_Source_LinkedIn::AUTHID];
+
+$source = SimpleSAML_Auth_Source::getById($sourceId);
+if ($source === NULL) {
+	throw new Exception('Could not find authentication source with id ' . $sourceId);
+}
+
+$source->finalStep($state);
+
+SimpleSAML_Auth_Source::completeAuth($state);
+