__ _ _ __ ___ / _` | '__/ _ \ | (_| | | | __/ \__,_|_| \___|
__ _____ \ \ /\ / / _ \ \ V V / __/ \_/\_/ \___|
_ _ ___ (_) __| | ___ / _ \| |/ _` |/ __| | (_) | | (_| | (__ \___/|_|\__,_|\___|
_ ___ _ _ ___| |_/ _ \ | | | |/ _ \ __\// / | |_| | __/ |_ \/ \__, |\___|\__| () |___/
Almost.
What? • Why? • When?/Status • FAQs
What?
This site is being used to track the progress of Matrix migrating to a Next-gen authentication protocol based on OAuth 2.0/OpenID Connect proposal. You can join the discussion at #matrix-auth:matrix.org.
We have also set up the Matrix OIDC Playground which contains Homeservers and Clients for you to try out.
There are also some videos below showing some of the use cases in action.
Why?
Matrix currently uses a custom authentication protocol baked into the Matrix spec, which focuses on providing client-native user-interface for authentication and account management. There are two main aspects leading to this change:
- authentication through a redirect in the system browser as a first-class citizen
- replacement of the current
m.login.sso
flow with an OAuth 2.0/OpenID Connect based flow
The umbrella proposal, MSC3861, starts with a detailed rationale on this project. Reading this MSC is highly recommended to understand this proposal. This is also the main place to discuss high-level decisions of this proposal.
When?
Good question. There are a number of moving parts to this project which are outlined below.
Jump to:
Matrix Spec
The proposal is split into multiple reasonably-long MSCs. This section lists them and report on their current status.
Proposal | Status |
---|---|
MSC3861: Next-generation auth for Matrix, based on OAuth 2.0/OIDC | ✅ Draft as dependencies are not ready yet |
MSC2964: Usage of OAuth 2.0 authorization code grant and refresh token grant | ✅ Ready to review |
MSC2965: Usage of OpenID Connect Discovery for authentication server metadata discovery | ✅ Ready to review |
MSC2966: Usage of OAuth 2.0 Dynamic Client Registration in Matrix | ✅ Ready to review |
MSC2967: API scopes | ✅ Ready to review |
MSC3824: OIDC aware clients | 🚧 Rework in progress |
MSC4108: Mechanism to allow OIDC sign in and E2EE set up via QR code | ✅ Feature complete |
MSC4190: Device management for application services | 🚧 Waiting on implementations |
MSC4191: Account management deep-linking | 🚧 First draft out |
Outstanding work missing
There are a few areas not yet written down in MSCs, some need more thinking:
- Guest accounts currently have no equivalent with the new proposals. An earlier proposal of MSC2967 defined scopes to map scopes to guest access, but as an effort to trim down the proposal, they got out of it as no convincing real-world implementation was done.
- Application services could be using the client credentails grant, instead of the current
hs_token
/as_token
, but for now this proposal chose to not touch this area. - Encrypted application-services currently rely on
/login
with them.login.application_service
method to create devices, which has been infamously removed from the implementation in Synapse/MAS. An alternative API to create devices is proposed in MSC4190, but no application service implement this API yet.
Homeservers
Homeserver | Status |
---|---|
Synapse | ✅ Supported | Docs |
Dendrite | ❌ Not supported |
Conduit | ❌ Not supported |
The current implementation in Synapse is done through matrix-authentication-service
(MAS).
The latter is a full rewrite of the internal authentication logic of Synapse.
This means that not all functionnalities and APIs Synapse currently supports are available or behave the same with MAS enabled.
Clients
MSC3824 proposes four types of Matrix client:
- Next-gen auth native client - This is a client that fully uses OIDC when talking to an OIDC enabled homeserver.
- Next-gen augh aware client - This is a client that is aware of OIDC but will still use existing auth types (e.g.
m.login.sso
) to auth with an OIDC enabled homeserver. - Legacy client with SSO support - This is a client that is not aware of OIDC but does support
m.login.sso
flow. e.g. Element Web, iOS, Android, FluffyChat, Nheko, Cinny - Legacy client without SSO support - This is a client that is not aware of OIDC at all and nor does it support
m.login.sso
flow. Typically auth is done viam.login.password
only.
Next-gen auth native clients
Known working implementations of the proposal include:
- Element X iOS
- Element X Android
- Element Web (under a lab flag)
🚫 There is no plan to make Element (Classic) iOS/Android Next-gen auth native clients at this time. Instead the focus is on Element X.
Next-gen auth Aware clients
These are the requirements for a client to be Next-gen auth-aware from MSC3824:
Requirement | Relevant spec(s) | |
---|---|---|
Support the m.login.sso auth flow | REQUIRED | Matrix Spec |
Where a delegated_oidc_compatibility value of true is present on an m.login.sso then only offer that auth flow to the user | RECOMMENDED | MSC3824 |
Append action=login and action=register parameters to the SSO redirect URLs | RECOMMENDED | MSC3824 |
Sign post and link users to manage their account at the OP web UI given by MSC2965 | RECOMMENDED | MSC2965 and MSC4191 |
Label the SSO button as “Continue” | RECOMMENDED | MSC3824 |
FAQs
Will I lose my old-style login/password?
The current implementation in Synapse with MAS provides SSO-based login and local password login. We expect other homeservers implementations to provide the same kind of features.
However, you will be entering your username/password into a UI controlled by the homeserver, not the client.
How do I do social login with this?
Similar to how the homeserver achieves this today, the next-gen auth implementation in homeservers can act as an identity broker and support login via upstream social (and other) identity providers.
Does it mean my client needs a web browser?
In its current form, the proposal embraces two main flows: the authorization code grant and the device code grant.
The authorization code grant works by having the client open/redirect to the homeserver, the homeserver authenticates the user, and then redirects back to the client. This flow works well in web contexts, as well as native contexts where opening the system browser (or equivalent) is feasible. On mobile, the platform usually provides specialised APIs to do so without leaving the app. Checkout the client implementation guide for details about this flow.
The device code grant can be used in contexts where the client has no good way to open the system browser, and/or when it’s not possible to get back to the client through a redirect. In this flow, the client gets from the homeserver a short URL and a short code that the user can manually enter in their browser, on the same device or not. The client then polls in the background, waiting for the authorisation to complete, whilst the user authenticates in the browser of their choice. “QR-code login” as defined by MSC4108 relies on this flow. Checkout the device code grant implementation guide for details about this flow.
How will this look in native mobile apps?
This section needs updating, now that we have stable implementations in mobile clients.
We’ve built proof of concept apps to explore this and show how it can behave:
In both cases it is a lightweight app built using the AppAuth SDK. The homeserver used here is an old version of matrix-authentication-service.
The plan is to build these out a bit further to explore some more of the handover points between the app and homeserver (e.g. for account management).
Does relying on the system browser widen the attack surface?
This is subjective, but we feel relatively confortable to rely on the system browser for multiple reasons:
- most browser have heavy sandboxing between tabs
- on native clients, the underlying operating system also sandboxes between the browser and the client
- this only affects user credentials not E2EE.
- this gives a clear seperation where the system browser is responsible for authenticating, the client is resposible for E2EE. We no longer have a single entity accessing both
- implementations can use many web primitives to further harden their security: matrix-autentication-service for example has no javascript during the login flow, and loads all its assets from the same domain, and uses sub-resource integrity for all of them.
But this still means the user has to execute code provided by the homeserver!
This is true, the flow will involve a device (not necessarily the same one as the one with the Matrix client) displaying a web page provided by the homeserver.
Again, the current implementation in MAS doesn’t require any javascript, so the browser can have javascript disabled and still complete the flow.
The homeserver already had access to the user’s password, so this proposal doesn’t change anything on that regard, which also means we are OK with a ‘lack of improvement’ here, as there is no particular regression here.
Remember that this is a one-time action at the time of logging in, at which point the client doesn’t have access to E2EE messages. Even if some browser-vulnerability in its HTML and CSS handling is used, which would have to break through the multiple layers of sandboxing from the browser and the underlying operating system, the homeserver would still not have access to the user’s E2EE messages.
Isn’t the UX worse for native desktop clients?
Again, this is subjective, but we also feel confortable with saying than the UX will be better, even for desktop native clients.
First, a good chunk of the users of the ecosystem is already using a browser-based flow through m.login.sso
, so this move will make sure that those users are considered as first-class citizens by client developers, enhancing the UX for them.
Second, many servers with open registrations have CAPTCHA protection through Google’s reCAPTCHA. The current implementation is insecure, as it requires homeservers to disable domain verification, making the CAPTCHA usually ask for stronger challenges from users. Some desktop native clients choose to open the system browser anyway for resolving this challenge.
The point here is that native clients already have to rely on system browsers in some cases anyway with the current APIs.
Another argument can then be considered for closed-registrations servers that only allow logging in with the current m.login.password
login API.
With the current APIs, clients are able to show a native-looking form, and this proposal is moving away from this.
We think that relying on the system browser even for password-based accounts is still better for multiple reasons:
- it makes password managers work, as they will save the password associated with the homeserver domain, instead of the client, making using different clients easier
- multiple clients on the same device will usually have to enter their credentials only once
- logging on an untrusted device (like a computer in a public library) is possible through a second trusted device (like a personal mobile phone) without the untrusted device ever seeing the user credentials
- it reduces the risk of phishing, as administrators can train their users to only ever enter their account credentials on one specific website, instead of having them enter their credentials in different clients
How will it work for automation/bot use cases?
For now, the existing m.login.password
isn’t going away, so existing scripts won’t break during migration.
On the long term, there are two things to consider:
- the spec could define a flow specialised for that, like standardise how Matrix could leverage the Client Credentials Grant for that
- implementations can imagine features to help with that. For example, matrix-authentication-service plans to add a “Personal access token” feature to help user issue long-lived access tokens for their bots.
How will this work with E2EE?
It works in the same way that the current password login works: login is separate from E2EE setup.
That said, there are some scenarios that OIDC can help with. For example, when signing in to a new device you can use the OIDC device flow on an existing login to both authorise the sign in and also verify the new device for E2EE.
Does this mean I can’t combine E2EE & account password?
In short, yes. However, in a world that is (gradually) moving away from passwords, this isn’t necessarily a bad thing.
Today there are also many cases where users don’t have a password: SSO, social login, web passkeys etc.
The reason that this doesn’t work well in OIDC is that there isn’t a standard OIDC/OAuth grant that allows for a trusted client to authenticate using a PAKE mechanism meaning that the password can remain in the client.
If the client was to just sent the password to the OpenID Provider like it does today then the E2EE could be broken by the OpenID Provider/homeserver operator.
Part of the reason why there isn’t a grant for this use case is that the OIDC model is predicated on the idea that the client is considered low on the trust ladder and so shouldn’t be trusted with the credentials.
However, with our use case for E2EE the client is high on the trust ladder as it is necessarily responsible for the E2EE integrity.
So, arguably a custom grant using PAKE could be used and not break the trust model in Matrix.
What’s this matrix-authentication-service
that I’ve heard about?
matrix-authentication-service
is a complete rewrite of Synapse’s authentication system, supporting both the next-gen auth APIs and the previous ones.
At this stage, it is still a separate service, requiring a one-way migration from a classic Synapse deployment. It is designed to be lightweight enough (using Rust) that it will be embedded in Synapse at some point.
It is designed to potentially work for other homeservers, so other implementations may choose to leverage it to replace their current auth system.
Are you really rebuilding all of Keycloak in matrix-authentication-service
?!
Hopefully not! In the same way that Matrix is not an authentication protocol, it also doesn’t make sense to completely reinvent a fully-featured identity provider.
Why encrypted bridges don’t work with Synapse + MAS?
The unstable encrypted application services relies on being able to ‘login’ as an application service-controlled user. This particular API doesn’t work with MAS.
In practice, most application services only use /_matrix/client/v3/login
and /_matrix/client/v3/logout
to create and delete Matrix devices.
This is why we also proposed MSC4190 to add APIs to manipulate devices for application services, without using /login
and /logout
.
This API is available since Synapse 1.121.0, and has yet to be adopted by the various bridges.
Will clients need to support both old-style and new-style auth?
For a period of time, yes.
Similarly, some homeservers (depending on how they are being used) will need to support both old-style and new-style client auth for a period of time.
Does this mean that the login page/screen’s branding won’t match the branding of my app any more?
Assuming that you are following best practise, then: yes, the branding on the login form is under the control of the homeserver administrator not the client.
That said, if you are operating your own client and homeserver then you can brand and customise both as you wish.
The openness of the Matrix ecosystem is a defining feature. That a user can choose which client and homeserver to use is a key part of that.
We believe that, by adopting the new auth model and making the division between the client and homeserver more explicit, we can better build trust in the open ecosystem and allow it to continue to grow and flourish.
The branding trade-off is an interesting aspect of this: yes, as a client implementor you may lose some control over the branding of the login page. However, you gain from a more streamlined authentication flow, as explained in better details in the motivation of MSC3861.
Hang on, isn’t this just an MSC? It all sounds very final?
Correct, it is a proposal at this stage. However, we need to prove it first - MSCs require proof in a working implementation before they can be approved.
We’ve outlined the plan here that assumes that the MSC will be successful.