Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update client information discovery method #133

Open
aaronpk opened this issue May 17, 2024 · 28 comments
Open

Update client information discovery method #133

aaronpk opened this issue May 17, 2024 · 28 comments

Comments

@aaronpk
Copy link
Member

aaronpk commented May 17, 2024

The current method of client information discovery (fetching the client_id and parsing the HTML page for microformats) has received a lot of pushback from various people otherwise interested in implementing IndieAuth. This method is also somewhat limited in that it requires defining a Microformats vocabulary for client information, rather than using the existing vocabulary of client information that's defined by RFC 7591 Dynamic Client Registration.

An alternative proposal for client information discovery was proposed in draft-looker-oauth-client-id-scheme, where the AS uses the client ID URL as the base URL and appends a .well-known string in order to find a JSON document with the client metadata. While this approach gets around the HTML/Microformats challenges, it is also not ideal because of the requirement of the .well-known path.

A middle ground (and interestingly, what Solid-OIDC has done), is to instead make the client ID URL be the URL to the metadata document.

So an IndieAuth client such as https://webmention.io would choose a URL to host its client metadata document, for example https://webmention.io/indieauth/client.json. This is the value it would use as the client_id in the OAuth flow.

The AS would see the client_id URL in the authorize request and fetch the URL directly in order to find the client metadata. The metadata values would be the values defined by Dynamic Client Registration, such as redirect_urls, client_name, etc.

@martymcguire
Copy link

After some discussion in the #indieweb-dev chat today between aaronpk and myself, some things I'm considering are:

Avoiding a new .well-known feels like a good goal.

Changing the meaning of client_id to be the URL to the metadata document feels reasonable, but I have concerns.

  • The current IndieAuth spec says clients SHOULD have a website at the URL in client_id - something intended for a human to read. Will human-readable information be lost with this change?
  • What do IndieAuth providers display on the authorization interface if this metadata file is missing or invalid? (and what are the implications of, for example, using the client_id domain name as a fallback?)

There are also considerations to be made for transition and roll-out.

IndieAuth providers that use client_id per the current spec (or even the previous version, before h(-x)-app microformats were specified) will show users a URL to a JSON document and will most likely make it clickable. I expect that will be a confusing user experience.

(aaronpk mentioned there aren't "that many" IndieAuth providers to update, but I posit that we can't easily know, just as one example, how many people are self-hosting selfauth or how long it will take selfauth to support this client_id change, and how and when users of selfauth would update.)

IndieAuth clients that implement the current spec will lose out on their rich appearance at IndieAuth providers that switch to the new spec. It would be nice to have a migration doc (and maybe a test tool) to help implementers migrate over!

Putting this at the end because I cannot tell if it is constructive, but I noticed that this proposal only mentions .well-known and changing the meaning of client_id. Am I walking into a trap if I ask about adding a link relation from the existing client_id-as-human-readable-page to the client information JSON document?

@dshanske
Copy link
Member

dshanske commented May 20, 2024

There's also the option of the information just being discoverable via the client_url but that means a second fetch.

I think that's what @martymcguire is referring to by the link rel, but confirming.

@aaronpk
Copy link
Member Author

aaronpk commented May 20, 2024

