Category Archives: .NET

generic .NET tag

Proud to be Back

Run DMCTo borrow from Run DMC:

Listen party people here’s a serious song
It’s right not wrong, I should say right on
I gotta tell you somethin that you all should know
It’s not a mystery it’s history and here’s how it go

While session history management has been around for a few years, it’s not something I’ve needed until recently. Necessity dictates working both with AJAX/Web APIs and SEO as well as the ability to share links via email or social media. And it may well have been that prior to now there could have been gaps in browser coverage. According to http://caniuse.com/#search=Session%20history%20management adoption is widespread. So even an SPA (single-page app) can reasonably mimic traditional web navigation without you having to hang your keister out in the wind as a developer.

After dinking around with a couple HTML5  history navigational examples, and getting bogged down with some unexpected results in my AJAX/WebAPI project I, er, back-tracked and built my own bare-bones navigational example. This covers both real and virtual pages, navigation within and without the page holding the virtual content (e.g. pasting a link or clicking on it from an email or tweet). Feel free to play around and see if you spot any inconsistencies or unexpected behavior.

Navigating from another page (Click on the Virtual page link, then hit any of the buttons or the link back to real.html and the back/forward buttons in the browser. )

See update below!

http://ststates.azurewebsites.net/real.html

Accounts for linking from outside the site:

http://ststates.azurewebsites.net/virt.html?page=2

Looking at Developer Tools > console in your browser will report the history state and what triggered a change (replaceState, pushState, or popState). View the source (including comments) and you’ll see that all three of these are needed to cover the various navigational cases.

Update

Well, not so proud when I found out that just using the out-of-the-box HTML5 implementation of session history management had a nasty problem: Changing the title would also change it in the history. So holding down the back button, for instance, would show the same link for different URLs, e.g. “?page=1” and “?page=2” would share a title. That would truly suck in a production environment where the title is supposed to match a slug.

So I turned to history.js, which solved that problem and (theoretically should work with HTML4, although I don’t have a convenient means of testing that). Additionally, it took care of the problem with Safari popping an event on loading and shortened my code by some 30 lines, simplifying the logic considerably.

http://ststates.azurewebsites.net/virt2.html?page=2

Authentication and Authorization with Auth0

Pre-Ramble

Apps that connect to services that allow users to contribute or distribute information become more complex than stand-alone apps, or even apps that just retrieve data, e.g. weather forecasts, from an online source. Connectivity, versioning and authentication/authorization all become issues. At least they do if you care about user experience and security.

In particular, authentication and authorization can be hard to do. Users expect to be able to use social authentication providers like Facebook or Twitter. They expect to not have to login repeatedly yet will find it hard to forgive privacy violations and security breaches (and rightfully so).

In my own quest to find tools and solutions in this area I was surprised how hard it was. Some providers, like Microsoft, have pretty decent answers for their own platforms. On Windows 8.x you can easily use Microsoft accounts and adopt the SSO (single sign-on) experience that makes it smoother for the user. With a little jiggering (and ignoring the cruft of the Live SDK) the same can be achieved with Windows Phone. Although the reason I say “pretty decent” is because the samples (even one written by ScottGu) were devoid of error handling to accommodate user cancellation or lack of connectivity.

The server-side of the equation is still a bit complicated. I covered this in my post http://code.stonetip.com/2014/01/31/using-microsoft-live-for-authentication-with-windows-8-x-and-windows-phone-8-apps/, which discussed how to process JWT (JSON Web Tokens) on the server. However, I was never comfortable with just this, knowing users would want other options

I kept looking for other approaches, spending mind-numbing hours with ADAL samples and Fiddler sessions…to the point where I was attempting to reverse-engineer the parts I needed – namely mobile-friendly login screens and true verification of signed tokens. One thing that became increasingly clear is that the providers of social auth have (and understandably so) absolutely no interest in working together to provide an integrated solution. Even within certain (evolving) standards like OAuth2 each has their own implementations and quirks.

