Colin's Journal: A place for thoughts about politics, software, and daily life.
Owlauth allows users to register a device (e.g. a phone) and then use this device to confirm their identify when logging into a website or application. For this to work the Owlauth app running on the phone needs to be able to receive push notifications of authentication requests. There are many centralised ways to push notifications to a phone, but as each domain owner can run their own Owlauth server, a centralised solution isn’t a good fit.
By taking advantage of Go’s cheap handling of concurrent processing with Goroutines, a simple HTTP based push approach can be used. Clients connect to the server:
The server returns before the Keep Alive timeout, which means that the client will reuse the same TCP (and SSL) session as for the first request. This makes this timeout and GET operation an effective ping that proves the connection is still established. If the TCP connection becomes invalid, the client’s HTTP library will open a new connection to the server, giving the desired reconnect behaviour.
The server implementation in Go is straightforward:
var requestedEtag string requestedEtag = r.Header.Get("If-None-Match") authChannel := reqStore.RegisterListener(dev.DeviceOwner) defer reqStore.UnregisterListener(dev.DeviceOwner, authChannel) clientGone := w.(http.CloseNotifier).CloseNotify() var request *reqdb.PendingRequests timeout := time.NewTimer(DeviceRequestGetTimeout) for { select { case req := <-authChannel: if req.GetEtag() != requestedEtag { request = &req // Return the ETag w.Header().Add("ETag", req.GetEtag()) return request, nil } // Just loop and try again. case <-clientGone: // Nothing to be done - just return log.Printf("Device gone - returning\n") w.Header().Add("ETag", requestedEtag) return nil, nil case <-timeout.C: log.Printf("Device request get timeout reached.\n") w.Header().Add("ETag", requestedEtag) return nil, nil } }
The reqStore object keeps track of outstanding authorisation requests and provides the details on a channel to all registered clients that are sat waiting in this GET.
The only other element of the equation on the client side is adopting a suitable retry strategy when http connections are not working. For desktops that could be just a simple back-off to a few seconds sleep. For the Android client it needs to taken into account the current network state to avoid excessive battery drain.
I’ve now got a basic version of this working on my phone. I’ll run it for a while and see how much battery impact it has.
Passwords on websites and in apps are the bane of internet usage. Much has been written (recently in TechCrunch – Kill The Password) on how painful they are to generate and remember. Password managers help with the challenge, but are a cumbersome band aid.
When building a website application, adding username and passwords is also painful, requiring extensive work to get working well and securely. So, what are the alternatives? There are some good ideas out there, but they tend to be complicated (OpenID Connect), or put large identity providers in a special position (Fido, OpenID Connect) or are centralized and cost money (e.g. Clef).
I think it’s possible to build a simple, distributed, secure authentication mechanism that allows users to login to sites without generating passwords. The vision is that a user can authenticate themselves easily:
I’ve been experimenting with how this could be done, documenting the specification on an Owlauth Github page, and writing an authentication server in Go that implements the specification. It’s not done yet – the current code sends email to the user with a link rather than a notification to a phone – but it’s close enough that it proves it can work.
In addition to the specification, I’ve also got a test application running (A larder app for tracking food best before dates) that authenticates using this method.
The challenge now is how to move this forward. Finishing the implementation to allow device based authentication is straightforward (I’ve got most of the code done), but it’s of no use if there isn’t a community of developers interested in deploying it.
The full list of my published Software
Email: colin at owlfish.com