From 222075e38e56ac074a09958a4a7d287f15263e5e Mon Sep 17 00:00:00 2001 From: Olav Morken <olav.morken@uninett.no> Date: Wed, 9 Feb 2011 11:22:27 +0000 Subject: [PATCH] New authentication source: authwindowslive Thanks to Brook Schofield for implementing this. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2737 44740490-163a-0410-bde0-09ae8108e29a --- attributemap/windowslive2name.php | 16 ++ modules/authwindowslive/default-disable | 3 + .../authwindowslive/docs/windowsliveid.txt | 20 +++ .../lib/Auth/Source/LiveID.php | 140 ++++++++++++++++++ modules/authwindowslive/www/linkback.php | 47 ++++++ 5 files changed, 226 insertions(+) create mode 100644 attributemap/windowslive2name.php create mode 100644 modules/authwindowslive/default-disable create mode 100644 modules/authwindowslive/docs/windowsliveid.txt create mode 100644 modules/authwindowslive/lib/Auth/Source/LiveID.php create mode 100644 modules/authwindowslive/www/linkback.php diff --git a/attributemap/windowslive2name.php b/attributemap/windowslive2name.php new file mode 100644 index 000000000..f43d0f99a --- /dev/null +++ b/attributemap/windowslive2name.php @@ -0,0 +1,16 @@ +<?php +$attributemap = array( + + // Generated Windows Live ID Attributes + 'windowslive_user' => 'eduPersonPrincipalName', // uid @ windowslive.com + 'windowslive_targetedID' => 'eduPersonTargetedID', // http://windowslive.com!uid + 'windowslive_uid' => 'uid', // windows live id + 'windowslive_mail' => 'mail', + + // Attributes Returned by Windows Live ID + 'windowslive.FirstName' => 'givenName', + 'windowslive.LastName' => 'sn', + 'windowslive.Location' => 'l', + //'windowslive.ThumbnailImageLink'=> 'jpegPhoto', // URL not image data + +); diff --git a/modules/authwindowslive/default-disable b/modules/authwindowslive/default-disable new file mode 100644 index 000000000..fa0bd82e2 --- /dev/null +++ b/modules/authwindowslive/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/authwindowslive/docs/windowsliveid.txt b/modules/authwindowslive/docs/windowsliveid.txt new file mode 100644 index 000000000..014427189 --- /dev/null +++ b/modules/authwindowslive/docs/windowsliveid.txt @@ -0,0 +1,20 @@ +Using the Windows Live ID authentication source with simpleSAMLphp +================================================================== + +Remember to configure `authsources.php`, with both your Client ID and Secret key. + +To get an API key and a secret, register the application at: + + * <http://msdn.microsoft.com/en-us/library/ff751474.aspx> + * <https://manage.dev.live.com> + +## Testing authentication + +On the SimpleSAMLphp frontpage, go to the *Authentication* tab, and use the link: + + * *Test configured authentication sources* + +Then choose the *windowsliveid* authentication source. + +Expected behaviour would then be that you are sent to Windows Live ID and asked to login. + diff --git a/modules/authwindowslive/lib/Auth/Source/LiveID.php b/modules/authwindowslive/lib/Auth/Source/LiveID.php new file mode 100644 index 000000000..2dcd532bf --- /dev/null +++ b/modules/authwindowslive/lib/Auth/Source/LiveID.php @@ -0,0 +1,140 @@ +<?php + +/** + * Authenticate using LiveID. + * + * @author Brook Schofield, TERENA. + * @package simpleSAMLphp + * @version $Id$ + */ +class sspmod_authwindowslive_Auth_Source_LiveID extends SimpleSAML_Auth_Source { + + /** + * The string used to identify our states. + */ + const STAGE_INIT = 'authwindowslive:init'; + + /** + * The key of the AuthId field in the state. + */ + const AUTHID = 'authwindowslive: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('LiveID authentication source is not properly configured: missing [key]'); + + $this->key = $config['key']; + + if (!array_key_exists('secret', $config)) + throw new Exception('LiveID authentication source is not properly configured: missing [secret]'); + + $this->secret = $config['secret']; + } + + + /** + * Log-in using LiveID platform + * + * @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::saveState($state, self::STAGE_INIT); + + SimpleSAML_Logger::debug('authwindowslive auth state id = ' . $stateID); + + // Authenticate the user + // Documentation at: http://msdn.microsoft.com/en-us/library/ff749771.aspx + $authorizeURL = 'https://consent.live.com/Connect.aspx' + . '?wrap_client_id=' . $this->key + . '&wrap_callback=' . urlencode(SimpleSAML_Module::getModuleUrl('authwindowslive') . '/linkback.php') + . '&wrap_client_state=' . urlencode($stateID) + . '&wrap_scope=WL_Profiles.View,Messenger.SignIn' + ; + + SimpleSAML_Utilities::redirect($authorizeURL); + } + + + + public function finalStep(&$state) { + + SimpleSAML_Logger::debug("oauth wrap: Using this verification code [" . + $state['authwindowslive:wrap_verification_code'] . "]"); + + // Retrieve Access Token + // Documentation at: http://msdn.microsoft.com/en-us/library/ff749686.aspx + $postData = 'wrap_client_id=' . urlencode($this->key) + . '&wrap_client_secret=' . urlencode($this->secret) + . '&wrap_callback=' . urlencode(SimpleSAML_Module::getModuleUrl('authwindowslive') . '/linkback.php') + . '&wrap_verification_code=' . urlencode($state['authwindowslive:wrap_verification_code']); + + $context = array( + 'http' => array( + 'method' => 'POST', + 'header' => 'Content-type: application/x-www-form-urlencoded', + 'content' => $postData, + ), + ); + + $result = SimpleSAML_Utilities::fetch('https://consent.live.com/AccessToken.aspx', $context); + + parse_str($result, $response); + + // error checking of $response to make sure we can proceed + if (!array_key_exists('wrap_access_token',$response)) + throw new Exception('[' . $response['error_code'] . '] ' . $response['wrap_error_reason'] . + "\r\nNo wrap_access_token returned - cannot proceed\r\n" . $response['internal_info']); + + SimpleSAML_Logger::debug("Got an access token from the OAuth WRAP service provider [" . + $response['wrap_access_token'] . "] for user [" . $response['uid'] . "]"); + + // Documentation at: http://msdn.microsoft.com/en-us/library/ff751708.aspx + $opts = array('http' => array('header' => "Accept: application/json\r\nAuthorization: WRAP access_token=" . + $response['wrap_access_token'] . "\r\n")); + $data = SimpleSAML_Utilities::fetch('https://apis.live.net/V4.1/cid-'. $response['uid'] . '/Profiles',$opts); + $userdata = json_decode($data, TRUE); + + $attributes = array(); + $attributes['windowslive_uid'] = array($response['uid']); + $attributes['windowslive_targetedID'] = array('http://windowslive.com!' . $response['uid']); + $attributes['windowslive_user'] = array($response['uid'] . '@windowslive.com'); + + if (array_key_exists('Entries',$userdata)) { + foreach($userdata['Entries'][0] AS $key => $value) { + if (is_string($value)) + $attributes['windowslive.' . $key] = array((string)$value); + } + + if (array_key_exists('Emails', $userdata['Entries'][0])) + $attributes['windowslive_mail'] = array($userdata['Entries'][0]['Emails'][0]['Address']); + + } + + + SimpleSAML_Logger::debug('LiveID Returned Attributes: '. implode(", ",array_keys($attributes))); + + $state['Attributes'] = $attributes; + } + +} diff --git a/modules/authwindowslive/www/linkback.php b/modules/authwindowslive/www/linkback.php new file mode 100644 index 000000000..a8fe872dc --- /dev/null +++ b/modules/authwindowslive/www/linkback.php @@ -0,0 +1,47 @@ +<?php + +/** + * Handle linkback() response from Windows Live ID. + */ + +if (array_key_exists('wrap_client_state', $_REQUEST)) { + $stateId = $_REQUEST['wrap_client_state']; + $state = SimpleSAML_Auth_State::loadState($stateId, sspmod_authwindowslive_Auth_Source_LiveID::STAGE_INIT); +} else { + throw new Exception('Lost OAuth-WRAP Client State'); +} + +// http://msdn.microsoft.com/en-us/library/ff749771.aspx +if (array_key_exists('wrap_verification_code', $_REQUEST)) { + + // Good + $state['authwindowslive:wrap_verification_code'] = $_REQUEST['wrap_verification_code']; + + if (array_key_exists('exp', $_REQUEST)) + $state['authwindowslive:wrap_exp'] = $_REQUEST['exp']; + +} else { + // wrap_error_reason = 'user_denied' means user chose not to login with LiveID + // redirect them to their original page so they can choose another auth mechanism + if ($_REQUEST['wrap_error_reason'] === 'user_denied') { + $e = new SimpleSAML_Error_UserAborted('User aborted authentication.'); + SimpleSAML_Auth_State::throwException($state, $e); + } + + // Error + throw new Exception('Authentication failed: [' . $_REQUEST['error_code'] . '] ' . $_REQUEST['wrap_error_reason']); +} + +/* Find authentication source. */ +assert('array_key_exists(sspmod_authwindowslive_Auth_Source_LiveID::AUTHID, $state)'); +$sourceId = $state[sspmod_authwindowslive_Auth_Source_LiveID::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); + -- GitLab