Identity providers should facilitate service discovery

Problem: when you split things up into different applications, it requires more work from the user to connect their accounts.

For example, The Sample can add subscribers to your newsletter, regardless of what newsletter platform you’re using. If you use the Zapier integration, it’s not too inconvenient: you just hit the “Connect to Zapier” button; pretty easy:

Connecting to Ghost is a bit harder. Ghost can be hosted by anyone, so you have to put in the URL to the Ghost instance you’re using:

You do also have to put in an API key, but that could be more convenient if Ghost implemented OAuth. You’d still have to put in the URL, but after that you could click a “Connect to Ghost” button.

In general, this kind of flow–forcing the user to enter a URL–is necessary if you want to support integration with anyone via protocols (as opposed to integrating only with a fixed number of centralized services). Friction like this can add up. It’s probably not a big deal in the example I’ve shown above, which is sort-of a b2b context, but in a consumer context it would be nice if we could avoid having people fiddle around with URLs.

Anyway, so this seed of an idea I have is that people are already well accustomed to at least one form of decentralized integration–email–and maybe other services could piggy back off of that. Basically, your email provider could maintain a registry of services that you’ve previously connected to and which protocols those services implement. Any time you use your email address to authenticate with a new service, that service can ask your email provider “please give me the URL of a service that implements <some protocol>.” Then the new service can present the user with a “Connect to <some service>” button.

Here’s how this might look in the Ghost example above:

  1. When you set up your Ghost instance, you enter “hello@example.com” as your email address.
  2. The Ghost instance does a DNS lookup on example.com to see if it supports this “protocol registry” thing.
  3. If not: then Ghost goes with it’s normal authentication flow (e.g. asks you to choose a password, or sends an authentication link to your email address). The rest of these steps are ignored.
  4. But if example.com does support the protocol registry thing: then Ghost connects to your email provider via an oauth flow (i.e. in addition to providing a protocol registry, example.com may as well be an oauth identity provider as well). Ghost tells example.com “My URL is <some ghost url> and I implement the Ghost protocol (version y)”.
  5. Later on, you sign up for The Sample. You authenticate to The Sample the same way Ghost does in step 2.
  6. The Sample asks your email provider, “Has this person connected to any services which implement the Ghost protocol?”, to which your email provider says “why yes, it’s over at <some ghost url>”.
  7. Now The Sample can give you a nice little “Connect to Ghost” button, no manual URL entry required.

Again, this probably isn’t a huge deal in this specific example–but on the margin, the more seamless protocol-based integrations can be, the more people can justify building them into their products. I have a few potential use-cases for Yakread which perhaps I’ll write up later.

I guess I’ll at least mention the relation to Grand unified theory of how social media ought to work – at the end of the day, you don’t necessarily want users to have to jump between completely separate websites/apps whenever they want to switch between publishing, reading, or discussion. You’d like to provide a completely integrated, seamless thingy like <every single social media site>. The friction of connecting to external services is a barrier here, and would result in a bias towards services implementing their own functions for publishing, reading, and discussion.

That could still fit with the grand unified theory as long as those functions are still interchangeable: you can publish something with <some service>, but if you decide to instead publish it on <some other service>, it will still be just as visible etc. to people who read on <some service>.

But it does seem like it might be nice if that didn’t have to be the case! With Yakread, I might eventually like to let people write and publish blog posts. Ideally I’d just add a “write” tab (next to the existing “read” tab), with an editor and such. It’d be cool if I could completely outsource the implementation of that to another service (like Platypub) instead of re-implementing the same blogging features that have already been built elsewhere.

OK, well… maybe that’s not a great example, because I could just throw in a “connect to platypub” button which integrates with a centralized service (e.g. at platypub.com). Maybe even have Platypub’s API support creating new users, so the “connect to platypub” thing is unnecessary–when you create a Yakread account, behind the scenes it also creates a platypub account. (And if you already have a platypub account, you can go into the settings and switch/merge). And if you want to use something other than the central platypub instance, you can… go into settings and paste in a URL. :person_shrugging:.

Maybe this would be more useful for Cross-platform RSS recommendations. Say you want to make subscribing to a newsletter via RSS just as convenient as subscribing via email, and you want to support whatever RSS reader the subscriber happens to use. When the person puts in their email address, you could contact their email provider and ask what RSS reader they use, then pass the RSS/OPML file along to it.

