Furthermore use Windows Live like Oauth and Openid to handle authentication of 320 million users. The user benefits from simple secure sign on and doesn't have to create a new account. They take their profile and all their contacts with them and lets you see who else on your site they know so they can instantly become friends and share your sites features.
Demo
Try the demo!This page describes how to embed the Windows Messenger app bar into your website. And in this exercise we create this....
Setup
Get an Appid+secret https://live.azure.com/Cloud/Provisioning/Services.aspx?ProjectId=0Code
View code<?php
/**
* Example: Embeding Windows live messenger directly into your website.
* This script is a starting place to understand how a site communicates with Windows Live services
* Relies on embeded client scripts hosted by microsoft, other than that it is standalone implementation
*
* @author Andrew Dodson
*
* SETUP
* ------------
* 1. Obtain an application ID from https://live.azure.com/Cloud/Provisioning/Services.aspx?ProjectId=0
* (More info about App ID at - http://msdn.microsoft.com/en-us/library/bb676626.aspx)
* 2. Place Application ID (appid) and Secret in $settings below
*/
$settings = array(
'appid' => 'appid-goes-here',
'secret' => 'secret-goes-here'
);
/**
* Build the AppTag attributes
*
* More Info @
* -----------------
* http://msdn.microsoft.com/en-us/library/microsoft.live.messenger.ui.tags.apptag_properties.aspx
*/
$msgrAppAttr = array(
// REQUIRED
// ---------------------
'privacy-url' => $_SERVER['REQUEST_URI'], // e.g. "Privacy.html"
'token-url' => $_SERVER['REQUEST_URI'].'?token', // "refreshMesengerToken.php"
'channel-url' => $_SERVER['REQUEST_URI'], // e.g. "Channel.html"
// Encrypt's the secret key
'application-verifier-token' => urlencode(( $token = ( 'appid=' . $settings['appid'] . '&ts=' . time() ) )
. '&sig=' . urlencode(base64_encode(hash_hmac("sha256",$token,
substr(
hash('sha256', 'SIGNATURE' . $settings['secret'], true),
0,
16),
true)
))),
// OPTIONAL
// ------------------------
'application-name' =>"Knarly Sandbox with Windows Live Login"
);
/**
* IS THIS PAGE ACTING AS A DELEGATION ASSIGNMENT?
* Typically this would be located at a completely seperate pathname defined by aforementioned "token-url"
*/
if(isset($_GET['token'])){
/**
* Process Consent Token which has been defined by the embeded script
* To create the Delegation token to ... (missing description)
*/
$parsedToken = explode_querystring( urldecode(urlencode($_COOKIE['msgr-consent-token'])) );
// Process this token... this is the confusing part
$token = base64_decode(urldecode($parsedToken['eact']));
$cryptkey = substr( hash('sha256', 'ENCRYPTION' . $settings['secret'], true), 0, 16);
$parsedToken = explode_querystring(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $cryptkey, substr($token, 16), MCRYPT_MODE_CBC, substr($token, 0, 16)));
/**
* Set delegation token
*/
setrawcookie('msgr-delegation-token', $parsedToken['delt'], 0, '/');
exit; // thats it
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:msgr="http://messenger.live.com/2009/ui-tags">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Example: Windows Live connection and Messenger</title>
<script type="text/javascript" src="http://www.wlmessenger.net/api/3.5/loader.js"></script>
<script language="javascript" type="text/javascript">
Microsoft.Live.Core.Loader.load(['messenger.ui.styles.core', 'messenger.ui']);
</script>
</head>
<body>
<a href='?source'>View source</a>
<h1>Example: Windows Live connection and Messenger</h1>
<msgr:app <?= implode_with_keys($msgrAppAttr) ?>></msgr:app>
<msgr:bar></msgr:bar>
</body>
</html>
<?php
/*****************************************************
* GENERIC FUNCTIONS: Extends PHP's functionality
*****************************************************/
/**
* Format an associative array (i.e. [key => value]) of attributes into a string
* @param array Key value associative array e.g. Dom Attributes
* @return String
*/
function implode_with_keys($a,$seperator=" ",$key_value_seperator='=', $value_enclose = '"', $key_enclose = ''){
$r = array();
foreach($a as $k => $o){
$r[] = $key_enclose.$k.$key_enclose.$key_value_seperator.$value_enclose.$o.$value_enclose;
}
return implode($seperator,$r);
}
/**
* Split the querystring (e.g. "key1=value1&key2=value2") into a PHP associative array
* @param String Querystring
* @return Array Associative array
*/
function explode_querystring($s){
$r = array();
foreach( explode('&',$s) as $o){
$a = explode('=', $o);
$r[$a[0]] = $a[1];
}
return $r;
}
?>
Token/Privacy/Channel -urls
These are all required attributes of the <msgr:app> tag and will throw fatal exceptions if omitted. In the example they are pointing to a black hole just for brevity sake. With the exception of token-url which is triggered once the consentToken is obtained in order to discover the Delegation ID.
<msgr:app
privacy-url="/winlive/messengerbar.php"
token-url="/winlive/messengerbar.php?token"
channel-url="/winlive/messengerbar.php"
application-verifier-token="appid%3D000000004002C81B%26ts%3D1262966287%26si...."
>
</msgr:app>
More on all these attributes at Properties. Note: the attribute names here are in CamelCase, whilst the html generated in the above script uses hyphens.
Going further: Using Messenger to find a unique user id to initiate a site session login.
At first i was stuck with this there didn't appear to be any unique key returned in this signin process which a website may use to additionally verify the user and any user specific content/access they have. Which the Windows Live ID API addresses but for some reason Messenger is unclear.
When i rooted around the code i found the $parsedToke['lid'] otherwise known as the location ID is unique to the LiveID account (please correct me if i'm wrong). I am wrong .. although i still haven't found what the location ID represents, Geographical or name perhaps of a hosting server.
Moving on.we can make a request to the server...
http://messenger.services.live.com/actions/signinstatus/
This path was obtained by looking at the net requests in Firebug. And to my knowledge is undocumented. Because they dont want wandering too far from the path.
So here we we send data with the content-type header application/json, and after the header we send json data. e.g
POST /actions/signinstatus/ HTTP/1.1
Host: messenger.services.live.com
Content-Type: application/json; charset=utf-8
Content-Length: 675
{"version":"1","authInfo":{"authType":2,"ticket":"DELEGATION_CODE"},"domain":"HOST_NAME","clientVersion":"3.5"}NOTE: replace DELEGATION_CODE obtained above and HOST_NAME your domain name e.g. perplexed.co.uk
If this all works out we should get a JSON response including the user identity. E.g
HTTP/1.1 200 OK
Cache-Control: no-cache
Content-Length: 843
Content-Type: application/json; charset=utf-8
X-MSNSERVER: BY2MSG3020402
Date: Fri, 15 Jan 2010 18:32:16 GMT
{
"identity": {
"liveId": "adrosetint@hotmail.com", "endpointId": "{00000000-4002-c81b-6cbd-89211d21e20f}", "puid": "", "cid": "7835569702010216975", "appId": "1073924123", "authenticationInfo": {
"authType": 2, "ticket": ""
}
}, "signInStatus": {
"isAuthenticated": true, "isAutoSignIn": false, "isManualSignIn": false, "isTrustedSignIn": false, "isApplicationBlocked": false, "isUnsupportedBrowser": true, "isUserSignedInViaSpopClient": false, "isUserSignedInViaMpopEndpoints": true, "isMpopSettingEnabled": true, "isUserBlocked": false, "isTicketExpired": false, "isAutoSignInEnabled": 0, "isAudioEnabled": true, "isFirstRunExperienceViewed": false, "isContactsSignatureRequired": true, "isUserSettingsKnown": true, "isAppSettingsKnown": true
}, "duration": "453", "reloaded": false
}Here's the code, This should be appended to the above code following on after we've obtained the Delegation code.
/**
* Post a request to the Provider Server to get a unique ID of the user
*/
$data = (str_replace('\\/','/',json_encode((object)array(
"version" => "1",
"authInfo" => (object)array(
"authType" => 2,
"ticket" => urldecode($parsedToken['delt'])
),
"domain" => $_SERVER['HTTP_HOST'],
'clientVersion' => "3.5"
))));
// Open Socket
if( $fp = fsockopen("messenger.services.live.com", 80, $err, $ers, 5) ){
fputs($fp, // HEADERS
implode(CRLF, array( "POST /actions/signinstatus/ HTTP/1.1",
"Host: messenger.services.live.com",
"Content-Type: application/json; charset=utf-8",
"Content-Length: " . strlen($data)
))
// BREAK
.CRLF.CRLF
// DATA
.$data);
// Split the response, [header] CRLF.CRLF [data]
$match = split(CRLF.CRLF, fread($fp, 4096),2);
// Turn the JSON resposne into an array
$resp = json_decode($match[1]);
// Set the LiveID and CID and store wherre ever you want em
$liveid = $resp->identity->liveId;
$cid = $resp->identity->cid;
}
else{
// errors
// can't make connection to server
var_dump( $err,$ers );
} 