-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New login flow: Use OAuth2 JWT as external identifier #12830
Conversation
This new login flow is an improved version of org.matrix.login.jwt The later * required the OICD provider's public key to be written to the homeserver.yml * accepted only one possible issuer of JWT tokens * has its own section in homeserver.yml and completely ignores 'oidc_providers' * Used the 'sub' from the JWT as localpart of the user's address * required the JWT to be sent in the body of the login request * Created a new user if it wasn't found - no configuration possible The new login flow (called org.matrix.login_oidc_jwt) * uses section 'oidc_providers' from homeserver.yml * accepts all configured providers as (possible) issuer of JWT tokens * uses the configured 'jwks_uri' to fetch the provider's public key * fetches the JWT either from the body and if there's none it checks the 'Authentication' http header * extracts iss/sub from JWT and searches the 'external_ids' of the user database. If such an entry is found the user is authorized; otherwise the user is rejected
New config parameters in section 'oidc_providers': * sso_jwt_enabled (boolean) - allows an admin to disable the new login flow for a given oidc_provider while at the same time keep the standard sso login flow for the oidc_provider allowed * standalone_jwt_audience (string) - if the new JWT login flow is allowed for an oidc_provider then this parameter can be used to enforce a specific audience claim to be contained in the JWT (otherwise the login attempt will be rejected)
Signed-off-by: Hannes Lerchl <[email protected]>
Signed-off-by: Hannes Lerchl <[email protected]>
[Edited by @richvdh for clearer formatting] This new login flow is an improved version of The latter
The new login flow (called
|
* generated sample_config * used black to format code * fixed tyoe hint findings of mypy
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.
Thanks very much for this contribution: I've not reviewed the code in detail, but it looks quite comprehensive.
I'm a bit confused about how this works though.
It's not really clear to me what benefit this offers over the existing JWT support (see https://matrix-org.github.io/synapse/latest/jwt.html). In particular, you appear to be skipping the OIDC flow (or at least, Synapse has no involvement with OIDC), so the use of oidc_providers
seems rather arbitrary. I may well be missing something here though.
I'll also mention, for completeness, that there are efforts underway to replace authentication in Matrix with standard OAuth2 mechanisms (see matrix-org/matrix-spec-proposals#2964). Part of that work will see most of Synapse's authentication code (including the current JWT support and OidcHandler
) ripped out, and replaced with an external authentication service (https://github.com/matrix-org/matrix-authentication-service).
[JSON Web Tokens](https://en.wikipedia.org/wiki/JSON_Web_Token) | ||
as external identifiers. | ||
The general mechanics is similar to other standard | ||
[authentication types](https://spec.matrix.org/v1.2/client-server-api/#authentication-types). |
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.
This link refers to "user-interactive authentication", which is not used by /_matrix/client/v3/login
.
A more relevant link is https://spec.matrix.org/v1.2/client-server-api/#login, which documents the authentication types currently supported by /login
.
Oh, I've just seen your comment at #12830 (comment) - sorry, I should have read that first. But honestly, the list you provide there sound like things that should be fixed in the existing JWT support, rather than completely reinventing it:
Ok, so let's add support for loading the keys from a URL to
... and support for multiple issuers
This sounds like a feature, not a bug? Why should they be the same thing?
Yup, it would be nice to add a mapping mechanism to
Given it's a custom API, I don't see why this is a problem?
Also something we can add to |
#9493 seems to implement some of these features for the current JWT flow. |
Thanks for your answers and thoughts I'd like to reorder your responses so "the bigger part" is combined at the end
Because both sections basically configure "the same thing". If an admin wants to allow users to log in via a redirect-based OIDC flow as well as through JWT acquired from another app, then there'll be two similar config section which imo violate the DRY principle. On the other hand my overview of the system and its history is very limited.
The Now these answers all seem to me to point towards
The behaviour of my proposed mechanism is different from the one of If so: how important is it to 100% keep the current behaviour intact or at least available? |
Right, it wasn't obvious that you wanted to allow users to log in via either OIDC or JWT (and use the same providers for both). That seems like a bit of a niche requirement to me, to be honest. Could you expand on the usecase for it?
Yeah, the problems here are actually worse than DRY, since Synapse will need to know that a user that arrives at I guess having an
Kinda, but it seems to me that model assumes that you're going to use the JWT for the duration of your interaction with the system. In this case we're just using it for a single That said, I don't see a huge issue with extending
The existing functionality is used, so we should avoid disrupting it more than absolutely necessary. But I think it should be possible to support both mechanisms via |
@@ -1986,6 +1986,20 @@ saml2_config: | |||
# match a pre-existing account instead of failing. This could be used if | |||
# switching from password logins to OIDC. Defaults to false. | |||
# | |||
# sso_jwt_enabled: by using the login flow org.matrix.login.sso_jwt it |
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.
shouldn't this rather be called something like allow_standalone_jwt
?
# standalone_jwt_audience: if sso_jwt_enabled is 'true' (or not set) | ||
# then we accept JWT token acquired via another application. In this case | ||
# there's an additional check: the audience claim given in the token | ||
# must contain this entry. | ||
# | ||
# If there is no audience configured then this check is skipped. |
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 does this only apply in the standalone case? Is there not a usecase for restricting by audience in the OIDC case?
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.
Also: I note that this is a list of acceptable audiences for jwt_config
. We should probably have the same here, for conistency.
# provider) via another application. If this should be disallowed | ||
# _for this oidc_provider_ then set this value to 'false'. | ||
# | ||
# If not set this defaults to 'true'. |
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.
should it not default to false? it seems like that would be safer.
also: if it is set, then there needs to be a JWKS for this provider, and some oidc providers do not have a jwks_uri
. If allow_standalone_jwt
is enabled for an oidc provider without a jwks_uri
, we should detect that and report an error.
Hi there, I did some prototyping and I think I'm going to re-implement this PR (based on the then latest Regarding your comments
I'm planning to
|
Also I have a (different) question: just today I stumbled upon the lines
and became aware that while Would it be OK, if I drop PyJWT and use authlib for jwt login, too? |
Yes, rationalising this sounds like it would be great, thank you! Suggest making a separate PR for it though, rather than mixing it in with other functionality changes. |
Might I also suggest that if the JWT logic becomes complicated, it could make sense to split some of it out into a separate handler (instead of embedding it all into the login REST servlet). |
Pull Request Checklist
EventStore
toEventWorkerStore
.".code blocks
.(run the linters)