This led me back to checking out Auth0 again (https://auth0.com/). Months ago, I’d looked into this service and ran into a couple difficulties with parts of the SDK and with the use of the Microsoft desktop sign-in page in a mobile browser. At the time, they also price-limited the number of providers you could use, which is no longer the case. Stupidly, I wrote Auth0 off. Perhaps if I’d not wanted to include Microsoft accounts I would have been off to the races. On the positive side, in the interim, I learned many useful things I might not have had I not turned the stones over myself.

One major lesson learned is that I really should have communicated the issues I had to Auth0. After whining a bit on Twitter about the login screen I got a tweet from them a few hours later asking me to try it again. Auth0 took the initiative to do what even Microsoft’s own properties fail to do: find the parameters that tell the Live servers that a mobile client is knocking at the door. Since then, Auth0 has been nothing but helpful in answering questions and pointing to solutions.

Right there, that should tell you the most important thing you need to know: These guys are serious about customer support. That’s on top of offering a service which goes way beyond just slapping a social auth login onto a website or in an app. One thing you’ll find after signing up for an account is that the help docs are tailored to work with your credentials. Often you can copy-and-paste pre-configured, working code or try it live from within the documentation. How cool is that?

Before reading on, I’d encourage you to sign up for an account. It’s free and will let you try out some of the things that follow. A downloadable code sample is at the end of this post.

Successful Ingredients for Authentication and Authorization

To me, the number one goal is for the user to have a smooth, secure experience. Like many things that share this design goal, this translates into more complexity for the developer. Granted, some of the issues that may occur are such edge cases that they have to be ignored. Yet there are things that may happen infrequently but still have a major impact on perception. For example, if a user cancels logging in (this might occur just from inadvertently hitting the back button) how impressive is it if your app freezes or crashes? Or hard as it may be to believe, your app may not be used every day or every week or even once a month. What do you do when the user fires it up after a long while and forgets which social provider login was used?

My number two goal is to keep my server assets secure, controlling who has access and which things they can view or modify. This isn’t some IT Admin lockdown control-freak thing. Without a reasonable level of security you open up your web services and user data to exploitation or destruction.

Since my services are dependent on OAuth2 that means the authentication vehicle is the JWT. It’s worth mentioning again that a JWT is encoded, not encrypted. The only protection mechanisms you have are the JWT’s signature – an HMAC of the header + payload sections of the JWT using the Client Secret (which should never, ever, be included in any client-side code) – and HTTPS. Other than for testing, never send JWTs over an insecure pipe.

Using a JWT means I need to know, among other items, three important things:

  1. Is it authentic?
  2. When does it expire?
  3. Who is the intended audience (and, no, that’s not the same as considering who you’re writing for, but rather the backend service)

Together, these establish the validity of the token. If don’t validate them, neither my service nor transactions with clients are secure.

Mixing it up

Putting the right pieces together in both the client and server-side code is a combination of having the right components, coordinating the flow of authorization and keeping track of tokens (for reuse) and expiration (requiring refreshing a token). Here’s a walk-through using an Auth0 Application, Auth0 API, a WebAPI/OWIN service and a Windows Phone client app.

It should be pointed out that Auth0 Applications and APIs are not the home of your application or server code. Rather, think of them as configurable authorization gateways that live on Auth0’s servers. Why have both an Auth0 Application and an API? While it’s possible to get by with just one set of credentials, separating the two provides more security (if the client credentials are compromised the server credentials aren’t automatically compromised as well). It also give you more flexibility. Say down the road you have three apps that use the same API but you no longer want to support or publish one of the apps. You could allow only the rest to have access, effectively blocking the discontinued app.

Even more important, since most of your assets, including all users’ data will probably reside on your servers, you can give the less-sensitive app tokens longer expiration times, e.g. 30 days, while keeping them short, e.g. 1 day or 4 hours, for API tokens. This would, for example, allow you to use the Auth0 Users console to block someone who is abusing your terms of service. (This wasn’t actually supported by Auth0 until I requested it…testament once again to their focus on customer service).

Auth0 is fairly straightforward but I had to ask a few questions to figure out how to get server tokens from the client app and renew either client or server tokens. Once I had the answers it became clear that:

  1. When a user is first logging in or the Client token is no longer valid (expired) Auth0 directs the client to the authorize endpoint. Depending on whether the user has ever logged in or the length of time since the last login, the user may be presented with the available choices for social providers or an individual provider’s login screen. In some cases, the provider may have cached the login, which requires no action on the user’s part.
  2. When it comes to client app token renewal or acquiring/renewing a server token, Auth0 has a delegation endpoint that accepts a client ID, a valid JWT, and a target ID. If renewing a Client token, you use the client ID as the target ID. If requesting an API token, the App ID will be the target ID.
    Since the delegation takes place on Auth0’s servers all the verification/validation happens without having to either resort to storing an API secret within an app or maintain the framework to do this yourself. I can’t say it too many times: Never store a secret client-side. There are numerous examples of apps (mobile and otherwise) being reverse-engineered all the time. Amazingly, even people that should know better do it (talking to you Visual Studio team – http://www.visualstudio.com/integrate/get-started/get-started-auth-oauth2-vsi)!

If you haven’t already done so, I’d recommend creating an Auth0 account and set up both a client app and an API for testing and playing around.

The first thing I recommend after creating an Auth0 account is to pick two or more social auth providers. This is done under the Connections section (found on the left-hand pane). The ones I’ve chosen to offer users are Google, Twitter, Microsoft and Facebook. After enabling a provider, you can try out logging in, which will give you a good idea of what information is returned by each.

The next step is to create an Application. Select Applications and then the new application button. In this case, choose a Windows Phone app. Enter a friendly name and choose which of the auth providers you want to use. The next page you’ll see is the Tutorial page, custom-configured to match your App’s settings. For now, there’s nothing that needs to be changed. But here a couple things to note:

  1. I would recommend leaving the callback URL as the auto-generated default. In practice, you shouldn’t need it because the app will not share a Client ID with the API
  2. At the bottom of the page, you’ll see the token expiration duration. The default duration is 36,000 seconds (10 hours). When testing or debugging it is really useful to be able to change this at will. (I’ve set it to as little as 120 seconds). This is a luxury you can’t obtain directly with social providers. Sometimes, I’ve switched to other tasks while waiting 24 hours to come back and see what happens when a token expired. You don’t have to do this with Auth0.
  3. If you select Facebook as a social provider you’ll need to register the app with the Facebook developer site. Not all providers, namely Microsoft, Google and Twitter, require this step.

I’ve provided a working sample with this post, but scanning the Tutorial page will give you an idea of how to implement Auth0 in a client app, including which NuGet package to install.

After creating a client Application, select APIs from the left-hand pane and create a new API. You’ll see there are (currently) 10 options. For our purposes, choose the OWIN option. This will customize the tutorial to be as close as possible to the sample code I’m providing.

Once both are created, you’re ready to create the Visual Studio projects (or use the sample code provided):

  1. Launch Visual Studio using Run as Administrator.
  2. In Visual Studio, right-click on your Solution and add a new project, selecting Web > ASP.NET Web Application. (Avoiding the cruft of the typical MVC template). Check the box for Web API:
  3. Open the NuGet console and run the following:
    1. Install-Package Microsoft.Owin.Security.Jwt
    2. Update-Package System.IdentityModel.Tokens.Jwt
    3. Update-Package Newtonsoft.Json
    4. Install-Package Microsoft.Owin.Host.SystemWeb (Note: Without this one, OWIN will never invoke the Startup.Auth.cs code shown below).
  4. Optionally, open the project’s properties, navigate to Web and change the server from IIS Express to Local IIS. This allows you to choose a Project Url using the machine name, e.g. http://<MY_MACHINE>/<my_project_name>, which makes it possible to test using actual devices or to view the Web API from another desktop machine. Hit the Create Virtual Directory button.NOTE: I found that I’m unable to see a local machine from some devices or WP 8.1 emulators. After looking at workarounds, which all seemed to require opening a firewall port, I just deployed the Web API to Azure and am using that website for testing.
  5. Open Web.Config and if there is not already an appSettings section, create it and add keys for the Auth0 Client ID, Client Secret and Domain, e.g:

    
    <appSettings>
     <add
     key="Auth0:ClientId"
     value="CLIENT_ID" />
    
    <add
     key="Auth0:ClientSecret"
     value="CLIENT_SECRET" />
    
    <add
     key="Auth0:Domain"
     value="https://DOMAIN" />
    
    </appSettings>
    
    

    (These keys can be found in the Settings section for the API on Auth0’s site under Apps/APIs).

  6. In the Project add a new class file to App_Start called “Startup.Auth.cs” and add the following code:
    using System.Configuration;
    using Microsoft.Owin.Security;
    using Microsoft.Owin.Security.DataHandler.Encoder;
    using Microsoft.Owin.Security.Jwt;
    using Owin;
    
    namespace auth0JWT2API
    {
     public class Startup
     {
     public void Configuration(IAppBuilder app)
     {
     var issuer = ConfigurationManager.AppSettings["Auth0:Domain"];
     var audience = ConfigurationManager.AppSettings["Auth0:ClientId"];
     var secret = TextEncodings.Base64Url.Decode(
     ConfigurationManager.AppSettings["Auth0:ClientSecret"]);
    
    // Api controllers with an [Authorize] attribute will be validated with JWT
     app.UseJwtBearerAuthentication(
     new JwtBearerAuthenticationOptions
     {
     AuthenticationMode = AuthenticationMode.Active,
     AllowedAudiences = new[] {audience},
     IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
     {
     new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret)
     }
     });
     }
     }
    }
    
  7. Create a WebApiConfig.cs file in App_Start:
    using System.Web.Http;
    namespace auth0JWT2API
    {
     public static class WebApiConfig
     {
     public static void Register(HttpConfiguration config)
     {
     // Web API routes
     config.MapHttpAttributeRoutes();
     }
     }
    }
    
    
  8. Open Global.asax.cs and edit it to:
    using System.Linq;
    using System.Web;
    using System.Web.Http;
    
    namespace auth0JWT2API
    {
     public class WebApiApplication : HttpApplication
     {
     protected void Application_Start()
     {
     GlobalConfiguration.Configure(WebApiConfig.Register);
    
    var config = GlobalConfiguration.Configuration;
    
    // Ignores browsers like Chrome requesting XML
     var appXmlType =
     config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
     config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
     }
     }
    }
    
    
  9. Next, in the Controllers folder, add a new empty controller named “PublicController.cs”. This, as you might guess, will be a controller that is open, i.e. no authorization is required.
    using System.Web.Http;
    namespace auth0JWT2API.Controllers
    {
     public class PublicController : ApiController
     {
     [Route("v1/public")]
     public string Get()
     {
     return "You've reached the open controller.";
     }
     }
    }
  10. Create a second controller called “PrivateController.cs” and add this code to it:
    using System;
    using System.Collections.Generic;
    using System.Security.Claims;
    using System.Web.Http;
    
    namespace auth0JWT2API.Controllers
    {
     [Authorize]
     public class AuthenticatedController : ApiController
     {
     [Route("v1/private")]
     public IEnumerable<string> Get()
     {
     var identity = User.Identity as ClaimsIdentity;
     if (identity == null) return new[] { "nuthin'" };
    
    var exp = identity.FindFirst("exp").Value;
     return new[] { "Auth user 1", "Auth user 2", String.Format("exp: {0}", exp) };
     }
     }
    }
    
    
  11. In the project’s properties, select Web and edit the Start URL to http://<MACHINE NAME>/auth0JWT2API/v1/public. Build and run the Web API. You should see a browser launch and, depending on which it is, either display this small JSON array or ask what you want to do with the JSON file:
  12. Try replacing “public” in the URL with “private”. You should get a message stating“Authorization has been denied for this request.”

    The reason being, of course, that no JWT bearer token was supplied to the controller, which is globally protected by the “[Authorize]” attribute.

So, great. Now I have a Web API that supports OAuth2 with both open and restricted routes. But how do I test this to make sure it really works? For one thing, you’ll get the same denied message whether you don’t supply a token or the token is invalid. For another, you’ll simply be unable to return anything useful.

Using a Client App to Test the API

It’s time to create a new client app. In this case, I’m making that a Windows Phone 8.0 Silverlight app.

  1. Add a new project in Visual Studio, selecting whatever Windows Phone template you like that is compatible with your test device.
  2. Using the NuGet Console, add the following packages:
    1. Install-Package Microsoft.Net.Http
    2. Install-Package Newtonsoft.Json
    3. Install-Package Auth0.WindowsPhone
  3. Create a class file named “Auth0UserProfile.cs” and add the following code. This gives us a tidy way to work with the decoded JSON:
    using System.Collections.Generic;
    namespace auth0Jwt2WP
    {
     public class Auth0UserProfile
     {
     public string clientID { get; set; }
     public string created_at { get; set; }
     public string email { get; set; }
     public List<string> emails { get; set; }
     public string family_name { get; set; }
     public string given_name { get; set; }
     public List<Identity> identities { get; set; }
     public string locale { get; set; }
     public string name { get; set; }
     public string nickname { get; set; }
     public string picture { get; set; }
     public string user_id { get; set; }
    
    public class Identity
     {
     public string access_token { get; set; }
     public string provider { get; set; }
     public object user_id { get; set; }
     public string connection { get; set; }
     public bool isSocial { get; set; }
     public string access_token_secret { get; set; }
     }
     }
    }
    
    
  4. Create another class file named “DecoderUtils.cs” and add the following code:
    using System;
    using System.Diagnostics;
    using System.Text;
    using Newtonsoft.Json;
    
    namespace Auth0JwtWP
    {
     public class DecoderUtils
     {
     public static TokenExpirationInfo GetTokenExpirationInfo(string token)
     {
     try
     {
     // Decode the token payload to get the expiration date
     var decodedPayload = DecodeJwtPayload(token);
    
    var decodedPayloadObj = JsonConvert.DeserializeObject(decodedPayload) as dynamic;
    
    var tokenExpirationInfo = new TokenExpirationInfo
     {
     Expiration = decodedPayloadObj.exp,
     IssuedAt = decodedPayloadObj.iat
     };
    
    return tokenExpirationInfo;
     }
     catch (Exception err)
     {
     Debug.WriteLine(err.Message);
    
    return null;
     }
     }
     public static string DecodeJwtPayload(string token)
     {
     try
     {
     var parts = token.Split('.');
     var payload = parts[1];
    
    var payloadBytes = Base64UrlDecode(payload);
    
    return Encoding.UTF8.GetString(payloadBytes, 0, payloadBytes.Length);
     }
     catch (Exception err)
     {
     Debug.WriteLine(err.Message);
    
    return null;
     }
     }
     public static byte[] Base64UrlDecode(string input)
     {
     try
     {
     var output = input;
     output = output.Replace('-', '+'); // 62nd char of encoding
     output = output.Replace('_', '/'); // 63rd char of encoding
     switch (output.Length%4) // Pad with trailing '='s
     {
     case 0:
     break; // No pad chars in this case
     case 2:
     output += "==";
     break; // Two pad chars
     case 3:
     output += "=";
     break; // One pad char
     default:
     throw new Exception("Illegal base64url string!");
     }
     var converted = Convert.FromBase64String(output); // Standard base64 decoder
     return converted;
     }
     catch (Exception err)
     {
     Debug.WriteLine(err.Message);
    
    return null;
     }
     }
    
    /// <summary>
     /// Returns decoded information containing a JWT's expiration and the time it was issued.
     /// The calculated lifespan is provided as a convenience.
     /// </summary>
     public class TokenExpirationInfo
     {
     public long IssuedAt { get; set; }
     public long Expiration { get; set; }
    
    public long Lifespan
     {
     get { return Expiration - IssuedAt; }
     }
     }
     }
    }
    
    
  5. Open MainPage.xaml and replace all the code with:
    <phone:PhoneApplicationPage
     x:Class="auth0Jwt2WP.MainPage"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
     xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     mc:Ignorable="d"
     FontFamily="{StaticResource PhoneFontFamilyNormal}"
     FontSize="{StaticResource PhoneFontSizeNormal}"
     Foreground="{StaticResource PhoneForegroundBrush}"
     SupportedOrientations="Portrait" Orientation="Portrait"
     shell:SystemTray.IsVisible="True"
     DataContext="{Binding RelativeSource={RelativeSource Self}}">
    
    <!--LayoutRoot is the root grid where all page content is placed-->
     <Grid x:Name="LayoutRoot" Background="Transparent">
     <Grid.RowDefinitions>
     <RowDefinition Height="42"/>
     <RowDefinition Height="*"/>
     <RowDefinition Height="96"/>
     </Grid.RowDefinitions>
     <!--TitlePanel contains the name of the application and page title-->
     <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="6">
     <TextBlock Text="AUTH0 JWT TEST" Style="{StaticResource PhoneTextNormalStyle}"
     Margin="0"/>
     </StackPanel>
    
    <ListBox Grid.Row="1" VerticalAlignment="Top" Margin="12 0 12 0"
     Name="OutputListbox" ItemsSource="{Binding OutputItems}"
     FontSize="16" Background="#2400F9FF" Padding="4" />
    
    <Button Grid.Row="2" Content="C Token" HorizontalAlignment="Left" Margin="10"
     VerticalAlignment="Bottom" Tap="JustClientToken" />
    
    <Button Grid.Row="2" Content="API Call" HorizontalAlignment="Center" Margin="10"
     VerticalAlignment="Bottom" Tap="TriggerApiCall" />
    
    <Button Grid.Row="2" Content="Clear" HorizontalAlignment="Right" Margin="10"
     VerticalAlignment="Bottom"
     Tap="ClearOutput" />
    
    </Grid>
    
    </phone:PhoneApplicationPage>
    
    
  6. Open MainPage.xaml.cs and replace all the code with:
    </pre>
    using System.Linq;
    using Auth0.SDK;
    using Newtonsoft.Json.Linq;
    using System;
    using System.Collections.ObjectModel;
    using System.Diagnostics;
    using System.IO;
    using System.IO.IsolatedStorage;
    using System.Net.Http;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Input;
    
    namespace auth0Jwt2WP
    {
     public partial class MainPage
     {
     private const string Auth0Domain = "<YOUR DOMAIN>";
     private const string Auth0ClientID = "<APP CLIENT ID>";
     private const string Auth0ApiID = "<API ID>";
    
    private const string BaseAddress = "<WEB API URI>";
    
    // Determines when we'd attempt to refresh a token, e.g. if expiration is 30 days, .1 = any time within 3 days of that.
     private const double TokenLifespanOffset = .1;
    
    private readonly IsolatedStorageSettings _applicationSettings = IsolatedStorageSettings.ApplicationSettings;
     private readonly ObservableCollection<string> _outputItems;
     private int _apiCallCount;
    
    private string _auth0ApiIdToken;
     private long _auth0ApiIdTokenExpiration;
     private long _auth0ApiTokenLifespan;
    
    private string _auth0ClientIdToken;
     private long _auth0ClientIdTokenExpiration;
     private long _auth0ClientTokenLifespan;
     private string _auth0Provider;
    
    private string _state;
    
    // Constructor
     public MainPage()
     {
     InitializeComponent();
    
    _outputItems = new ObservableCollection<string>();
     }
    
    public ObservableCollection<string> OutputItems
     {
     get { return _outputItems; }
     }
    
    private async Task TestAPICall()
     {
     try
     {
     _apiCallCount++;
    
    _outputItems.Add(String.Empty);
     _outputItems.Add(String.Format("API called: {0}", _apiCallCount));
    
    var completed = await CheckApiToken();
    
    if (completed)
     {
     try
     {
     Dispatcher.BeginInvoke(() => _outputItems.Add("Making remote request..."));
     var httpClient = new HttpClient { BaseAddress = new Uri(BaseAddress) };
    
    httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + _auth0ApiIdToken);
    
    var response = await httpClient.GetAsync(httpClient.BaseAddress + "v1/private");
    
    if (response.IsSuccessStatusCode)
     {
     var output = await response.Content.ReadAsStringAsync();
    
    Dispatcher.BeginInvoke(() => _outputItems.Add(String.Format("results: {0}", output)));
     }
     else
     {
     throw new Exception(response.StatusCode.ToString());
     }
     }
     catch (Exception err)
     {
     _outputItems.Add(err.Message);
     }
     }
     else
     {
     Dispatcher.BeginInvoke(() => _outputItems.Add("API call failed."));
     }
     }
     catch (Exception err)
     {
     Debug.WriteLine(err.Message);
    
    Dispatcher.BeginInvoke(() => _outputItems.Add(err.Message));
     }
     }
    
    private async Task<bool> CheckApiToken()
     {
     var apiTokenCheckSucceeded = false;
    
    try
     {
     // Any operation dependent on having a valid client token should always call this first.
     var clientCheckCompleted = await CheckClientToken();
    
    if (clientCheckCompleted)
     {
     Dispatcher.BeginInvoke(() => _outputItems.Add("Client token check okay."));
    
    // Do we need a new API token?
     var currentEpochTime = GetSecondsSinceEpoch();
     _applicationSettings.TryGetValue("auth0ApiIdToken", out _auth0ApiIdToken);
     _applicationSettings.TryGetValue("auth0ApiIdTokenExpiration", out _auth0ApiIdTokenExpiration);
     _applicationSettings.TryGetValue("auth0ApiTokenLifespan", out _auth0ApiTokenLifespan);
    
    var offsetExpTime = _auth0ApiIdTokenExpiration - (_auth0ApiTokenLifespan * TokenLifespanOffset);
    
    if (currentEpochTime < offsetExpTime && _auth0ApiIdToken != null)
     {
     Dispatcher.BeginInvoke(() => _outputItems.Add("API token is still good."));
    
    return true; // token is still good.
     }
    
    var delegateTokenObject = await GetDelegationToken(Auth0ApiID, Auth0ClientID, _auth0ClientIdToken);
    
    // Get the new API token
     _applicationSettings["auth0ApiIdToken"] = _auth0ApiIdToken = delegateTokenObject.IdToken;
    
    var tokenExpirationInfo = DecoderUtils.GetTokenExpirationInfo(_auth0ApiIdToken);
    
    _applicationSettings["auth0ApiIdTokenExpiration"] =
     _auth0ApiIdTokenExpiration = tokenExpirationInfo.Expiration;
    
    // Get the API token lifespan - used with subsequent transactions to determine if a new token is required
     _applicationSettings["auth0ApiTokenLifespan"] =
     _auth0ApiTokenLifespan = tokenExpirationInfo.Lifespan;
    
    apiTokenCheckSucceeded = true;
    
    Dispatcher.BeginInvoke(() => _outputItems.Add("A new API token was obtained."));
     }
     else
     {
     Dispatcher.BeginInvoke(() => _outputItems.Add("Client token check failed."));
     }
     }
     catch (Exception err)
     {
     Debug.WriteLine(err.Message);
     }
    
    return apiTokenCheckSucceeded;
     }
    
    private async Task<bool> CheckClientToken()
     {
     try
     {
     // Do we need a new client token?
     _applicationSettings.TryGetValue("auth0ClientIdToken", out _auth0ClientIdToken);
     _applicationSettings.TryGetValue("auth0ClientIdTokenExpiration", out _auth0ClientIdTokenExpiration);
     _applicationSettings.TryGetValue("auth0ClientTokenLifespan", out _auth0ClientTokenLifespan);
    
    var currentEpochTime = GetSecondsSinceEpoch();
    
    var offsetExpTime = _auth0ClientIdTokenExpiration - (_auth0ClientTokenLifespan * TokenLifespanOffset);
    
    if (currentEpochTime < offsetExpTime && _auth0ClientIdToken != null)
     {
     Dispatcher.BeginInvoke(() => _outputItems.Add("Client token is still good."));
    
    return true; // token is still good
     }
    
    if (currentEpochTime < _auth0ClientIdTokenExpiration && _auth0ClientIdToken != null)
     {
     // Renew with a delegate token. This avoids having the user log in again
     var delegateTokenObject =
     await GetDelegationToken(Auth0ClientID, Auth0ClientID, _auth0ClientIdToken);
    
    // Get the new client token
     _applicationSettings["auth0ClientIdToken"] = _auth0ClientIdToken = delegateTokenObject.IdToken;
    
    _outputItems.Add("Client token was renewed.");
     }
     else // Get a new token via user login
     {
     var auth0 = new Auth0Client(Auth0Domain, Auth0ClientID);
    
    // Try to use the last-logged provider
     _applicationSettings.TryGetValue("auth0Provider", out _auth0Provider);
    
    // If _auth0Provider is null, will present all providers to user
     var user = await auth0.LoginAsync(_auth0Provider);
    
    _state = user.State;
    
    // Get the client token
     _applicationSettings["auth0ClientIdToken"] = _auth0ClientIdToken = user.IdToken;
    
    // Get the user profile so we extract the provider, e.g. "windowslive", for future streamlined login
     // Note: In a production app, this would also be the source of user name, email and other useful values
     var profile = user.Profile.ToObject<Auth0UserProfile>();
    
    _applicationSettings["auth0Provider"] =
     _auth0Provider = profile.identities.FirstOrDefault().provider;
    
    _outputItems.Add("A new Client token was obtained.");
     }
    
    var tokenExpirationInfo = DecoderUtils.GetTokenExpirationInfo(_auth0ClientIdToken);
    
    // Get the client token expiration
     _applicationSettings["auth0ClientIdTokenExpiration"] =
     _auth0ClientIdTokenExpiration = tokenExpirationInfo.Expiration;
    
    // Get the client token lifespan - used with subsequent transactions to determine if a new token is required
     _applicationSettings["auth0ClientTokenLifespan"] =
     _auth0ClientTokenLifespan = tokenExpirationInfo.Lifespan;
    
    return true;
     }
     catch (Exception err)
     {
     Debug.WriteLine(err.Message);
    
    throw new Exception(err.Message);
     }
     }
     private async void JustClientToken(object sender, GestureEventArgs e)
     {
     try
     {
     _outputItems.Add("Starting JustClientToken.");
    
    await CheckClientToken().ContinueWith(async task =>
     {
     await Task.Run(() =>
     {
     if (!task.IsFaulted && task.Result)
     {
     Dispatcher.BeginInvoke(() => _outputItems.Add("JustClientToken completed okay."));
     }
     else
     {
     Dispatcher.BeginInvoke(() => _outputItems.Add("JustClientToken failed."));
     }
     });
     });
     }
     catch (Exception err)
     {
     _outputItems.Add(err.Message);
     }
     }
     private async void TriggerApiCall(object sender, GestureEventArgs e)
     {
     await TestAPICall();
     }
     private void ClearOutput(object sender, GestureEventArgs e)
     {
     _outputItems.Clear();
     }
     public async Task<DelegateTokenObject> GetDelegationToken(string targetClientId, string clientId,
     string clientToken)
     {
     if (string.IsNullOrEmpty(clientToken))
     {
     throw new InvalidOperationException("You need to login first or specify a value for id_token parameter.");
     }
    
    try
     {
     var endpoint = string.Format("https://{0}/delegation", Auth0Domain);
    
    var parameters = String.Format(
     "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&id_token={0}&target={1}&client_id={2}&state={3}",
     clientToken,
     targetClientId,
     clientId,
     _state);
    
    var httpClient = new HttpClient();
    
    var request = new HttpRequestMessage(HttpMethod.Post, endpoint)
     {
     Content = new StreamContent(new MemoryStream(Encoding.UTF8.GetBytes(parameters)))
     };
    
    request.Content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
    
    var result = await httpClient.SendAsync(request);
    
    var content = await result.Content.ReadAsStringAsync();
    
    var delegationResult = JObject.Parse(content) as dynamic;
    
    var delegateTokenObject = new DelegateTokenObject
     {
     Expires = delegationResult.expires_in,
     IdToken = delegationResult.id_token,
     };
    
    return delegateTokenObject;
     }
     catch (Exception err)
     {
     Debug.WriteLine(err.Message);
    
    return null;
     }
     }
    
    public long GetSecondsSinceEpoch()
     {
     var t = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
     return (long)t.TotalSeconds;
     }
    
    public class DelegateTokenObject
     {
     public long Expires { get; set; }
     public string IdToken { get; set; }
     }
     }
    }

    Note: Don’t forget to substitute your particular values for the Auth0 domain, client ID, API client ID and API base address!

