UCWA and fun with Node

A stumbling block for aspiring UCWA developers can be the admin step that adds a custom domain to the cross-domain authorization list. In some cases the JavaScript developer may not have that sort of access to make changes which puts them into the position where their tinkering never starts. JavaScript has this limitation because it needs to rely on a cross-domain iframe to facilitate sending messages to UCWA and that iframe has a script that injects the origin of the requester into a header called X-Ms-Origin. This header is then checked against a cross-domain authorization list maintained on the Lync Server and if it is not present will result in a 403 response:

X-Ms-diagnostics: 28070;source="000DCO2L50FE1A.domain.com";reason="Service does not allow a cross domain request from this origin."

Easy Solution

An easy solution for developers is to install Fiddler and create a custom filter to remove the X-Ms-Origin header.

Fiddler Filter

The downside to this approach is remembering to disable this filter when moving to production testing to be able to catch whether or not the proper domain is added to the cross-domain authorization list.

Another Way

So let's assume for some reason the easy solution is not feasible in your development environment and you are tied to using JavaScript for the application's interaction with UCWA. If we also assume that there is no access to make changes to Lync Server to add/remove logic to enable alternate routes of communication with UCWA. Node provides an interesting option as it has the ability to create an Http(s) server that could proxy request. I talked about this as a potential solution quite some time ago, but lost the code along the way and figured maybe it made sense to revisit the idea.

Commandline Parsing

For this solution it would be ideal if it would do the following:

  • Host an Http(s) server
  • Allow optional certificate
  • Allow optional port
  • Proxy requests to UCWA
  • Wrap responses from UCWA

Taking this list into consideration, it made sense to create or find a way to handle commandline parsing for Node applications. The commandline parsing function I was writing was becoming a bit complex and after much looking over packages I decided upon minimist as it had no extra package dependencies, supported type enforcement (boolean, string), and default values. Basically the developer could hope to make use of the proxy server as follows:

node> ucwa-proxy [--port --secure [--pfx --passphrase] --logging]

  • --port - port to host server on (default 4666)
  • -- secure - whether to host server as Http or Https (default true)
  • -- pfx - Path to PKCS#12 certificate file (default ./certs/node-ucwa.pfx)
  • -- passphrase - optional certificate password (default '')
  • -- logging - logs the request object prior to proxying (default false)

I did some additional argument processing to determine if the user wanted to host an Http or Https server and basic handling around whether or not a custom certificate path is reachable from supplied values. As a result of reading the certificate from a path and not an array of bytes (I do think this would be fun to force a developer to post a string of certificate bytes) means this application will also depend on fs

parseArgs

Hosting

Support both Http and Https add the appropriate related packages. One questionable dependency I added was express not because it I have opinions one way or another, but because the application is only responding to logic at a single location, /proxy. I may reconsider the decision and have the application remove the dependency and fail requests other than POST on /proxy, but for now it will remain. Url processing was handled by Url so that the hostname, path, and port could easily be determined from the supplied request Url.

platform

Logic

The brunt of the proxy logic is contained in how the request should be proxied to UCWA.

{
    url - url to proxy
    method - Http verb (get, post, put, delete),
    headers - optional collection of headers to apply to proxied request,
    data - optional request body
}

The logic for this is contained in a handler defined for POST at /proxy and it is interested in taking objects format as what appears above providing a default Content-Type, calculating Content-Length, issuing a request to the provided url using the specified Http verb, and finally taking the response or error and reporting it back to the original request. Additional headers and data can be sent along with the request as well.

Examples

For a simple case where we want to make an AutoDiscovery request to https://lyncdiscover.domain.com the expected proxy request would appear as seen below.

Proxy Request proxyRequest

Proxy Response proxyResponse

For a more complex case (custom headers and data being sent), the request response pairs might appears as seen below.

Proxy Request complexProxyRequest

Proxy Response complexProxyResponse

Final Thoughts

It was interesting to re-visit this idea as the original code, as I remember it, did not provide commandline parsing, Http server hosting or error handling. It gave me a reason to take a look into Node package development, create a package (node-ucwa), and create a fun developer tool in the process. Contained in the node package is a sample Fiddler trace, named Simple.saz, that demonstrates a series of proxy requests that could be issued to log-in to UCWA making use of the proxy.

Node package: node-ucwa Github repo: node-ucwa