Anyway! I’ll probably come back to this if/when I’m implementing something where this would be useful.

Here’s another take on this, thinking along the lines of We need user-centric data.

Identity providers should provide shared storage which 3rd party services can use to communicate. (See the dns lookup thing in the previous post: if your email address is hello@example.com, then any service you sign up to with that address can check to see if your identity provider–example.com–supports this shared storage thing).

example.com could provide an API for reading, writing, and listening to changes on this shared storage. when you make an app, instead of writing a bunch API integrations for services you want to integrate with, you just use the shared storage. if you use a data schema that’s recognized by other services, then they can interop with your app simply by using the shared storage.

some advantages:

  • integrations become data-oriented (in the Clojurey/functional programming sense of the word–you operate on a few standard data structures rather than a bunch of different mini languages). 3rd party services operate on those data structures via a single shared language (example.com’s API, which btw should be a standardized protocol). There is still the significant work of figuring out what your schemas should be, but at least there’s not a bunch of accidental complexity on top of that. I think this would significantly reduce the amount of effort it takes to write integrations.

  • schemas don’t have to be tied to a specific app. schemas can be used as protocols. E.g. you could have a schema for “RSS subscription”. your rss reader can create rss subscriptions in the shared storage, and then if you E.g. switch to a different rss reader, it will already have access to all your subscriptions. (btw this would make it possible for rss feeds to have the exact same signup flow as email newsletters).

I wonder if you could package up common functionality into plugins. E.g. take the RSS reader example. say you’ve signed up for two different rss readers. they both need the RSS feeds to be polled, but they don’t both have to be the one to do it. could you have a plugin of some sort which contains the RSS polling stuff? both rss readers could somehow tell example.com that they depend on that plugin. if it’s not already installed (whatever that means), then example.com could install it. so when you’re making your rss reader, you don’t have to reimplement functionality that’s already been done a million times; instead you focus on the distinctive features.

i have thought very little about how permissions will work. this might be difficult. you’d do oauth style permissions, but where do the available permissions come from? example.com can’t define them since it just provides a generic data store. the schemas are all defined by the 3rd party services. so the 3rd party services must also somehow provide the permission definitions. (It would be easy to give all-or-nothing access with read-only and read-write levels; it’s finer-grained stuff that would be harder.)

This also needs to have a good story for users who aren’t using one of these special identity providers. e.g. say you sign up to a service with a gmail.com address. Maybe that service could integrate with a “default special identity provider.” it could create an account for you. From the perspective of the identity provider, the account would be authenticated as something like “user 12345 from service A”, not “hello@gmail.com” or whatever. or something like that. If you do later signup for a special identity service (need to figure out a name for this), there should be a way to migrate your old auto-created account.

Basically we want all this to happen without users needing to know that anything different from what they’re used to is happening. e.g. say you sign up for RSS Reader A and make some subscriptions, using your “hello@example.com” email address (which as far as you’re aware is just a plain old email account). Then you sign up for RSS Reader B with the same address. When you sign up, example.com shows you a screen saying “give RSS Reader B permission to see your subscriptions from RSS Reader A?” (or something like that). You say “yes”, and then you get redirected back to RSS Reader B, and all your subscriptions are magically there. No need to download an OPML file. You wouldn’t even need to know what RSS is.

If you’re making an app that doesn’t need any back-end functionality other than a CRUD data store, then this might be all you need–your app could be frontend only.

Possible way to get this started (whether as a startup or as an open source project): make an authentication service kind of like magic.link (I.e. “sign in by clicking a link in your email” without having to code it yourself–though it looks like they’re now focusing specifically on web3, so that might not be clear from their landing page). I think that would actually be useful in its own right; maybe I’ll write down more thoughts about that later. expand it into a backend-as-a-service offering. the crud data store would come next. after that, add the plugin system. write a bunch of plugins, which developers can use by simply reading/writing data to the crud data store. kinda like how in firebase you can send an email by creating a document. basically make it so people can create apps with tons of integrations easily, without having to write the integrations themselves.

and structure it in a way so that end users who sign up on any site that uses this can get direct access to their data, merge it to their main account as discussed, etc.