Select an emulator and run the app. On the screen, hit the “C Token” button to obtain just a client token. You should be redirected to a web-browser control page showing the social auth providers you selected. Choose one and log in. You’ll then be taken back into the app page and should see something like the third image in this series:

Find this line in the CheckClientToken method:


// Get the client token


_applicationSettings[“auth0ClientIdToken”] = _auth0ClientIdToken = user.IdToken;

If you set a breakpoint, you can grab the token and try it out in a browser-based decoder. Auth0 provides one at http://jwt.io/. If you paste the encoded JWT into the window on the left, you’ll see the decoded results to the right. If you copy and paste your client secret (found in the Settings section of your client Application on the Auth0 website) and check the “secret base64 encoded” checkbox, you should see your JWT signature verified:

Now try clicking on the API Call button. You should see something like this:

A bit of explanation: The output is letting you know that a new client token was obtained, it was verified, and a new API token was obtained. This was then used to make calls to the remote server. In this case, I’ve drastically shortened the expiration times for the client and API tokens (a great feature of Auth0 when it comes to testing). I’ve also used an offset factor to create a “refresh window” for the tokens, e.g:

// Determines when we’d attempt to refresh a token, e.g. if expiration is 30 days, .1 = any time within 3 days of that.

private
const
double
TokenLifespanOffset = .1;


