Update JWT login type to support JWKS, custom sub claim, and encode special chars in user ID#9493
Update JWT login type to support JWKS, custom sub claim, and encode special chars in user ID#9493boti7 wants to merge 14 commits intomatrix-org:developfrom MQSdk:feature/jwt-auth
Conversation
Signed-off-by: Botond Horvath <hello@boti7.com>
… ID for JWT logins Signed-off-by: Botond Horvath <hello@boti7.com>
…logins Signed-off-by: Botond Horvath <hello@boti7.com>
Signed-off-by: Botond Horvath <hello@boti7.com>
|
Looks like reasonable improvements! 👍 This seems broken on Python 3.5 (which pyjwt technically doesn't support: jpadilla/pyjwt#585, Synapse will be dropping it shortly). Also could you see if any of the documentation under |
|
@boti7 It seems that some unrelated changes were pushed onto this branch for CI. If those are improvements that would be useful we should do them as a separate PR. Did you see my comment above? Note that we'll be dropping support for Python 3.5 soon, so might make sense to just wait on that if possible. |
|
@clokep this was my fault. We'll roll it all back. |
|
(Also merging in develop should fix the mypy issues.) |
clokep
left a comment
There was a problem hiding this comment.
Looks pretty reasonable overall. I suspect it would be a nice follow-up to move the JWT code into a separate handler instead of sprinkling it into LoginRestServlet.
|
|
||
| if not key and self.jwt_jwks_uri: | ||
| jwks_client = PyJWKClient(self.jwt_jwks_uri) | ||
| signing_key = jwks_client.get_signing_key_from_jwt(token) |
There was a problem hiding this comment.
Does this make a synchronous HTTP call? If so we ideally would do this via a SimpleHttpClient or push this into the background.
There was a problem hiding this comment.
Yes, seems like it makes a synchronous HTTP call. It is also possible to implement the loading and parsing of JWKS without PyJWT, like in OidcHandler, then we have more control over the request and caching.
There was a problem hiding this comment.
Fetching this for every login seems quite inefficient. I wonder if we should do something on start-up (like OIDC). It looks like PyJWKClient is quite simple!
|
I just made a small change to From my side it's totally fine to wait until you drop support for Python 3.5. Also merged in develop, but there are still some mypy issues. |
|
We've now dropped Python 3.5 support 🎉 |
|
I think we're still waiting for some changes here? If nothing else there is a merge conflict. @boti7 please nudge if/when its ready for review 🙂 |
|
@boti7 I'll clean up this conflict and PR. Desperately need escaped sub claim. Auth0 lovingly uses a pipe to separate auth method and ID. |
Rebase JWT-auth changes onto upstream/develop
|
Looks like the JWT tests are failing when using old-deps, possibly need to bump the minimum version of the library? |
|
@erikjohnston It's ready for review from my side. |
clokep
left a comment
There was a problem hiding this comment.
Looks pretty good overall! I wonder if there's enough JWT logic here now that we should move this code to a separate JwtHandler. What do you think?
| "sentry": ["sentry-sdk>=0.7.2"], | ||
| "opentracing": ["jaeger-client>=4.0.0", "opentracing>=2.2.0"], | ||
| "jwt": ["pyjwt>=1.6.4"], | ||
| "jwt": ["pyjwt>=2.1.0"], |
There was a problem hiding this comment.
I asked the packages whether this change would be OK. Can you remind me why we're bumping this?
There was a problem hiding this comment.
Looks like supported versions of Debian and Fedora are on 1.7.1 still. Would it be possible to use that?
There was a problem hiding this comment.
PyJWKClient was added in v2.0.0 and caching of signing keys is supported since v2.1.0: https://github.com/jpadilla/pyjwt/blob/master/CHANGELOG.rst#v210
There was a problem hiding this comment.
I'm not really sure what to do about this, although I do wonder if we should be using PyJWKClient since it bypasses the reactor / current methods for communicating with external resources.
|
|
||
| if not key and self.jwt_jwks_uri: | ||
| jwks_client = PyJWKClient(self.jwt_jwks_uri) | ||
| signing_key = jwks_client.get_signing_key_from_jwt(token) |
There was a problem hiding this comment.
Fetching this for every login seems quite inefficient. I wonder if we should do something on start-up (like OIDC). It looks like PyJWKClient is quite simple!
| subject_claim = self.jwt_subject_claim or "sub" | ||
| user = payload.get(subject_claim, None) |
There was a problem hiding this comment.
We already did the fallback to sub in the config code, no need to do it again.
| subject_claim = self.jwt_subject_claim or "sub" | |
| user = payload.get(subject_claim, None) | |
| user = payload.get(self.jwt_subject_claim, None) |
There was a problem hiding this comment.
The issue is that tests don't use the config code but set hs.config directly, so without specifying a fallback here, many tests in JWTTestCase would fail. What do you suggest to solve this?
There was a problem hiding this comment.
The config code should get run during tests, see:
Lines 469 to 472 in fe604a0
There was a problem hiding this comment.
Were you able to try this again? It should run fine during tests.
Co-authored-by: Patrick Cloke <clokep@users.noreply.github.com>
|
Removing my review -- this has a couple of open questions still that are waiting for responses! |
|
Hey @boti7, are you able to continue working on this? 🙂 Also note that there is now a conflict in |
|
Given the lack of activity, I'm going to close this. @boti7 feel free to reopen if you'd like to continue working on this! Anyone else is free to pick it back up in a new PR as well 🙂 |
This PR adds the following optional fields to the JWT login type configuration:
jwks_uriallows specifying a JSON Web Key Set endpoint where RSA signing keys can be retrieved from, instead of using a secret or public key from the configuration.subject_claimallows specifying a claim other than the default "sub" to use as localpart of the Matrix ID.normalize_user_idenables mapping the localpart from other character sets using themap_username_to_mxid_localpartfunction.Pull Request Checklist
EventStoretoEventWorkerStore.".code blocks.Signed-off-by: Botond Horvath hello@boti7.com