Almost every week I read online about how FaaS [Functions as a Service] or serverless is the future of cloud computing. The premise is simple - you write some piece of code and add a trigger point to it - and everything else such as deployment, metrics, scaling etc are all taken care of. I generally would avoid it for anything more than submitting forms from a frontend [probably why Node.js is almost always supported] or basic REST middleware anything more involved than that is pushing it.
Things like Lambdas or Cloud functions are great for what they are but you are constrained to the runtime environments that are supported. It would be great if I could deploy a docker container instead, which would give me a lot more flexibility. What sucks also is the cold startup time. If your function is not receiving traffic - it will scale down to zero and such you will pay a penalty for when the next request comes in. If you are putting a JVM based app this can be quite unbearable due to the warmup period during which response times are slower [which is lost every time the app scales down to 0].
A little while back, I read about fly.io on Hacker News and was quite intrigued. Three commands and your app is deployed. Think of fly.io as a CDN for your docker images. You can deploy your image, expose a port and fly will set up a DNS that routes to that port from 443 for you and it won’t scale down to 0 during low traffic periods.
// install flyctl
I wanted to try it out and see how easy it would be to run something like this. They also give $10/month service credit to allow for hobbyist devs to experiment with. I decided to deploy JWTs as a service on fly.
The stack is simple. Kotlin as the language. Vert.x as the framework. Auth0 JWT library to create and validate the JWTs. Jib to create the docker image and OpenJ9 as the JVM.
The base URL for this service is:
The two main routes are
POST /api/v1/token to generate a new token and
GET /api/v1/validate?token=<token> to validate the given token.
The POST request takes a JSON body in the following format
The API is quite forgiving around the body and has sane defaults as a fallback. If you do not want to open up Postman to make the POST request - you can also use the debug route which generates a JWT valid for 5 minutes from
Making the above request returns back
Paste the token in
jwt.io to see what the payload is. JWTs are signed but not encrypted [they can be] so you can see what has been added to them. Therefore, never add sensitive information such as passwords to the token.
To validate the above token we use the second route, which will return
If the token were to be manipulated with. let’s say by changing the subject, the validation will fail.
I timed myself on how long it took me to build and deploy the image and it was less than one minute - not too bad. The deploy steps were
mvn compile jib:dockerBuild
I am using the ID since I am using jib to create a docker image instead of a docker file. If you have a docker file it will pick it up automatically from the current directory.
Looking at the code that is running - it’s pretty straight forward.
// init vertx
The JSON body can be converted to a Kotlin data class in one line using
val generateTokenRequest = Json.decodeValue(it.body, GenerateToken::class.java)
This is how the token is created, signed and returned in the response.
val algorithm = Algorithm.HMAC256("very-private-secret-key")
When you are doing REST-style stuff and don’t have strict definitions like Protobuf - it can be tedious to do a lot of validations on the request that comes in. Thankfully, Vert.x provides out of the box support for validations using its Web API contract module. For the validate route, the token query param is required - and all I have to add is this one line validation handler that takes care of the entire thing.
val validationHandler = HTTPRequestValidationHandler.create().addQueryParam("token", ParameterType.GENERIC_STRING, true)
When verifying a JWT there can be exceptions thrown if it were invalid or expired. The goto way to deal with that would be try/catch. I still see Kotlin devs using try/catch like they are writing Java - but that feels very unnatural to the language. A better approach is to use
runCatching - something like the following
Start the server as following
The jib maven plugin super simple to add to your pom file - here is a snippet from mine
And there you go - a fully functioning JWT middleware deployed in almost no time. The full list of supported endpoints are:
Base URL: https://jwt-service.fly.dev/
Edit: The deploy is so fast and painless that I went back and added the link to this article on the base route at https://jwt-service.fly.dev/. Hmm, there is potential here.