-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Add JWT documentation and improve sample config #7776
Changes from all commits
e341ec9
08578a8
820dfc3
0302489
0c0030b
cd7e06d
9f101aa
a619e90
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Improve the documentation of the non-standard JSON web token login type. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
# JWT Login Type | ||
|
||
Synapse comes with a non-standard login type to support | ||
[JSON Web Tokens](https://en.wikipedia.org/wiki/JSON_Web_Token). In general the | ||
documentation for | ||
[the login endpoint](https://matrix.org/docs/spec/client_server/r0.6.1#login) | ||
is still valid (and the mechanism works similarly to the | ||
[token based login](https://matrix.org/docs/spec/client_server/r0.6.1#token-based)). | ||
|
||
To log in using a JSON Web Token, clients should submit a `/login` request as | ||
follows: | ||
|
||
```json | ||
{ | ||
"type": "org.matrix.login.jwt", | ||
"token": "<jwt>" | ||
} | ||
``` | ||
|
||
Note that the login type of `m.login.jwt` is supported, but is deprecated. This | ||
will be removed in a future version of Synapse. | ||
|
||
The `jwt` should encode the local part of the user ID as the standard `sub` | ||
claim. In the case that the token is not valid, the homeserver must respond with | ||
`401 Unauthorized` and an error code of `M_UNAUTHORIZED`. | ||
|
||
(Note that this differs from the token based logins which return a | ||
`403 Forbidden` and an error code of `M_FORBIDDEN` if an error occurs.) | ||
|
||
As with other login types, there are additional fields (e.g. `device_id` and | ||
`initial_device_display_name`) which can be included in the above request. | ||
|
||
## Preparing Synapse | ||
|
||
The JSON Web Token integration in Synapse uses the | ||
[`PyJWT`](https://pypi.org/project/pyjwt/) library, which must be installed | ||
as follows: | ||
|
||
* The relevant libraries are included in the Docker images and Debian packages | ||
provided by `matrix.org` so no further action is needed. | ||
|
||
* If you installed Synapse into a virtualenv, run `/path/to/env/bin/pip | ||
install synapse[pyjwt]` to install the necessary dependencies. | ||
|
||
* For other installation mechanisms, see the documentation provided by the | ||
maintainer. | ||
|
||
To enable the JSON web token integration, you should then add an `jwt_config` section | ||
to your configuration file (or uncomment the `enabled: true` line in the | ||
existing section). See [sample_config.yaml](./sample_config.yaml) for some | ||
sample settings. | ||
|
||
## How to test JWT as a developer | ||
|
||
Although JSON Web Tokens are typically generated from an external server, the | ||
examples below use [PyJWT](https://pyjwt.readthedocs.io/en/latest/) directly. | ||
|
||
1. Configure Synapse with JWT logins: | ||
|
||
```yaml | ||
jwt_config: | ||
enabled: true | ||
secret: "my-secret-token" | ||
algorithm: "HS256" | ||
Comment on lines
+63
to
+64
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I should note also that I did test this using a private key / public key pair, but for testing using the shared secret is much simpler. |
||
``` | ||
2. Generate a JSON web token: | ||
|
||
```bash | ||
$ pyjwt --key=my-secret-token --alg=HS256 encode sub=test-user | ||
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0LXVzZXIifQ.Ag71GT8v01UO3w80aqRPTeuVPBIBZkYhNTJJ-_-zQIc | ||
``` | ||
3. Query for the login types and ensure `org.matrix.login.jwt` is there: | ||
|
||
```bash | ||
curl http://localhost:8080/_matrix/client/r0/login | ||
``` | ||
4. Login used the generated JSON web token from above: | ||
|
||
```bash | ||
$ curl http://localhost:8082/_matrix/client/r0/login -X POST \ | ||
--data '{"type":"org.matrix.login.jwt","token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0LXVzZXIifQ.Ag71GT8v01UO3w80aqRPTeuVPBIBZkYhNTJJ-_-zQIc"}' | ||
{ | ||
"access_token": "<access token>", | ||
"device_id": "ACBDEFGHI", | ||
"home_server": "localhost:8080", | ||
"user_id": "@test-user:localhost:8480" | ||
} | ||
``` | ||
|
||
You should now be able to use the returned access token to query the client API. |
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -45,10 +45,37 @@ def read_config(self, config, **kwargs): | |||||||||||
|
||||||||||||
def generate_config_section(self, **kwargs): | ||||||||||||
return """\ | ||||||||||||
# The JWT needs to contain a globally unique "sub" (subject) claim. | ||||||||||||
# JSON web token integration. The following settings can be used to make | ||||||||||||
# Synapse JSON web tokens for authentication, instead of its internal | ||||||||||||
# password database. | ||||||||||||
# | ||||||||||||
# Each JSON Web Token needs to contain a "sub" (subject) claim, which is | ||||||||||||
# used as the localpart of the mxid. | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's no guarantee the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently it is assumed that it meets the restrictions. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I looked at this again since I wasn't 100% sure this was true and the string just gets jammed into one of our synapse/synapse/rest/client/v1/login.py Lines 376 to 380 in 21a212f
So yeah, this is essentially completely unchecked. 😢 |
||||||||||||
# | ||||||||||||
# Note that this is a non-standard login type and client support is | ||||||||||||
# expected to be non-existant. | ||||||||||||
# | ||||||||||||
# See https://github.com/matrix-org/synapse/blob/master/docs/jwt.md. | ||||||||||||
# | ||||||||||||
#jwt_config: | ||||||||||||
# enabled: true | ||||||||||||
# secret: "a secret" | ||||||||||||
# algorithm: "HS256" | ||||||||||||
# Uncomment the following to enable authorization using JSON web | ||||||||||||
# tokens. Defaults to false. | ||||||||||||
# | ||||||||||||
#enabled: true | ||||||||||||
|
||||||||||||
# This is either the private shared secret or the public key used to | ||||||||||||
# decode the contents of the JSON web token. | ||||||||||||
# | ||||||||||||
# Required if 'enabled' is true. | ||||||||||||
# | ||||||||||||
#secret: "provided-by-your-issuer" | ||||||||||||
|
||||||||||||
# The algorithm used to sign the JSON web token. | ||||||||||||
# | ||||||||||||
# Supported algorithms are listed at | ||||||||||||
# https://pyjwt.readthedocs.io/en/latest/algorithms.html | ||||||||||||
# | ||||||||||||
# Required if 'enabled' is true. | ||||||||||||
# | ||||||||||||
#algorithm: "provided-by-your-issuer" | ||||||||||||
""" |
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 am somewhat tempted to cheekily change this to a 400. If we ever move login to be more UIA like we won't be able to use 401
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.
Yeah so similar to my comment:
Doing this likely makes sense, but the first step was to document what is going on.