To understand this, consider what happens when you cache tokens on the client vis-à-vis the user’s interaction with the app. You want the user to have a friction-free experience, i.e. not have to log in every time they use the app. Yet tokens expire. And there’s security to consider. Let’s say, for example, that we decide to allow the app to have a 30-day expiration for the client token. That’s pretty generous, but at least some users won’t use an app that often. It seems reasonable for them to have to log in again (using their social credentials, the choice of which is also cached…more on that minor potential Achilles heel later). For more frequent users (and we want to reward their loyalty, right J) for 27 days the cached token will be used and no calls will need to be made to Auth0’s servers to renew it. If the user uses the app any time within the last three days of the cycle, a new token will be issued.

The API tokens (which generally have a shorter lifespan, e.g. 8 hours) work in a similar way. But here the purpose is simply to avoid trying to use an expired token to make a remote server call. While the JWT specification provides for an optional grace period on using an expired token, I’d prefer to have some leeway. Also, as with client tokens, this avoids excessive calls to Auth0.

Again, there is value in having separate client and API authentication. This gives you the latitude you need to have independent expiration lengths. As mentioned, it might be just fine to allow a client to have a token that lasts 30 days. But the API may need more protection than that, hence shorter token lifespans. Consider for example a set of applications and services revolving around some social scenario. Then you get a user who is a troll or malicious that needs to be locked out, whether temporarily or permanently. Auth0 has a provision for blocking users, which takes effect immediately – but it only prevents the issuance of new tokens. So if you have a troll with a cached token good for hitting the API for 10 days, you’d have to rely on some other way to keep them from wreaking havoc while not impacting other users. With an independent API authorization you could, for instance, temporarily shorten the expiration time. This won’t noticeably impact users. It will only increase authentication calls for API tokens.

