By this point today I was hoping to have released a new version of Rogallo, complete with client certificate support. It is more or less all there and ready to go, but I ran into a small problem, something which confused me.
You see, according to the documentation for the Gemini Protocol, when there's a request by a capsule for a client certificate, that certificate should be scoped to the host, port and path and all paths below it. So that means that if example.com/foo causes a certificate to be requested, it's good for example.com/foo and example.com/foo/bar, but it isn't valid for example.com/other.
Makes sense.
The problem I ran into pretty quickly, with my implementation of this in Wasat and Rogallo, was this: I hit a site (a microblogging site of sorts) that had a joining page at example.com/join. Once you joined up and set your user name, you'd normally land at example.com/me. They're sibling paths and so should not use the same certificate. However, this was done via redirection, so I did some work to "clone" a certificate when there's a redirection.
But then it got more complicated. The site also lets you follow other people. This means that if you visit example.com/other-user you should also still have the client certificate in place so the capsule knows who you are (because client certificates are also, in effect, session cookies, as I understand it), so you can perform the follow. Again, this is a sibling path, and there's no redirection, so the certificate is no good because, at this point, it's scoped to example.com/join and example.com/me.
Meanwhile: testing this with Lagrange, it had no such problem whatsoever. How was it getting around this issue? Was I doing something wrong? Was I misreading the specification for the protocol? Was Lagrange being a bit more relaxed about its certificate scope?
After doing some digging, it would seem that it's the latter. It looks like it, and perhaps other clients, take a pragmatic approach to certificate scopes and generally scope them to the host and port alone, ignoring the path (in the case of Lagrange it seems to sort of actually divorce the certificates from the URIs anyway, treating certificates more as identities you can associate with any capsule, etc).
Given this, at least for now, I'm going to take that approach. Any time a certificate needs to be generated in Rogallo, I'm going to give the user the option (on by default) to scope the certificate to the whole host/port combination. Later on I might add the ability to fully manage certificates (right now that can be done by editing the certificates file in the data directory, but a proper UI for it would be nice).
Which brings me to this release of Wasat. v0.4.0 adds some extra functionality to GeminiURI that allows changing and removing individual parts of the URI. There's a new replace method that can be used to create a clone of a URI with various parts changed. Also, if you just want to change one specific part or simply prefer method chaining approaches, I've also added more with_ methods similar to the pre-existing with_query method, so now there's also with_host, with_port and with_path.
With these in place I can go back to Rogallo and carry on with the last bits of work I want to do on client certificate support, with Wasat making it easy for me to clone up and chop and change URIs to suit the scoping requirements.
Have a comment or query about this post? Feel free to drop me a line about it.