Category Archives: Microsoft

Anything related to Microsoft technologies or the company

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

Windows 10 and Compatibility

Prior to upgrading to Windows 10 yesterday, I was graciously informed by the updater that my all-in-one printer – a Panasonic KX-MB271 – wasn’t compatible. I appreciated knowing this up front. I also was disappointed because the printer has seen low use and I have extra toner cartridges for it. Still, I chose to go with the upgrade (pluses outweighing this one minus).

Sure enough, I couldn’t print. However, I opened Device Manager and manually selected the drivers for the printer and scanner. This required drilling down into some specific folders, e.g. D:panasonicMFSDriversObjectPrinterWin7VistaXp_x64GDI for the printer. But it worked. The printer is back in business.

Although…when I rebuild my work desk I will probably find a new home for it and park a Wi-Fi/networkable printer in the nearby storeroom where my router and cable modem live.

Note: You can use http://www.microsoft.com/en-us/windows/compatibility/CompatCenter/Home to check for compatible devices. However, it definitely works best if you have the specific part number, e.g. kx-mb271 rather than kxmb271. And, as this post points out, never take it for granted that you’re SOL.

The Beauty of Anonymity

No, not the kind commonly found on the Internet, which is often anything but. Rather, C#’s Anonymous types, introduced way back in 2007 with C# 3.0 and more often than not ignored by me until now.

I used to avoid JSON. Its syntax seemed just like every other delimited format I’d ever seen. In short, a headache to parse. XML is more verbose. Yet (at least for me) more humanly readable. That was until I found two things:

  1. XML parsing across different browsers is an even bigger headache
  2. With JSON I can create almost identical classes on both a C# server and a Javascript client

Later, the relationship was strengthened by the discovery of services like http://json2csharp.com/, which will create a C# class for you out of a JSON sample, as will more recent versions of Visual Studio. That’s great for dealing with someone else’s API output.

But sometimes a class seems like overkill. What if you have just one place where you really, really need to send just a bit of JSON to the client? For example, in one of my SignalR hubs, I need to send three things:

  1. brief message
  2. start time
  3. end time

SignalR, by the way, always sends JSON so all you need is some way to package (enclassulate?)  your data. Enter the Anonymous type, which if you use Linq you’ve probably already seen many times, e.g:

var productQuery =
    from prod in products
    select new { prod.Color, prod.Price };

foreach (var v in productQuery)
{
    Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price);
}

With a var, the usage is basic: “var foo = new { someData = “something” };” Anonymous types support nesting too, so I was able to tidily separate my message data from my duration data. Here’s a sample method in the SignalR hub on the server:

public void AnonTypeDemo(string groupID)
{
    var startTime = DateTime.UtcNow;

    var endTime = startTime + TimeSpan.FromMinutes(10);

    // the anonymous type
    var data = new { message = "started", duration = new { startTime, endTime } };

    Clients.Group(groupID).anonTypeDemo(data);
}

The method sends a JSON string that looks like this:

{
    "message": "started",
    "duration": {
        "startTime": "2015-02-24T18:19:48.8008904Z",
        "endTime": "2015-02-24T18:29:48.8008904Z"
    }
}

On the client side, a Javascript method will be called by the SignalR client to process the received data:


myHub.client.anonTypeDemo = function (data) {

    console.log(data);

    var message = data.message;

    var startTime = data.duration.startTime;
    var endTime = data.duration.endTime;
}

And that’s all he wrote.

Real-time mapping with SignalR and a client app

A couple months ago I watched a live seminar given by @bradygaster and @jongalloway on SignalR. During their presentation, they demoed a web mapping app where all the attendees could share their locations with anyone viewing the web page. It occurred to me that capturing GPS data from a phone would be a good test of SignalR’s capabilities – namely how quickly and reliably it could transfer rapid bursts of data. I put together a web app with a Bing Map and a barebones Windows Phone client app that sends GPS data (lat, lon, altitude and speed) to a SignalR hub running in the web app.

