diff --git a/attributemap/windowslive2name.php b/attributemap/windowslive2name.php index e0821f16df8ac36fbc3cf4879c0eddc6ce889fff..1c5496c90dd63e3c9006c38ff13644cda5b37402 100644 --- a/attributemap/windowslive2name.php +++ b/attributemap/windowslive2name.php @@ -10,5 +10,13 @@ $attributemap = array( 'windowslive.FirstName' => 'givenName', 'windowslive.LastName' => 'sn', 'windowslive.Location' => 'l', + // Attributes returned by Microsoft Graph - http://graph.microsoft.io/en-us/docs/api-reference/v1.0/resources/user + 'windowslive.givenName' => 'givenName', + 'windowslive.surname' => 'sn', + 'windowslive.displayName' => 'displayName', + 'windowslive.id' => 'uid', + 'windowslive.userPrincipalName' => 'eduPersonPrincipalName', + 'windowslive.mail' => 'mail', + 'windowslive.preferredLanguage' => 'preferredLanguage', ); diff --git a/config-templates/authsources.php b/config-templates/authsources.php index 1d44dc6d96c586b855fe6515fdf446b1c378037b..a936f64bae3c83b0e486734c70304f86227a803e 100644 --- a/config-templates/authsources.php +++ b/config-templates/authsources.php @@ -242,9 +242,9 @@ $config = array( */ /* - // Windows Live ID Authentication API. + // Microsoft Account (Windows Live ID) Authentication API. // Register your application to get an API key here: - // https://manage.dev.live.com + // https://apps.dev.microsoft.com/ 'windowslive' => array( 'authwindowslive:LiveID', 'key' => 'xxxxxxxxxxxxxxxx', diff --git a/modules/authwindowslive/lib/Auth/Source/LiveID.php b/modules/authwindowslive/lib/Auth/Source/LiveID.php index 3b7c75ccaa228d4b92b3ff8f19dbc03d9585934f..f71b4db6308742b34c7bff7067b2627acbeecc66 100644 --- a/modules/authwindowslive/lib/Auth/Source/LiveID.php +++ b/modules/authwindowslive/lib/Auth/Source/LiveID.php @@ -63,12 +63,14 @@ class sspmod_authwindowslive_Auth_Source_LiveID extends SimpleSAML_Auth_Source { 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' + // Documentation at: https://azure.microsoft.com/en-us/documentation/articles/active-directory-v2-protocols-oauth-code/ + $authorizeURL = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize' + . '?client_id=' . $this->key + . '&response_type=code' + . '&response_mode=query' + . '&redirect_uri=' . urlencode(SimpleSAML_Module::getModuleUrl('authwindowslive') . '/linkback.php') + . '&state=' . urlencode($stateID) + . '&scope=' . urlencode('openid https://graph.microsoft.com/user.read') ; \SimpleSAML\Utils\HTTP::redirectTrustedURL($authorizeURL); @@ -78,15 +80,17 @@ class sspmod_authwindowslive_Auth_Source_LiveID extends SimpleSAML_Auth_Source { public function finalStep(&$state) { - SimpleSAML\Logger::debug("oauth wrap: Using this verification code [" . - $state['authwindowslive:wrap_verification_code'] . "]"); + SimpleSAML\Logger::debug("authwindowslive oauth: Using this verification code [" . + $state['authwindowslive: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']); + // Documentation at: https://azure.microsoft.com/en-us/documentation/articles/active-directory-v2-protocols-oauth-code/#request-an-access-token + $postData = 'client_id=' . urlencode($this->key) + . '&client_secret=' . urlencode($this->secret) + . '&scope=' . urlencode('https://graph.microsoft.com/user.read') + . '&grant_type=authorization_code' + . '&redirect_uri=' . urlencode(SimpleSAML_Module::getModuleUrl('authwindowslive') . '/linkback.php') + . '&code=' . urlencode($state['authwindowslive:verification_code']); $context = array( 'http' => array( @@ -96,38 +100,32 @@ class sspmod_authwindowslive_Auth_Source_LiveID extends SimpleSAML_Auth_Source { ), ); - $result = \SimpleSAML\Utils\HTTP::fetch('https://consent.live.com/AccessToken.aspx', $context); + $result = \SimpleSAML\Utils\HTTP::fetch('https://login.microsoftonline.com/common/oauth2/v2.0/token', $context); - parse_str($result, $response); + $response = json_decode($result,true); // 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']); + if (!array_key_exists('access_token',$response)) + throw new Exception('[' . $response['error'] . '] ' . $response['error_description'] . + "\r\nNo access_token returned - cannot proceed\r\n" . implode(', ', $response['error_codes'])); - SimpleSAML\Logger::debug("Got an access token from the OAuth WRAP service provider [" . - $response['wrap_access_token'] . "] for user [" . $response['uid'] . "]"); + SimpleSAML\Logger::debug("authwindowslive: Got an access token from the OAuth service provider [" . + $response['access_token'] . "]"); - // 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\Utils\HTTP::fetch('https://apis.live.net/V4.1/cid-'. $response['uid'] . '/Profiles',$opts); + // Documentation at: http://graph.microsoft.io/en-us/docs/overview/call_api + $opts = array('http' => array('header' => "Accept: application/json\r\nAuthorization: Bearer " . + $response['access_token'] . "\r\n")); + $data = \SimpleSAML\Utils\HTTP::fetch('https://graph.microsoft.com/v1.0/me',$opts); $userdata = json_decode($data, TRUE); + // This is the simplest case + if(!array_key_exists('@odata.context',$userdata) OR array_key_exists('error',$userdata)) + throw new Exception('Unable to retrieve userdata from Microsoft Graph [' . $userdata['error']['code'] . '] ' . $userdata['error']['message']); $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']); - + $attributes['windowslive_targetedID'] = array('https://graph.microsoft.com!' . (!empty($userdata['id']) ? $userdata['id'] : 'unknown')); + foreach($userdata AS $key => $value) { + if (is_string($value)) + $attributes['windowslive.' . $key] = array((string)$value); } diff --git a/modules/authwindowslive/www/linkback.php b/modules/authwindowslive/www/linkback.php index fcfd3d66e6cf08248bb84ab5192fed60a390110d..2aa264722b854a60c0de1af3bfbca8684f47b14c 100644 --- a/modules/authwindowslive/www/linkback.php +++ b/modules/authwindowslive/www/linkback.php @@ -4,30 +4,30 @@ * Handle linkback() response from Windows Live ID. */ -if (!array_key_exists('wrap_client_state', $_REQUEST)) { - throw new Exception('Lost OAuth-WRAP Client State'); +if (!array_key_exists('state', $_REQUEST)) { + throw new Exception('Lost OAuth Client State'); } -$state = SimpleSAML_Auth_State::loadState($_REQUEST['wrap_client_state'], sspmod_authwindowslive_Auth_Source_LiveID::STAGE_INIT); +$state = SimpleSAML_Auth_State::loadState($_REQUEST['state'], sspmod_authwindowslive_Auth_Source_LiveID::STAGE_INIT); // http://msdn.microsoft.com/en-us/library/ff749771.aspx -if (array_key_exists('wrap_verification_code', $_REQUEST)) { +if (array_key_exists('code', $_REQUEST)) { // Good - $state['authwindowslive:wrap_verification_code'] = $_REQUEST['wrap_verification_code']; + $state['authwindowslive:verification_code'] = $_REQUEST['code']; if (array_key_exists('exp', $_REQUEST)) - $state['authwindowslive:wrap_exp'] = $_REQUEST['exp']; + $state['authwindowslive:exp'] = $_REQUEST['exp']; } else { - // wrap_error_reason = 'user_denied' means user chose not to login with LiveID + // 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') { + if ($_REQUEST['error'] === 'user_denied') { $e = new SimpleSAML_Error_UserAborted(); SimpleSAML_Auth_State::throwException($state, $e); } // Error - throw new Exception('Authentication failed: [' . $_REQUEST['error_code'] . '] ' . $_REQUEST['wrap_error_reason']); + throw new Exception('Authentication failed: [' . $_REQUEST['error'] . '] ' . $_REQUEST['error_description']); } // Find authentication source