In my post Doing One Thing With Microservices, I gave the example of handling JSON Web Token verification in a separate service, so the ASP.NET 5 or Node.js/Express middleware consumes the service as part of the authentication process.
I had some feedback in the comments and on Twitter where people were questioning the need for a separate service to handle this stuff, so I’d like to address this in more detail.
The Purist response
There is, of course, the microservice purist/zealot argument that we need to start deconstructing our applications like this anyway, and that microservices are the new package/module/library, but there are also more compelling reasons than that.
The Pragmatist response
My project is mostly written in C# and ASP.NET 5, but a couple of things are done in Node, and I may very well factor certain other things out into Python, so I can use some of the excellent libraries that are available there, or to Rust or another native-compilation language if I need some really fast, native processing of data.
However this goes, these services are all exposed directly to the HTML application, using CORS to allow requests across sub-domains. So each of them has to handle the JWT verification themselves, which means finding a library for each platform/language, or writing one myself if none exist.
Using a separate, standalone service means I can use one library to handle the verification, in whichever platform/language provides the best performance for that particular task.
The Strategist response
(Strategist may not be the best word, but I can’t think of a better one right now for "someone who plans for the future".)
Security is a big issue, and the secure storage and handling of secrets is an area that is seeing a lot of new development lately. One way of managing your secrets is to use a Key Vault, such as Azure Key Vault.
Azure Key Vault actually provides an API for signing and verifying digests using a private key that is held securely within the vault, and never needs to be retrieved/downloaded to a less secure environment. So, in production, I might choose to use that as my method of handling JWT verification. There is a .NET SDK, and a package for Node.js, so I could consume those from my projects, but then I’m pulling in multiple dependencies and duplicating the code that consumes that service across the different platforms. Also, as far as I can tell, the .NET SDK for Key Vault doesn’t support .NET Core yet, so I’d have to run everything on Mono in my Linux/Docker stack, which incurs a fair amount of overhead. And for Python and other languages, there are no high-level packages for working with Key Vault, so I have to use the REST API.
Factoring the JWT handling out into a microservice means I can write it once, in Node.js, using Microsoft’s NPM package. The microservice exposes two endpoints:
/sign, which is consumed by the login microsite, and
/verify, which is consumed by all the other services.
I can also have a simple stub image on my development machine without the external dependencies.
And if, in the future, I want to switch to a different Key Vault implementation, I can make that change without needing to recompile and redeploy potentially dozens of services. If I need to run services on a different cloud platform, I can create an alternate image for those deployments which uses that platform’s secure key storage service.
I hope that offers some acceptable explanation as to why I would extract something as "trivial" as JWT verification into a stand-alone service. As always, feedback in the comments or on Twitter is always appreciated.