Every time data is received the web map displays a red dot. Every 30th time it displays a custom marker showing altitude and speed. If the data is coming from the phone app, this translates into approximately every 300 meters. Using the apps while driving was interesting in that it graphically pointed out gaps in cellular data coverage between Helena and Missoula, Montana. While running or biking it was also interesting – to a certain extent. rtr2 I actually left a screen capture video running during one bike ride. On the descent I reached 48 mph. Yet reviewing even that portion of the video later was like watching paint dry. So if you’re thinking it would be exciting to watch your friends run in real time on a map, well. That isn’t to say that something like this doesn’t have applications. On the commercial side, while the developers of SignalR make no warranties to its suitability, an app running in the background could show delivery driver or utility worker locations. Or as your SWAT team is moving into position…uhm, in light of current events we won’t go there. Need to know where your kids are?

Personally, I’d like to be able to fire up an app, send an email to one or more friends to check a link so they know where to go to help me get an elk off some rocky, heavily timbered mountain (I actually sent a screenshot off the phone app to a friend more because I wanted someone to know where I was this year since it was -10F. In that situation, of course, the best and first thing I did was build a healthy fire).

In the interest of getting this post done, I’m not going to go through just a few of the project steps. I’d encourage anyone with Visual Studio to clone https://github.com/stonetip/realtimeRun, which contains the complete project code aside from Nuget packages (just do a restore). A couple of things:

  1. Run VS as Administrator, particularly if you’d like to create a virtual directory for the web app. This allows testing from a device, which is nice if you actually want to walk around within range of your wi-fi router.
  2. While it’s great to use the Location tab/map in a Windows Phone emulator, it’s a pain to get the emulator to see a local machine on your network. I recommend setting up a test site on Azure and deploy to that (you’ll need to configure the URL in the Windows Phone app to point to it). Then the emulator will work AND you can play with the app anywhere you have a wi-fi or cellular data connection.
  3. SignalR supports Websockets. IIS8 does too, but you’ll need to enable it under Windows Features:enable_ws

    If using Azure, you’ll need to visit the CONFIGURE section for the website inside the Portal and enable it. If you don’t feel like doing either, no big deal. Other protocols are fine. SignalR will intelligently pick one.

 

The Web App

Creating  a SignalR web app is fairly easy (provided you’ve added the requisite Nuget packages). In an Owin-based web app like this one, a single line added to the Startup.cs file will kick it off:

app.MapSignalR();

The next step is to create a Hub class. In my case, this is a simple class that receives data from a client and passes data to all clients that have the client method “broadcastLatLon”:

using Microsoft.AspNet.SignalR;

namespace RealtimeRun
{
    public class MapHub : Hub
    {
        // The Send method is used on a client to deliver data to the server
        public void Send(string lat, string lon, double? altitude, double? speed)
        {
            // In return, the server broadcasts the data to all clients.
            // Those that have the broadcastLatLon method will use the data on the client
            Clients.All.broadcastLatLon(lat, lon, altitude, speed);
        }
    }
}

That’s it for the backend code. Everything else in the web app is done in the client page, in this case map.aspx. One thing you’ll need is to provide a Bing Maps API key (info here).  You could, of course, adapt this sample to use Google Maps, HERE Maps or any other web mapping service. We’re just dealing with client and server methods that are sending text strings – nothing mysterious or requiring a masters in GIS.

