Friday, January 24, 2014

JSON Web Token (JWT) with Simple.Web - Part 2 (Cleanup)

As I am trying to learn more and more about this F# thing and functional programming, in general, I realized that there was a way to cleanup my code from last post to make it more readable. By taking a hint from Scott Wlaschin's post on Railway Oriented Programming, I realized I could pull a lot of the pattern matching out of my code (where it makes sense) and move it into a bind function. Seeing it in my code reminded me a lot of factoring out common terms in math. In this case, we're factoring out the initial check of Some/None.

(As an aside, Scott's website F# for Fun and Profit is a fountain of knowledge and is worth spending a lot of time studying.)

So, we need a function that will do the Some/None checking for us and, since this is the common name everybody uses, we'll call it bind:

Edit: Thanks to Liam McLennan for pointing out that Option.bind can (should) be used instead of writing our own. (Great to have others reviewing my thoughts and it is much appreciated!)

This function takes a function and an Option<'a> as inputs. If the Option<'a> is Some, we take the value of it and bind it to the function f. If the Option<'a> is None, we just return None and our function f is never called.

I also like the infix operator that Scott uses and decided to use the same one for this version of bind. I'm keeping it all in the same module since it's specific to Option<'a> and fairly trivial to write out where it is needed. I'm sure in a larger project it would make sense to wrap all of these common functions into a helper module, but it is small enough.

Edit: And this is how the infix operator can be written using Option.bind:

So we can compose two functions together and into a third. Our new function takes whatever the input is for f1 and binds the output from f1 to f2, thus returning whatever f2 returns. If f1 returns None, then f2 is never called and None is returned from our new function. As such, that means f2 needs to return Option<'a> to keep the signature legal.

But why?

Why would we introduce this to our code? Like when we factor out terms when solving a math problem, we are (usually) reducing the complexity of the problem. If we take one of our original functions, we see that we have to test Option<'a>.isSome and Option<'a>.isNone. Not only do we have to test this in this function, we have to test it in all of them. When we factor this out, we reduce the complexity of our code and reduce the amount of repetitive tests. So, one of our old function:

becomes

In fact, the more functions we have where we're checking for Some/None, the more valuable our bind function becomes.

Cleaned-up code

So here is the same code as the last post but with the new bind function and operator.

Suggestions?

I am always interested in hearing suggestions on how to make my code even better. Have something I could improve? Let me know!

Minor Update (26 Jan 2014)

I realized, after the fact, that I did not use the Simple.Web extension method to write the header. By forgetting this, the header would never actually get written because a NullReferenceException would be thrown. (The context.Response.Headers is initially null.) So, instead of instantiating the dictionary or anything crazy, we just use the extension method which takes care of everything for us. The good news is, this is actually much cleaner than the previous code.

Friday, January 17, 2014

JSON Web Token (JWT) with Simple.Web

I have been experimenting with Simple.Web and F# and trying to find different ways to exercise aspects of the framework. One of the things that is always annoying to me is writing authentication code. Fortunately, Simple.Web makes a distinction between how we authenticate users and how we track who is authenticated. I am not going to get into the Simple.Web handler that would actually authenticate the user, in this post, but am going to focus on how we can use JSON Web Tokens (JWT) in place of cookies and how we can leverage this within Simple.Web (using F# of course!).

Luckily for us, there are plenty of NuGet packages that implement JWT and so we can start there. I used the JWT package written by John Sheehan. It is open source and simple to use. I do have one nitpick about the package that I'll get to. (Read: I am too lazy at the moment to write my own solution since it's not really that hard.) So, we just need to "Install-Package JWT" to add it to our project.

JWT exposes some static methods wherein we pass our package we want serialized along with a "secret key" and we will receive a token we can pass back to the client. When the call comes back in, we pull the token out of the request headers and then can deserialize it. This is the annoyance with this package. We have two options to deserialize: JWT.JsonWebToken.Decode which returns a JSON string, or JWT.JsonWebToken.DecodeToObject which returns an object. My annoyance is that we get an object in the signature, but looking at the source code, the token we pass in is deserialized as a Dictionary. So, you have to cast to Dictionary to pull the values out. I would rather have this be a generic where I can specify what I want this to be deserialized into, or just make the signature Dictionary. As such, since I also use JSON.NET as my JSON serializer, I opted to have JWT return the JSON string and then delegated the object creation to JSON.NET. JSON.NET can also create our object without a public, default constructor which makes it nice to use with records. Enough of that, though.

