Handling Go: An Auth Design Pattern

Golang is one of my favorite languages. Security is important to me and Go has made a lot of novel improvements to application security. The language has several features designed to help developers write good code and make good security decisions. Go can't always hold your hand though, and a design pattern to keep authenticated API endpoints protected and well written is something that I've seen lots of applications do incorrectly.

Here's what an authenticated API endpoint might look like. For my examples I'll be using the Gorilla Sessions Library since it's familiar and secure.

This is a small amount of code and looks okay, but we can do better. A big deficiency of this design is each API endpoint is required to handle authentication itself which leads to bugs and inconsistency. Changing the authentication flow, or how authentication is performed must be made for each API endpoint.

The Solution - Authenticated

The solution to the problems with the bad solution is to use a ServeMux*.

By nesting a mux for authenticated API endpoints inside of a mux that handles authentication we keep all the authentication code in one place and all authenticated API endpoints are handled consistently. Here's what it looks like.

This is a much better solution than requiring each API endpoint to fend for itself.

The Complete Solution - Now With Less Authentication.

This design also provides a nice place for unauthenticated API endpoints that will live peacefull alongside their authenticated counter-parts. Instead of setting the status code to 401 (http.StatusUnauthorized) and returning, unauthenticated API endpoints can live inside of a third mux. The code would look like this, instead.

What Have We Learned

Lots of people are writing their go code too fast and causing a lot of code duplication and inconsistency issues because of it. Taking a little bit of time to architect a more elegant solution saves a lot of headache in the long run.

* - Gorilla, the group that made the session library that is used in this blog post also has a mux package that is really great. I didn't use that here.

ejj, Jan 2016