Granted, this scenario alone is enough to make me want to use additional ways within my own user database and API to deal with such users. But it is still helpful to have such a combination blocking and short expiration times. The latter also limits the ability of XSRF (cross-site request forgery) attacks.

It’s worth noting that Auth0 (as of version 1.2.2 of their Windows Phone SDK) fixed an UX issue when users are blocked. Before, you’d be stuck in the web browser control. Now it returns control to the app and back to the calling code. There is an error message explaining the user is blocked, which you could trap for if you desire to do more than just deliver a generic message. (I wouldn’t give them that message, but might deliver an explanatory message in general terms).

A Minor Problem

I haven’t quite figured this one out. Suppose a user doesn’t log in for a long time or uninstalls/re-installs my app (or installs it on a new device). Since the “preferred” social auth provider will no longer be cached if the user doesn’t remember which one they used before, then it’s possible to lose the association between the user and all their data. For now, I’ll be relying on providing a support email address to handle this edge case, but it still bothers me. I could add some sort of check that tries to see if there is some common association between the profiles provided by each provider, but that can be problematic in other ways.

Download Sample

http://stonetip.com/auth0/auth0JWT2_sample.zip

Web API, JSON by Default in Web Browsers

I use a few methods for examining and debugging JSON output. One of those is to view it in a browser. If that browser is Internet Explorer, then the file just gets opened automatically in Notepad++ (which, nicely, will also just keep updating an existing file, avoiding tab clutter). There, I use the JSON Viewer plugin, which is decent enough, if a bit unpolished. If the browser is Chrome, I use JSONView. One advantage is that if the JSON doesn’t end up formatted, you know right away it isn’t valid. But, unlike JSONLint it can’t tell you where the problem is.

For whatever inane reason (XML is dead, right? :-)) Chrome likes to tell servers that it accepts XML. So your “purist” Web API that is set up to deliver only JSON gets this request and fails to serialize into XML. So Chrome just gets a big, nasty error message back.

Fortunately, there is way to head this off at the pass. In the Web API global.asax.cs file you can remove the XML formatter (if you’re never going to use it):