Where's the code?

Moving onto the Simple.Web side of the house, we need to provide a Simple.Web.Authentication.IAuthenticationProvider which can be done in any IStartupTask. IAuthenticationProvider only has two methods on it, GetLoggedInUser and SetLoggedInUser. (This is how Simple.Web separates the idea of authenticating versus tracking the authentication.) GetLoggedInUser is given a Simple.Web.Http.IContext which contains references to the request and response objects. SetLoggedInUser also receives the context but also receives the IUser given from your authentication handler.

Since we need something to describe the types of things we're putting into our token, let's create a record to describe it.

So now we can track the user's id, name, and the expiration date of the token. We're using int64 here because it is easier to use DateTime.UtcNow.ToBinary() than it is to serialize the date. (At least this is the case with JWT which relies on JavaScriptSerializer.) I like the decomposition we can achieve with F#, so let's move now to write a little helper function that grabs the "Authorization" header from the request. We'll use Option to signal whether we find something or not.

Next, we need something that will pull the token out of the Authorization header, if it exists:

And then we need to turn that token into the Payload record we created above:

And, finally, let's take that Payload, if it exists, and turn it into an IUser if isn't expired.

Putting it all together

So now we can compose these functions and create our IAuthenticationProvider. One of my favorite things about F# is the ability to instantiate an interface without having to create a class. For such a simple interface, that works well here.

So this function takes in a "secret key" and returns a new IAuthenticationProvider. While I didn't cover it explicitly, the SetLoggedInUser should be simple enough to understand. All we need to do is tell Simple.Web to use it when a request needs to be authenticated. As I mentioned before, this can easily be done from an IStartupTask:

Authentication Module in Entirety

Edit: I have cleaned-up the code a little bit. The changes can be found here.

Conclusion

In under 60 lines of code we can put together a rudimentary JWT solution for our Simple.Web applications. When I get a moment, I will toss this up on GitHub so if you might have some improvements you can share them.

Saturday, January 11, 2014

Simple.Web F# Project Template Updates

F# Runtime Update

Thanks, again, to Dan Mohl for sharing some changes made to the ASP.NET MVC/WebAPI templates that I was able to apply to the Simple.Web F# project template. I had been digging into the template to figure out how to get allow changing the target F# runtime when you use the template to create a project but was unsuccessful. Fortunately, part of what Dan shared was a way to fix this-which I don't think I would have been able to figure out on my own. So, that's the first change made to the template.

Changes for Simple.Web Handlers

When I first started working with Simple.Web and tried using it with F# I ran into issues that made me have to build my handlers like so:

[<UriTemplate("/")>]
type Index() as this =
    member __.Get() = Status 200

    interface IGet with
        member __.Get() = this.Get()

I wasn't too happy about having to have so much duplication and double dispatch back to a handler's own methods, but most everything else worked out nicely that I just kind of accepted it, got used to it, and moved on. Once I had my first pull request into the main repository, Ryan Riley had commented on the pull request and asked why I was doing this. I'm glad he asked because I didn't even think about it. Luckily, I ran a little test and was able to pull out the extra method call!

[<UriTemplate("/")>]
type Index() = // No more aliasing required
    interface IGet with
        member __.Get() = Status 200

That cuts the lines of code, and complexity, in half, which is a huge win for F#. Again, it is nice to have another set of eyes out there actively looking at my work to help make it better.

Changes for Simple.Web NuGet Packages

One of the things I wanted to fix in this template was the fact that a C# file was automatically inserted into the project. This was due to the fact that I took a dependency on the Simple.Web.AspNet package. Fortunately, all this package does is reference Fix and Fix.AspNet. Since I have those packages available, I was able to safely remove the Simple.Web.AspNet package and just reference the other two directly. No more C# file to delete!

Update: Just to be a bit more clear about the Simple.Web.AspNet C# file, it was the OwinSetup file that usually goes with the C# project. The F# version has been with the F# Simple.Web template from the start.

Thanks so much to everybody who has downloaded, used, and provided feedback on this template.