WebView Single-Sign On
With the wide use of the WebView control acting as a portal into a LOB intranet, there's no shortage of developers who are looking into creating a Single-Sign-On (SSO) experience for their users. In Windows 8.1, we now have two good ways of making this happen.
The first way we have for creating a functional SSO is via the use of the Enterprise authentication capability. When activated in a Store app, this allows the WebView to connect to internal web servers and will automatically pass the Windows credentials from the logged-in user on that machine. This requires that the logged-in user have an account in the domain and is authorized to access that web server. In this case, WebView acts exactly like Internet Explorer when passing the credentials. The web server should be configured for Windows Integrated Authentication (using the Negotiate protocol, which consists of the use of NTLM and Kerberos authentication schemes).
It's rather easy to set this up - simply check off the "Enterprise Authentication" and "Private Networks (Client and Server)" selections in the Package.appxmanifest of Visual Studio 2013 (also in 2012):
When browsing to your internal sites, it "just works". However, there is a caveat with using the Enterprise Authentication capability: for use in a Store app that is sold in the Store, the Store account must be a "Company Account". To have a Company Account requires additional certification steps which can be found here: https://msdn.microsoft.com/en-us/library/windows/apps/jj863494.aspx.
The second way we can provide a Single-Sign-On experience is via the use of Basic Authentication . Basic Authentication is widely-used, and is supported by almost all (if not all) browsers. Its main drawback is that it passes the username and password in cleartext (unencrypted), although the information is Base-64 encoded. We can easily remedy this problem by ensuring that our website is protected not only by Basic Authentication, but also by the use of SSL (certificates). Basic Auth over SSL is one of the strongest forms of Web security.
Prior to Windows 8.1, we couldn't really get WebView to work without a prompt for credentials when accessing a website protected by Basic Authentication. However, WebView 8.1 provides a new method which makes this easy: NavigateWithHttpRequestMessage.
The use of this method allows us to add headers to an outgoing HTTP request. What we do to use Basic Authentication is to Base-64 encode the username/password, then pass that information into the NavigateWithHttpRequestMessage. Here's source code for making this work:
Windows.Web.Http.HttpRequestMessage httpRequestMessage = new Windows.Web.Http.HttpRequestMessage(Windows.Web.Http.HttpMethod.Get, new Uri("https://servername/index.html"));httpRequestMessage.Headers.Add("Authorization", "Basic " + CryptographicBuffer.EncodeToBase64String(CryptographicBuffer.ConvertStringToBinary("username:password",BinaryStringEncoding.Utf8)));WebView1.NavigateWithHttpRequestMessage(httpRequestMessage);
It's important to note that the Header information must be formatted in exactly the way shown in order for the server to recognize it.
Enterprise Authentication methods are great because they use the credentials that you used when you logged into the machine - this prevents you from needing to re-log in when your Store apps starts up. This allows only the person using the machine at that time to pass in those credentials. But what about the Basic Authentication scheme? Where do those come from?
In Windows 8, we introduced the PasswordVault. The concept is terrific: store and retrieve passwords based on the specific app. You can add and retrieve the credentials using this code:
// using Windows.Security.Credentials must be included // To set a password PasswordVault MyPasswordVault = new PasswordVault(); PasswordCredential MyPasswordCredential = new PasswordCredential(Appname, Username, Password); MyPasswordVault.Add(MyPasswordCredential); //To retrieve a password PasswordVault MyPasswordVault = new PasswordVault(); PasswordCredential MyPasswordCredntial = MyPasswordVault.Retrieve(Appname, UserName);
In order to ensure that you're retrieving the correct credential for the signed-on user, you may consider linking the password to the Microsoft Account by matching the Password Vault name to the Microsoft account name.
Windows Store apps now provide a good scenario for SSO in both Enterprise and small business apps. I hope you find this a useful addition to your app's capabilities.
Comments are encouraged, and feel free to tweet to me at WinDevMatt. Also, this blog's hashtag is #WSDevSol