using System;
using System.Linq;
using System.Web;
using System.Web.Http;

namespace GeoDataAPI
{
    public class Global : HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);

            // Ignores browsers like Chrome requesting xml.
            var config = GlobalConfiguration.Configuration;
            var appXmlType =
                config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
            config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
        }
    }
}

Another approach is to use

config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));

But I found this caused a problem with third-party data that contained HTML break tags. The JSON was sent out with carriage returns, which caused it to be invalid. If you don’t need XML, I recommend the other way of doing this.

Using Microsoft Live for Authentication with Windows 8.x and Windows Phone 8 Apps

If you’re the impatient type and are just looking for a code sample, check out https://github.com/stonetip/authTest. I would also appreciate any comments or suggestions to make the code better. The solution contains a Web API service and Windows 8/Windows Phone apps.

I first started looking into this because I needed a way to authenticate users and didn’t want to build or maintain such a system. Additionally, people are used to being able to use social media accounts, which reduces resistance to trying out something new. For the time being, since my apps are for these two platforms I’ve chosen to focus on using just Live authentication. A good part of that is the user experience with more comprehensive approaches wasn’t very satisfactory. A significant design goal is to re-use as much code as possible across Windows 8 and Windows Phone.

Performing authentication and using to securely connect to a service involves some significant steps and pieces:

1)      Registering Client Apps and Services with the Windows Store and Microsoft Live

2)      Setting up a Service

3)      Assembling the right combination of code to authenticate properly and at the right times.

4)      Using the Live SDK and a JWT (JSON Web Token) decoding and verification library

Furthermore, there are certain design goals that need to be met:

1)      Avoid having user log in as much as possible…preferably only once.

2)      Maintain security, both locally and on the server

3)      Make the experience as seamless as can be

4)      Re-use as much code as possible across Windows 8 and Windows Phone

Like many things, it was overwhelming at first to see how the pieces of the puzzle fit together. This is complicated somewhat by differences in the way Windows 8 and Windows Phone handle signing in and staying signed in/authenticated. As you may know, Windows 8 operates on the principal of SSO (single sign on) with Microsoft accounts. Applications don’t have their own interface for signing in. All the user will see upon installing the application is a one-time pop-up asking for permission to use whatever scopes the app has requested. All you have to do is include wl.signin in your sign-in scopes.

 image001  image002
Windows 8 Windows Phone

Note: See below on how to reset this after you’ve tested it with an account

Windows Phone, on the other hand, doesn’t use SSO. Fortunately the Live SDK handles this as long as you, again, remember to include wl.offline_access. Then the only difference is that you have to sign in (via a browser pop-up in the app) to your Microsoft account one time.

Note: If you’ve looked at Live SDK samples for Windows Phone they include a sign-in button (or at least used to when I first investigated them). It’s not necessary to use. The code included in this post and in the accompanying download will demonstrate that.

So how does the authentication process work anyway?

It’s important to have an overview of the process. The application needs to be able to authenticate itself with the server. This is handled by communicating with Live (when necessary), which returns a JWT (JSON Web Token). The JWT is then passed to the server with every call (yes, that’s right) as an Authorization header. The server validates the JWT and if it passes returns the requested data.

image003

At no time are user credentials or client secrets stored within the client. This is critical because no matter what steps you take to obfuscate code there’s no guarantee the app won’t be compromised.

What’s a JWT and what does it contain?

A JSON Web Token is a string containing three parts – a header, a claims section, and a signature. The first two are JSON strings, e.g  {“typ”:”JWT”,  “alg”:”HS256″}, which are base-64 encoded. The signature is hashed using – and this is important – the client secret Live generates for your app (more on this in a moment). It is also encoded, then all three parts are concatenated, separated with a period, such as:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cm46bWljcm9zb2Z0OmFwcHVyaSI6ImFwcGlkOi8vMDAwMDAwMDBYWFhYWFhYWCIsInZlciI6MSwidWlkIjoieHl6MTIzIiwiaXNzIjoidXJuOndpbmRvd3M6bGl2ZWlkIiwiZXhwIjoxMzkxMTA2MjQ5LCJ1cm46bWljcm9zb2Z0OmFwcGlkIjoiMDAwMDAwMDBYWFhYWFhYWCIsImF1ZCI6Im15c2l0ZS5henVyZXdlYnNpdGVzLm5ldCIsInR5cCI6IkpXVCJ9.56c3v2DvM-XzC5tbKgcJWXsPYwV13ZJZPdqS-TxuGrM

This particular example would be decoded as:

Header

{

    “alg”: “HS256”,

    “typ”: “JWT”

}

Claims

{

“urn:microsoft:appuri”: “appid://00000000XXXXXXXX”,

“urn:microsoft:appid”: “00000000XXXXXXXX”,

“uid”: “xyz123”,

“iss”: “urn:windows:liveid”,

“exp”: 1391106249,

“ver”: 1,

“typ”: “JWT”,

“aud”: “mysite.azurewebsites.net”

}

Signature (encoded)

56c3v2DvM-XzC5tbKgcJWXsPYwV13ZJZPdqS-TxuGrM

The items that are important as far as server validation is concerned are the issuer and audience. Also of importance is the expiration UTC date/time, which is expressed in Unix epoch seconds. This is covered more in the Sample section.

One thing you should understand about JWTs is that they are not encrypted. Only the signature is. So if not debugging traffic, strongly consider using HTTPS. If you need to authenticate a user, whatever traffic you’re sending probably needs to be encrypted anyway.

Note: uid (user id) is a unique user id specific to the app (as registered with Live). In other words, the uid will be the same for both a Windows 8 app and a Windows Phone app using the same app registration. And it will be the same across multiple devices. Another id source, of course, is the user’s id from_liveClient.GetAsync(“me”). However, if you’re going to use an ID, say stored in a remote DB, the app-specific one would be better. If the data is ever compromised, it would be harder for someone to use against other Live-based apps or services linked to the user.

A couple web-based pages where you can view a decoded JWT are http://openidtest.uninett.no/jwt and https://developers.google.com/wallet/digital/docs/jwtdecoder. The latter looks a little funky in IE but it works. The Federation Lab page will also encode a JWT, but neither one will actually validate the signature.

Registering an Application

