End-user authentication for Go web applications

Published on March 16, 2014 by Matt Cottingham.

Follow @mattrco

A year ago, I was evaluating methods by which an end user could authenticate1 with our forum service, Microco.sm, which is written almost entirely in Go. Among the various options at the application level2 were:

Forums users are a privacy conscious bunch. In my experience, the intersection between the set of avid forum users and avid social network users is small.

In light of this, we chose Persona in part because it offered a good experience for users and developers, and didn't require an account with a social network. We've been happy with it, but I would hesitate to recommend it for new projects because I'm uncertain of the project's future4.

In any case, the landscape is now rather different. Various packages which provide authentication have surfaced, so along with more traditional methods like HTTP basic, there are many options for authentication.

This article is a work-in-progress which should serve as a branching point for your own research. Feel free to email or tweet suggestions. And thanks to everyone who replied to the original question.

OAuth

It's probably illuminating to start with OAuth(2), since it's so widespread.

Gomniauth is a package that supports multiple providers (Google, Github, Facebook, et. al.) and even integrates with a simple RESTful framework, Goweb.

Instead of building authentication right into your application, another approach is to use a reverse proxy. Bitly have created google_auth_proxy which you can use "in front of" your application to handle authentication.

If you want to look at example code, the Revel web framework provides examples for Twitter and Facebook OAuth integration.

There are some Oauth1.0a packages out there, too.

HTTP Basic

It looks like the web framework Martini supports HTTP basic auth. Similarly to if you implemented HTTP basic auth using the standard library, you'd need to handle storing passwords. The advantage here is that it is structured as middleware that can be swapped in or out when needed.

Update: I've been pointed to this package which implements HTTP basic auth with a storage backend (file or SQL database).

Hawk looks interesting (Go implementation) and comes from Eran Hammer who previously worked on the Oauth2 spec. You can think of it like HTTP basic auth, but with partial request verification. Instead of including a key with every request, it is used to calculate a request MAC that is included instead. There's a good introduction to Hawk here.

Cookie-based sessions

If you don't mind doing some of the plumbing yourself, the session management capability provided by the Gorilla web toolkit looks helpful. It's a great toolkit even if you don't make use of the sessions package.

Mozilla Persona

I think it's worth mentioning Persona, even with the recent changes. We've been using it for months in production with few issues. From our research it seems to be generally liked by end-users.

There are some examples of Go usage with Persona here.

One gripe I have with Persona is the "identity bridges" which will detect certain email providers (say, Gmail), and ask the user to log in to that account, meaning they don't have to enter a Persona password. I think this causes more confusion than the convenience it provides. The motive (email provider authenticates you) is understandable but it needs explaining to some users.


Disclaimer: security is your responsibility. I'm not responsible for security issues caused by implementing what is written here, or using any of the linked resources.

[1] Just authentication, no authorisation covered here. For simplicity, let's assume your application is the only one users need to authenticate with.
[2] Gateways certainly shouldn't be ruled out but are beyond the scope of this discussion.
[3] Not new at all if you count it as the evolution of BrowserID, but as a brand it was new. Apart from overloading the name "Persona" which was already used by Mozilla for customisable Firefox themes. Sigh...
[4] http://identity.mozilla.com/post/78873831485/transitioning-persona-to-community-ownership

Oauth logo by Chris Messina. Persona logo by Mozilla Contributors.