A next step for the new federated login mechanism?
FedCM
Implementing login in a secure and privacy-preserving way is very tricky. Ideally the browser would take an active role in the process; rather than just shuffling bytes back and forth, it should "know" that a login attempt is taking place, and take appropriate steps to ensure that the user is aware of what's going on, and - importantly - that they have consented to the web site becoming aware of their identity.
FedCM provides this browser mechanism, and efforts are being made to extend it to "open world" systems, with the first adopter being IndieAuth.
My experimental "open world" login system implements this, but there's a chicken-and-egg problem: servers won't implement it if there are no clients, and clients won't implement it if there are no servers. What are we to do?
ATProto
The most successful "open world" authentication system right now is BlueSky's OAuth for ATProto, which has about 36 million users and a rapidly growing number of clients including Roomy and Frontpage. It seems to me this would make an ideal candidate for further work on FedCM.
Since FedIAM supports both ATProto OAuth and FedCM, I've naturally started to think about what it would take to combine the two.
I'm not the only one thinking about this: link, link
FedCM for ATProto?
I'm going to skip over a lot of the technical background here and assume that readers are familiar with the basic protocols here:
For IndieAuth, FedCM replaces the authorization endpoint with a new flow for obtaining an authorization code. It looks roughly like this:
-
The client provides its client ID and a PKCE challenge. Importantly, this happens speculatively, before the client knows anything about the visiting user or about which auth server it will be talking to.
-
The browser handles all the interaction with the user. It knows which auth server(s) they might want to use, and communicates with them to choose the account they want to log in with. The authorization code is generated by the server and passed to the browser.
-
Finally the browser returns the auth code to the client. This is also the moment when the client learns which auth server is being used and what the user's ID is. The client can now continue the OAuth flow by requesting a token from the server's token endpoint - using the PKCE verifier to prove that it is the same client which started the flow.
Client ID and PKCE challenge
ATProto and IndieAuth both use Client ID Metadata Documents and PKCE S256 so this step doesn't need to change.
Pushed Authorization Requests
From ATProto OAuth:
Authorization Servers must support PAR and clients of all types must use PAR for Authorization Requests.
PAR adds an additional request from the client to the auth server before the browser is redirected to the auth endpoint. The idea is to pass the details of the auth request directly from client to server, without forcing them to pass through the browser as an intermediary; there are a couple of advantages to doing this, but the important thing here is that FedCM will not allow this to happen. Anything that the client needs to specify must be passed via the browser, before the identity of the user (or their server) is known.
Luckily ATProto doesn't add very much to the auth request that's not present in IndieAuth. There is one thing to consider, though, which is...
Demonstrating Proof of Possession
The atproto OAuth profile mandates use of DPoP for all client types when making auth token requests to the Authorization Server and when making authorized requests to the Resource Server. See RFC 9449 for details.
Clients must initiate DPoP in the initial authorization request (PAR).
DPoP adds a public/private key pair to each authentication session so that the client can prove that it is the same one which started the session in the first place.
With no initial PAR request it's obviously not possible for DPoP to start at this point.
The options appear to be
-
DPoP starts with the token request. This seems like it would be easiest to implement, but means that the protection it offers doesn't cover the initial authorisation request.
-
The client includes its DPoP key in the initial request, along with its client ID and PKCE challenge. FedCM's params parameter accepts a JSON object, so there's enough extensibility here to include the DPoP key. I'm guessing that we'll want to include a signature, too, so that the request actually proves possession of the key; I'm not cryptographically savvy enough to know exactly what should be signed, but it occurs to me that the PKCE challenge contains a useful amount of randomness.
At any rate, the details of DPoP need to be agreed on by people who are far more experienced with auth protocol design than I am.
Scopes
ATProto OAuth is about more than just authentication. It also yields an access token that the client can use to create records, such as BlueSky posts, on the user's PDS. OAuth covers this with the idea of scopes, which allow the client to specify what kinds of access it is asking for, and for the server to tell it which permissions the user has decided to allow.
This seems kind of out of scope for FedCM, and doesn't feature in the IndieAuth profile, but for ATProto purposes it's clearly very important; authentication without authorization would not be able to provide a lot of the features that ATProto login can grant access to.
Some thoughts on requesting scopes have been recorded here and here. I haven't read through them in detail, but this is clearly another area where decisions will need to be made before it's worth trying to implement anything.