Cookie Authentication using Scalatra and JWTs

As part of my work with Arcadia, I've built a Rails application that added a cookie that contains a JWT (pronounced jot). Great! That was fairly simple. Then I had to go over to our Scala application and get it to accept the JWT as identification. Right now, we were keeping it pretty simple and we only care if it's valid. This post will cover what I think is the simplest way to do that, from start to finish. Or you can skip all that and just go look at the full gist.

We want to start off with the JWT parsing. And before we add the code to actually do that, let's add some tests! I decided to use the JWT Scala library and, in particular, jwt-core. It had, in my opinion, the most easy-to-understand documentation so I could indeed RTFM and get my work done. Since I didn't need to add encoding in the actual application (the tokens would be encoded in another application), I added a quick line to encode a token within the tests.

Now that I have my tests, let's add the actual code to decode the JWT! Thanks to JWT Scala, this is pretty simple! The real secret sauce is in this line: userTokenData = parse(decoded).extract[Token].data. That does a lot of heavy lifting! decoded is just a string and parse turns it into this Jvalue object thanks to json4s, but that object is a bit hard to work with. However, I can extract it out to my case class, Token, which is downright magical. If it doesn't include all the fields that I have in Token, it will produce an error. Perfect!

Next I need a reusable Authentication object. This wasn't too bad because I found out that HttpServletRequest has a method called getCookies which... returns the cookies. Excellent. I'm sure this looks weird as an Either, but in this case I really did want Some or None because I didn't care about returning the error to the actual user. I did want to log it though, hence the liberal use of println.

Last, but definitely not least, I need a servlet. Well... tests for the servlet, then the servlet 😛. This is where I actually ran into trouble because I wasn't sure how to pass cookies to the get request in a test. With some help from my boss, we found out that get takes a headers param and you can pass a cookie if it looks like this: headers = Map("Cookie" -> cookie_value). To be honest, it required a bit of trial and error and I'm still trying to figure out exactly what values are being passed.

Screen Shot 2018-05-02 at 11.33.45 AM.png

And finally... my servlet! Short and sweet.

Getting Started With Play After Working In Rails

I've now been using Scala since November (so a little over 4 months) and Play since January (exactly two months today). When I first started writing this application, I was brand new to Scala. My boss recommended Scalatra since he had some experience. Since I had none, I agreed and got started. I learn by example, so I first went through and found some projects that I could look at and base my project off. With Rails, this was easy. The Rails Guides are FANTASTIC (I miss them so much). With Scalatra, this was much more challenging. I made some progress, but then I came to a screeching halt, which caused my boss to post to Reddit asking for suggestions. Lemme pull out some of my favorite comments:

On stack overflow there are around ~250 questions tagged with scalatra. There are around 15k play framework related questions. You're pretty much on your own if you go scalatra.
Akka HTTP you pretty much have to have a PhD to understand.
Play lacks a coherent, functional API, documentation for a good 60% of it, and completely lacks the composability and ease of use of alternative frameworks like http4s. Most of these problems with Play are due to poor planning, and being a Lightbend technology which is contorted to work with Akka(and akka-http), yet another poor Lightbend tech. It's a pervasive rot in the community, just like Akka.

GREEEAAAAAAATTTTT. Anyway, we decided to try Play It has documentation (the bar, it is low), at least one book written about it, and some decent templates. I migrated my project over to Play and got going. One of the major differences I noticed between Play and Rails is that Play is not very opinionated. In general, if you look at a Rails project, everything is generally in the same place. Pretty much everyone uses ActiveRecord and the RDMS you choose doesn't really matter. With pretty much any Rails project, you can initialize the database with rake db:create. This is not the case for Play. As far as I can tell, you have to create the database and then Play will run evolutions (migrations). The real problem I have is that there also is no standard. Slick is very popular, but we decided to use the newer kid in class, Quill. And I couldn't find a single example of someone using Play 2.6, Quill, and PostgreSQL. And Play 2.6 is a breaking release from Play 2.5. I found one template that used Play 2.5, Quill, and PostgreSQL, but it broke when I upgraded to Play 2.6. Right now I'm having some database connectivity issues, but I'm hoping to resolve those soon. As soon as I get the app working, I'm going to create a template so hopefully, others won't have as hard of a time as I have.

Overall, I sorta wish I was still working in Rails? I love the simplicity of Ruby and how easy Rails makes it to get a decent CRUD app up and running. It definitely would have only taken me one week to make this app in Rails and it's taken four months (and counting) in Scala.