|Introduction • Terms • Clients|
|Error List • Commands • Relying Party Suite • Spotlife|
|XMPP • HTTP Gateway • Tabs • Activities|
|Development Tools • MSNP Grid|
|Polygamy • URLs used by MSN|
|Introduction • P2P • Object Descriptor • Display Pictures • File Transfer|
|Microsoft Messenger for Mac|
|MSNP on WebTV (MSNTV)|
TWN ("Tweener") authentication is the way MSN Messenger plugs into Microsoft's Passport Authentication framework. Passport authentication is Microsoft's attempt to provide a "single sign-on" system for all Internet services, from Messenger to on-line banking. Some background information about it is available on MSDN. Understanding Tweener doesn't require any background knowledge of Passport, but you will need a basic understanding of the HyperText Transfer Protocol version 1.0 or 1.1.
Tweener authentication involves the following steps:
- The client stores the string sent in the USR response.
- The client (optionally) connects to the Passport "Nexus", and retrieves the URL of a login server. This result doesn't change very often, so it can be cached.
- Using the stored string, passport, and password, the client authenticates itself with this login server. The server will either redirect the client to another login server, report a failure in the login process, or return a "ticket" to be sent back to the notification server in the USR reply.
Authentication with MS Passport involves sending HTTPS requests to Microsoft's Passport servers in order to retrieve a passport "ticket", which is then sent to the Protocols/MSNP/Notification Server. HTTPS is HyperText Transfer Protocol encrypted using "Secure Sockets Layer". It is recommended that you find a library for your chosen programming language that supports HTTPS - even if you choose to write your own HTTP parser, you should not try to implement SSL (it's far too complex and security-sensitive to implement as part of a larger project). Passport servers allow you to either send your login details as an HTML file in the body of the request or as headers of the HTTPS request itself.
Connecting to the Nexus involves sending an HTTPS GET request for the URL "https://nexus.passport.com/rdr/pprdr.asp". The server should always reply with a 200 OK message with an empty body. The important information is contained in the "PassportURLs" header, which contains a comma-separated list. The "DALogin" field of this header contains the address of the login server. This value isn't technically a valid URL, so your HTTPS library might require you to add "https://" to the start of it.
The client should then send an HTTPS GET request for the URL given to it by the Nexus. The request should include an "Authorization" header. The value of this header is one long string with no spaces, made up of the string "Passport1.4 OrgVerb=GET,OrgURL=http%3A%2F%2Fmessenger%2Emsn%2Ecom,sign-in="), your URL-encoded passport, ",pwd=", your URL-encoded password, ",", and the challenge string given to you by the Notification Server.
The full string contains other variables, some of which are mutable. The "ct" variable that gets sent is optional, and can even be set into the future in order to create a ticket that will become valid in the future. (Tickets are currently valid for five minutes before, and thirty seconds after their "ct" time). Gaim currently increases this value by 200 in order to have less chance of timing out (which was possible on a slow link with the default thirty second window). The "lc" variable sets the locale, "tw" is the "time window", and "id" is the ID of the key used to encrypt the returned ticket. (IDs 2 and 507 are for Hotmail and Messenger respectively, but are interchangeable).
The server's response should be either a 200 OK message (for success), 302 Found (for redirection) or 401 Unauthorized (for failure). The message will contain either an "Authentication-Info" or a "WWW-Authenticate" header. It's not known why two different header names are used, although at present "WWW-Authenticate" is only used with failed logins. It's safest to assume that the two header names are interchangeable. The header's value will begin with " Passport1.4 ", then a comma-separated list of fields of the form "key=value". The first field will have a key "da-status" and a value of "success", "failed" or "redir" (redirect).
If the response is a failure, the header will include a "cbtxt" field with a URL-encoded error message, and a "cburl" field that contains the URL of a picture you might want to display along with it.
If the response is a redirection, there will be a separate "Location" header, which includes the URL of the login server which the client is being redirected to. At the time of writing, the client will only be redirected if it has a passport that ends in "@hotmail.com" or "@msn.com". The client must begin the login step again.
If the response is a success, the header will include a "from-PP" field, which contains the ticket to return to the Notification Server. This field has a slightly unusual format, in that the value is inside apostrophes and includes several equals signs (but no commas).
Note: Although you should use HTTPS you can in fact send the HTTP requests to port 80 and the servers will accept this. However this does mean sending your password unencrypted so is not recomended
Client connects to nexus.passport.com, port 443
>>> GET /rdr/pprdr.asp HTTP/1.0\r\n\r\n
<<< HTTP/1.1 200 OK\r\n <<< Server: Microsoft-IIS/5.0\r\n <<< Date: Mon, 02 Jun 2003 11:57:47 GMT\r\n <<< Connection: close\r\n <<< PassportURLs: ...DALogin=login.passport.com/login2.srf, ... <<< Content-Length: 0\r\n <<< Content-Type: text/html\r\n <<< Cache-control: private\r\n\r\n
nexus.passport.com closes the connection
Client connects to url specified in the DALogin field, port 443
>>> GET /login2.srf HTTP/1.1\r\n >>> Authorization: Passport1.4 OrgVerb=GET,OrgURL=http%3A%2F%2Fmessenger%2Emsn%2Ecom,sign-in=example%40passport.com,pwd=password,lc=1033,id=507,tw=40,fs=1,ru=http%3A%2F%2Fmessenger%2Emsn%2Ecom,ct=1062764229,kpp=1,kv=5,ver=2.1.0173.1,tpf=43f8a4c8ed940c04e3740be46c4d1619\r\n >>> User-Agent: MSMSGS\r\n >>> Host: login.passport.com\r\n >>> Connection: Keep-Alive\r\n >>> Cache-Control: no-cache\r\n\r\n
<<< HTTP/1.1 302 Found\r\n <<< Server: Microsoft-IIS/5.0\r\n <<< Date: Mon, 02 Jun 2003 11:58:32 GMT\r\n <<< PPServer: H: LAWPPLOG5C006\r\n <<< Connection: close\r\n <<< Content-Type: text/html\r\n <<< Expires: Mon, 02 Jun 2003 11:57:32 GMT\r\n <<< Cache-Control: no-cache\r\n <<< cachecontrol: no-store\r\n <<< Pragma: no-cache\r\n <<< P3P: CP="DSP CUR OTPi IND OTRi ONL FIN"\r\n <<< Authentication-Info: Passport1.4 da-status=redir\r\n <<< Location: https://loginnet.passport.com/login2.srf?lc=1033\r\n\r\n
To continue authentication connect to the server specified in the location header, and resend the authentication request.
<<< HTTP/1.1 200 OK\r\n <<< Server: Microsoft-IIS/5.0\r\n <<< Date: Mon, 02 Jun 2003 11:59:00 GMT\r\n <<< PPServer: H: LAWPPIIS6B061\r\n <<< Connection: close\r\n <<< Content-Type: text/html\r\n <<< Expires: Mon, 02 Jun 2003 11:58:00 GMT\r\n <<< Cache-Control: no-cache\r\n <<< cachecontrol: no-store\r\n <<< Pragma: no-cache\r\n <<< P3P: CP="DSP CUR OTPi IND OTRi ONL FIN"\r\n <<< Set-Cookie: MSPSec1= ; expires=Thu, 30-Oct-1980 16:00:00 GMT;domain=.passport.com;path=/;HTTPOnly= ;version=1\r\n <<< Set-Cookie: MSPSec=5Cdd1SshOELpwqafsSuYSiDEuEtP1PUaX99YOZcaoJP3vkIn7DXozt868I7eJNjcWG; HTTPOnly= ; domain=.passport.com;path=/;secure=\r\n <<< Set-Cookie: MSPAuth=5yDBU0BqvDa7UiY9W9nVEncRXCLD4gjLmtEr2XkunnafkOgdgG5x*CEpqe7MyZEOir*EiA1PbwLKzqCGO671TeTQ$$; HTTPOnly= ; domain=.passport.com;path=/\r\n <<< Set-Cookie: MSPProf=5a0mKE6PKDsxz!*4apQt0amnQOGLYqcCm78ie!MmHq0KnAiIJM0z0Zajs8NL7ux7Ae0hnH5AAoB!zXIZ9jTA2rcQttC*RKKRsc9k7JflwThB!H0Qa*6ipGcdj5co6taPir; HTTPOnly= ; domain=.passport.com;path=/\r\n <<< Set-Cookie: MSPVis=507;domain=.passport.com;path=/\r\n <<< Set-Cookie: MSPPreemail@example.com; HTTPOnly= ; domain=.passport.com;path=/;Expires=Wed, 30-Dec-2037 16:00:00 GMT\r\n <<< Set-Cookie: MSPShared= ; HTTPOnly= ; domain=.passport.com;path=/;Expires=Thu, 30-Oct-1980 16:00:00 GMT\r\n <<< Authentication-Info: Passport1.4 da-status=success,tname=MSPAuth,tname=MSPProf,tname=MSPSec,from-PP='t=53*1hAu8ADuD3TEwdXoOMi08sD*2!cMrntTwVMTjoB3p6stWTqzbkKZPVQzA5NOt19SLI60PY!b8K4YhC!Ooo5ug$$&p=5eKBBC!yBH6ex5mftp!a9DrSb0B3hU8aqAWpaPn07iCGBw5akemiWSd7t2ot!okPvIR!Wqk!MKvi1IMpxfhkao9wpxlMWYAZ!DqRfACmyQGG112Bp9xrk04!BVBUa9*H9mJLoWw39m63YQRE1yHnYNv08nyz43D3OnMcaCoeSaEHVM7LpR*LWDme29qq2X3j8N',ru=http://messenger.msn.com\r\n <<< Content-Length: 0\r\n\r\n
The ticket is in the 'Authentication-Info' header, it starts with "t=", it begins after the first single quote and ends before the second.
<<< HTTP/1.1 401 Unauthorized\r\n <<< Server: Microsoft-IIS/5.0\r\n <<< Date: Mon, 02 Jun 2003 11:58:15 GMT\r\n <<< PPServer: H: LAWPPIIS6B077\r\n <<< Connection: close\r\n <<< Content-Type: text/html\r\n <<< Expires: Mon, 15 Sep 2003 07:57:14 GMT\r\n <<< Cache-Control: no-cache\r\n <<< cachecontrol: no-store\r\n <<< Pragma: no-cache\r\n <<< P3P: CP="DSP CUR OTPi IND OTRi ONL FIN"\r\n <<< PassportConfig: ConfigVersion=11\r\n <<< WWW-Authenticate: Passport1.4 da-status=failed,srealm=Passport.NET,ts=-3,prompt,cburl=http//www.passportimages.com/XPPassportLogo.gif,cbtxt=Type%20your%20e-mail%20address%20and%20password%20correctly.%20If%20you%20haven%E2%80%99t%20registered%20with%20.NET%20Passport%2C%20click%20the%20Get%20a%20.NET%20Passport%20link.\r\n <<< Content-Length: 390\r\n\r\n