All posts by Jon

Ah, the Suspense

Unless you’re going for pinpoint animation timings it’s really pretty straightforward to create timers on a web page…or so I thought. I threw one together – a simple countdown timer that would get passed a duration, a DIV in which to display the time, a formatter function to make the time pretty, and a callback. It worked well. That is, until I tried it on my Windows Phone and happened to exit the browser while the timer was running.

I came back to the test page and the timer picked up where it left off. In some situations, this would be fine. But in my use the timer is meant to be triggered (more or less) at the same time for a group of users (via SignalR). It would be bad if one user got a text message during a 5-minute session, suspended the browser temporarily to check it, and then got an additional 30 seconds or whatever to keep on entering items after the session ended.

Was this just a Windows Phone issue? Nope. I tried it on an iPhone 5S and had the same issue. It makes sense. Phones need to conserve power whenever possible so suspending running code in a browser tab when it’s invisible is logical. I fixed this issue by setting an initiated time, using Math.round(new Date().getTime() / 1000. Each time the timer interval is called (once per second) the current time is gotten (also in seconds) and then the difference is compared to the elapsed time. And, if necessary, the timer’s remaining time is adjusted (by subtracting the suspended time span from the overall duration).

I ran into another minor issue: Hitting the test button that triggered the timer again would result in multiple intervals running. I needed to clear the current interval first. In this case, I decided to store the current interval ID in the display element, using the jQuery data function. After all, it’s the element being affected by the code.

This is the sort of thing that might be papered over easily by manipulating the UI so the triggering mechanism, e.g. a button, can’t be used more than once. But baking this little fail-safe right into the code heads off any unanticipated uses down the road. For example, perhaps the timer might be reset every time a user guesses the correct answer in a game and moves on to another question.

Here’s the complete code for the timer:

See the Pen zxWwOM by Jon Nehring (@stonetip) on CodePen.

JQuery HTML5 custom attributes

I came across what looks to be a good solution to managing UI elements (visibility, opacity, etc.) without resorting to burying styles in an attached CSS file. With HTML5, you can use custom attributes prefaced with “data-”, e.g:

<h1 data-groups="foo, bar">I have a session code</h1>

<p data-groups="bar">Enter it here to join a session</p>

You can extract that data, for example:

<div id="divNewSession" data-groups="foo">
var groupData = $("#divNewSession").data("groups");

Which would generally only make sense with something specific, such as a the DIV in this example. But you could also act globally on various elements that all share a data attribute, such as making them all invisible. You can even differentiate with keyword searches or a wildcard (contains) search:

// Any element with a data-group attribute containing "foo" will be affected
$("*[data-groups*='foo']").css("background", "black");

// Any element with a data-group attribute only containing "bar" will be affected
$("*[data-groups='bar']").css("background", "red");

Note the * after groups in the first example. This will act on any element even if the data-groups attribute contains more than just “foo”. Also pay careful attention to the use of double vs. single quotes. IE and Chrome didn’t care, but Safari did.

I like this approach because:

  • It’s easy to see the relationship between an element and an attribute
  • The relationship isn’t buried in an external CSS file or deep within a pile of javascript code
  • It doesn’t clutter up a CSS file with miscellaneous styles used just to control temporary states, e.g:
    #divNewSession { visibility: collapse; }
  • It’s flexible. An element might be affected in one case, ignored in another.
  • Use of a custom attribute avoids confusion or collisions with any other code or namespaces

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

Towards More Positive Ratings and Useful Feedback

The developers of  the Circa News app recently posted an article describing how they’ve successfully increased positive ratings and directed user frustrations to feedback instead. Note, as they point out, there’s no way to do this without having a good app in the first place:

tl;dr: 1) Build a great app, 2) Don’t annoy your users, 3) Ask nicely, don’t beg

This is very personable:

circa_news_feedback

And a positive result:

 “The best part about the above experience is that for those users who are truly not enjoying their experience, they’re giving us their unfiltered feedback.”

I’ve placed buttons for both rating and feedback in the About or Info sections of my apps. The ratings have been good 4.5 stars on average, but light. I do get feedback via email from users asking for features or occasional fixes.

In either case, implementing something similar might trigger more of both – and in a way that doesn’t piss off the potentially favorable reviewer. It is a little sneaky to shunt displeased users off to feedback, but apps do live and die by ratings. If they want to, users can still find the rating button. It gives them a place to vent their frustrations and gives the developer a chance to redress the issues – a win for both.

Read more at https://medium.com/circa/the-right-way-to-ask-users-to-review-your-app-9a32fd604fca

Thanks to Barrett Golding (@hearvox) for pointing me to the article.

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.

Designing a Versatile Logo

Good logo design has always been hard. The number one characteristic of successful logos – ones that stand the test of time – is simplicity. The best example is GE’s logo, which was created in the 1890s and revamped somewhat in 2004:

It’s only gotten harder with the advent of digital media and mobile device screens of all resolutions. On the other hand, tools have gotten better and for those who aren’t artistically-inclined more resources, such as typefaces and icons, are readily available.