Some quick thoughts on the new proposal:

  • The client_id would be the json document, but the JSON document would contain a client_uri which would be the human-readable home page for the app (this is already defined in the Dynamic Client Registration protocol which defines the vocabulary of this document)
  • If the metadata file is missing or invalid, the AS SHOULD fall back to displaying the domain name of the client_id. (This would provide a reasonable fallback both since it's likely the client developer would have a web page there anyway, but also because the security model of the web is based on domain names so the user would at least see that they are authorizing a client at this domain)

As far as a migration path goes, that's definitely a bit challenging from the AS perspective. I agree that many AS's will show the full client_id URL and make it clickable, which would not be a good UX if someone clicked it.

Another option for migration is to tie the new client_id behavior to the presence of the (relatively) new indieauth-metadata URL. While it's not perfect, since that has been "out there" for a while, it could at least reduce the chances of the wrong UX. For example:

  • Client discovers the user's indieauth server from their profile URL
    • If the client discovers the indieauth-metadata link rel, use the client JSON document as the client ID
    • If the client discovers the authorization_endpoint link rel, use the client home page as before

Adding a link rel from the client home page to the client metadata JSON document doesn't really solve the problem of indieauth server implementers wanting to avoid the HTML parsing step, which is another drawback to the existing spec, and something that I have heard a lot of pushback on from anyone not already 100% bought in to microformats.

@dshanske
Copy link
Member

Some quick thoughts on the new proposal:

  • The client_id would be the json document, but the JSON document would contain a client_uri which would be the human-readable home page for the app (this is already defined in the Dynamic Client Registration protocol which defines the vocabulary of this document)
  • If the metadata file is missing or invalid, the AS SHOULD fall back to displaying the domain name of the client_id. (This would provide a reasonable fallback both since it's likely the client developer would have a web page there anyway, but also because the security model of the web is based on domain names so the user would at least see that they are authorizing a client at this domain)

As far as a migration path goes, that's definitely a bit challenging from the AS perspective. I agree that many AS's will show the full client_id URL and make it clickable, which would not be a good UX if someone clicked it.

Another option for migration is to tie the new client_id behavior to the presence of the (relatively) new indieauth-metadata URL. While it's not perfect, since that has been "out there" for a while, it could at least reduce the chances of the wrong UX. For example:

  • Client discovers the user's indieauth server from their profile URL
    • If the client discovers the indieauth-metadata link rel, use the client JSON document as the client ID
    • If the client discovers the authorization_endpoint link rel, use the client home page as before

Adding a link rel from the client home page to the client metadata JSON document doesn't really solve the problem of indieauth server implementers wanting to avoid the HTML parsing step, which is another drawback to the existing spec, and something that I have heard a lot of pushback on from anyone not already 100% bought in to microformats.

Is it microformats if it is a link header and json file? Manifest files do that and do they get complaints?

@aaronpk
Copy link
Member Author

aaronpk commented May 22, 2024

I followed the breadcrumbs from that "Login with Weird" above, and found this discussion on Rauthy:

sebadob/rauthy#146

That's a good motivator for updating to this JSON document client metadata discovery method.

@aaronpk
Copy link
Member Author

aaronpk commented May 22, 2024

Is it microformats if it is a link header and json file? Manifest files do that and do they get complaints?

The pushback is on parsing HTML. Who are the consumers of manifest files? I suspect that's a very different audience than the consumers of the client metadata we're talking about here.

@aaronpk
Copy link
Member Author

aaronpk commented May 22, 2024

I might just switch this over for a few of my indieauth clients right now. Worst case is someone's IndieAuth server shows them a slightly longer URL than normal, and they see a JSON page if they click it. But other than that everything else about the flow will still work fine, it's not actually a breaking change.

@martymcguire
Copy link

Nice! I would likely follow suit if there were, say, a blog post explaining what you changed and why. :}

@anderspitman
Copy link

anderspitman commented May 23, 2024

Would this proposal work with clients running on localhost that can't serve the required document? I'm not sure if IndieAuth currently supports that use case anyway.

The current IndieAuth spec says clients SHOULD have a website at the URL in client_id - something intended for a human to read. Will human-readable information be lost with this change?

HTTP content negation could solve this, right? IIRC that's pretty heavily used in the Fediverse to return JSON for machines and HTML for humans.

@martymcguire
Copy link

HTTP content negation could solve this, right? IIRC that's pretty heavily used in the Fediverse to return JSON for machines and HTML for humans.

FWIW content negotiation is also often a source of great pain when it comes to development and interop. https://snarfed.org/2023-03-24_49619-2

@aaronpk
Copy link
Member Author

aaronpk commented May 23, 2024

Would this proposal work with clients running on localhost that can't serve the required document? I'm not sure if IndieAuth currently supports that use case anyway.

For clients that are running on localhost (e.g. a mobile app), the assumption is that the mobile app also has a web page about the app which is where the metadata is discovered from.

@anderspitman
Copy link

anderspitman commented May 23, 2024

FWIW content negotiation is also often a source of great pain when it comes to development and interop. https://snarfed.org/2023-03-24_49619-2

These are valid concerns. You have to decide if the tradeoffs are worth it. Note that in practice I think a lot of the drawbacks of content negotiation tend to be specific to the data API case (see here). It might not cause as many problems in this situation.

@anderspitman
Copy link

For clients that are running on localhost (e.g. a mobile app), the assumption is that the mobile app also has a web page about the app which is where the metadata is discovered from.

That would limit the app to running it's OAuth2 client on a specific port, which might be taken by another app, right?

@aaronpk
Copy link
Member Author

aaronpk commented May 23, 2024

No, there is an exception for exact redirect URI matching for localhost URLs, see:

Alternatively, a mobile app on iOS/Android can use app-claimed HTTPS URLs as the redirect URI, so the localhost issue goes away entirely.

@anderspitman
Copy link

I wasn't aware of that; nice!

@aaronpk
Copy link
Member Author

aaronpk commented May 23, 2024

I just implemented this in webmention.io and indielogin.com. Here's the PR that adds support to indielogin.com as a client:

https://github.com/aaronpk/indielogin.com/pull/117/files

loqibot pushed a commit to aaronpk/webmention.io that referenced this issue May 23, 2024
@aaronpk
Copy link
Member Author

aaronpk commented May 23, 2024

I updated my IndieAuth server on aaronparecki.com to look for the JSON data as well. It's not open source so I can't link to the changes, but it was super easy.

Since I want to support both for a while, I first try to parse the page as JSON to extract the values. If that fails, I fall back to the existing behavior of parsing the page for Microformats. So it's really not a huge deal to add this new behavior to an IndieAuth server asap.

@aaronpk
Copy link
Member Author

aaronpk commented May 23, 2024

I also started working on a spec that describes this discovery method as an OAuth extension:

https://github.com/aaronpk/draft-parecki-oauth-client-id-metadata-document

https://drafts.aaronpk.com/draft-parecki-oauth-client-id-metadata-document/draft-parecki-oauth-client-id-metadata-document.html

Since this isn't actually anything unique to IndieAuth, other flavors of OAuth might also want to take advantage of this mechanism.

@gRegorLove
Copy link
Member

I implemented this on https://indiebookclub.biz. Git commit: gRegorLove/indiebookclub@4b68574

@aaronpk
Copy link
Member Author

aaronpk commented Jul 11, 2024

This has been updated in the latest published version of the spec! Thanks for the input everyone!

https://indieauth.spec.indieweb.org/#client-information-discovery

If you have an implementation of this, whether that's publishing the metadata or consuming it, please comment below! I am collecting examples to include in the presentation of the OAuth draft at the IETF meeting on July 25th!

@fluffy-critter
Copy link
Contributor

I've been taking a break from IndieWeb stuff (and software development in general) but was just referred to this thread by Aaron's post in mastodon#4800. Has there ever been an implementor's migration guide created as suggested earlier in this thread?

I'd like to continue to support IndieAuth as much as I'm able to, within reason, but poring over specifications to see what's changed since the last time I'd touched them years ago isn't my idea of a good time.

@aaronpk
Copy link
Member Author

aaronpk commented Jul 25, 2024

So far no migration guide, tho I do still want to write that up. There is the change log in the spec which at least calls out the changes.

@dshanske
Copy link
Member

I've been taking a break from IndieWeb stuff (and software development in general) but was just referred to this thread by Aaron's post in mastodon#4800. Has there ever been an implementor's migration guide created as suggested earlier in this thread?

I'd like to continue to support IndieAuth as much as I'm able to, within reason, but poring over specifications to see what's changed since the last time I'd touched them years ago isn't my idea of a good time.

How many years ago?

@fluffy-critter
Copy link
Contributor

The last time I made any significant changes to Authl's IndieAuth client was around three and a half years ago.

@martymcguire
Copy link

Working through supporting this on my own IndieAuth server today. I think I found an inconsistency.

In 4.2.1 Client Metadata:

client_id - the client identifier. [...] The client_uri MUST be a prefix of the client_id.

But a couple of sentences later:

Authorization servers SHOULD warn the user if the hostname of the client_uri is different from the hostname of the client_id.

I read that first MUST to mean that a mismatch is a fatal error, and the IndieAuth server should 400 and fail the request. But that second sentence states that a mismatch should be displayed as a warning, implying the user may be offered a chance to continue the flow.

@martymcguire
Copy link

Thanks all for the discussion and aaronpk and gRegor for the examples.

I've got a first-pass PR to support this in the Taproot/indieauth server that drives my personal site(s), as linked above.

I also added it to the IndieWeb Webring 🕸️ 💍 and my active Micropub clients at https://bayside.pub/

Commits:

@gRegorLove
Copy link
Member

Working through supporting this on my own IndieAuth server today. I think I found an inconsistency.

Good catch. I think I would lean toward the MUST interpretation, with the AS returning a 400. I think that's in line with the similar requirement for issuer and the indieauth-metadata URLs: https://indieauth.spec.indieweb.org/#issuer-identifier

@paulrobertlloyd
Copy link

paulrobertlloyd commented Aug 25, 2024

Indiekit now supports this method of getting information about a client (as of v1.0.0-beta.18).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

7 participants