Note that in this app I use a secondary config file, called AppSecrets.config to avoid using my key directly in Web.config and have that exposed in the Github repository (see http://www.mattburkedev.com/keep-your-azure-secrets-safely-out-of-git/). BTW, if you’re using Visual Studio with Git, I highly recommend using the Github VisualStudio.gitignore file. It’s chock full of exclusionary goodness. The Web.config file contains a commented-out section showing what the contents of AppSecret.config should look like.

The map.aspx file shows a map along with a convenient test button (which will place a random marker within a few kilometers of your location each time its clicked) and a line showing the coordinates, altitude and speed: web_app Once you get the app up and running, try clicking the daylights out it. This will give you an immediate visual indication that things are working. I won’t go into more detail on the map.aspx file. The code is well-commented.

Update

I was asked what would happen if more than one person (or even one person using multiple browsers or devices) was sending data. All of it would show up on the map. That’s because this sample doesn’t differentiate between clients. SignalR does provide support for distinct users. Check out Working with Groups in SignalR for more on this.

 

The Phone Client

This is about as barebones a client as you can get…just enough UI to let you know its working. A couple of things you need to do

  1. Open WMAppManifest.xml and on the Capabilities tab, make sure that ID_CAP_LOCATION is active.
  2. In App.xaml.cs, add these variables and change or add these two sections to:
    public static Geolocator Geolocator { get; set; }
    public static bool RunningInBackground { get; set; }
    
    private void Application_RunningInBackground(object sender, RunningInBackgroundEventArgs args)
    {
        RunningInBackground = true;
    }
    
    private void Application_Activated(object sender, ActivatedEventArgs e)
    {
        RunningInBackground = false;
    }
    

Next we’ll turn our attention to the MainPage.Xaml layout. All that’s needed is one UI element inside the LayoutRoot:


Just a simple TextBlock to tell us the GPS is working by displaying coordinates, altitude and speed. In MainPage.xaml.cs, after adding or restoring the Nuget packages,  there’s not a lot to do. The SignalR part is minimal: a couple private vars, a start method (which gets invoked in the MainPage ctor upon Loaded, and a send method, which I imaginatively named SendMessage.

public async Task StartSignalRHub()
{
    try
    {
        _hubConnection = new HubConnection(SiteUrl);

        _hub = _hubConnection.CreateHubProxy("MapHub");

        await _hubConnection.Start();
    }
    catch (Exception err)
    {
        Debug.WriteLine(err.Message);
    }
}

public void SendMessage(string lat, string lon, double? altitude, double? speed)
{
    try
    {
        _hub.Invoke("send", lat, lon, altitude, speed);
    }
    catch (Exception err)
    {
        Debug.WriteLine(err.Message);
    }
}

Similarly, the geolocation portion consists of a start method to fire it up (which gets invoked either upon loading or navigating to the page):

public void StartGeolocation()
{
    if (App.Geolocator != null) return;

    App.Geolocator = new Geolocator { DesiredAccuracy = PositionAccuracy.High, MovementThreshold = 10 }; // 10 meters (to limit data transmission)
    App.Geolocator.PositionChanged += Geolocator_PositionChanged;
}

private void Geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
    var roundedLat = Math.Round(args.Position.Coordinate.Latitude, 6);
    var roundedLon = Math.Round(args.Position.Coordinate.Longitude, 6);
    var altitude = args.Position.Coordinate.Altitude;
    var speed = args.Position.Coordinate.Speed != null && Double.IsNaN((double)args.Position.Coordinate.Speed) ? 0 : args.Position.Coordinate.Speed;

    Debug.WriteLine("{0}, {1} altitude: {2}, speed: {3}", roundedLat, roundedLon, altitude, speed);

    SendMessage(roundedLat.ToString(CultureInfo.InvariantCulture),
        roundedLon.ToString(CultureInfo.InvariantCulture), altitude, speed);

    Dispatcher.BeginInvoke(() =>
        TblockLatLonBlock.Text =
            String.Format("{0}, {1} altitude: {2}, speed: {3}", roundedLat, roundedLon, altitude, speed));
}

Note in StartGeolocation that the MovementThreshold has been set to 10 (meters). I did this because I wanted to generate a reasonable amount of data but not dump tons of points onto the map. Similarly, in the map.aspx page, a label is generated only every 30 points, so if the data is coming from the phone app that means about every 300 meters. As mentioned before, it’s usually easier to test and debug if you have published the website to Azure or anywhere capable of running the web app which has a resolvable domain name. If you have done the voodoo that allows your local machine to be visible to your Windows Phone emulators, that’s great too. I just never have time to mess with that.

Whatever you use, the SiteUrl string needs to be set to the root of that site, e.g. “http://myMapTest.azurewebsites.net/” so that the phone app has somewhere to send its data. When everything is set up, open a browser window to the map.aspx page. With the phone app as the startup project, launch it for debugging and try it out. Under Additional Tools in the emulator, if you select Location, you can set a series of points and then replay them. For example, I’ve create a reenactment of the historic canoe route from my former digs on Juanita Dr. in Kirkland, WA to Spud’s fish ‘n’ chips. (The return trip usually was much slower, but paddling hard alleviated our guilt over chowing down on all those fries):

juanita_dr

Hit play and watch the epic voyage unfold in the web browser: spuds

Nifty little algorithm

This one’s in C# but almost same syntax would apply in javascript:

public static int GreatestCommonDenominator(int a, int b)
{
    while (true)
    {
        if (b == 0) return a;

        var a1 = a;
        a = Math.Min(a, b);
        b = Math.Max(a1, b) % Math.Min(a1, b);
    }
}

What the buckets does it do? Gives you the greatest common denominator so that if you’re trying to provide viewers with a ratio, e.g 2:3, and you’re starting with numbers like 180:270. One note: It expects integers only.

So what would you do if the ratio is 181:270, which won’t reduce? You could add a few rules, depending on how important it is to be exact vs. approximate. For example, use a string function to get the length of the numbers, divide them by 10, round the results and then do the comparison. If still no change, repeat.

Picking the Right Voice for Windows Phone

Recently, I had an interesting problem come up when testing localization (in French and Spanish in my case) in conjunction with letting the user choose a female or male voice in one of my Windows Phone apps (http://www.windowsphone.com/en-us/store/app/fn8/dd72d13d-1a7b-42c4-81d3-adbc98d4b002). The main part of the problem is basically financial, i.e. given the economics of app development it isn’t feasible to localize for many languages, let alone variants (cultures), e.g. whatever dialect of French is spoken in lower, mid-western Upper Volta. Additionally, given the inefficient workings of the Windows Phone store, it takes forever to submit (or even update) an app for each supported language. In my case, I have asked my translators to use a international a flavor as possible to cover as many markets as I can. Localizing into a language will still allow you to reach all the cultures that support the base language, e.g. localizing into Spanish will work for users in Spain (es-es) as well as Mexico (es-mx).

Part of the problem is technical. If you go this route, then when the user selects a gender for an installed voice, the app has to be able to match the appropriate voices from among those installed. With my first approach what I found when testing was that no voices were being selected at all in a device set to Mexican Spanish. The reason became immediately apparent when debugging:

The app was working fine in English because I was looking for a culture name and because en-us was the default culture for the app, it was finding that. But since the Spanish-speaking user is only getting a generic Spanish translation, the app was looking for a culture name of es-mx and blithely skipping over plain ol’ es.

So then I switched to grabbing the two-letter ISO language name instead. That made the app feliz in Español, but now on my device set to American English I was getting a male voice with a British accent when the radio button was set to female.

Another quick debug session and I could see that American voices Mike and Zira had some friends in the house I didn’t know about, including George and Susan from Great Britain and their friends Raul from Mexico and Stefan from Germany. All obviously there to enjoy Cortana’s predictions on the World Cup.

So here’s what can only be described as an amateurish hack to deal with this issue. Well, as my co-workers and I used to tell our boss in a previous job, all our code is “QDC – quick, dirty, or cheap. Pick any two.”

var twoLetterIsoLanguageName = CultureInfo.CurrentCulture.TwoLetterISOLanguageName;

var currentCultureName = CultureInfo.CurrentCulture.Name;

IEnumerable<VoiceInformation> voiceInfos = from voice in InstalledVoices.All select voice;

var localVoices = new List<VoiceInformation>();

// See if any voices match the current culture specifically
foreach (var voiceInfo in voiceInfos)
{
 if (voiceInfo.Language == currentCultureName)
 {
 localVoices.Add(voiceInfo);
 }

 localVoices =
 localVoices.OrderByDescending(v => v.Language).ThenByDescending(v => v.Gender).ToList();
}

// No matches? Go for the generic language instead
if (localVoices.Count < 1)
{
 foreach (var voiceInfo in voiceInfos)
 {
 var primaryLangStr = voiceInfo.Language.Split('-')[0];

 if (primaryLangStr == twoLetterIsoLanguageName)
 {
 localVoices.Add(voiceInfo);
 }

 localVoices =
 localVoices.OrderByDescending(v => v.Language).ThenByDescending(v => v.Gender).ToList();
 }
}

App.StorageSettings.TryGetValue("VoiceGender", out _voiceGender);

_speechSynthesizer.SetVoice(localVoices.ElementAt(_voiceGender));

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.

Working with JSON and C#–for Lazy Programmers

It just so happens that only a day ago I embarked on using Nokia’s HERE Places API in a new app. Then this morning saw a tweet by Lance McCarthy:

And, after checking out http://json2csharp.com/, realized I was much better off using its generated classes than what I had been doing, which was just grabbing what I needed into a relatively barebones class using a dynamic object.

Dynamics are great. But in this case, it’s so much better using the generated class. If it wasn’t for the json2csharp converter I wouldn’t bother because I don’t need all that is spewed out by the Places API…and it is verbose. But just getting Intellisense alone makes it pure gold. (Shout out to Lance and to Jonathan Keith, the creator/maintainer of the site).

Let’s look at some code comparisons. Creating a new object using the class is a bit more verbose, but certainly no more complicated:

var placeInfo = await Task.Factory.StartNew(() => JsonConvert.DeserializeObject<HerePlaceInfo>(responseStr), cancellationToken);

vs:

dynamic dynObject = await Task.Factory.StartNew(() => JObject.Parse(responseStr), cancellationToken);

But from then on it gets much nicer working with it:

var oTitle = placeInfo.related.publicTransport.href;

vs:

var dTitle = dynObject.related["public-transport"].href.Value;

The former provides Intellisense all the way (very useful for delving into nested JSON schemas) as well as a less complicated, shorter syntax.

You may have noticed in this particular example the “public-transport” key has a hyphen. That is something I wish the authors of the HERE Places API hadn’t done. The Json2Csharp converter flagged this since it couldn’t create a proper camelCase name. Even if it had, that wouldn’t do any good because it wouldn’t automatically match incoming JSON, leaving us with a null value.

To get around this, you can give the item a legal name and decorate it:

[JsonProperty(PropertyName = "public-transport")]
public PublicTransport publicTransport { get; set; }

You don’t have to do anything to the class that it references, e.g:

public class PublicTransport
{
public string title { get; set; }
public string href { get; set; }
public string type { get; set; }
}

Here’s another example, digging into the location data to mine the latitude and longitude:

var locationY = placeInfo.location.position[0];
var locationX = placeInfo.location.position[1];

var locPoint = new Point(locationX2, locationY2);

vs.

var locationY = (double) dynObject.location.position[0];
var locationX = (double) dynObject.location.position[1];

var locPoint = new Point(locationX, locationY);

And if you still aren’t convinced, consider that with a dynamic you can’t use LINQ (at least not easily…and I’ll leave that to others):

var categories2 = placeInfo.categories.Select(category => category.title).ToList();

vs:

var categories = new List<string>();

var catArray = dynObject.categories;

foreach (var category in catArray)
{
categories.Add(category.title.Value);
}

If the JSON2Csharp class seems verbose, keep in mind you can comment out or delete the parts you won’t need. That won’t prevent JSON.NET from populating the object instance.

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.