UCWA with directors or multiple pools

In developing a UCWA application, you may come across a situation where you end up transitioning between more than one pool during the start-up process. The documentation on http://ucwa.lync.com is light on this area, and the provided UCWA sample does not handle this scenario directly. If you do not properly handle the web ticketing during pool changes, then you will commonly run into an error once you try to access your applications resource. 

HTTP/1.1 500 Internal Server Error
X-Ms-diagnostics: 28032;source="Lync-SE.NNY.local";reason="The web ticket is invalid.

If you follow the steps listed on http://ucwa.lync.com/documentation/KeyTasks-CreateApplication then the first time the problem will surface will generally be on Step 9.  Instead of getting a 201 as expected, you may get the above 500 error instead.  The reason this occurs is because you have used a web ticket from one pool when trying to communicate with a different pool.  Web tickets are only valid on the pool which issued them. 

You may have to change pools because your environment uses directors to service lyncdiscover.domain.com, or you have multiple Lync front end pools and lyncdiscover.domain.com is pointed at Pool A, but your actual user account is homed on Pool B.  In either of these cases, your initial connection steps will be completed against the pool servicing lyncdiscover.domain.com up to step 8.  At step 8 if your account is hosted on a different pool, then the _links provided will have the external web services FQDN for your home pool, instead of the FQDN you had been connected to up to this point.

This may look something like this:

GET https://webdir.nnylync.info/Autodiscover/AutodiscoverService.svc/root/oauth/user?originalDomain=nnylync.info HTTP/1.1
Authorization: Bearer cwt=AAEBHAEFAAAAAAAFFQAAALtGgOI4o_RhEkWWK1MEAACBEDp8srKSInRRsMUh3b7vStaCArAQgyCi3SnwxgLCUr_YoF_XOv0-ZnI-np_NhzH8eCu_yHEXfoYIXmTYAt5_0QgNEDp8srKSInRRsMUh3b7vStY

HTTP/1.1 200 OK
Content-Length: 269
Content-Type: application/json

{"_links":{"self":{"href":"https://lyncweb.nnylync.info/Autodiscover/AutodiscoverService.svc/root/user"},"applications":{"href":"https://lyncweb.nnylync.info/ucwa/oauth/v1/applications"},"xframe":{"href":"https://lyncweb.nnylync.info/Autodiscover/XFrame/XFrame.html"}}}

If you'll note, the GET was sent to webdir.nnylync.info, while the _links in the response are all to lyncweb.nnylync.info.

If we then blindly proceed with step 9 and send the POST to https://lyncweb.nnylync.info/ucwa/oauth/v1/applications while including the Authorization header, then we will run into the 500 error response, since the web ticket we have is issued for webdir.nnylync.info, and is not valid on lyncweb.nnylync.info.

The best way to deal with this situation will be to detect when the domain for our request changes, and if it does, omit the Authorization header.  By omitting the Authorization header the connection to the new pool will throw a 401 allowing you to retrieve a new web ticket from the new pool.  Basically you can jump back to step 4, proceed to the point where you have the web ticket at step 6, and then resume your request on step 9 and include the new web ticket in the Authorization header which should now succeed since it is a web ticket from that pool.

Continuing from the previous response it might look like this:

POST https://lyncweb.nnylync.info/ucwa/oauth/v1/applications HTTP/1.1
Accept: application/json
Content-Type: application/json

{"userAgent":"UCWA Samples","endpointId":"380a9e10-c680-488c-8f15-94e7cd87d28f","culture":"en-US"}

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer trusted_issuers="", client_id="00000004-0000-0ff1-ce00-000000000000"
WWW-Authenticate: MsRtcOAuth href="https://lyncweb.nnylync.info/WebTicket/oauthtoken",grant_type="urn:microsoft.rtc:windows,urn:microsoft.rtc:anonmeeting,password"


POST https://lyncweb.nnylync.info/WebTicket/oauthtoken HTTP/1.1
Accept: application/json
Content-Type: application/x-www-form-urlencoded;charset='utf-8'
Content-Length: 57

grant_type=password&username=nny%5Cfry&password=********

HTTP/1.1 200 OK
Content-Length: 250
Content-Type: application/json

{"access_token":"cwt=AAEBHAEF…FECMUFwI","expires_in":28132,"ms_rtc_identityscope":"local","token_type":"Bearer"}


POST https://lyncweb.nnylync.info/ucwa/oauth/v1/applications HTTP/1.1
Accept: application/json
Content-Type: application/json
Authorization: Bearer cwt=AAEBHAEF…FECMUFwI
Content-Length: 98

{"userAgent":"UCWA Samples","endpointId":"380a9e10-c680-488c-8f15-94e7cd87d28f","culture":"en-US"}

HTTP/1.1 201 Created


Attached is a version of Authentication.js which has been modified to handle this scenario.  It may not be the best solution, but this should demonstrate the process outlined above and allow the sample to work in this kind of topology.

Authentication.js