Using WS-Federation with Windows Store and .NET rich clients

In general, rich client apps use OAuth flow to obtain authorization tokens to a web service. However, that flow may not be available from the authentication servers. In the following I am using an alternative approach: WS-Federation, well supported by ASP.NET web services. The solution consists of a web service, often used to provide REST services to rich client apps (Windows Store or .NET WPF, WinForms, etc.) and an authentication server (STS), e.g. Windows Azure Active Directory.

The basic approach is to:

  1. Establish WS-Federation trust between the STS
    and the web service (e.g.
  2. Host a web browser control in the rich client
    application, use it to allow passive WS-Federation redirection between the web
    service and the authentication service (STS).
  3. Detect the final redirection from the
    authentication server to the web service and verify that it includes
    authentication token
  4. Re-use authentication cookies returned by the
    web service in any subsequent REST calls to the web service.

For the Windows Store 8.1 app I used the WebView control for the WS-Federation passive redirection exchange. Simplified code-behind used to detect completion of the authentication flow is shown below (errors and exception are ignored; the xaml page contains a WebView control called _login and a TextBlock called _result). The GetValues method shows a call to the web service.

        string _webApp =
  // web service

        protected override void
  OnNavigatedTo(NavigationEventArgs e)


            _login.Source = new
  Uri(_webApp);  // navigate to web
  service, which should start ws-fed flow


        bool _isAuthenticated =

        private async void
  HandleNavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs


  (args.Uri.ToString() == _webApp) // navigating back to web service


  (args.IsSuccess) // assuming authentication completed


  _login.Visibility = Visibility.Collapsed;

  _isAuthenticated = true;

  GetValues();  // call some service
  requiring prior authentication




        async Task GetValues()


            var client = new Microsoft.Web.Http.HttpClient();  // NOT System.Net.Http.HttpClient

            var values = await
  client.GetStringAsync(new Uri(_webApp + "api/values"));

            _result.Text =


Unlike any other .NET http client Microsoft.Web.Http.HttpClient shares its cookie store with other WinINet based code in your app, in this case with the browser control. Hence the GetValues method REST call will include the FedAuth cookies returned earlier during the authentication exchange through the WebView control.

In a .NET client (WPF or WinForms) http clients (HttpClient, WebClient, HttpWebRequest) do not share cookies with each other or other clients (browser controls) and therefore additional code needs to be provided to copy the cookies returned as part of the passive browser authentication to the http client making subsequent REST calls. Following code shows such an implementation in a WPF client:

public partial class MainWindow : Window



    static extern bool
  InternetGetCookieEx(string pchURL, string pchCookieName, StringBuilder
  pchCookieData, ref System.UInt32 pcchCookieData, int dwFlags, IntPtr

    static int


    static extern int


    public MainWindow()




    private void
  HandleNavigated(object sender, NavigationEventArgs args)


        if (args.Uri.ToString()
  == _webApp)


  _progressBar.Visibility = System.Windows.Visibility.Collapsed;

  _progressBar.IsIndeterminate = false;

  _authCookies.Add(GetCookie(_webApp, "FedAuth"));

  _authCookies.Add(GetCookie(_webApp, "FedAuth1"));

            _login.Source = new
  Uri(_webApp + "api/values");



    Cookie GetCookie(string
  url, string cookieName)


        UInt32 length = 2024;

        StringBuilder cookie =
  new StringBuilder((int)length);

  (!InternetGetCookieEx(_webApp, cookieName, cookie, ref length,


            var error =

            throw new
  Exception("COM error: " + error.ToString());


        var cookieValue =
  cookie.Remove(0, cookieName.Length + 1); // remove leading 'FedAuth='

        return new
  System.Net.Cookie(cookieName, cookieValue.ToString()) { HttpOnly = true };


    string _webApp =

  _authCookies = new CookieCollection();

    async Task GetValues()


        var handler = new

  handler.CookieContainer.Add(new Uri(_webApp), _authCookies);

        handler.UseCookies =

        var client = new

        string values =



            values = await
  client.GetStringAsync(new Uri(_webApp + "api/values"));


        catch (Exception ex)




        _result.Text = values;


    private void
  HandleLogon(object sender, RoutedEventArgs e)


  = System.Windows.Visibility.Visible;

        _login.Source = new



    private async void
  HandleCallAPI(object sender, RoutedEventArgs e)


        _login.Visibility =

        await GetValues();




The xaml page for the WPF app looks as follows:

<Window x:Class="WpfTestClient.MainWindow"



  Title="MainWindow" Height="500"


  Orientation="Horizontal" VerticalAlignment="Top"

  Content="Logon" Click="HandleLogon" Width="100"

  Content="Call API" Click="HandleCallAPI"
  Width="100" Height="40"/>


  Background="Gray" Margin="120">

  x:Name="_result" TextWrapping="Wrap" />


  x:Name="_login" Margin="40"
  Navigated="HandleNavigated" />

  x:Name="_progressBar" IsIndeterminate="True"
  Opacity="0.4" Visibility="Collapsed"/>



 The approach, as outlined allows for the initial authentication flow. It should be expanded to include token renewal and logout support.






Comments (0)

Skip to main content