-
Notifications
You must be signed in to change notification settings - Fork 385
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
MSC2966: Usage of OAuth 2.0 Dynamic Client Registration in Matrix #2966
base: main
Are you sure you want to change the base?
MSC2966: Usage of OAuth 2.0 Dynamic Client Registration in Matrix #2966
Conversation
| `contacts` | Array of strings representing ways to contact people responsible for this client, typically email addresses | Required | No | | ||
| `tos_uri` | URL that points to a human-readable terms of service document for the client | Required | Yes | | ||
| `policy_uri` | URL that points to a human-readable policy document for the client | Required | Yes | | ||
| `redirect_uris` | Array of redirection URIs for use in redirect-based flows | Required with the `authorization_code` grant ype | No | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
something I don't really understand here (or about OAuth2 dynamic registration in general):
What is to stop me, as an attacker, registering a "client" with branding (name, logo, etc) that looks like a trusted client, but with a redirect_uri that points to a site I control?
I then send the user a link which will take them through the login flow, and redirect back to my site. Assuming I can persaude the user to open the link, I can then harvest the authorization code and thence gain access to their account?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case the auth server would at least prompt for explicit consent as it would be considered as a separate client from the legitimate one.
One thing that could be enforced would be to have the different URIs (at least redirect_uris
and client_uri
) to be on the same origin. Quoting from RFC 7591 sec. 5:
In a situation where the authorization server is supporting open client registration, it must be extremely careful with any URL provided by the client that will be displayed to the user (e.g.,
logo_uri
,tos_uri
,client_uri
, andpolicy_uri
). For instance, a rogue client could specify a registration request with a reference to a drive-by download in thepolicy_uri
, enticing the user to click on it during the authorization. The authorization server SHOULD check to see if thelogo_uri
,tos_uri
,client_uri
, andpolicy_uri
have the same host and scheme as the those defined in the array ofredirect_uris
and that all of these URIs resolve to valid web pages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case the auth server would at least prompt for explicit consent as it would be considered as a separate client from the legitimate one.
of course; but how is the user meant to tell that they are now being asked for consent to a phishing app?
One thing that could be enforced would be to have the different URIs (at least redirect_uris and client_uri) to be on the same origin.
Wouldn't this preclude the use of desktop clients, which often register custom URI schemes to get the auth code back from a browser to the client?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed elsewhere: it turns out that on Windows and MacOS at least, desktop apps can register for parts of the https://
namespace. So that only really leaves Linux where you can only register for an entire URI scheme (via an x-scheme-handler/...
mimetype).
So it should be possible to create a system which makes this look user-friendly for everyone except Linux users, who presumably are a bit more comfortable with obscure URIs anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My client generates a localhost address on demand during SSO currently. This MSC makes it sound like I need to switch to a fixed schema instead, which means running multiple instances of my software in parallel will become much harder. How would I solve having 2 separate instances of my app running and I want to only sign into one of them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My client generates a localhost address on demand during SSO currently. This MSC makes it sound like I need to switch to a fixed schema instead, which means running multiple instances of my software in parallel will become much harder. How would I solve having 2 separate instances of my app running and I want to only sign into one of them?
This is covered by the "Native clients" part of this spec: apps can register localhost
without port, and the server must accept a dynamic port during the authorisation
## Proposal | ||
|
||
If a Matrix server wants to be used by any third-party client, its authentication server must allow dynamic registration of OAuth 2.0 clients. | ||
The client registration endpoint is advertised in the OIDC discovery document and can be used as per [RFC 7591 sec. 3](https://tools.ietf.org/html/rfc7591#section-3). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sure this is obvious if you're familiar with OAuth2, but for context I'd find it really helpful if you could clarify when a client would register itself with a given server in the context of Matrix. Presumably, whenever the user chooses a homeserver to log into? (Is the client expected to remember a list of homeservers it has registered against?)
| `contacts` | Array of strings representing ways to contact people responsible for this client, typically email addresses | Required | No | | ||
| `tos_uri` | URL that points to a human-readable terms of service document for the client | Required | Yes | | ||
| `policy_uri` | URL that points to a human-readable policy document for the client | Required | Yes | | ||
| `redirect_uris` | Array of redirection URIs for use in redirect-based flows | Required with the `authorization_code` grant ype | No | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My client generates a localhost address on demand during SSO currently. This MSC makes it sound like I need to switch to a fixed schema instead, which means running multiple instances of my software in parallel will become much harder. How would I solve having 2 separate instances of my app running and I want to only sign into one of them?
If a client changes its `redirect_uris`, should the old ones be considered for a period of time? | ||
If multiple versions of the same client coexist at the same time, should older versions of the software be able to override the metadata of the newer version? | ||
|
||
If an authorization server allows unsigned clients, the number of client registration might explode exponentially. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this a problem?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this should be problem, imho. This is the whole goal of an open ecosystem like matrix. Anyone at any time can build a client and use it. You are not vendor bound. Allowing this to be restricted imho goes against the core idea of an open ecosystem which matrix tries to be.
Edit also see: #3861 (comment)
- makes some metadata optional - better explain how each metadata field is used - better explain what the restrictions on redirect_uris are - remove the signed metadata part - mention the client metadata JSON document alternative
It is recommended that the `client_uri` is a web page that provides information about the client. | ||
This page should be able to be accessed without requiring authentication. | ||
|
||
This URI is a common base for all the other URIs in the metadata: those must be either on the same host or on a subdomain of the host of the `client_uri`. | ||
For example, if the `client_uri` is `https://example.com/`, then one of the `redirect_uris` can be `https://example.com/callback` or `https://app.example.com/callback`, but not `https://app.com/callback`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For a self-hostable web client like Element web, the recommended uri would be element.io
but if I host an instance of it on example.com
, I wouldn't be able to set a proper redirect_uri
with the recommended uri.
How important is this requirement really? What about informing the user about the differing host in the redirect uri during authorization?
Of course clients could also bundle in their landing pages and policies or set up a redirect to work around the issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a feature, not a bug. "element.mycompany.corp" is "Element Web hosted by MyCompany", as there are no assurance that it's an untempered Element Web hosted by Element the company
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not for the MSC text, but Element Web could add an /about
route that it ships for this purpose.
Co-authored-by: Tonkku <[email protected]>
85d1958
to
0e2f0f1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
overall this looks good, though I think it needs implementations to be able to move to FCP. I'll document those requirements in a separate review.
It is recommended that the `client_uri` is a web page that provides information about the client. | ||
This page should be able to be accessed without requiring authentication. | ||
|
||
This URI is a common base for all the other URIs in the metadata: those must be either on the same host or on a subdomain of the host of the `client_uri`. | ||
For example, if the `client_uri` is `https://example.com/`, then one of the `redirect_uris` can be `https://example.com/callback` or `https://app.example.com/callback`, but not `https://app.com/callback`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not for the MSC text, but Element Web could add an /about
route that it ships for this purpose.
- `tos_uri`: URL that points to a human-readable terms of service document for the client | ||
- `policy_uri`: URL that points to a human-readable policy document for the client |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
blocking: what is the difference between policy and terms of service?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those are all defined in RFC 7591:
tos_uri
URL string that points to a human-readable terms of service
document for the client that describes a contractual relationship
between the end-user and the client that the end-user accepts when
authorizing the client. The authorization server SHOULD display
this URL to the end-user if it is provided. The value of this
field MUST point to a valid web page. The value of this field MAY
be internationalized, as described in [Section 2.2](https://www.rfc-editor.org/rfc/rfc7591.html#section-2.2).
policy_uri
URL string that points to a human-readable privacy policy document
that describes how the deployment organization collects, uses,
retains, and discloses personal data. The authorization server
SHOULD display this URL to the end-user if it is provided. The
value of this field MUST point to a valid web page. The value of
this field MAY be internationalized, as described in [Section 2.2](https://www.rfc-editor.org/rfc/rfc7591.html#section-2.2).
Compared to the RFC, this is adding requirements on them (coherence with the client_uri), are suggestions for clients to advertise them and suggestions to servers to display them if provided
|
||
**Note**: in this example, the server has not registered the locale-specific values for `client_name`, `tos_uri`, and `policy_uri`, which is why they are not present in the response. The server also does not support the `urn:ietf:params:oauth:grant-type:token-exchange` grant type, which is why it is not present in the response. | ||
|
||
The client must store the `client_id` for future use. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mentioned in the umbrella MSC: does the client need to remember this over multiple browsers/sessions, or just while the single user session logs in?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarified in c7e55ec, plus mentioned in "Potential issues"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implementation requirements:
- Client using
web
flow - Client using
native
flow - Server supporting both flows (may be two different servers)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Known working clients with the web flow:
- Element Web
Known working clients with the native flow:
- Element Desktop
- Element X iOS
- Element X Android
Server supporting both:
- Synapse with Matrix Authentication Service
- Dendrite with Matrix Authentication Service (PR)
This proposal requires the client to know the following authorization server metadata about the homeserver: | ||
|
||
- `registration_endpoint`: the URL where the client is able to register itself. | ||
|
||
The discovery of the above metadata is out of scope for this MSC and is currently covered by [MSC2965](https://github.com/matrix-org/matrix-doc/pull/2965). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
presumably if there's no registration_endpoint
, the server doesn't support dynamic client registration. That should be documented in the MSC as a thing clients should expect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how to handle this. Basically there are two possibilities:
- make client registration mandatory. That would be aligned with the 'openness' of Matrix, as you should be able to use any client with any compliant server. Not supporting this would then mean the server not spec-compliant?
- make it optional and explain here what this means. This makes it clearer in the spec that its possible to use this in 'closed' ecosystems, where servers impose which client is allowed to use it
Rendered
Dependencies: