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

[WIP] MSC2964: Delegation of auth from homeserver to OpenID Provider #2964

Draft
wants to merge 24 commits into
base: old_master
Choose a base branch
from

Conversation

sandhose
Copy link
Member

@sandhose sandhose commented Jan 14, 2021

Rendered

Fixes: matrix-org/matrix-spec#636

Status:

  • Spec is feature complete
    • Address username/password login flow using ROPC
    • QR flow
    • Device ID management
  • Reviewed for consistency with MSC3861
  • Implementations believed to be complete enough

Dependencies:

Implementations:

Homeservers

OIDC Provider

Clients

In OIDC-native mode:

@turt2live turt2live changed the title MSC2964: [WIP] Matrix profile for OAuth 2.0 [WIP] MSC2964: Matrix profile for OAuth 2.0 Jan 14, 2021
@turt2live turt2live marked this pull request as draft January 14, 2021 17:27
@turt2live turt2live added kind:feature MSC for not-core and not-maintenance stuff proposal A matrix spec change proposal labels Jan 14, 2021
@sandhose
Copy link
Member Author

Related issue: matrix-org/matrix-spec#636

Related MSCs: #2965, #2966, #2967


In this MSC, there are a few areas that still need work.

First, it outlines different profiles of clients. One important client type that is not yet covered by it are CLI tools.
The natural fit for this would be the client credential grant, taking form of either a client_secret or a secret key for JWT signing.
The problem with this is that it authenticates as "the client", not a user. How users should delegate authorization to other clients is a bit unclear. Maybe RFC 8693 helps with that.

Second, there are the parts that we enforce.
For example, I chose to enforce PKCE for public clients. Since most of Matrix clients are public, I think it makes sense to enforce the current best practices here.
Another example would be credentials for confidential clients. Right now nothing is specified, but it might make sense to encourage the usage of keypairs instead of client secrets. If we encourage that, should it be enforced?
Last example, in the part about the request to the authz endpoint, I mention that the state parameter should be unpredictable. Some profiles go further than that to enforce a minimum entropy for this parameter.

