So, I’ve started yet another web programming project, a generic authentication wrapper library for Python. Because I need something like this for Publ and just want to do it once.
The reason for doing this is that there are a lot of authentication standards out there, and it’s a constantly shifting target, and most of them are a pain in the butt for site builders to implement or for end users to use.
Originally I wanted to use IndieLogin as my authentication broker for Publ, but it turns out that it’s designed solely to support IndieAuth and RelMeAuth – but is purposefully not acting as a clearing-house for existing OAuth endpoints. Which is to say, if you want to authenticate with IndieLogin, you’re supposed to set up a profile page somewhere which either links to an IndieAuth endpoint or uses RelMeAuth links to direct to a well-known OAuth broker such as Github or Twitter.
Now, don’t get me wrong, I think IndieAuth is a fine protocol, and RelMeAuth has a lot of merit to it as well. However, the fact of the matter is that IndieAuth has basically no adoption just yet (aside from the enthusiasts who are developing this stuff), and supporting RelMeAuth requires the ability to set up a profile page which presents a technical barrier to the vast majority of Internet users. And, IndieLogin doesn’t support OpenID 1.x, which is considered a “dead” protocol despite still being pretty widely-supported. Chances are you have an OpenID 1.x provider already (even if you don’t know it), and even if you don’t, it’s very easy to get an OpenID 1.x identity on launchpad.net.
Federated Internet identity is pretty difficult to deal with right now. There are dozens of standards out there, and whenever some group comes along to fix it, they do it by making a new standard. This makes it an ever-shifting target, and most of the standards are, frankly, overly complex and are built upon mechanisms that aren’t user-centric. Right now most of them are built on top of OAuth which was not designed to provide federated identity – it instead provides central points of API access, which a lot of websites use as an identity key but users don’t realize just how much it gives access to things.
For example, if a website uses OAuth to support login via Twitter or Tumblr or Facebook, the website you’re logging into gets access to craptons of your private information, and often sneaks in permission to post to those services on your behalf without you knowing when or what. And, to make things worse, OAuth isn’t a universal standard for identity; instead, every single website that supports OAuth needs a separate set of API keys and a separate interface for getting the profile data. It’s not federated or decentralized, it’s just a bunch of separate points of failure. And it means that you can’t run your own OAuth identity provider and expect anyone else to support it.
Now, IndieAuth, OpenID Connect (which has nothing to do with OpenID 1.x, protocol-wise), and Mastodon all use OAuth plus WebFinger (in subtly different and incompatible ways) to support federated identity via OAuth, but they still have certain levels of protocol lock-in and their own tradeoffs. And they still don’t quite hit the sweet spot of what I need in Publ. (Also I have serious issues with how WebFinger was designed, but let’s not get into that right now, this is already enough of a ranty wall of text as it is.)
Anyway, what I’m trying to do with Authl is make it easier for Python-based websites to extensibly support a bunch of auth backends, and provide a much more uniform user experience. The idea being that it makes all logins look more or less like an OpenID login – the user provides a URL that represents who they are, and Authl selects the most appropriate login mechanism for that, based on the site’s configuration.
My preferred identity provider would be OpenID 1.x, because that is the easiest to deal with for a lot of reasons and, again, is quite pervasive. I also plan on implementing an email “magic link” authenticator. If I feel like it I’ll also do an OAuth one with versions for Twitter, Mastodon, and IndieAuth. Maybe RelMeAuth too since adding that wouldn’t be all that difficult, I don’t think.
If you build a site using Authl for authentication, you’ll still need to manage your own OAuth tokens for the various sites you want to support, but hopefully it will make managing the login flow for those things not so onerous. OAuth has a bunch of other challenges too though, so that’s kind of a low priority for me.
Someone could probably implement something like IndieLogin with a wider swath of support using Authl. That’s not my goal, personally; I don’t want to host an auth provider for the entire Internet. I just want to make it easier for me to set up an auth provider for my own website to suit my own needs for Publ.
That need being, “Hey, I posted a friends-only entry, and I want my friends to be able to see it without them needing to set up a fucking website to prove they are who they say they are.”
Maybe in the future, Dreamwidth and WordPress will support IndieAuth. But that’s not the present, and I’m trying to build stuff that I can use now, not in some theoretical perfect future.
And in the meantime, having the ability to support multiple authentication mechanisms in a flexible way means I won’t have to tear everything down and rebuild it when the next big thing comes along. I can just add another handler to Authl and keep on truckin'.
My main thing is not wanting to tie Publ to a specific set of identity providers, and I’m doing Authl as a separate library that Publ uses because I am absolutely sure that there is someone out there who wants something like this for their own Python web apps as well. (And I want to keep all of the UX under the control of the web app, not provide any sort of one-size-fits-all approach because I know better than to think I can provide a universal UX or URL scheme or whatever.)
The UX will be difficult to figure out; some have already pointed out to me that users have been trained to not care about/understand URLs at this point, which is unfortunate. I have made a very basic UI mockup for how it might work, though, which hopefully has a nice middle ground between flexibility and the so-called “NASCAR problem” (where you have a separate login button/badge/flow for every third-party provider). It is very much a work in progress, of course. And I know the terminology isn’t the be-all end-all of obviousness for all users, although it feels Good Enough for my usual audience.
And of course this is only to provide identity, and maybe some basic profile support as part of it. For now I’m just focusing on the identity URL itself. But I’m not trying to wrap all of the functionality that OAuth provides anyway.
There’s also a huge open question about how things like Atom feeds will work. I think I still need some authenticated Atom stuff because simply providing a persistent session is heckin' dangerous and I really don’t like the idea of magic Atom feed URLs because it 1. sucks for discovery and 2. sucks for privacy. Unfortunately, AutoAuth is pretty closely tied to IndieAuth, so while I could support that as part of supporting IndieAuth, I doubt anyone would actually be able to use it.
But I’d already pretty much settled on having my unauthenticated feeds include placeholder entries anyway (because it’s the least-bad compromise for the current state of feed readers), so maybe I don’t care so much. It’s something I can figure out Later.
- Discussion on IndieLogin.com
- My thoughts on how to add auth to Publ (focusing on the Publ side of things, rather than the auth mechanism itself, with a bit of a hand-wave around the protocol itself)
- My rationale for not going with IndieLogin/IndieAuth
- A frustrated Mastodon thread about the state of auth
- My scattered design docs for Authl, in particular how I envision actually using it from Flask (and therefore Publ)