The Community Group is seeking developer feedback, so if any of you are working/interested in the subject, either from Fediverse or other background, then participate on the GH issue, or alternatively respond on the fedi to Sam Goto of the Google Chrome team.
@angus awesome, thank you! After playing with FedCM this past week I think it has a ton of potential. Having a plugin that would allow any Discourse admin to enable their users to help in testing out FedCM would be huge. The API surface for FedCM itself is quite simple. I suspect most of the work for a plugin will be interacting with Discourse’s sessions.
Here’s a couple resources I’ve found most helpful:
Up-to-date instructions for trying out FedCM:
For implementing:
In terms of my implementation, one caveat of FedCM is that it doesn’t currently specify a format for the returned token. There’s already an implementation for IndieAuth that integrates well with some of their semantics. I’m currently doing something slightly simpler for LastLogin. I’m just returning an OIDC ID token, which the client is expected to hand to the backend which will then verify it and create a session.
I’ve got a test instance running at lastlogin dot net (sorry can only post 2 links). Note this should currently be considered insecure, but should be fairly complete for testing FedCM.
I’m happy to handle the Discourse end of things. If you could give me some kind of access to your test instance, that’ll help me implement this in Discourse faster (if relevant my email is angus at pavilion dot tech). As an aside, I note that @thisismissem has said there may be some more spec work to do here. Is this the right time to be implementing this?
Here’s basically my understanding and take on the situation. 3rd party cookies (among other things) are going away because big tech is being pressured by regulation to improve privacy. But that will break federated login, which currently mostly happens via OAuth2 and OIDC from large providers. Google’s answer is FedCM, which Mozilla and Apple both support. Google as an organization is not incentivized to make FedCM work for anyone other than big tech. However, the people inside google who are actually implementing it are sympathetic to the open web, and are willing to make changes to the spec to allow you to use any IdP you want. This isn’t going to happen unless people build prototypes and a) prove that it can work with good UX and b) show some demand for it. I’ve decided the upside is worth me investing in trying out a half baked spec and giving feedback to improve it.
So yes, the spec is not finished, but in this case that’s a good thing because we can help push things in a direction that is much better for decentralization.
In terms of this Discourse plugin specifically. Even if you only had time to make a working draft prototype, that would save me a lot of time because I would only need to learn how to modify it, rather than starting from scratch learning Ruby+Discourse. I’m willing to do that if I have to (I’ve always admired Ruby from a distance, just never had a strong reason to use it), but it would be much faster with some help.
If you could give me some kind of access to your test instance
How much access would you like? It’s currently running publicly at https://lastlogin.net and you’re welcome to hit it with whatever tests you like. If you prefer something you can start/stop yourself that can be arranged.
But the big issue is “how do you get a client_id before you know the IdP?”, that’s going to be the blocker for many. At the moment, IndieAuth “discovers” the client metadata via parsing microformats in the html at the client_id URL.
The IETF OAuth draft specification I’m currently working on is allowing client_id to be a JSON document, this is inspired by the Solid-OIDC Client Identifier Documents — essentially we’re lifting this up to be part of OAuth 2.
This means that you pass a client_id of your client identifier metadata document, and the IdP automatically registers a client for that client_id if necessary, using the data in that document.
Can you explain in more detail the problem here, or maybe link me to a previous discussion that covers it by chance?
Currently the client_id is set by the RP in the call to navigator.credentials.get(), that’s been sufficient for my purposes so far. Are there use cases it doesn’t cover?
How do you know what client_id to use before you know the IdP at which the client is registered?
If you make it a URL, then the IdP must do something to potentially create a client, if a client with that client_id doesn’t already exist: how does the IdP do that?
Like, somehow N different servers all need to somehow know about your client app (RP)
In IndieAuth, it’s expected to fetch a HTML page and extract out client information via microformats.
Ah ok I think I see where you’re coming from. For my usage, the only necessary function of a client_id is to provide an audience value for the IdP to create an OIDC ID token. No other data is needed.
Essentially the flow I’m aiming for in LastLogin is:
Could a moderator (@angus ?) kindly promote the New joiners here (@apitman, @samuelgoto) to Basic level? (Asking because from reading about Trust Levels I understood manual promotion may be considered appropriate, and Sam said out-of-band that he wanted to post again but was limited.)
But the big issue is “how do you get a client_id before you know the IdP?
@thisismissem the way I am solving things like these with Rauthy currently is by instead of accepting a json for the client id, which would end up in a possibly very huge URL and may leak client-internal information in logs and stuff, is by accepting a URL instead. But this URL does not point to an HTML you have to parse, but simply to a JSON on a remote host which can be deserialized into a valid client config.
Basically like with OIDC dynamic client registration, but as ephemeral clients.
This keeps the URL short and you don’t need anything in advance, as well as you don’t need to parse HTML and its super easy to use. You are in charge of your own config then and can even easily modify it in the future without the need to care about remote-managed dynamically registered clients, which would not work with FedCM anyway, because the RP will not know the IdP beforehand.
Edit:
If you make it a URL, then the IdP must do something to potentially create a client, if a client with that client_id doesn’t already exist: how does the IdP do that?
That can’t exist, because the client_id will be the URL itself, not some self-chosen name, and you will not save any of this information. It is stateless.
I can also see why you’ve landed on this flow. That said, there is a slight difference between this flow and the solution @thisismissem is proposing.
This seems to be similar to what @thisismissem is suggesting? Maybe I’m misunderstanding.
I think I’m going to let this settle a bit before implementing it in a Discourse plugin. I feel you guys are close, but I don’t want to jump the gun. I hope this doesn’t come across the wrong way, I’m keen to implement this, but I think the approach needs to be settled a bit more first for a RP implementation to make sense.
Yes, correct. You can basically already see this in solid-oidc, but I’m writing an official spec for it for OAuth, such that it can be referenced everywhere, rather than everyone implementing slightly different things
Also, fwiw, everything here was already discussed between myself and Aaron, I was hoping to get a draft up before announcing it, but as people were talking intent-to-implement, I wanted to warn that we’ll soon have a spec that solves a bunch of the problems
So is the primary functionality we’re looking for with a client ID document the ability to present an RP name/logo/etc, or are there some additional capabilities that are unlocked by having one?
Agreed. My flow is working for my prototype, but I suspect I might be missing something important and want to understand better the tradeoffs.
Totally understandable! I might end up taking a crack at this myself so people can use FedCM to log in to IndieBits using FedCM on LastLogin. This would also be a good way to test if my minimal flow has any holes in it.
Would you potentially be available on a chat platform to answer Discourse/Ruby questions occasionally?