Thursday, May 26, 2016

UCWA 2.0 and Skype for Business online: Authentication without a browser

Authentication without a browser

Many samples that demonstrate authenticating with UCWA 2.0 use the Office 365 log-in page in the web browser. However, it's also possible to write a C# console application that doesn't require opening a web browser for the user to authenticate. This requires create a native Azure AD application. This quote from the Microsoft article Authentication using Azure AD explains the difference:
"As part of registration, you specify whether your app is a Web application, such as an MVC or Web Forms solution, or a native app, such as a smart phone or other mobile device. Azure AD uses this information to generate resources your app will need to authenticate with Azure."
Once the native app is registered in Azure AD then its time to write the code that does the authentication dance with the UCWA and Skype for Business online servers, which goes something like this.

Authenticating with UCWA 2.0

  1. Make an auto-discovery request to the service endpoint to find the user's UCWA home pool
  2. Request an access token from the server location that the auto-discovery request provided
  3. Make an auto-discovery request with the new access token to the UCWA application resource
    1. Possibly make the above request again if a redirect or user resource is returned instead of an application URL. If the application URL isn't returned, replace the UCWA application resource from the above step with either the redirect resource or user resource.
  4. Once the application services root URL is obtained from the previous step, request an access token from that server
  5. With the new access token, send a POST request to the application resource URL to register your console app with the UCWA server.

There's a helpful StackOverflow post about the above flow, found here.

The trick to getting authentication to work with a headless client is that the username and password need to be available to the program to pass to the resource when requesting an access token, such as:

var ar = await authContext.AcquireTokenAsync(resourceUri, UcSettings.ApplicationId, new UserCredential(UcSettings.Username, UcSettings.Password));