Say you want to build a very cool application that allows a user to write posts on a website about their lunch and have their friends read it. You’re diligent and focused so you want to build out your core functionality before worrying about frills like “user authentication”. But you’re also wise, so you know that auth shouldn’t be an afterthought. How do you go about doing this?

Let’s take the POST /posts endpoint, where a user will submit their food pics to post them. You can’t just build this endpoint without any regard to who the authenticated user is, because it’s not enough to just know the user is authenticated, you also need to know exactly who is authenticated so that you know which timeline to update. If the endpoint were more complex you might also need to know other information about the user - their profile data, permissions assigned to them, etc.

To accomplish this, you should design a schema that represents the user’s session. That could look like whatever you want and whatever is appropriate for your application1. Mine will look like this:

{
	"user_id": "12345",
	"user": { /* your user representation here */ },
	"scopes": ['post.create'],
	"plan": "premium"
}

Now, I did that suboptimally so that I could point out something you should be careful of. My session object has a scopes property. Scopes are a Thing in a variety of authentication schemes, and when designing your session representation, you might be tempted to create one that very closely resembles the format for the specific authentication scheme that you chose for your application. In general, this is a bad idea. Differing terminology or definitions between authentication schemes will create confusion if in the future you ever need to switch schemes, or support more than one simultaneously. Developer experience is another concern. What’s a “scope”? That term may not be familiar to everybody, so you might choose a more generic label like permissions instead.

The problem here would be more obvious if you designed it at first as essentially a decoded version of your token scheme, then tried to introduce a second. You’d be forced to map the second token scheme onto the first, which is less than ideal. In this case scopes isn’t an awful label and the rest of my object is fairly generic, so I’ll leave it as is. Ultimately you can always “learn from your mistakes” and “update your code later” so it’s not worth stressing out too much about this. You can’t really know the answers until you’ve worked with a variety of schemes anyway (or read somebody who has done) and unfortunately for y’all (and for myself) I too lack that experience.

So I’ll call it scopes. I’m sure it’ll be fine.

Now that you have your session representation, you need a way to access it from your request handler. This… may be easier said than done. I am wholly unfamiliar with web development in statically typed languages, so I don’t know how common or easy it is to pass this kind of custom data. This feels like a basic desire so I’d hope it’s widely supported but I haven’t looked into it so I won’t assume. I’ll update this later if I have time to dig into a few different platforms. For now I’ll talk about JavaScript since it’s what I know.

Most (or all?) NodeJS web frameworks enable you to attach one or more request handlers to a route. The handlers are chained, and each handler is usually responsible for something discrete. One of the handlers (usually the last or second to last) is the actual handler for the route - the one that performs the specific business logic for that endpoint. The other handlers could be error handlers, authentication handlers, validation handlers, cache handlers, or any other functionality you might want to be able to reuse. The request can be intercepted and modified at any point along the way. The generic, reusable handlers are sometimes called middleware.

To put this in perspective, this is what this might look like in our super cool application:

Incoming request -> Auth handler -> Validation handler -> Route handler -> Response

We have two middlewares that run before our route handler. First we check whether the user is allowed to make this request at all. If not, we can respond early with a 401 or 403 error. If they are allowed, we’ll make sure the request is well-formed, and if it is we’ll handle the request by posting the status.

In NodeJS, I’d have my auth handler validate my token - either a cookie or a header - then pull all the information in the session object… somehow. If the token is stateful it will need to do lookups, otherwise it can decode the token itelf to populate the object. Either way, it will create the session object and just stick it right on the request itself req.session = {/*...*/} so that the route handler can access it later in the chain.

By following this pattern, you can isolate your business logic from your authentication implementation, using the session representation as the anchor2. With a properly-designed endpoint, we can simply add authentication on top as a layer.

This is the high-level explanation of how to do this. I’ll write a followup later showing an implementation to make it concrete.

  1. This seems like a good candidate for standardization now that I think about it. We can come up with a list of the most used auth schemes and (I’d bet) come up with a reasonably common model for each. XKCD standards meme etc etc blahblah. 

  2. I talk a lot about “anchors” in architecture. These are the pivot points that you define and are strict about in order to make the rest of your system modular and fungible. These are usually message contracts (maybe always but I want to think about it before I commit).