I’ve found that it easiest to first associate a Windows Store app from within Visual Studio. Right-click on the project, select Store> Associate App with the Store… to do this. Once it’s done, under the Dashboard on the developer site (https://appdev.microsoft.com/StorePortals/en-us/Home/Index), find the app and click on its Edit link. Select Services. You’ll see a link to navigate to Live Services, e.g. “If you have an existing WNS solution or need to update your current client secret, visit the Live Services site.”

From there, you’ll see the “If your app uses Live Connect services, review:” heading and can use the Authenticating link to get your Client secret (which should only be used server side because you should be just sending a valid JWT).

image006

Copy the Client secret to Notepad or similar so you will have it available to place in the web.config of the Web API service. Then use the Representing your app link to fill in the details on the app, such as the redirect URI:

image008

The Redirect URI will be the LiveCredential used in your Windows 8 app. So make a note to have that available.

Note: Generally, you’ll want to restrict JWT issuing unless you have more than one store app that uses the same backend service. Don’t worry, this doesn’t affect also using a Windows Phone app.

If you are using the service with a Windows Phone app, you will also need to visit https://dev.live.com and select your app from My Apps, then API Settings and enable Mobile client app. This page is also where you will find your Client ID. Not to be confused with the Client secret, this is a value you will use for the LiveCredential in a Windows Phone app. (Incidentally, if you compare the MainPage.xaml.cs files in my Win8/WP8 projects you’ll see that this is the only difference aside from a few usings).

The App and Service Samples

I’ve provided two barebones apps for Windows 8 and Windows Phone, along with a Web API service. What they demonstrate is a way to stay signed into an app securely, pass a JWT to the server along with a POST, validate the JWT and return data. Live JWTs are issued with a 24-hour expiration. So even though your client app may not require logging in more than once, this means the app still needs to keep track of the latest expiration time and request a new token if needed. Otherwise the server will refuse to return data if it can’t validate the token.

The way I prefer to handle this is to have the server extract the expiration when it receives the JWT and return that to the client in the response headers. My samples don’t store the expiration in IsolatedStorage nor do anything to examine it under various usage scenarios, other than when launching. In any production code, you’d want to be sure to incorporate whatever’s needed to ensure a smooth, error-free experience for your users.

I spent a fair amount of time looking into the server-side code and decided to use the System.IdentityModel.Tokens.JwtSecurityTokenHandler for validation. I’d tried another library and fed it a token with a purposely altered signature, which it didn’t reject. They may have fixed it since, but I know this one works. All requests are routed through a handler set up in Global.asax.cs. Configuration settings unique to the app registration and server are stored in Web.config, e.g:

<add key=”AllowedAudience” value=”mysite.azurewebsites.net” />

<add key=”ClientSecret” value=”[APP CLIENT SECRET]” />

<add key=”Issuer” value=”urn:windows:liveid” />

These are placed inside appSettings.

Global.asax.cs will need to have references to System.IdentityModel and System.IdentityModel.Tokens added. Under the Application_Start method, add:

ConfigureTokenValidation(GlobalConfiguration.Configuration);

Note: Once this is implemented, along with the code below, the service will only work with valid JWTs. During initial setup, just to see that the service is working, comment this line out. You can enter a URL in a browser, such as http://[MACHINENAME]/AuthTestWebAPI/api/values and should see a JSON test string, e.g. [“value1″,”value2”].

Create a Configure method:

private static void ConfigureTokenValidation(HttpConfiguration config)

{

config.MessageHandlers.Add(new TokenValidationHandler());

}

And here’s the TokenValidationHandler class:

Note that the JWT’s expiration is extracted from the Thread.CurrentPrincipal, which contains all the decoded JWT claims. The expiration is then injected back into the Request, using a custom header. I think this is the first time I’ve ever done this for an internal operation on a server, but hey it works and seems a reasonable enough way to pass the value onto the ValuesController that will return a response to the client. I prefer to leave times in Unix epoch seconds when shuttling them around between server and client rather than transform them to DateTimes. It’s a smaller, less encoded value.

On the client side, it’s important not only to have the expiration to know when to ask for a new JWT, but also to know not to ask. If you had code that kept asking for a new JWT every time the user visits a page, resumes an app or even when first launching, it creates a noticeable delay. In testing, I’ve seen it usually take about 6 seconds to acquire a JWT. So you want to do so only when necessary.

Another configuration step is to set up the AuthTestWebAPI project up for local testing. You can still use the same audience URI (and, in fact, need to). But under Properties > Web I’d recommend setting it up to run on a local IIS server under the machine name. That will allow testing on your local network. I use a Surface tablet and a phone for this. Select Local IIS, provide a URL with your machine name, and click on Create Virtual Directory:

image010

Note: You’ll need to run Visual Studio as Administrator to do this!

And while on the subject of configuration and local testing, in the AuthTestWin8 project, open Package.appxmanifest, navigate to capabilities and be sure to select Private Networks (Client & Server) or you won’t be able to access an intranet URL via the application.

image011

Testing with the Clients

Once the service is configured (including enabling the ConfigureTokenValidation method), try running the client apps. If everything is working, you should see something like this:

image012

Try hitting the Test Server Auth button a couple times. Note that the Time value changes, but not the Expiration. That’s because the expiration time is being compared to the last known expiration time (again, something you’d normally store in IsolatedStorage). This way, an unnecessary call to the Live servers is avoided. You will notice, however, with the Windows Phone app that upon launch the app will always get a new token, while the Win 8 app will not. This is something, again, where I’d use IsolatedStorage to store the token and expiration time and check the last known expiration time to see if a new token is required. If not, the stored token could continue to be passed to the server.

Resetting the Permissions Dialog

Sometimes you want to return to a state where you can mimic the user’s initial installation experience, including seeing the Live Permissions dialog. It may come as a surprise, but uninstalling/reinstalling the app won’t do it. What you need to do is visit https://account.live.com/Permissions, log on under whatever user account you’re using for testing and click on the Manage apps and services link (https://account.live.com/consent/Manage). On that page, look for the app, e.g. AuthTest, click on Edit and remove it. This will allow you to start over again.

IKnow IEquatable

Well, now anyway. Sometimes I think the statement “Necessity is the mother of invention.” should – when applied to coders – be restated as “Necessity is the mother of fruitless hacks, StackOverflow searches and more code.” Catchy, eh?

Prior to my somewhat painful re-education (not going to use a diaeresis this time), I was operating under the ridiculous assumption that comparing to collections would be straightforward…if not downright simple. But my code kept telling me two identical collections were not. Of course a better coder would immediately recognize a reference problem underlying this. First I had blithely tried:

if (savedExercisesCollection != ExercisesCollection)
{
 for (int i = 0; i < ExercisesCollection.Count; i++)
 {
 ExercisesCollection[i].Order = i;
 }

App.StorageSettings["SettingsChanged"] = true;
}

But that was always returning true. Next, I turned to LINQ (’cause it is the solver of all problems, isn’t it?). Well, at any rate, my thinking was that it would actually compare the values. And it is elegantly concise:

if (savedExercisesCollection.Except(ExercisesCollection).Any())
{
 for (int i = 0; i < ExercisesCollection.Count; i++)
 {
 ExercisesCollection[i].Order = i;
 }</pre>
App.StorageSettings["SettingsChanged"] = true;
 }

I had also tried SequenceEqual but with the same sad results…until I stumbled across the IEqualityComparer<T> IEquatable @ http://msdn.microsoft.com/en-us/library/bb348567.aspx.

if (!savedExercisesCollection.SequenceEqual(ExercisesCollection))
{
 for (int i = 0; i < ExercisesCollection.Count; i++)
 {
 ExercisesCollection[i].Order = i;
 }

App.StorageSettings["SettingsChanged"] = true;
}

Now I was on the path to righteousness. All it would take is adding a comparer to my original class. I approached this with some trepidation since I’m relying on being able to serialize portions of that class. But the only way to know if something will blow up is to light the fuse. Turns out no worries.

I modified the class as follows:

[DataContract]
 public class Exercise : IEquatable<Exercise>
 {
 public List<Asset> AssetsList;

public Exercise(int id, int order, string description)
 {
 Id = id;

Order = order;

Description = description;

AssetsList = new List<Asset>();
 }

[DataMember]
 public int Id { get; set; }

[DataMember]
 public int Order { get; set; }

[DataMember]
 public string Description { get; set; }

 public bool Equals(Exercise other)
 {
 //Check whether the compared object is null.
 if (ReferenceEquals(other, null)) return false;

//Check whether the compared object references the same data.
 if (ReferenceEquals(this, other)) return true;

//Check whether the products' properties are equal.
 return Id.Equals(other.Id) && Order.Equals(other.Order);
 }

The take-home lesson from this is that unless an ObservableCollection is instantiated from the same source as another they are not automatically comparable. I can see this knowledge coming in handy when rehydrating a chunk of JSON, for instance to compare a remotely stored to-do list with one on the client.

Did ya hear the one about the serial killer?

Turns out his victim was found floating in a tub full of corn flakes and milk. Bahhh, dahhh, dahhh, da.

Anyway, in this case it was more that the serializer got killed…by an uncoöperative class. (BTW, that’s not an umlaut over the second “o”. It’s a diaeresis. Lovely sounding term. More on the subject: http://www.newyorker.com/online/blogs/culture/2012/04/the-curse-of-the-diaeresis.html). Typically, this happens because the class has a constructor with parameters. I couldn’t get around that. Well, I don’t want to anyway. I also didn’t want to depart from my vanilla JSON serializer, although in the past I’ve found SilverlightSerializer to be a solution when all else fails…like serializing an entire model. (Why would you want to do that? Long story, for some other time).

The solution is to simply mark up the class with the DataContract attribute and use DataMember for each of the members you want to serialize. In my case, this had the advantage of not serializing a voluminous sub-list I don’t want included. And it allows this class to be used in several places, rather than creating a separate Dictionary or similar.


[DataContract]
public class Exercise
{
 public List<Asset> AssetsList;

public Exercise(int id, int order, string description)
 {
 Id = id;

Order = order;

Description = description;

AssetsList = new List<Asset>();
 }

[DataMember]
 public int Id { get; set; }

[DataMember]
 public int Order { get; set; }

[DataMember]
 public string Description { get; set; }
}

And, voila, we end up with something that can be saved to IsolatedStorage:

[{“Description”:”JUMPING JACKS”,”Id”:0,”Order”:0},{“Description”:”WALL SIT”,”Id”:1,”Order”:1},{“Description”:”PUSH UPS”,”Id”:2,”Order”:2},{“Description”:”CRUNCHES”,”Id”:3,”Order”:3},{“Description”:”STEP UPS”,”Id”:4,”Order”:4},{“Description”:”SQUATS”,”Id”:5,”Order”:5},{“Description”:”TRICEPS DIP”,”Id”:6,”Order”:6},{“Description”:”PLANK”,”Id”:7,”Order”:7},{“Description”:”HIGH KNEES”,”Id”:8,”Order”:8},{“Description”:”LUNGES”,”Id”:9,”Order”:9},{“Description”:”PUSH UP & ROTATE”,”Id”:10,”Order”:10},{“Description”:”SIDE PLANK”,”Id”:11,”Order”:11}]

Using .NET 4.5 Task Async and Await with WPF and SQL Server

Most of the examples I’ve seen of  using the new async, await and Task methods in .NET 4.5 have been aimed at Windows 8 (Metro or “UI Style”) apps. This is understandable, given Microsoft’s push towards both a new OS and to populate the Windows 8 Store. But for some (many?) developers there is also a need to support both Windows 7 and Windows 8 Desktop. Notably missing from the WinRT scenario is the ability to directly connect to SQL Server. I (mostly) get the reasons for that, although it seems against Microsoft’s interests to cede that space to SQLite instead of a sandboxed, light version of SQL Server.

Anyway, I put together a sample WPF application (download below) that supports asynchronous connections to SQL Server. You can cancel or restart the demo query, which populates a ListView with data from the AdventureWorks DB Production.WorkOrder table, which had a decent number of records for testing. I really wanted to simulate some real world conditions, such as server-side delays, so that’s included too. One of my beefs with many of the samples I come across is that they never include decent error handling, especially to accomodate network latency or timeouts. This sample also includes the Microsoft.Data.ConnectionUI SQL Server connection dialog box.

One advantage of making a WPF app asynchronous is it no longer locks up while running a process. Try dragging the window around while the ListView is being populated with data. Yay, no UI-thread blocking!

Clicking the Start button triggers the StartTest method. Notice that in the query, I’ve embedded an artificial server-side delay of 3 seconds – WAITFOR DELAY ’00:00:03′; – which will simulate a slow server return. Also, a queryTimeout has been set to 120 seconds. If you set the WAITFOR delay longer than that, you will see an error occurs and is handled. I did my best to include specific SQL Server error handling so we get actual error details, rather than just “some crap happened and that’s all we know.”


private async void StartTest(object sender, RoutedEventArgs e)
{
try
{
 if (_connectionString == String.Empty)
 {
 var scsb = new SqlConnectionStringBuilder(Settings.Default.DBConnString);

_connectionString = scsb.ConnectionString;

if (_connectionString == String.Empty)
 {
 throw new Exception("Please use Change DB to first select a server and database.");
 }
 }

if (DbInfo.DbName == String.Empty)
 {
 throw new Exception("Please use Change DB to first select a database from the server.");
 }

// Note: If the start test button was disabled, this would be unnecessary
 _cts.Cancel();

// Re-initialize this. Otherwise, StartTest won't work.
 _cts = new CancellationTokenSource();

DataItemsList.Clear();

// Note the simulated delay, which will happen on the DB server. You can vary this to see its effect.
 // Try dragging the window around after hitting the start test button.
 const string query =
 @"WAITFOR DELAY '00:00:03'; SELECT * FROM [Production].[WorkOrder];";

// Note that setting the WAITFOR delay to exceed this, eg. 00:02:01, will trigger an exception
 int queryTimeout = 120;

RequestStatus = "started";

await ProcessQueryCancelleable(_connectionString, query, queryTimeout, _cts.Token);
}
catch (Exception ex)
{
 MessageBox.Show(ex.Message + " (from StartTest)");

Debug.WriteLine(ex.Message);
}
}

The ProcessQueryCancelleable method. Note the use of the CancellationToken…’cause users might actually want to cancel a long-running query. Inside this method is another simulated delay (await Task.Delay(TimeSpan.FromMilliseconds(1));):

/// <summary>
/// Runs a cancelleable query
/// </summary>
/// <param name="connectionString">SQL Server connection string</param>
/// <param name="query">SQL query</param>
/// <param name="timeout">SqlDataReader timeout (maximum time in seconds allowed to run query). Note: Try varying this in conjunction
/// with the WAITFOR DELAY in the SQL query, e.g. make it shorter than the WAITFOR or maybe a second longer</param>
/// <param name="cancellationToken">Allows cancellation of this operation</param>
/// <returns></returns>
private async Task ProcessQueryCancelleable(string connectionString, string query, int timeout,
 CancellationToken cancellationToken)
{
 // await Task.Delay(TimeSpan.FromSeconds(5));

try
 {
 // Keep sqlConnection wrapped in using statement so disposal is handled automatically
 using (var sqlConnection = new SqlConnection(connectionString))
 {
 await sqlConnection.OpenAsync(cancellationToken);

using (SqlCommand cmd = sqlConnection.CreateCommand())
 {
 cmd.CommandTimeout = timeout;

cmd.CommandText = query;

using (SqlDataReader dataReader = await cmd.ExecuteReaderAsync(cancellationToken))
 {
 while (!dataReader.IsClosed)
 {
 // While the dataReader has not reached its end keep adding rows to the DataItemsList
 while (await dataReader.ReadAsync(cancellationToken))
 {
 // Process dataReader row
 WorkOrder workOrder = GetWorkOrderFromReader(dataReader);

DataItemsList.Add(workOrder);

// Another simulated delay...this one internal
 await Task.Delay(TimeSpan.FromMilliseconds(1));
 }

if (!dataReader.NextResult())
 {
 dataReader.Close();
 }
 }

Debug.WriteLine("done with reader");

RequestStatus = "finished";
 }
 }
 }
 }
 catch (SqlException sqlEx)
 {
 Debug.WriteLine(sqlEx.Message);
 }
}

Download C# Project (an MDF with just the WorkOrders table is included)