MSNP15:SSO
From MSNPiki
Overview ·
Changes ·
Single Sign-On ·
Ticket Tokens
New features: Locations · Roaming Content
Contents |
RPS/SSO Authentication
When you authenticate with MSNP15, you will notice that the USR command has changed slightly. Here is the new format:
Abstract
Client: USR <TrId> SSO I <email>\r\n Server: USR <TrId> SSO S <policy> <base64 encoded nonce>\r\n Client: USR <TrId> SSO S <ticket> <base64 encoded response structure>\r\n Server: USR <TrId> OK <email> <verified> 0\r\n
Example
Client: USR 10 SSO I buddy@live.com\r\n Server: USR 10 SSO S MBI_KEY_OLD E4Fhehbe0q2Je+SUSp7IRnJV+rN4uME75ljIpUjIZ1Si+DgmrfuiIL+AFmkMA6Wv\r\n Client: USR 11 SSO S t=... HAAAAAEAAAADZgAABIAAAA...\r\n Server: USR 11 OK buddy@live.com 1 0\r\n
After you receive the first "SSO S" command, you should take your given policy and connect to https://login.live.com/RST.srf.
Remark: For the account which ends up with @msn.com, this should be https://msnia.login.live.com/pp550/RST.srf.
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsse="http://schemas.xmlsoap.org/ws/2003/06/secext" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing" xmlns:wssc="http://schemas.xmlsoap.org/ws/2004/04/sc" xmlns:wst="http://schemas.xmlsoap.org/ws/2004/04/trust"> <Header> <ps:AuthInfo xmlns:ps="http://schemas.microsoft.com/Passport/SoapServices/PPCRL" Id="PPAuthInfo"> <ps:HostingApp>{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}</ps:HostingApp> <ps:BinaryVersion>4</ps:BinaryVersion> <ps:UIVersion>1</ps:UIVersion> <ps:Cookies></ps:Cookies> <ps:RequestParams>AQAAAAIAAABsYwQAAAAxMDMz</ps:RequestParams> </ps:AuthInfo> <wsse:Security> <wsse:UsernameToken Id="user"> <wsse:Username>email@live.com</wsse:Username> <wsse:Password>PasswordGoesHere</wsse:Password> </wsse:UsernameToken> </wsse:Security> </Header> <Body> <ps:RequestMultipleSecurityTokens xmlns:ps="http://schemas.microsoft.com/Passport/SoapServices/PPCRL" Id="RSTS"> <wst:RequestSecurityToken Id="RST0"> <wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType> <wsp:AppliesTo> <wsa:EndpointReference> <wsa:Address>http://Passport.NET/tb</wsa:Address> </wsa:EndpointReference> </wsp:AppliesTo> </wst:RequestSecurityToken> <wst:RequestSecurityToken Id="RSTn"> <wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType> <wsp:AppliesTo> <wsa:EndpointReference> <wsa:Address>domain</wsa:Address> </wsa:EndpointReference> </wsp:AppliesTo> <wsse:PolicyReference URI="policy parameter"></wsse:PolicyReference> </wst:RequestSecurityToken> ... ... </ps:RequestMultipleSecurityTokens> </Body> </Envelope>
Inside of ps:RequestMultipleSecurityTokens, you have a list of domains you want to authenticate to. You start from RST0 and you move to RST1 and so on. This allows you to get your MSPAuth and MSPProf cookies for multiple different domains all at the same time.
Some examples of sites that you can authenticate with
Domain: http://Passport.NET/tb Policy Ref URI: - Purpose: Unknown, but it's required for the request to succeed.
Domain: messengerclear.live.com Policy Ref URI: <obtain from the USR command> Purpose: Authentication for messenger.
Domain: messenger.msn.com Policy Ref URI: ?id=507 Purpose: Messenger website authentication.
Domain: contacts.msn.com Policy Ref URI: ?fs=1&id=24000&kv=9&rn=93S9SWWw&tw=0&ver=2.1.6000.1 New Policy Ref URI: MBI (used in WLM 8.5.1288.816) Purpose: Authentication for the Contact server.
Domain: messengersecure.live.com Policy Ref URI: MBI_SSL Purpose: Unknown
Domain: spaces.msn.com or spaces.live.com Policy Ref URI: MBI Purpose: Authentication for the Windows Live Spaces
Domain: livecontacts.live.com Policy Ref URI: MBI Purpose: Live Contacts API, a simplified version of the Contacts SOAP service
Domain: storage.live.com Policy Ref URI: MBI Purpose: Storage REST API
The response to this query when successful, looks like this.
<S:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <S:Header> There is really data here, but for space it has be removed </S:Header> <S:Body> <wst:RequestSecurityTokenResponseCollection xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wst="http://schemas.xmlsoap.org/ws/2004/04/trust" xmlns:wsse="http://schemas.xmlsoap.org/ws/2003/06/secext" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy" xmlns:psf="http://schemas.microsoft.com/Passport/SoapServices/SOAPFault"> <wst:RequestSecurityTokenResponse> <wst:TokenType>urn:passport:legacy</wst:TokenType> <wsp:AppliesTo xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"> <wsa:EndpointReference> <wsa:Address>http://Passport.NET/tb</wsa:Address> </wsa:EndpointReference> </wsp:AppliesTo> <wst:LifeTime> <wsu:Created>2006-12-06T05:12:10Z</wsu:Created> <wsu:Expires>2006-12-07T05:12:10Z</wsu:Expires> </wst:LifeTime> <wst:RequestedSecurityToken> <EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#" Id="BinaryDAToken0" Type="http://www.w3.org/2001/04/xmlenc#Element"> <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"> </EncryptionMethod> <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:KeyName>http://Passport.NET/STS</ds:KeyName> </ds:KeyInfo> <CipherData> <CipherValue> cipher data you don't need to worry about </CipherValue> </CipherData> </EncryptedData> </wst:RequestedSecurityToken> <wst:RequestedTokenReference> <wsse:KeyIdentifier ValueType="urn:passport"></wsse:KeyIdentifier> <wsse:Reference URI="#BinaryDAToken0"></wsse:Reference> </wst:RequestedTokenReference> <wst:RequestedProofToken> <wst:BinarySecret>ignore this one</wst:BinarySecret> </wst:RequestedProofToken> </wst:RequestSecurityTokenResponse> <wst:RequestSecurityTokenResponse> <wst:TokenType>urn:passport:compact</wst:TokenType> <wsp:AppliesTo xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"> <wsa:EndpointReference> <wsa:Address>messengerclear.live.com</wsa:Address> </wsa:EndpointReference> </wsp:AppliesTo> <wst:LifeTime> <wsu:Created>2006-12-06T05:12:10Z</wsu:Created> <wsu:Expires>2006-12-06T13:12:10Z</wsu:Expires> </wst:LifeTime> <wst:RequestedSecurityToken> <wsse:BinarySecurityToken Id="Compactn"> t=<ticket goes here>&p= </wsse:BinarySecurityToken> </wst:RequestedSecurityToken> <wst:RequestedTokenReference> <wsse:KeyIdentifier ValueType="urn:passport:compact"></wsse:KeyIdentifier> <wsse:Reference URI="#Compactn"></wsse:Reference> </wst:RequestedTokenReference> <wst:RequestedProofToken> <wst:BinarySecret>binary secret (you need this)</wst:BinarySecret> </wst:RequestedProofToken> </wst:RequestSecurityTokenResponse> <wst:RequestSecurityTokenResponse> <wst:TokenType>urn:passport:legacy</wst:TokenType> <wsp:AppliesTo xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"> <wsa:EndpointReference> <wsa:Address>site domain</wsa:Address> </wsa:EndpointReference> </wsp:AppliesTo> <wst:LifeTime> <wsu:Created>2006-12-06T05:12:10Z</wsu:Created> <wsu:Expires>2006-12-06T05:20:30Z</wsu:Expires> </wst:LifeTime> <wst:RequestedSecurityToken> <wsse:BinarySecurityToken Id="PPTokenn"> t=<site ticket here>&p=<site profile here> </wsse:BinarySecurityToken> </wst:RequestedSecurityToken> <wst:RequestedTokenReference> <wsse:KeyIdentifier ValueType="urn:passport"></wsse:KeyIdentifier> <wsse:Reference URI="#PPTokenn"></wsse:Reference> </wst:RequestedTokenReference> </wst:RequestSecurityTokenResponse> ... ... </wst:RequestSecurityTokenResponseCollection> </S:Body> </S:Envelope>
In your response, you will need to look for the wst:RequestSecurityTokenResponseCollection section. This section contains the list of credentials for each site you requested. If your policy reference URI contained something like MBI, MBI_SSL or MBI_KEY_OLD, the your ticket/MSPAuth&MSPProf will be in the <wsse:BinarySecurityToken Id="Compactn"> where n is the same number as the RSTn request. If the policy reference contains a string starting in a question mark (like the end of a url), your security data will be in <wsse:BinarySecurityToken Id="PPTokenn"> Technically speaking you should check the <wst:TokenType> tag.
For logging in to messenger, you will need to grab your ticket, and the contents of the <wst:BinarySecret> tag.
Computing the return value
Now that you have your ticket and your Binary secret, we need to create a structure of information to send back to the server. The C++ style structure look like this:
typedef struct tagMSGRUSRKEY
{
unsigned long uStructHeaderSize; // 28. Does not count data
unsigned long uCryptMode; // CRYPT_MODE_CBC (1)
unsigned long uCipherType; // TripleDES (0x6603)
unsigned long uHashType; // SHA1 (0x8004)
unsigned long uIVLen; // 8
unsigned long uHashLen; // 20
unsigned long uCipherLen; // 72
// Data
unsigned char aIVBytes[8];
unsigned char aHashBytes[20];
unsigned char aCipherBytes[72];
}MSGUSRKEY;
Note that these values are all Little-Endian. unsigned long is 4 bytes.
If you use the default values that messenger give, the sizes of the BYTE arrays will be correct, if you do not use the default values, you'll have to adjust properly.
aIVBytes is an array of random data that is used in the encryption process.
Here's how to create the hashes: Base64 decode your nonce. Derive a SHA-1/TripleDES key from the decoded data. Use that key to perform this pseudo-code.
hash1 = SHA1-HMAC("WS-SecureConversationSESSION KEY HASH")
hash2 = SHA1-HMAC(hash1, "WS-SecureConversationSESSION KEY HASH")
hash3 = SHA1-HMAC(hash1)
hash4 = SHA1-HMAC(hash3,"WS-SecureConversationSESSION KEY HASH")
Take all 20 bytes from hash2 and the first 4 bytes from hash4. Store that in 'key2' Now do the samething only this time use the string "WS-SecureConversationSESSION KEY ENCRYPTION" and store it in 'key3'
No generate 8 bytes of random data. In your encryption library, set IV as these bytes, and set the mode to CBC.
Import key2 and create a new SHA-1 HMAC hash. Import key3. Use the HMAC hash and the imported key3 to TripleDES encrypt/hash the data. Fill In the structure above and the base64 encode it.
Now take the base64 encoded structure and send it back to the server. If you've done everything right, you should received the OK reply.
Test Values
Nonce: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= Binary Secret: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= IV(hex): 00 00 00 00 00 00 00 00 Result (newline added readability): HAAAAAEAAAADZgAABIAAAAgAAAAUAAAASAAAAAAAAAAAAAAA7XgT5ohvaZdoXdrWUUcMF2G8OK2JohyY cK5l5MJSitab33scxJeK/RQXcUr0L+R2ZA9CEAzn0izmUzSMp2LZdxSbHtnuxCmptgtoScHp9E26HjQVkA9YJxgK/HM=
Nonce: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB= Binary Secret: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB= IV(hex): 00 00 00 00 00 00 00 00 Result (newline added readability): HAAAAAEAAAADZgAABIAAAAgAAAAUAAAASAAAAAAAAAAAAAAAywfWRZVnRRZTqPkW6HBIrOmPuYiFbzcpv YmP2QzhpH+VdKwtqUTt/gdbDqlMZvR1o7ve9ex44otMOxYtnNYIQ+lfoj+PKcsHT+T7GA1hfMsTVbGqoYYe3B5/WW0=
Code Examples
C (Linux) sso
VC++ (MFC) MBI Hash Example
C++ QT4 QCA - SSO Crypto Example
VB .NET: MBI Code
Java: ticket and hash code
References
Zoronax's Blog
MSNP15 authentication scheme REd
MSNP15 繁體中文相關資訊