Recently, I decided to create a web and app-based service called NoteVote. Basically, if you hate sitting through long meetings, this will be a tool you’ll like. While it may seem odd, one thing I do whenever coining a new name is to test how it will lend itself to branding. Someone else might jump straight into coding but at heart I’m a UI/UX guy.
The first things that came to mind were to include elements such as a note icon and a thumbs up icon, as well as both a logotype (a logo including text) and a stand-alone logo (suitable for app icons, favicons or uses where space is constrained). I also looked through my typefaces and chose to use Banda (the regular weight is free), which is a friendly, clean and well-spaced design (the kind you’d invite your mother to see).  My first iteration was this:
notevote_initial
I sent this around to a few friends – people with varied backgrounds (sculptor, web/app developer, English/writing professor, grass-fed beef rancher and one of my favorite people, Chrysti the Wordsmith – to see what they thought.

The artist was the first to get back to me and his comment was, “I wish there was an alternative yay or nay for the thumb; Facebook has made us all sick of looking at that icon, but I see why you like it—its a clean logo.” So…a few more iterations:

notevote_iterations

There are things I like about these. Yet, aside from the over-used check mark, what they lacked was the humanistic element. Other logos I’ve designed that have worked well have at least suggested that, e.g:
infused
So it was back to the thumbs up. “Talk to the hand!” 🙂 And from there, tweaking various aspects of the design. One thing I wanted to be sure of is that the line weight of the artwork was exactly the same as the fontweight. In Illustrator, this is as easy as converting a character to outlines, selecting a leg, and copy/pasting it, then looking at the reported width:
notevote_n
I also wanted the note icon to look square – like a Post-It. (Never mind that bending the corner is usually associated more with a sheet icon. Sometimes rules are meant to be bent). I started with a square, created the bent corner, then made three significant alterations.
  1. Both logotype and standalone variations
  2. Joining the hand and note icons
  3. Removing the upper left-hand corner

Variations are necessary because, as mentioned, a logo needs to be able to accommodate a variety of branding uses. Joining elements marries the design elements into a cohesive whole. This serves to unite the cognitive concepts expressed in the logo as well as differentiate it from similar designs. Removing the corner was done to counterbalance the break above the n in the logotype variation and to suggest both speed and the notion that once the note-taking part is done it takes a backseat to voting on the best ideas.

Surprisingly, the second proved the most challenging. I had something in mind similar to approaches like this (although I dug this up just now, well after the fact):

postscript_peewee

My first attempts were like this:

notevote_join_1
And that would be fine. I found, however, after printing it out and looking at it on my phone that it didn’t feel quite right. So I did this and digitized the inner curve:
notevote_curve_digitized
That’s some high-tech shinola, there, resulting in:
notevote_join_2
Other considerations are noted here:
notevote_logo_annotated
Going with a single color and ensuring that the artwork is using it properly – i.e. no masks, mixed RGB/CMYK or other colors – means it is effortless to change it to accommodate light or dark backgrounds and to avoid color clashes. The SVG version is tiny and can be used just like this in a web page, meaning it will never be jaggy, regardless of page sizing or screen resolution. Who wants to create endless raster variations?
<img alt=”logosrc=”images/site/notevote_logo_blue.svgid=”headerLogo” />
I hope this helps you with design considerations. Feel free to direct questions my way via  or http://notevote.uservoice.com/ which is also where you can sign up for the NoteVote beta.

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

Cancelling Windows Phone SpeechSynthesizer under different conditions

While testing one of my apps I realized that long bits of speech were interfering with other sound effects in the app. Since they (unfortunately) can’t play simultaneously, I needed a way to cancel the speech sound if it exceeded three seconds. And, yes, this has a negative side-effect of abruptly cutting off mid-sentence. However, that’s mitigated by the same text appearing on screen.

I also need the Task to be cancelled externally if, for example, the user switches to another page or resets the app to the beginning. The following code is able to do both these things:

public async Task TextToSpeech(string text, CancellationToken externalCancellationToken)
{
 try
 {
 var internalCancellationTokenSource = new CancellationTokenSource();
 var internalCancellationToken = internalCancellationTokenSource.Token;

using (
 var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(internalCancellationToken,
 externalCancellationToken))
 {
 linkedCts.CancelAfter(3000);

var alreadyPlayed = false;

while (!linkedCts.IsCancellationRequested)
 {
 if (!alreadyPlayed)
 {
 _speechSynthesizer.SpeakTextAsync(text);

alreadyPlayed = true;
 }

if (linkedCts.Token.IsCancellationRequested)
 {
 _speechSynthesizer.CancelAll();
 }
 }
 }
 }
 catch (Exception err)
 {
 Debug.WriteLine(err.Message);
 }
}

There are a couple funky things to note: You’ll get a warning about the async modifier on the Task. Remove it and the app won’t compile because it will expect a return type. Why not use a void method? It wouldn’t be cancellable. The other is the use of the SpeechSynthesizer.CancelAll() method. You can set SpeechSynthesizer.SpeakTextAsync() to an IAsyncAction, e.g. “var task = _speechSynthesizer.SpeakTextAsync(text);” and do task.Cancel(). But this didn’t seem to have any effect.

So use the CancelAll method and be sure to wrap it in a try-catch block to head off the error it will throw.

Drawing an Anatomically Correct Directional Arrow

It’s far down the list of issues I’ve ever dealt with, yet the ubiquitous directional arrow has always bothered me a bit because the blades are too thick. This is because it is naively rendered using the same stroke width. I took a look at it and realized that the proper blade thickness should be based on the blades’ angle. This can be determined mathematically by taking the square root of the cosine, e.g.

clip_image001.gif

So a line that was 3 pixels wide becomes 2.53 pixels wide (3 x .840896). Here’s a schematic showing the construction steps (click or tap to embiggen):

arrow_drawing_schematic_4

The effect is less pronounced at shallow angles, more so at steeper angles (with a corresponding need for correction):

clip_image003.png

Update:

The morning after originally publishing this post, I saw a proper example of one of these arrows…on a North American Van Lines moving truck. Who woulda thunk? But a little analysis of the logo with an arrow overlaid that has blades at a 37.5° angle shows their designer was, uhm, pardon the pun, thinking along the same lines:

NorthAmericanVanLines

NorthAmericanVanLines2

It’s very close to fitting the formula.