Playing with FIDO U2F
February 12, 2018

I expect you’re wondering what I’ve been up to. I don’t blame you, I’ve been wondering too.

In order that we can all sleep easy at night, I think I’m going to blog a bit of a developer diary.

I’m not sure I’ll manage a post every day, but I’ll try to keep a regular commentary.

In all seriousness I don’t expect it to be of great interest to anyone else, but in the past I’ve found it a useful discipline to keep a log of what I’ve been doing each day, and I may as well do it here.

Since finishing with Sketch I’ve been playing with a few very small new projects, but I’ve also spent a lot of time catching up on a large backlog of boring admin tasks.

I’ve no doubt that I’ll talk about some of my own projects in the future, but actually the thing I’ve been working on most over the last couple of weeks is the open source project Safari-FIDO-U2F.

I got interested in the idea of using hardware keys for authentication a year or so ago, and bought a couple of cheap ones to play around with.

Having done so I discovered that there’s no native support for them in Safari! Luckily there was a plugin project on Github that looked like it might do the trick.

I gave it a go, and it didn’t really work, but I decided to rummage around a bit in the code, and came up with one or two minor suggestions which I submitted as PRs.

The original developer got in touch and said words to the effect of “thanks very much, but I’m afraid I’m not really maintaining it any more as I no longer use OS X” for work.

The project appealed to me, so I decided that I’d keep hacking away at it anyway, and after a bit of back-and-forth I sort of ended up inheriting it.

I think what attracted me most, other than the chance to get the keys working, was just that it was a really small codebase, and I figured that even with my very limited free time, I might be able to actually help.

So last year I tinkered with it every now and then, but that limited free time thing made it hard to do much.

It also turned out to be quite a specialised domain, and although there wasn’t much code, it was quite gnarly. FIDO U2F support in general is at a pretty early stage, and only really works out of the box on Chrome. This means that sites which support it at all sometimes assume that if you’re not using Chrome, there’s no point bothering. They also sometimes make assumptions based on the Google/Chrome implementation, which the Safari plugin has to try to play along with.

The architecture of Safari app extensions in general is a bit messy anyway, mostly because of security considerations. The extension is written in Swift, but also injects javascript into each page. It’s the javascript bit that client pages talk to, and it bounces messages over to the Swift bit to do the heavy lifting, which in turn has to ping the responses back to the javascript side. It’s actually worse than that as there are two javascript components, with one acting as a bridge, doing the initial injection and then passing messages to and fro. Safari talks to the native code via XPC, and the extension is actually embedded in its own application bundle (the application doesn’t have to be running, and doesn’t talk to the extension even when it is running). This is all a bit of debugging nightmare, as anyone who’s ever done any sort of cross-process or plugin development can probably imagine. It is possible to symbolically debug both sides, but it’s not easy. Especially when you have no unit tests on either side - which the code I inherited didn’t (that’s not a criticism, the original project was a quick hack and awesome in that it paved the way and showed how to do the actual hardware bit).

Because of all this, not a lot happened to it in 2017, but even with very limited input from me, a few people showed a bit of interest in using it, and I still quite wanted to be able to use it myself. So when I had some free time this year, I decided I’d take another look, and I’ve spent a few days over the last couple of weeks doing quite a bit of rewriting.

It’s still not perfect, but it is now starting to actually work. Most critically, I can use it log into Github with a hardware key, which was my original use case.

I’ve pretty much rewritten all the original code, on both the Swift and JS sides. I’ve also added unit tests to both sides (using xctest for the Swift, and Jest for the javascript). It’s given me the excuse to play with Travis-CI too, and I’ve got that set up now to run the tests and keep me honest.

There’s probably still quite a bit of cleanup I could do. I’m no Javascript expert, despite finding myself having to do quite a lot of it on Sketch, since our plugin architecture relied on it. Come to that, I’m no Swift expert either, since Sketch was a pretty mature codebase and basically still Objective-C.

I won’t go into any more detail here about the actual code. Take a look at the Github project if you’re interested, or ping me.

It’s been a fun little project, and I expect I’ll keep tinkering with it for a while, though I suspect it has a limited lifespan.

Ultimately I imagine that either U2F keys will take off, in which case support will get baked into Safari itself and this plugin will become obsolete, or someone will come up with a better mechanism for hardware two-factor authentication, and U2F will slide off into obscurity, taking the plugin with it :)