Merge remote-tracking branch 'origin/main' into quenting/schemars-0.9
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
- [Policy engine](./topics/policy.md)
|
||||
- [Authorization and sessions](./topics/authorization.md)
|
||||
- [Use the Admin API](./topics/admin-api.md)
|
||||
- [Get an access token](./topics/access-token.md)
|
||||
|
||||
# Reference
|
||||
|
||||
|
||||
2452
docs/api/spec.json
2452
docs/api/spec.json
File diff suppressed because it is too large
Load Diff
@@ -240,8 +240,13 @@
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"client_secret_file": {
|
||||
"description": "Path to the file containing the client secret. The client secret is used\n by the `client_secret_basic`, `client_secret_post` and\n `client_secret_jwt` authentication methods.",
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"client_secret": {
|
||||
"description": "The client secret, used by the `client_secret_basic`,\n `client_secret_post` and `client_secret_jwt` authentication methods",
|
||||
"description": "Alternative to `client_secret_file`: Reads the client secret directly\n from the config.",
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
@@ -1561,7 +1566,9 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"kid": {
|
||||
"type": "string"
|
||||
"description": "The key ID `kid` of the key as used by JWKs.\n\n If not given, `kid` will be the key’s RFC 7638 JWK Thumbprint.",
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"password_file": {
|
||||
"type": "string",
|
||||
@@ -1579,10 +1586,7 @@
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kid"
|
||||
]
|
||||
}
|
||||
},
|
||||
"PasswordsConfig": {
|
||||
"description": "User password hashing config",
|
||||
@@ -1701,9 +1705,13 @@
|
||||
"type": "string",
|
||||
"default": "localhost:8008"
|
||||
},
|
||||
"secret_file": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"secret": {
|
||||
"description": "Shared secret to use for calls to the admin API",
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"endpoint": {
|
||||
"description": "The base URL of the homeserver's client API",
|
||||
@@ -1711,23 +1719,30 @@
|
||||
"format": "uri",
|
||||
"default": "http://localhost:8008/"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"secret"
|
||||
]
|
||||
}
|
||||
},
|
||||
"HomeserverKind": {
|
||||
"description": "The kind of homeserver it is.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Homeserver is Synapse",
|
||||
"description": "Homeserver is Synapse, version 1.135.0 or newer",
|
||||
"type": "string",
|
||||
"const": "synapse"
|
||||
},
|
||||
{
|
||||
"description": "Homeserver is Synapse, in read-only mode\n\n This is meant for testing rolling out Matrix Authentication Service with\n no risk of writing data to the homeserver.",
|
||||
"description": "Homeserver is Synapse, version 1.135.0 or newer, in read-only mode\n\n This is meant for testing rolling out Matrix Authentication Service with\n no risk of writing data to the homeserver.",
|
||||
"type": "string",
|
||||
"const": "synapse_read_only"
|
||||
},
|
||||
{
|
||||
"description": "Homeserver is Synapse, using the legacy API",
|
||||
"type": "string",
|
||||
"const": "synapse_legacy"
|
||||
},
|
||||
{
|
||||
"description": "Homeserver is Synapse, with the modern API available (>= 1.135.0)",
|
||||
"type": "string",
|
||||
"const": "synapse_modern"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -2165,6 +2180,14 @@
|
||||
"description": "Whether the `login_hint` should be forwarded to the provider in the\n authorization request.\n\n Defaults to `false`.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"on_backchannel_logout": {
|
||||
"description": "What to do when receiving an OIDC Backchannel logout request.\n\n Defaults to `do_nothing`.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/OnBackchannelLogout"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -2363,6 +2386,14 @@
|
||||
"description": "The Jinja2 template to use for the localpart attribute\n\n If not provided, the default template is `{{ user.preferred_username }}`",
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"on_conflict": {
|
||||
"description": "How to handle conflicts on the claim, default value is `Fail`",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/OnConflict"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2391,6 +2422,21 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"OnConflict": {
|
||||
"description": "How to handle an existing localpart claim",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Fails the sso login on conflict",
|
||||
"type": "string",
|
||||
"const": "fail"
|
||||
},
|
||||
{
|
||||
"description": "Adds the oauth identity link, regardless of whether there is an existing\n link or not",
|
||||
"type": "string",
|
||||
"const": "add"
|
||||
}
|
||||
]
|
||||
},
|
||||
"DisplaynameImportPreference": {
|
||||
"description": "What should be done for the displayname attribute",
|
||||
"type": "object",
|
||||
@@ -2440,6 +2486,26 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"OnBackchannelLogout": {
|
||||
"description": "What to do when receiving an OIDC Backchannel logout request.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Do nothing",
|
||||
"type": "string",
|
||||
"const": "do_nothing"
|
||||
},
|
||||
{
|
||||
"description": "Only log out the MAS 'browser session' started by this OIDC session",
|
||||
"type": "string",
|
||||
"const": "logout_browser_only"
|
||||
},
|
||||
{
|
||||
"description": "Log out all sessions started by this OIDC session, including MAS\n 'browser sessions' and client sessions",
|
||||
"type": "string",
|
||||
"const": "logout_all"
|
||||
}
|
||||
]
|
||||
},
|
||||
"BrandingConfig": {
|
||||
"description": "Configuration section for tweaking the branding of the service",
|
||||
"type": "object",
|
||||
@@ -2538,6 +2604,10 @@
|
||||
"description": "Whether to enable self-service password registration. Defaults to\n `false` if password authentication is enabled.\n\n This has no effect if password login is disabled.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"password_registration_email_required": {
|
||||
"description": "Whether self-service password registrations require a valid email.\n Defaults to `true`.\n\n This has no effect if password registration is disabled.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"password_change_allowed": {
|
||||
"description": "Whether users are allowed to change their passwords. Defaults to `true`.\n\n This has no effect if password login is disabled.",
|
||||
"type": "boolean"
|
||||
|
||||
@@ -4,7 +4,7 @@ This document aims to get you started with contributing to the Matrix Authentica
|
||||
|
||||
## 1. Who can contribute to MAS?
|
||||
|
||||
Everyone is welcome to contribute code to [Synapse](https://github.com/element-hq/matrix-authentication-service), provided that they are willing to license their contributions to Element under a [Contributor License Agreement](https://cla-assistant.io/element-hq/matrix-authentication-service) (CLA). This ensures that their contribution will be made available under an OSI-approved open-source license, currently Affero General Public License v3 (AGPLv3).
|
||||
Everyone is welcome to contribute code to [Matrix Authentication Service](https://github.com/element-hq/matrix-authentication-service), provided that they are willing to license their contributions to Element under a [Contributor License Agreement](https://cla-assistant.io/element-hq/matrix-authentication-service) (CLA). This ensures that their contribution will be made available under an OSI-approved open-source license, currently Affero General Public License v3 (AGPLv3).
|
||||
|
||||
Please see the [Element blog post](https://element.io/blog/synapse-now-lives-at-github-com-element-hq-synapse/) for the full rationale.
|
||||
|
||||
@@ -72,6 +72,7 @@ Make sure your code adheres to our Rust and TypeScript code style by running:
|
||||
|
||||
- `cargo +nightly fmt` (with the nightly toolchain installed)
|
||||
- `npm run format` in the `frontend` directory
|
||||
- `make fmt` in the `policies` directory (if changed)
|
||||
|
||||
When updating SQL queries in the `crates/storage-pg/` crate, you may need to update the `sqlx` introspection data. To do this, make sure to install `cargo-sqlx` (`cargo install sqlx-cli`) and:
|
||||
|
||||
@@ -86,11 +87,18 @@ While you're developing and before submitting a patch, you'll want to test your
|
||||
|
||||
- Run `cargo clippy --workspace` to lint the Rust code.
|
||||
- Run `npm run lint` in the `frontend` directory to lint the frontend code.
|
||||
- Run `make fmt` and `make lint` in the `policies` directory to format and lint the included policy.
|
||||
|
||||
### Run the tests
|
||||
|
||||
- Run the tests to the backend by running `cargo test --workspace`. This requires a connection to a PostgreSQL database, set via the `DATABASE_URL` environment variable.
|
||||
If you haven't already, install [Cargo-Nextest](https://nexte.st/docs/installation/pre-built-binaries/).
|
||||
|
||||
- Run the tests to the backend by running `cargo nextest run --workspace`. This requires a connection to a PostgreSQL database, set via the `DATABASE_URL` environment variable.
|
||||
- Run the tests to the frontend by running `npm run test` in the `frontend` directory.
|
||||
- To run the tests for the included policy, change to the `policies` directory and run one of:
|
||||
- `make test` (needs Open Policy Agent installed)
|
||||
- `make PODMAN=1 test` (runs inside a container; needs Podman installed)
|
||||
- `make DOCKER=1 test` (runs inside a container; needs Docker installed)
|
||||
|
||||
## 8. Submit a pull request
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ At this point, the releaser should check the changelog and ensure the "Set as pr
|
||||
1. Wait for [CI to churn] and the [draft release to appear]. This takes about 30 minutes.
|
||||
1. Double-check the changelog on the draft release.
|
||||
1. Check the "Set as pre-release" checkbox, and publish the release.
|
||||
1. Delete the N-2 release branch on [Localazy], meaning that once the 0.16 release cycle begins, the 0.14 release branch will be deleted.
|
||||
1. Delete the N-2 release branch on [Localazy](https://localazy.com/console/branching), meaning that once the 0.16 release cycle begins, the 0.14 release branch will be deleted.
|
||||
- Create new release candidates if needed:
|
||||
1. Run the `translations-download` workflow on the release branch.
|
||||
1. Wait for the [translation download PR] to be automatically merged.
|
||||
@@ -117,7 +117,7 @@ At this point, the releaser should check the changelog and ensure the "Set as pr
|
||||
[`translations-download` workflow]: https://github.com/element-hq/matrix-authentication-service/actions/workflows/translations-download.yaml
|
||||
[`release-branch` workflow]: https://github.com/element-hq/matrix-authentication-service/actions/workflows/release-branch.yaml
|
||||
[`release-bump` workflow]: https://github.com/element-hq/matrix-authentication-service/actions/workflows/release-bump.yaml
|
||||
[`build` workflow]: https://github.com/element-hq/matrix-authentication-service/actions/workflows/build
|
||||
[`build` workflow]: https://github.com/element-hq/matrix-authentication-service/actions/workflows/build.yaml
|
||||
[translation download PR]: https://github.com/element-hq/matrix-authentication-service/pulls?q=is%3Apr+label%3AA-I18n
|
||||
[CI to churn]: https://github.com/element-hq/matrix-authentication-service/actions/workflows/build.yaml?query=event%3Apush+actor%3Amatrixbot
|
||||
[draft release to appear]: https://github.com/element-hq/matrix-authentication-service/releases
|
||||
|
||||
@@ -23,6 +23,32 @@ $ mas-cli manage add-email <username> <email>
|
||||
$ mas-cli manage verify-email <username> <email>
|
||||
```
|
||||
|
||||
## `manage promote-admin`
|
||||
|
||||
Make a user admin.
|
||||
|
||||
```
|
||||
$ mas-cli manage promote-admin <username>
|
||||
```
|
||||
|
||||
**This doesn't make all the users sessions admin, but rather lets the user request admin access in administration tools.**
|
||||
|
||||
## `manage demote-admin`
|
||||
|
||||
Make a user non-admin.
|
||||
|
||||
```
|
||||
$ mas-cli manage demote-admin <username>
|
||||
```
|
||||
|
||||
## `manage list-admin-users`
|
||||
|
||||
List all users with admin privileges.
|
||||
|
||||
```
|
||||
$ mas-cli manage list-admins
|
||||
```
|
||||
|
||||
## `manage set-password`
|
||||
|
||||
Set a user password.
|
||||
@@ -93,8 +119,11 @@ $ mas-cli manage lock-user <username> --deactivate
|
||||
|
||||
Unlock a user.
|
||||
|
||||
Options:
|
||||
- `--reactivate`: Whether to reactivate the user.
|
||||
|
||||
```
|
||||
$ mas-cli manage unlock-user <username>
|
||||
$ mas-cli manage unlock-user <username> --reactivate
|
||||
```
|
||||
|
||||
## `manage register-user`
|
||||
|
||||
@@ -135,7 +135,9 @@ matrix:
|
||||
|
||||
# Shared secret used to authenticate the service to the homeserver
|
||||
# This must be of high entropy, because leaking this secret would allow anyone to perform admin actions on the homeserver
|
||||
secret: "SomeRandomSecret"
|
||||
secret_file: /path/to/secret/file
|
||||
# Alternatively, the shared secret can be passed inline.
|
||||
# secret: "SomeRandomSecret"
|
||||
|
||||
# URL to which the homeserver is accessible from the service
|
||||
endpoint: "http://localhost:8008"
|
||||
@@ -170,7 +172,8 @@ clients:
|
||||
# Confidential client
|
||||
- client_id: 000000000000000000000FIRST
|
||||
client_auth_method: client_secret_post
|
||||
client_secret: secret
|
||||
client_secret_file: secret
|
||||
# OR client_secret: c1!3n753c237
|
||||
# List of authorized redirect URIs
|
||||
redirect_uris:
|
||||
- http://localhost:1234/callback
|
||||
@@ -194,35 +197,7 @@ secrets:
|
||||
# Signing keys
|
||||
keys:
|
||||
# It needs at least an RSA key to work properly
|
||||
- kid: "ahM2bien"
|
||||
key: |
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAuf28zPUp574jDRdX6uN0d7niZCIUpACFo+Po/13FuIGsrpze
|
||||
yMX6CYWVPalgXW9FCrhxL+4toJRy5npjkgsLFsknL5/zXbWKFgt69cMwsWJ9Ra57
|
||||
bonSlI7SoCuHhtw7j+sAlHAlqTOCAVz6P039Y/AGvO6xbC7f+9XftWlbbDcjKFcb
|
||||
pQilkN9qtkdEH7TLayMAFOsgNvBlwF9+oj9w5PIk3veRTdBXI4GlHjhhzqGZKiRp
|
||||
oP9HnycHHveyT+C33vuhQso5a3wcUNuvDVOixSqR4kvSt4UVWNK/KmEQmlWU1/m9
|
||||
ClIwrs8Q79q0xkGaSa0iuG60nvm7tZez9TFkxwIDAQABAoIBAHA5YkppQ7fJSm0D
|
||||
wNDCHeyABNJWng23IuwZAOXVNxB1bjSOAv8yNgS4zaw/Hx5BnW8yi1lYZb+W0x2u
|
||||
i5X7g91j0nkyEi5g88kJdFAGTsM5ok0BUwkHsEBjTUPIACanjGjya48lfBP0OGWK
|
||||
LJU2Acbjda1aeUPFpPDXw/w6bieEthQwroq3DHCMnk6i9bsxgIOXeN04ij9XBmsH
|
||||
KPCP2hAUnZSlx5febYfHK7/W95aJp22qa//eHS8cKQZCJ0+dQuZwLhlGosTFqLUm
|
||||
qhPlt/b1EvPPY0cq5rtUc2W31L0YayVEHVOQx1fQIkH2VIUNbAS+bfVy+o6WCRk6
|
||||
s1XDhsECgYEA30tykVTN5LncY4eQIww2mW8v1j1EG6ngVShN3GuBTuXXaEOB8Duc
|
||||
yT7yJt1ZhmaJwMk4agmZ1/f/ZXBtfLREGVzVvuwqRZ+LHbqIyhi0wQJA0aezPote
|
||||
uTQnFn+IveHGtpQNDYGL/UgkexuCxbc2HOZG51JpunCK0TdtVfO/9OUCgYEA1TuS
|
||||
2WAXzNudRG3xd/4OgtkLD9AvfSvyjw2LkwqCMb3A5UEqw7vubk/xgnRvqrAgJRWo
|
||||
jndgRrRnikHCavDHBO0GAO/kzrFRfw+e+r4jcLl0Yadke8ndCc7VTnx4wQCrMi5H
|
||||
7HEeRwaZONoj5PAPyA5X+N/gT0NNDA7KoQT45DsCgYBt+QWa6A5jaNpPNpPZfwlg
|
||||
9e60cAYcLcUri6cVOOk9h1tYoW7cdy+XueWfGIMf+1460Z90MfhP8ncZaY6yzUGA
|
||||
0EUBO+Tx10q3wIfgKNzU9hwgZZyU4CUtx668mOEqy4iHoVDwZu4gNyiobPsyDzKa
|
||||
dxtSkDc8OHNV6RtzKpJOtQKBgFoRGcwbnLH5KYqX7eDDPRnj15pMU2LJx2DJVeU8
|
||||
ERY1kl7Dke6vWNzbg6WYzPoJ/unrJhFXNyFmXj213QsSvN3FyD1pFvp/R28mB/7d
|
||||
hVa93vzImdb3wxe7d7n5NYBAag9+IP8sIJ/bl6i9619uTxwvgtUqqzKPuOGY9dnh
|
||||
oce1AoGBAKZyZc/NVgqV2KgAnnYlcwNn7sRSkM8dcq0/gBMNuSZkfZSuEd4wwUzR
|
||||
iFlYp23O2nHWggTkzimuBPtD7Kq4jBey3ZkyGye+sAdmnKkOjNILNbpIZlT6gK3z
|
||||
fBaFmJGRJinKA+BJeH79WFpYN6SBZ/c3s5BusAbEU7kE5eInyazP
|
||||
-----END RSA PRIVATE KEY-----
|
||||
- key_file: keys/rsa_key
|
||||
- kid: "iv1aShae"
|
||||
key: |
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
@@ -257,16 +232,24 @@ The following key types are supported:
|
||||
- ECDSA with the P-384 (`secp384r1`) curve
|
||||
- ECDSA with the K-256 (`secp256k1`) curve
|
||||
|
||||
Each entry must have a unique (and arbitrary) `kid`, plus the key itself.
|
||||
The key can either be specified inline (with the `key` property), or loaded from a file (with the `key_file` property).
|
||||
Each entry in the list corresponds to one signing key used by MAS.
|
||||
The key can either be specified inline (with the `key` property),
|
||||
or loaded from a file (with the `key_file` property).
|
||||
The following key formats are supported:
|
||||
|
||||
- PKCS#1 PEM or DER-encoded RSA private key
|
||||
- PKCS#8 PEM or DER-encoded RSA or ECDSA private key, encrypted or not
|
||||
- SEC1 PEM or DER-encoded ECDSA private key
|
||||
|
||||
A [JWK Key ID] is automatically derived from each key.
|
||||
To override this default, set `kid` to a custom value.
|
||||
The `kid` can be any case-sensitive string value as long as it is unique to this list;
|
||||
a key’s `kid` value must be stable across restarts.
|
||||
|
||||
For PKCS#8 encoded keys, the `password` or `password_file` properties can be used to decrypt the key.
|
||||
|
||||
[JWK Key ID]: <https://datatracker.ietf.org/doc/html/rfc7517#section-4.5>
|
||||
|
||||
## `passwords`
|
||||
|
||||
Settings related to the local password database
|
||||
@@ -313,6 +296,12 @@ account:
|
||||
# This has no effect if password login is disabled.
|
||||
password_registration_enabled: false
|
||||
|
||||
# Whether self-service registrations require a valid email
|
||||
#
|
||||
# Defaults to `true`
|
||||
# This has no effect if password registration is disabled.
|
||||
password_registration_email_required: true
|
||||
|
||||
# Whether users are allowed to change their passwords
|
||||
#
|
||||
# Defaults to `true`.
|
||||
@@ -740,6 +729,13 @@ upstream_oauth2:
|
||||
# authorization request.
|
||||
#forward_login_hint: false
|
||||
|
||||
# What to do when receiving an OIDC Backchannel logout request.
|
||||
# Possible values are:
|
||||
# - `do_nothing` (default): do nothing, other than validating and logging the request
|
||||
# - `logout_browser_only`: Only log out the MAS 'browser session' started by this OIDC session
|
||||
# - `logout_all`: Log out all sessions started by this OIDC session, including MAS 'browser sessions' and client sessions
|
||||
#on_backchannel_logout: do_nothing
|
||||
|
||||
# How user attributes should be mapped
|
||||
#
|
||||
# Most of those attributes have two main properties:
|
||||
@@ -770,6 +766,12 @@ upstream_oauth2:
|
||||
#action: force
|
||||
#template: "{{ user.preferred_username }}"
|
||||
|
||||
# How to handle when localpart already exists.
|
||||
# Possible values are (default: fail):
|
||||
# - `add` : Adds the upstream account link to the existing user, regardless of whether there is an existing link or not.
|
||||
# - `fail` : Fails the upstream OAuth 2.0 login.
|
||||
#on_conflict: fail
|
||||
|
||||
# The display name is the user's display name.
|
||||
displayname:
|
||||
#action: suggest
|
||||
@@ -795,6 +797,37 @@ upstream_oauth2:
|
||||
#template: "@{{ user.preferred_username }}"
|
||||
```
|
||||
|
||||
## `branding`
|
||||
|
||||
Configuration section for tweaking the branding of the service.
|
||||
|
||||
```yaml
|
||||
branding:
|
||||
# A human-readable name. Defaults to the server's address.
|
||||
#service_name:
|
||||
|
||||
# Link to a privacy policy, displayed in the footer of web pages and
|
||||
# emails. It is also advertised to clients through the `op_policy_uri`
|
||||
# OIDC provider metadata.
|
||||
#policy_uri:
|
||||
|
||||
# Link to a terms of service document, displayed in the footer of web
|
||||
# pages and emails. It is also advertised to clients through the
|
||||
# `op_tos_uri` OIDC provider metadata.
|
||||
#
|
||||
# This also adds a mandatory checkbox during registration. The value of
|
||||
# this config item will be stored in the `user_terms` table to indicate
|
||||
# which ToS document the user accepted. Note that currently changing this
|
||||
# value will not force existing users to re-accept terms.
|
||||
#tos_uri:
|
||||
|
||||
# Legal imprint, displayed in the footer in the footer of web pages and emails.
|
||||
#imprint:
|
||||
|
||||
# Logo displayed in some web pages.
|
||||
#logo_uri:
|
||||
```
|
||||
|
||||
## `experimental`
|
||||
|
||||
Settings that may change or be removed in future versions.
|
||||
|
||||
@@ -4,9 +4,8 @@ The [default policy](../topics/policy.md#authorization-requests) shipped with MA
|
||||
|
||||
- [`openid`](#openid)
|
||||
- [`email`](#email)
|
||||
- [`urn:matrix:org.matrix.msc2967.client:api:*`](#urnmatrixorgmatrixmsc2967clientapi)
|
||||
- [`urn:matrix:org.matrix.msc2967.client:device:[device id]`](#urnmatrixorgmatrixmsc2967clientdevicedevice-id)
|
||||
- [`urn:matrix:org.matrix.msc2967.client:guest`](#urnmatrixorgmatrixmsc2967clientguest)
|
||||
- [`urn:matrix:client:api:*`](#urnmatrixclientapi)
|
||||
- [`urn:matrix:client:device:[device id]`](#urnmatrixclientdevicedevice-id)
|
||||
- [`urn:synapse:admin:*`](#urnsynapseadmin)
|
||||
- [`urn:mas:admin`](#urnmasadmin)
|
||||
- [`urn:mas:graphql:*`](#urnmasgraphql)
|
||||
@@ -33,13 +32,13 @@ The default policy allows any client and any user to request this scope.
|
||||
|
||||
Those scopes are specific to the Matrix protocol and are part of [MSC2967].
|
||||
|
||||
### `urn:matrix:org.matrix.msc2967.client:api:*`
|
||||
### `urn:matrix:client:api:*`
|
||||
|
||||
This scope grants access to the full Matrix client-server API.
|
||||
|
||||
The default policy allows any client and any user to request this scope.
|
||||
|
||||
### `urn:matrix:org.matrix.msc2967.client:device:[device id]`
|
||||
### `urn:matrix:client:device:[device id]`
|
||||
|
||||
This scope sets the device ID of the session, where `[device id]` is the device ID of the session.
|
||||
Currently, MAS only allows the following characters in the device ID: `a-z`, `A-Z`, `0-9` and `-`.
|
||||
@@ -49,15 +48,6 @@ There can only be one device ID in the scope list of a session.
|
||||
|
||||
The default policy allows any client and any user to request this scope.
|
||||
|
||||
### `urn:matrix:org.matrix.msc2967.client:guest`
|
||||
|
||||
This scope grants access to a restricted set of endpoints that are available to guest users.
|
||||
It is mutually exclusive with the `urn:matrix:org.matrix.msc2967.client:api:*` scope.
|
||||
|
||||
Note that MAS doesn't yet implement any special semantic around guest users, but this scope is reserved for future use.
|
||||
|
||||
The default policy allows any client and any user to request this scope.
|
||||
|
||||
## Synapse-specific scopes
|
||||
|
||||
MAS also supports one Synapse-specific scope, which aren't formally defined in any specification.
|
||||
@@ -67,7 +57,7 @@ MAS also supports one Synapse-specific scope, which aren't formally defined in a
|
||||
This scope grants access to the [Synapse admin API].
|
||||
|
||||
Because of how Synapse works for now, this scope by itself isn't sufficient to access the admin API.
|
||||
A session wanting to access the admin API also needs to have the `urn:matrix:org.matrix.msc2967.client:api:*` scope.
|
||||
A session wanting to access the admin API also needs to have the `urn:matrix:client:api:*` scope.
|
||||
|
||||
The default policy doesn't allow everyone to request this scope.
|
||||
It allows:
|
||||
|
||||
@@ -1,74 +1,46 @@
|
||||
# Homeserver configuration
|
||||
|
||||
The `matrix-authentication-service` is designed to be run alongside a Matrix homeserver.
|
||||
It currently only supports [Synapse](https://github.com/element-hq/synapse) through the experimental OAuth delegation feature.
|
||||
It currently only supports [Synapse](https://github.com/element-hq/synapse) version 1.136.0 or later.
|
||||
The authentication service needs to be able to call the Synapse admin API to provision users through a shared secret, and Synapse needs to be able to call the service to verify access tokens using the OAuth 2.0 token introspection endpoint.
|
||||
|
||||
## Provision a client for the Homeserver to use
|
||||
|
||||
In the [`clients`](../reference/configuration.md#clients) section of the configuration file, add a new client with the following properties:
|
||||
|
||||
- `client_id`: a unique identifier for the client. It must be a valid [ULID](https://github.com/ulid/spec), and it happens that `0000000000000000000SYNAPSE` is a valid ULID.
|
||||
- `client_auth_method`: set to `client_secret_basic`. Other methods are possible, but this is the easiest to set up.
|
||||
- `client_secret`: a shared secret used for the homeserver to authenticate
|
||||
|
||||
```yaml
|
||||
clients:
|
||||
- client_id: 0000000000000000000SYNAPSE
|
||||
client_auth_method: client_secret_basic
|
||||
client_secret: "SomeRandomSecret"
|
||||
```
|
||||
|
||||
**Don't forget to sync the configuration file** with the database after adding the client, using the [`config sync`](../reference/cli/config.md#config-sync---prune---dry-run) command.
|
||||
|
||||
## Configure the connection to the homeserver
|
||||
|
||||
In the [`matrix`](../reference/configuration.md#matrix) section of the configuration file, add the following properties:
|
||||
|
||||
- `kind`: the type of homeserver to connect to, currently only `synapse` is supported
|
||||
- `homeserver`: corresponds to the `server_name` in the Synapse configuration file
|
||||
- `secret`: a shared secret the service will use to call the homeserver admin API
|
||||
- `secret`: a shared secret the service will use to call the homeserver MAS API
|
||||
- `endpoint`: the URL to which the homeserver is accessible from the service
|
||||
|
||||
```yaml
|
||||
matrix:
|
||||
homeserver: localhost:8008
|
||||
secret: "AnotherRandomSecret"
|
||||
kind: synapse
|
||||
homeserver: example.com
|
||||
endpoint: "http://localhost:8008"
|
||||
secret: "AVeryRandomSecretPleaseUseSomethingSecure"
|
||||
# Alternatively, using a file:
|
||||
#secret_path: /path/to/secret.txt
|
||||
```
|
||||
|
||||
## Configure the homeserver to delegate authentication to the service
|
||||
|
||||
Set up the delegated authentication feature in the Synapse configuration in the `experimental_features` section:
|
||||
Set up the delegated authentication feature **in the Synapse configuration** in the `matrix_authentication_service` section:
|
||||
|
||||
```yaml
|
||||
experimental_features:
|
||||
msc3861:
|
||||
enabled: true
|
||||
|
||||
# Synapse will call `{issuer}/.well-known/openid-configuration` to get the OIDC configuration
|
||||
issuer: http://localhost:8080/
|
||||
|
||||
# Matches the `client_id` in the auth service config
|
||||
client_id: 0000000000000000000SYNAPSE
|
||||
# Matches the `client_auth_method` in the auth service config
|
||||
client_auth_method: client_secret_basic
|
||||
# Matches the `client_secret` in the auth service config
|
||||
client_secret: "SomeRandomSecret"
|
||||
|
||||
# Matches the `matrix.secret` in the auth service config
|
||||
admin_token: "AnotherRandomSecret"
|
||||
|
||||
# URL to advertise to clients where users can self-manage their account
|
||||
# Defaults to the URL advertised by MAS, e.g. `https://{public_mas_domain}/account/`
|
||||
#account_management_url: "http://localhost:8080/account/"
|
||||
|
||||
# URL which Synapse will use to introspect access tokens
|
||||
# Defaults to the URL advertised by MAS, e.g. `https://{public_mas_domain}/oauth2/introspect`
|
||||
# This is useful to override if Synapse has a way to call the auth service's
|
||||
# introspection endpoint directly, skipping intermediate reverse proxies
|
||||
#introspection_endpoint: "http://localhost:8080/oauth2/introspect"
|
||||
matrix_authentication_service:
|
||||
enabled: true
|
||||
endpoint: http://localhost:8080/
|
||||
secret: "AVeryRandomSecretPleaseUseSomethingSecure"
|
||||
# Alternatively, using a file:
|
||||
#secret_file: /path/to/secret.txt
|
||||
```
|
||||
|
||||
The `endpoint` property should be set to the URL of the authentication service.
|
||||
This can be an internal URL, to avoid unnecessary round-trips.
|
||||
|
||||
The `secret` property must match in both the Synapse configuration and the Matrix Authentication Service configuration.
|
||||
|
||||
## Set up the compatibility layer
|
||||
|
||||
The service exposes a compatibility layer to allow legacy clients to authenticate using the service.
|
||||
@@ -81,3 +53,17 @@ The following Matrix Client-Server API endpoints need to be handled by the authe
|
||||
- [`/_matrix/client/*/refresh`](https://spec.matrix.org/latest/client-server-api/#post_matrixclientv3refresh)
|
||||
|
||||
See the [reverse proxy configuration](./reverse-proxy.md) guide for more information.
|
||||
|
||||
|
||||
## Migrating from the experimental MSC3861 feature
|
||||
|
||||
If you are migrating from the experimental MSC3861 feature in Synapse, you will need to migrate the `experimental_features.msc3861` section of the Synapse configuration to the `matrix_authentication_service` section.
|
||||
|
||||
To do so, you need to:
|
||||
|
||||
- Remove the `experimental_features.msc3861` section from the Synapse configuration
|
||||
- Add the `matrix_authentication_service` section to the Synapse configuration with:
|
||||
- `enabled: true`
|
||||
- `endpoint` set to the URL of the authentication service
|
||||
- `secret` set to the same secret as the `admin_token` that was set in the `msc3861` section
|
||||
- Optionally, remove the client provisioned for Synapse in the `clients` section of the MAS configuration
|
||||
|
||||
@@ -24,6 +24,7 @@ The general configuration usually goes as follows:
|
||||
- `response_type`: `code`
|
||||
- `response_mode`: `query`
|
||||
- `grant_type`: `authorization_code`
|
||||
- (optional) `backchannel_logout_uri`: `https://<auth-service-domain>/upstream/backchannel-logout/<id>`
|
||||
- fill the `upstream_oauth2` section of the configuration file with the following parameters:
|
||||
- `providers`:
|
||||
- `id`: the previously generated ULID
|
||||
@@ -65,6 +66,30 @@ The template has the following variables available:
|
||||
- `user`: an object which contains the claims from both the `id_token` and the `userinfo` endpoint
|
||||
- `extra_callback_parameters`: an object with the additional parameters the provider sent to the redirect URL
|
||||
|
||||
|
||||
## Allow linking existing user accounts
|
||||
|
||||
The authentication service supports linking external provider identities to existing local user accounts.
|
||||
|
||||
To enable this behavior, the following option must be explicitly set in the provider configuration:
|
||||
|
||||
```yaml
|
||||
claims_imports:
|
||||
localpart:
|
||||
on_conflict: add
|
||||
```
|
||||
`on_conflict` configuration is specific to `localpart` claim_imports, it can be either:
|
||||
* `add` : when a user authenticates with the provider for the first time, the system checks whether a local user already exists with a `localpart` matching the attribute mapping `localpart` , _by default `{{ user.preferred_username }}`_. If a match is found, the external identity is linked to the existing local account.
|
||||
* `fail` *(default)* : fails the sso login.
|
||||
|
||||
To enable this option, the `localpart` mapping must be set to either `force` or `require`.
|
||||
|
||||
> ⚠️ **Security Notice**
|
||||
> Enabling this option can introduce a risk of account takeover.
|
||||
>
|
||||
> To mitigate this risk, ensure that this option is only enabled for identity providers where you can guarantee that the attribute mapping `localpart` will reliably and uniquely correspond to the intended local user account.
|
||||
|
||||
|
||||
## Multiple providers behaviour
|
||||
|
||||
Multiple authentication methods can be configured at the same time, in which case the authentication service will let the user choose which one to use.
|
||||
@@ -73,6 +98,25 @@ In such cases, the `human_name` parameter of the provider configuration is used
|
||||
|
||||
If there is only one upstream provider configured and the local password database is disabled ([`passwords.enabled`](../reference/configuration.md#passwords) is set to `false`), the authentication service will automatically trigger an authorization flow with this provider.
|
||||
|
||||
## Backchannel logout
|
||||
|
||||
The service supports receiving [OpenID Connect Back-Channel Logout](https://openid.net/specs/openid-connect-backchannel-1_0.html) requests.
|
||||
Those are notifications from the upstream provider that the user has logged out of the provider.
|
||||
|
||||
The backchannel logout URI must be configured in the provider as `https://<auth-service-domain>/upstream/backchannel-logout/<id>`, where `<id>` is the `id` of the provider.
|
||||
|
||||
By default, the authentication service will not perform any action when receiving a backchannel logout request.
|
||||
The [`on_backchannel_logout`](../reference/configuration.md#upstream_oauth2) option can be used to configure what to do when receiving a backchannel logout request.
|
||||
|
||||
Possible values are:
|
||||
|
||||
- `do_nothing`: Do nothing, other than validating and logging the request
|
||||
- `logout_browser_only`: Only log out the MAS 'browser session' started by this OIDC session
|
||||
- `logout_all`: Log out all sessions started by this OIDC session, including MAS 'browser sessions' and client sessions
|
||||
|
||||
One important caveat is that `logout_all` will log out all sessions started by this upstream OIDC session, including 'remote' ones done through the Device Code flow.
|
||||
Concretely, this means that if QR-code login is used to log in on a phone from a laptop, when MAS receives a backchannel logout request from the upstream provider for the laptop, MAS will also log out the session on the phone.
|
||||
|
||||
## Sample configurations
|
||||
|
||||
This section contains sample configurations for popular OIDC providers.
|
||||
@@ -93,12 +137,11 @@ upstream_oauth2:
|
||||
response_mode: "form_post"
|
||||
token_endpoint_auth_method: "sign_in_with_apple"
|
||||
sign_in_with_apple:
|
||||
|
||||
# Only one of the below should be filled for the private key
|
||||
private_key_file: "<Location of the PEM-encoded private key file>" # TO BE FILLED
|
||||
private_key: | # TO BE FILLED
|
||||
# <Contents of the private key>
|
||||
|
||||
|
||||
team_id: "<Team ID>" # TO BE FILLED
|
||||
key_id: "<Key ID>" # TO BE FILLED
|
||||
claims_imports:
|
||||
@@ -386,6 +429,9 @@ Follow the [Getting Started Guide](https://www.keycloak.org/guides) to install K
|
||||
| Client Protocol | `openid-connect` |
|
||||
| Access Type | `confidential` |
|
||||
| Valid Redirect URIs | `https://<auth-service-domain>/upstream/callback/<id>` |
|
||||
| Front channel logout | `Off` |
|
||||
| Backchannel logout URL | `https://<auth-service-domain>/upstream/backchannel-logout/<id>` |
|
||||
| Backchannel logout session required | `On` |
|
||||
|
||||
5. Click `Save`
|
||||
6. On the Credentials tab, update the fields:
|
||||
@@ -554,4 +600,4 @@ To use a Rauthy-supported [Ephemeral Client](https://sebadob.github.io/rauthy/wo
|
||||
"access_token_signed_response_alg": "RS256",
|
||||
"id_token_signed_response_alg": "RS256"
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
31
docs/topics/access-token.md
Normal file
31
docs/topics/access-token.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Get an access token
|
||||
|
||||
The [Matrix Authentication Service repository contains a simple shell script](https://github.com/element-hq/matrix-authentication-service/blob/main/misc/device-code-grant.sh) to interactively get an access token with arbitrary scopes.
|
||||
It requires `sh`, `jq` and `curl` to be installed.
|
||||
This can be run from anywhere, not necessarily from the host where MAS is running.
|
||||
|
||||
```sh
|
||||
sh ./misc/device-code-grant.sh [synapse-url] <scope>...
|
||||
```
|
||||
|
||||
This will prompt you to open a URL in your browser, finish the authentication flow, and print the access and refresh tokens.
|
||||
|
||||
This can be used to get access to the MAS admin API:
|
||||
|
||||
```sh
|
||||
sh ./misc/device-code-grant.sh https://synapse.example.com/ urn:mas:admin
|
||||
```
|
||||
|
||||
Or to the Synapse admin API:
|
||||
|
||||
```sh
|
||||
sh ./misc/device-code-grant.sh https://synapse.example.com/ urn:matrix:org.matrix.msc2967.client:api:* urn:synapse:admin:*
|
||||
```
|
||||
|
||||
Or even both at the same time:
|
||||
|
||||
```sh
|
||||
sh ./misc/device-code-grant.sh https://synapse.example.com/ urn:matrix:org.matrix.msc2967.client:api:* urn:mas:admin urn:synapse:admin:*
|
||||
```
|
||||
|
||||
Note that the token will only be valid for a short time (5 minutes by default) and needs to be revoked manually from the MAS user interface.
|
||||
@@ -46,7 +46,9 @@ If admin API is enabled, MAS will also serve the specification at `/api/spec.jso
|
||||
|
||||
## Authentication
|
||||
|
||||
All requests to the admin API are gated using access tokens obtained using OAuth 2.0 grants.
|
||||
All requests to the admin API are gated either using access tokens obtained using OAuth 2.0 grants,
|
||||
or using personal access tokens (which must currently be issued through the Admin API).
|
||||
|
||||
They must have the [`urn:mas:admin`](../reference/scopes.md#urnmasadmin) scope.
|
||||
|
||||
### User-interactive tools
|
||||
|
||||
@@ -129,6 +129,33 @@ It may also be used in the future as a foundation for a new Application Service
|
||||
This works by presenting the client credentials to get back an access token.
|
||||
The simplest type of client credentials is a client ID and client secret pair, but MAS also supports client authentication with a JWT ([RFC 7523]), which is a robust way to authenticate clients without a shared secret.
|
||||
|
||||
## Personal sessions (personal access tokens)
|
||||
|
||||
Personal access tokens are a credential that can be issued to give access to a user,
|
||||
with predefined scopes and a predefined expiry time.
|
||||
Either before or after expiry, the owner of the token can regenerate it, which produces a new
|
||||
access token with the same scopes but a new expiry time.
|
||||
|
||||
Personal access tokens are intended to fulfill two basic use cases:
|
||||
|
||||
1. an easy way to obtain a clean token for your own user, for use in automation and scripts;
|
||||
2. a way to obtain a token for administrative access of another user, either for ad-hoc administrative operations or to set up a bot or similar service.
|
||||
|
||||
In the future, users will be able to create their own personal access tokens, but this is currently not implemented
|
||||
so (1) is currently not supported.
|
||||
|
||||
For now, personal access tokens must be created, regenerated and revoked by administrators through the [Admin API], satisfying use case (2).
|
||||
[Element Admin](https://github.com/element-hq/element-admin), available by default in Element Server Suite, can be used to do this interactively.
|
||||
You can also use the online beta deployment at [admin-beta.element.dev](https://admin-beta.element.dev/). <!--- TODO stable deployment -->
|
||||
|
||||
### Validity
|
||||
|
||||
Personal sessions can be used so long as:
|
||||
|
||||
- the owner (creator) of the token is still an active and unlocked user (or static OAuth 2 client); and
|
||||
- the actor (target user, or user being controlled by the token) has not been deactivated. Though the actor is allowed to be locked.
|
||||
|
||||
|
||||
[MSC4108]: https://github.com/matrix-org/matrix-spec-proposals/pull/4108
|
||||
[RFC 6749]: https://datatracker.ietf.org/doc/html/rfc6749
|
||||
[RFC 7523]: https://datatracker.ietf.org/doc/html/rfc7523
|
||||
@@ -140,3 +167,4 @@ The simplest type of client credentials is a client ID and client secret pair, b
|
||||
[`urn:synapse:admin:*`]: ../reference/scopes.md#urnsynapseadmin
|
||||
[`urn:mas:graphql:*`]: ../reference/scopes.md#urnmasgraphql
|
||||
[`urn:mas:admin`]: ../reference/scopes.md#urnmasadmin
|
||||
[Admin API]: ./admin-api.md
|
||||
|
||||
@@ -24,11 +24,10 @@ As such, they usually can be bypassed through the admin API or the CLI if needed
|
||||
|
||||
### User attributes
|
||||
|
||||
The policy is evaluated in three different scenarios:
|
||||
The policy is evaluated in the following different scenarios:
|
||||
|
||||
- [`register.rego`]: During user registration, either with password credentials or with an upstream OAuth 2.0 provider. This calls the [`email.rego`] and [`password.rego`] policies as well.
|
||||
- [`register.rego`]: During user registration, either with password credentials or with an upstream OAuth 2.0 provider. This calls the [`email.rego`] policy as well.
|
||||
- [`email.rego`]: When a user adds a new email address to their account.
|
||||
- [`password.rego`]: When a user changes their password.
|
||||
|
||||
### Client registration
|
||||
|
||||
@@ -69,8 +68,7 @@ This is especially important as in the future it will make it possible to implem
|
||||
To understand the authorization process and how sessions are created, refer to the [authorization and sessions](./authorization.md) section.
|
||||
|
||||
|
||||
[`register.rego`]: https://github.com/element-hq/matrix-authentication-service/blob/main/policies/register.rego
|
||||
[`email.rego`]: https://github.com/element-hq/matrix-authentication-service/blob/main/policies/email.rego
|
||||
[`password.rego`]: https://github.com/element-hq/matrix-authentication-service/blob/main/policies/password.rego
|
||||
[`client_registration.rego`]: https://github.com/element-hq/matrix-authentication-service/blob/main/policies/client_registration.rego
|
||||
[`authorization_grant.rego`]: https://github.com/element-hq/matrix-authentication-service/blob/main/policies/authorization_grant.rego
|
||||
[`register.rego`]: https://github.com/element-hq/matrix-authentication-service/blob/main/policies/register/register.rego
|
||||
[`email.rego`]: https://github.com/element-hq/matrix-authentication-service/blob/main/policies/email/email.rego
|
||||
[`client_registration.rego`]: https://github.com/element-hq/matrix-authentication-service/blob/main/policies/client_registration/client_registration.rego
|
||||
[`authorization_grant.rego`]: https://github.com/element-hq/matrix-authentication-service/blob/main/policies/authorization_grant/authorization_grant.rego
|
||||
|
||||
Reference in New Issue
Block a user