Third there is device handling in general. MSC2967 talks a bit about this, but there will definitely be some changes to the device API.
An example of this is that we might want to surface client metadata when querying the devices instead of just an arbitrary name.
Another open question is should a device be deleted on logout? If so, how do we handle device that are used by multiple clients (which is technically possible with the solution proposed in #2967)?

@@ -0,0 +1,190 @@
# MSC2964: Matrix profile for OAuth 2.0

The current authentication mechanisms in Matrix does look like a lot like OAuth 2.0 without most of its security mechanisms.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UIA and OAuth have two different goals, though. OAuth could be e.g. a UIA stage

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While it is still under discussion, the end goal is to completely replace the current authentication mechanism of Matrix with OAuth 2.0, not add OAuth as a UIA stage. This series of MSC are written with this in mind

The redirect URIs used by the clients must match exactly with the ones registered to prevent open redirection attaks.
The full redirect URI must be included in the authorization request.

The client might include a login hint to what MXID the user is trying to use.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So far the spec only requires a username on login and /login then returns the MXID. At work we actually utilize this so that the login username has nothing to do with the MXID you have in the end.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to see some more info on what a "login hint to what MXID" is. Can that be the username or does it have to be the mxid? Does the client now have to do the mxid mapping, that so far was pretty much implementation defined?

Copy link
Contributor

@zecakeh zecakeh Aug 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understood correctly, like the name suggests, it's only a hint, to avoid the user having to enter their MXID/username several times.

For example, with a client you would have these steps:

  1. The user enters a MXID in the client to login.
  2. The client discovers the homeserver from the MXID, according to the spec. While doing that it also sees that the homeserver supports OIDC.
  3. The client directs the user to the OIDC auth server, and inserts in the request the MXID that the user entered as a login hint.
  4. The user opens the login page on the auth server, and the username field is pre-filled according to the MXID that was provided.

In no way it should limit the choice of username for the user, or force the auth server or homeserver to use it. That's what I understand of the intentions for that field from the OIDC spec anyway.

Although ultimately the auth server is free to do whatever it pleases and might also ignore this parameter altogether.

I would guess it's also up to the auth server and homeserver to decide if the username used for authentication matches the one in the MXID. Irc, it's already the case in Synapse's OIDC config where one can chose to map the username from the auth server to anything else.

To get the final MXID, the client needs to call the homeserver's GET /whoami endpoint with the access token that was obtained during auth.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, often clients actually use separate fields for server and username (or the server is even preconfigured). Users then just enter "FirstName LastName", so would that be an acceptible login hint or does it have to be an mxid?

@@ -0,0 +1,190 @@
# MSC2964: Matrix profile for OAuth 2.0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Soru is not sure if these OAuth proposals in their current form work. There are a couple fundamental issues with them:

  1. Bad UX: For native desktop clients and phone clients, the user is basically forced to be re-directed to the browser and complete login steps there. For web-clients the user is re-directed upon login to another website.
  2. A possible mentioned work-around for the first issue was privileged clients, so that e.g. matrix.org privileges app.element.io. While that does not have to happen, if an easy solution to a bad UX issue is to introduce privileged clients, it will happen sooner or later, if we want or not.
  3. This removes the ability for us to ever do something like [WIP] MSC2957: Cryptographically Concealed Credentials #2957 or ever implement login with just one password for both authentication and SSSS:
    3.1. OAuth steps are completed on the website --> we execute code to handle our password from the server. The entire point of [WIP] MSC2957: Cryptographically Concealed Credentials #2957 is to not trust the server with this
    3.2. We'd need to get the calculated SSSS key from webbrowser to client somehow
  4. That only few clients implement SSO currently shows the high entry-barrier for client-dev if you want to login with SSO. Requiring OAuth for every login will significantly lift the entry barrier for new clients
  5. for embedded/limited clients the idea proposed was that you need an external device w/ browser to complete the login

An idea would be to use oauth just for sso, and replace m.login.sso with m.login.oauth and introduce UIA to /login (#2835). While a server could chose to just always use oauth then, instead of "normal" login, this would negate all the extra stuff we would get by using OAuth scopes.

Another idea would be to not require a browser / browser-like environment to complete the needed OAuth steps, and (for point 3), not execute any code given by the server for being able to authenticate yourself.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I synced with @sandhose on this last week, as I share some of the same concerns above (and hadn't had a chance to discuss them before these MSCs were written) Taking them point by point:

  1. Bad UX: In practice there are basically two auth flows in Matrix today - either basic username+password, or some kind of SSO which requires a web UI. It's critical that we continue to support basic username+password for all the various Matrix clients and bots which use this, allowing them to have simple native UI (at the expense of the security dubiousness of encouraging people to hand their main account password over to some random native app). For other flows, we already need the ability to bounce through a web UI, and in practice we've seen several major security issues due to inventing those flows ourselves rather than leveraging OAuth - so I see the appeal here in switching to an existing standard. Am I missing a native auth flow that wouldn't be covered by this? Meanwhile, if you're on a basic client and want to get an OAuth scope, the client can provide a URI to let the user finish the auth in a web browser - this feels like an improvement on the current situation.
  2. Given your server is the one authing your login, not your client, it doesn't seem unreasonable that if the server doesn't know if it can trust the client, the server should be the one displaying the UI (webpage) needed to auth the client. However, if your server wants to specialcase some known trusted clients to let them iframe the server SSO flow, that doesn't seem unreasonable, and would improve common cases where a given server steers new users into using a default client without making things worse for other clients.
  3. Totally agreed that this is in conflict with MSC [WIP] MSC2957: Cryptographically Concealed Credentials #2957 - i've asked @sandhose to go figure out how to fix that, as cryptographic login is super desirable. (It's worth noting that cryptographic login is in general incompatible with SSO however, so perhaps it just ends up being a separate login flow alongside the basic auth one for non-SSO situations?)
  4. Totally agreed we should keep plain login around too.
  5. Solved by keeping plain login around too.

However, I'm not sure that the right solution is to turn m.login.sso into m.login.oauth and add UIA to /login. We then end up with both the complexity of UIA and OAuth2 flying around. Instead, how about we aim to have 3 separate login flows: plain login, OAuth (covering all SSO), and cryptologin?

The main flaw I see is that we'd need a place to support TOTP-style 2FA such that it works for all flows if configured (it feels suboptimal to make it SSO-only, given cryptologin + 2FA sounds very desirable, for instance)

Copy link
Contributor

@Sorunome Sorunome Jan 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally sounds good, yes. Another issue would be that with plain login we don't have the scope management.

As for the concerns, the issue is that for TOTP (or basically any other 2fa) we need more back-and-forth communication one way or another. The cryptographic authentication might also require that (while no exact flows are layd out yet in the MSC, a login does require a few requests back-and-forth, though). It seems to soru that the simplest solution for that is adding UIA to /login, but yes, i seems like duplicate work.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead, how about we aim to have 3 separate login flows: plain login, OAuth (covering all SSO), and cryptologin?

I'm not entirely convinced by this. Some servers (of which matrix.org will soon be one) allow either username/password or SSO (via social login). If we split username/pass and OAuth into two separate flows, we effectively undo the work we did for social login in presenting the Identity Providers next to the username/password box, since we're now back to "log into matrix.org" (without knowing anything on the client side about what auth mechanisms matrix.org might offer).

Of course that's a problem with OAuth generally, but at least if the username/password mechanism follows the same flow as other logins, we don't get this jarring "username/password" vs "everything else".

There is another problem with Social Login, which is solved by having the server manage the choice of login flow (OAuth-stylee), which is: how to correctly brand login buttons without having to have support for every conceivable brand in every client.

I'm not sure I want to discuss this further here; the point is basically that I think we need to take a hard look at whether what we have designed for Social Login is the right solution, or whether we need to do something more OAuthy.

To pick up a couple of other points:

@Sorunome wrote:

  1. That only few clients implement SSO currently shows the high entry-barrier for client-dev if you want to login with SSO. Requiring OAuth for every login will significantly lift the entry barrier for new clients

Disagree. I'm not convinced the entry barrier for SSO is any higher than username/pass, since it's just a couple of redirects; the server takes care of most of it. IMHO the reason few clients implement SSO is because there is no need to: few servers currently implement SSO.

@ara4n wrote

[re embedded clients]
Solved by keeping plain login around too.

except it's not, is it? It only solves it for servers which choose to offer a username/password flow, with no 2FA? That might work for specific deployments, but it doesn't sound like a general solution.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@richvdh

https://github.com/matrix-org/matrix-doc/pull/2785Disagree. I'm not convinced the entry barrier for SSO is any higher than username/pass, since it's just a couple of redirects; the server takes care of most of it. IMHO the reason few clients implement SSO is because there is no need to: few servers currently implement SSO.

I think the issue here is not really the code needed to do the requests but actually that there might be a webpage to be displayed to do the actual SSO. Which usually tends to be hard for native desktop apps and TUI clients as those have a harder time communicating with a browser (and with those that do js sometimes even). Thats in my opinion the main challenge of SSO currently. Though if OAuth gives token/code based auth (as google does it for example) this would be an upgrade and make this easier. (google shows you a token a user can easily copy from their browser so the client doesnt need to spin up a local server to redirect too or similar).

Also I agree with @richvdh on the embedding part (basicly what I said above).

I overall do like having oauth in the spec as a main login thing but I have the feeling in the current proposal it either breaks many clients and servers at once or atleast clutters the login process. I personally like the feature proposed but not the way it is implemented. Though I cannot offer another solution to this.

@turt2live turt2live added the needs-implementation This MSC does not have a qualifying implementation for the SCT to review. The MSC cannot enter FCP. label Jun 8, 2021
Comment on lines 149 to 152
Whenever the client ask for a token (either with a refresh token or by initiating a authorization code flow) the authentication server returns the list of scopes for which the token is valid.
This helps client track what scopes they currently have access to, and let them upgrade temporarily a token with additional scopes to perform privileged actions.
The authorization server can also downgrade the scopes of a session after a certain time by returning a reduced list of scopes when refreshing the token.
The scope definitions are out of scope of this MSC and are defined in [MSC2967](https://github.com/matrix-org/matrix-doc/pull/2967).
Copy link
Contributor

@ShadowJonathan ShadowJonathan May 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't this be replaced with; the client requesting for a seperate token with only the required scope to perform this action, only for it to be dropped (deactivated) immidiately after?

Something about upgrading the same token doesn't sit well with me from a security perspective, it might be a deliberately locked-down token, and/or multiple actions at once could race to upgrade/downgrade the current token.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having a separate token purely for one scope / set of scopes sounds like a really good idea, especially for race condition reasons. Races could be also avoided by introducing state on AS/OP side, but that is quite out of scope of oauth2 specification (if I'm not mistaken)

At the same time, it would make specification compatible with more possible OP implementations.

Making it single use would be easily doable using jti claim on that token.

@hughns hughns changed the title [WIP] MSC2964: Matrix profile for OAuth 2.0 [WIP] MSC2964: Delegation of auth from homeserver to OIDC Provider May 25, 2022
@hughns hughns changed the title [WIP] MSC2964: Delegation of auth from homeserver to OIDC Provider [WIP] MSC2964: Delegation of auth from homeserver to OpenID Provider Feb 8, 2023
@turt2live turt2live added the matrix-2.0 Required for Matrix 2.0 label Mar 3, 2023

## Dependencies

- [MSC2964](https://github.com/matrix-org/matrix-spec-proposals/pull/2964)
Copy link
Contributor

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 loop :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind:feature MSC for not-core and not-maintenance stuff matrix-2.0 Required for Matrix 2.0 needs-implementation This MSC does not have a qualifying implementation for the SCT to review. The MSC cannot enter FCP. proposal A matrix spec change proposal
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet