Skip to content
Delthas edited this page Nov 9, 2017 · 28 revisions

There's lots of ways to authenticate.

Microsoft accounts

Microsoft accounts are the ones that look like email addresses, previously known as "passport", and have many similarities with previous MSN login methods.

web-compact-ticket method

This method works for HTTPS longpolling connections, using http headers and cookies, and is the outlook.com web client uses.

Getting the cookies using a browser widget

This is based on the method that the skype clients use for microsoft account, but just getting the resulting cookies.

Open a browser to

https://login.live.com/oauth20_authorize.srf?client_id=00000000480BC46C&scope=service%3A%3Alw.skype.com%3A%3AMBI_SSL&response_type=token&redirect_uri=https%3A%2F%2Flogin.live.com%2Foauth20_desktop.srf&state=999&locale=en

Allow the user to log in as normal. When they're done, the browser will be redirected to https://login.live.com/oauth20_desktop.srf with an enormous fragment. The fragment might be useful, but what the webclient requires is the three cookies MSPAuth, MSPProf, WLSSC.

note that this client ID is the only one with access to the service::skype.com::MBI_SSL scope (as far as we know), previously created oauth2 clients ids (such as those needed for the now-defunct MSN XMPP gateway) won't work here.

Similarly, the redirect_uri parameter can't be changed to something more useful, returning this error in the fragment:

The provided value for the input parameter redirect_uri is not valid. The expected value is https://login.live.com/oauth20_desktop.srf or a URL which matches the redirect URI registered for this client application.

See also:

Login without a browser

Request the same URL as the previous section. Keep the MSPOK cookie.

Buried in the Javascript is a HTML <input> element, with name="PPFT". Keep the value attribute of this element.

Using the same query string as the first request, POST to https://login.live.com/ppsecure/post.srf, with the MSPOK cookie and a body consisting of url-encoded parameters:

Parameter Notes
PPFT The PPFT value you got from the first request
login Microsoft account name
passwd Password for that account

If all goes well, you are redirected to the same place as the previous section. If not, look for sErrTxt: followed by a Javascript string, the string including an error message.

Authenticating with HTTPS method and cookies

When sending HTTPS requests to the gateway, include the X-MSN-Auth: Use-Cookie header and the MSPAuth, MSPProf, WLSSC cookies from above

Then, when sending the ATH command, use <user><web-compact-ticket /></user> as the whole payload.

ATH 2 CON\USER 37

<user><web-compact-ticket /></user>

The outlook.com web client seems to request a UIC too from https://skypewebexperience.live.com/v1/User/Initialization (with cookies + the trouterurl and connectionid POST parameters). If requested correctly, the UIC is in the MappingContainer field of the json response.

Authenticating with oauth

The Location: HTTP-Header field in the 302 redirect from post.srf above contains a redirect-URL of oauth20_desktop.srf which contains an access_token and a refresh_token which you should extract (note that it's URLencoded, of course!):

Location: https://login.live.com/oauth20_desktop.srf?lc=1031#access_token=....very long base64 string here....&token_type=bearer&expires_in=86400&scope=service::lw.skype.com::MBI_SSL&refresh_token=....another base64 string....&state=999&user_id=...some hex int64...

There is also expires_in parameter in seconds that specifies the number of seconds from now on when the acquired token expires. Currently this is always 1 day.

Using the refresh_token, POST to https://login.live.com/oauth20_token.srf with parameters client_id=00000000480BC46C&scope={requested scope}&grant_type=refresh_token&refresh_token={refresh_token} as described in the OAuth docs by Microsoft. The requested scope can be one of the following:

Scope Description
service::login.skype.com::MBI_SSL Required for Login on real Skype Login-Server using i.e. skylogin. This is the way Skype does it.
service::ssl.live.com::MBI_SSL To be used as <ssl-compact-ticket> on ATH CON\USER on Skype login
service::chatservice.live.com::MBI_SSL To be used as <ssl-compact-ticket> on ATH CON\USER on MSN login
service::contacts.msn.com::MBI_SSL Used for Contact list handling already known from MSNP18
service::m.hotmail.com::MBI_SSL ActiveSync contactlist auth token, if you want (and can) use it.
service::lw.skype.com::MBI_SSL Used i.e. to get skype_token for cloud based APIs

You get back a bunch of JSON data to parse including the same parameters as in the OAuth Location: response above. You need to extract the access_token from there:

{ "access_token":"....some base64 encoded token you need...", "expires_in":86400, "refresh_token":"...base64 encoded refresh token, not needed...", "scope":"...the scope that you requested...", "token_type":"bearer", "user_id":"...your user_id..." }

ssl-compact-ticket method (Skylogin)

This method can be used to authenticate with the help of our SkyLogin library and the Skype login-Servers.

Getting the ssl-compact ticket with OAuth.

Just fetch the service::ssl.live.com::MBI_SSL token via the method mentioned above.

Getting the UIC

The UIC is required to successfully logon. First, fetch a service::login.skype.com::MBI_SSL token via the method mentioned above. Call SkyLogin_PerformLoginOAuth() with that token as a parameter. Then call SkyLogin_GetCredentialsUIC() with an output buffer of 1024 bytes to fill in UIC.

If it was successful, do login with:

ATH 2 CON\USER 110

<user>
  <ssl-compact-ticket>t={service::ssl.live.com::MBI_SSL token}</ssl-compact-ticket>
  <uic>{UIC acquired from Skylogin}</uic>
  <id>{Your MSN username}</id>
  <alias>{Username of Skype Partner account}</alias>
</user>

If you don't have the username of the Skype Partner account, you can get it from Skylogin with SkyLogin_GetUser().

ssl-compact-ticket method (chatservice.live.com)

This method can be used to authenticate with just plain Web-Calls without the need to use our Skylogin-Library. This is not working anymore, as skypewebexperience host went down. Use skylogin library

skype_token (Cloud based APIs)

If you want to use the cloud based APIs, i.e. for Sharing images with other contacts via the Microsoft servers (don't expecty any privacy by using MSN protocol anyway, everything is stored and logged on Microsoft's servers), you need another token, the skype_token. Here is how to get it:

  1. Fetch service::lw.skype.com::MBI_SSL OAuth token

Get the service::lw.skype.com::MBI_SSL OAuth token like described in Authenticating with oauth.

  1. Request skypetoken

POST https://api.skype.com/rps/skypetoken with the following POST fields:

scopes:         client
clientVersion:  0/7.4.85.102/259/
access_token:   {skype.com oauth token}
partner:        999

and you will receive the token as json:

{
    "expiresIn": 86400,
    "skypetoken": "....base64 skype token..."
}

Skype usernames

Logging in with skype usernames requires using a bunch of cryptography to generate the UIC as well.

There's a python implementation of skype username login here: https://github.com/uunicorn/pyskype We wrote our own C implementation (the already mentioned SkyLogin library) that you can use as a library for your client: https://github.com/msndevs/skylogin

The login flow with a Skype username is easer than all the OAuth stuff required for MSN accounts mentioned above. On CNT call, you get a nonce:

CNT 5 CON 126

<connect-response>
  <ver>2</ver>
  <qostest>false</qostest>
  <nonce>3d97e3ac-4df8-3d88-c35f-e96242d1efcd</nonce>
</connect-response> 

User Skylogin SkyLogin_PerformLogin() with username and password to login to Skype server. Then generate the UIC with SkyLogin_CreateUICString() using the given nonce and you get back a UIC if login succeeds. Then just login with that UIC:

ATH 2 CON\USER 110

<user><uic>{your UIC}</uic><id>{Your Skype Username}</id></user>

skype_token (Cloud based APIs)

If you want to use the cloud based APIs, i.e. for Sharing images with other contacts via the Microsoft servers (don't expecty any privacy by using MSN protocol anyway, everything is stored and logged on Microsoft's servers), you need another token, the skype_token. Here is how to get it:

  1. Calculate passwordHash The passwordHash is the base64-encoded form of the well known MD5-Hash from Skype login:

{username}\nskyper\n{password}

(without curly braces, I just use them to indicate a variable, \n is a newline as known from printf).

  1. Request skypetoken POST https://api.skype.com/login/skypetoken with the following POST fields:
scopes:         client
clientVersion:  0/7.4.85.102/259/
username:       {username}
passwordHash:   {pw hash calculated in 1.}

and you will receive the token as json:

{
    "expiresIn": 86400,
    "skypetoken": "....base64 skype token..."
}

Flowchart for login process

#After ATH After you sent your ATH and login succeeded, you receive an auth-response:

ATH 6 CON 131

<auth-response>
  <new-thread-allowed>false</new-thread-allowed>
  <p2p-migration-allowed>false</p2p-migration-allowed>
</auth-response>

Following that, you need to introduce your client to the server by sending the BND CON\MSGR command to the server:

BND 7 CON\MSGR 180

<msgr>
  <ver>2</ver>
  <altVersions><ver>1</ver></altVersions>
  <client>
    <name>Skype</name>
    <ver>0/6.16.0.105/259/</ver>
  </client>
  <epid>EB80C4E5-10DC-11D2-8C04-00A0C94C5D75</epid>
</msgr>

epid is an UUID identifying your machine. This is already known from earlier MSN versions. verspecifies the protocol version you support. In Version 2, you can register for status notifications and get and must send Registration: MIME-Headers.

The server replies with a BND answer and a nonce that you need to auth with:

BND 7 CON 660
UtcTime: 1431516231
Set-Registration: ....long base64 string....
Registration-Token-Expiry: 1431602631
Context: 1B8D4AA7AD8F8D02

<msgr-response>
  <ver>2</ver>
  <utctime>1431514361</utctime>
  <nonce>1489346893432768563572687681</nonce>
  <sample-window>0</sample-window>
</msgr-response>

You need to calculate a challenge from the Nonce to authenticate yourself as official client. The algorithm is the same as with earlier CHL-Answers in protocol. This involves calculation based on Protocol Challenge and Product ID. You can use:

Key Value
productKey YMM8C_H7KCQ2S_KL
productId PROD0090YUAUV{2B

After calculating the challenge from it, issue a PUT MSGR\CHALLENGE with that in order to login:

PUT 8 MSGR\CHALLENGE 531
Registration: ....long base64 string you received from Set-Registration answer....

<challenge>
  <appId>PROD0090YUAUV{2B</appId>
  <response>c99982d67ac970226e97c23b686d06cc</response>
</challenge>

appId is the productKey to be sent. As an answer you receive another ATH CON reply:

ATH 0 CON 158
Context: 1B8D4AA7AD8F8D02

<auth-response>
  <new-thread-allowed>false</new-thread-allowed>
  <p2p-migration-allowed>false</p2p-migration-allowed>
</auth-response>

Now you are successfully logged in and can propagate your online status with PUT MSGR\PRESENCE etc.

Refresh

In order to not drop off the network, you need to resend ATH CON\USER command every 23 hours. If you are using i.e. OAuth Tokens, be sure to refresh them before so that they aren't expired.

You receive the above mentioned reply, but you don't need to do anything further like sending BND, ATH is enough to refresh the connection.

If you do not refresh connection, you are receiving error 922 after expiration (usually 24 hours) on next action.