sgo.to

Self-Issued OpenID Providers

These are my personal notes while reading about the SIOP spec.

TL;DR; SIOP is an extension to OIDC that allows your identity to be unbundled from your identity provider, portable across them and hence resilient to their unavailability (e.g. when they cease to exist).

In the typical OIDC flow, IDPs issue idtokens that are signed by the IDP for one of their own users:

{
// The IDP is the issuer.
"iss": "https://idp.example",
// And the sub is a local user of the IDP.
"sub": "0x8271AB18",
"name": "S. Goto",
}

The sub is only unique within the namespace of the iss. That means that, when the RP is constructing their user's table it needs to record both the iss as well as the sub and check both in order for the user to prove ownership of a specific user account.

i.e. it is not enough that you prove that you are a sub, because the same subject can co-occur in different issuers, so the RP needs to check for the pair <sub, iss>.

The problem, here, clearly, is that the user's access to their own account in the RP is tied to the existance of the issuer, the IDP.

But, what happens when your IDP goes out of business?

Spoiler alert: you lose access to your account, because only your IDP has access to its own private key that it has used to sign all of the user's accounts (e.g. so it can't even offer an export).

That's where SIOP comes in.

Self-Issued OPs

The key feature that Self-Issued OPs do differently than traditional OPs is that they issue idtokens using public/private keys of their users rather then of their services.

{
// The issuer is no longer the IDP ...
// "iss": "https://idp.example",
// ... but rather, self asserted:
"iss": "0x01FEB839",
// And the sub is no longer tied to the IDP ...
// "sub": "0x8271AB18",
// ... but rather, self asserted:
"sub": "0x01FEB839",
// Standard claims are also self asserted:
"name": "B. Russel"
}

That fundamentally changes how reliable the scheme is because both the iss and the sub are under the user's control.

Note that you can tell the difference between a SIOP issued idtoken to a non-SIOP issued idtoken by checking if the iss and the sub fields are the same.

What makes B Russel a special user is that he no longer depends on the IDP existing to prove ownership of their user's account in the RP, as opposed to S. Goto and J. Doe.

Now, the first question that I asked myself was: how in the world is the relying party going to trust something that is self-asserted?

The key insight to me here is that, when sub is a public key it becomes two important things:

  1. guaranteed to be unique and
  2. trivially verifiable if you have the corresponding private key

Ok, then, the second question I asked myself was: what happens when you lose access to your public/private keys?

It is obvious to me that users wouldn't be competent to manage their own public/private keys, but much like an IDP manages its own public/private keys, it can also manage the user's public/private keys with equal competence.

In addition to that, because the user controls their own public / private keys, the user can choose to have as many SIOP IDPs as it pleases, and see them come and go, while still having enough replication to be confident that their keys are reliably recoverable.

Which is kind of cute.

Now ... you must be thinking ... what about the other self asserted attributes? Sure, I can see how you can prove possession of a private key, but how can you prove that your name is "S. Goto" and not "J. Doe"? Or that your email is "foo@bar.com"?

Well, that's where another part of the SIOP scheme comes along, but I'm going to leave that for another time :)