Open ThisIsMissEm opened 4 months ago
At Bluesky, we actually have another use case in mind:
Allow a dev that does not own/deployed a publicly available client metadata on the internet, to use a "loopback client" with a production server. In this case, what we do is we hard code the metadata in the authorization server, using query strings to allow customizing it.
e.g. http://localhost/?client_name=My%20app&redirect_uris=http%3A%2F%2F127.0.0.1%2Fcb
would be resolved by the authorization server into:
{
"client_id": "http://localhost/?client_name=My%20app&redirect_uris=http%3A%2F%2F127.0.0.1%2Fcb",
"client_name": "My app",
"redirect_uris": ["http://127.0.0.1/cb"],
"grant_types": ["authorization_code", "implicit", "refresh_token"],
"scope": "openid profile offline_access",
"token_endpoint_auth_method": "none",
"application_type": "native",
"dpop_bound_access_tokens": true,
}
Note that in this case, the authorization server adds other restrictions to the client, such as forbidding prompt=none
, reducing the validity of tokens, not displaying images & links, etc. The authorization page basically reads "A program on your device wants to get credentials for your account".
This is our exact implementation: https://github.com/bluesky-social/atproto/blob/main/packages/oauth/oauth-types/src/atproto-loopback-client-metadata.ts
@matthieusieben the way we did this at Inrupt for working on Solid apps was to host a client_id at a temporary publicly accessible URL.
The other option is using something that exposes your localhost server to the public internet (which I'd not really recommend)
The reason for this is that the Authorization Server cannot access a localhost URL (without requesting to itself), so the URL of the client_id must resolve to a publicly accessible resource
We know about these solutions. And we also agree that this is what devs should ideally do.
However, we believe it is critical for our business to make it as easy as possible for 3rd party devs to integrate with our systems, which is why we chose this approach. This is particularly important because we decided to adopt the current BCP, which impose a bunch of stuff (DPoP, PKCe, etc) that make OAuth client particularly difficult to implement. Having to expose a json file on the web is arguably quite simple, but we really want to cut any corner we can here.
For this reason, we:
1) Do require Server Side Request Forgery protection to be in place on the OAuth Provider
2) Add an exception for localhost
to be interpreted as described
I realize now that there is another solution that we did not envision; that is to offer a "client metadata as a service" endpoint that would use query params to build the client metadata.
I guess that the use of the localhost
hostname makes it clear to the authorization server that it is a particular type of client, and that additional restrictions should be applied.
I realize now that there is another solution that we did not envision; that is to offer a "client metadata as a service" endpoint that would use query params to build the client metadata
This was something that the dev tools team I was on floated as an idea, but we went with writing a generator / validator as a project for @laurin-w — unfortunately product at inrupt killed the project after it was built.
If you do support a client_id metadata documents as a service system, I'd recommend limiting it only to localhost & private IP addresses, as to make it a development-only service, such that it can't compromise production systems.
FYI: At Hellō https://console.hello.coop we separate development redirect URIs from production redirect URIs. We only allow developers and testers that are registered with the team to use development redirect URIs. We then enable localhost and 127.0.0.1 by default on app creation to simplify getting up and running.
This simplifies development without the security concerns of a deployment that uses localhost.
@dickhardt so you've two clients? one for development and one for production usage? This seems fine to me. Another approach I've seen pretty commonly is to just run a development AS and a production AS, and have laxer requirements on the former.
However, I don't think the client_id
URI can be a non-public URI, since the AS SHOULD request the document at this location or fail the authorization request; perhaps it's worth making this a MUST? i.e., MUST request the document, unless it has a cached copy with respect to cache-control HTTP headers.
Just one client. If the provided redirect_uri is not in the list of production redirect_uris, then I check if it is a develop redirect_uri and if the user is part of the team. This is when I would allow localhost development flows. Here is a screenshot of our console page.
To support localhost, perhaps you have to be a registered developer at the AS?
I don't think I have all the context of the use cases everyone else involved is wanting to solve. It does seem like there could be different requirements for developers vs users.
It seems one of the requirements is to someone can deploy software or use a service that has their own metadata and their own client_id without having to register their app ahead of time. The question is can they do that on localhost.
Another concern in the case of http://localhost
clients is the ability to declare the scopes that the client will actually request.
There are basically two approaches here:
The drawback of the approach we decided to adopt is that is it quite counter intuitive with what you would expect the server to do with "regular" accessible client metadata documents. In the case a metadata document is actually available, we do require that document to list all the scopes that may be requested during an auth flow, and will return an error if more scopes are requested at auth time.
I think the direction I'm most leaning towards here is having a service hosted for localhost & development usage, I'm chatting with Fastly about if they could host such.
A feature of localhost dev is that it works when offline
Right, but for this internet draft, it's specifically about authentication against decentralised services.
Sure, you could run the Authorization Server and App both on localhost and support localhost client ID metadata documents, that'd be fine, but it's very common that the Authorization Server is say, mastodon.social
in which case you need a Client ID Metadata Document that can be fetched by mastodon.social
So we could add language that localhost
URIs for Client ID Metadata Documents are supported only if the Authorization Server is also on localhost.
Works for me. I was calling out potential confusion using the localhost term when using a service
Yeah, I think the current language was written such that it worked first for production environments, which tbh makes sense & in that scenario typically the AS and Client app are not operated by the same entity
We've currently a restriction for
client_id
URIs that they MUST be https scheme.In development environments where all software is running on localhost, we should probably provide an exception to that rule, given the issues that can be faced (self-signed certificates, custom root certificates, etc) with settings up HTTPS in development.