Use the stable MAS integration of Synapse in the documentation and in mas-cli doctor (#4902)
This commit is contained in:
@@ -14,6 +14,7 @@ use std::process::ExitCode;
|
||||
use anyhow::Context;
|
||||
use clap::Parser;
|
||||
use figment::Figment;
|
||||
use hyper::StatusCode;
|
||||
use mas_config::{ConfigurationSection, RootConfig};
|
||||
use mas_http::RequestBuilderExt;
|
||||
use tracing::{error, info, info_span, warn};
|
||||
@@ -43,7 +44,7 @@ impl Options {
|
||||
r"The homeserver host in the config (`matrix.homeserver`) is not a valid domain.
|
||||
See {DOCS_BASE}/setup/homeserver.html",
|
||||
)?;
|
||||
let admin_token = config.matrix.secret().await?;
|
||||
let secret = config.matrix.secret().await?;
|
||||
let hs_api = config.matrix.endpoint;
|
||||
|
||||
if !issuer.starts_with("https://") {
|
||||
@@ -99,17 +100,14 @@ Make sure that the MAS config contains:
|
||||
|
||||
http:
|
||||
public_base: {issuer:?}
|
||||
# Or, if the issuer is different from the public base:
|
||||
issuer: {issuer:?}
|
||||
|
||||
And in the Synapse config:
|
||||
|
||||
experimental_features:
|
||||
msc3861:
|
||||
enabled: true
|
||||
# This must exactly match:
|
||||
issuer: {issuer:?}
|
||||
# ...
|
||||
matrix_authentication_service:
|
||||
enabled: true
|
||||
# This must point to where MAS is reachable by Synapse
|
||||
endpoint: {issuer:?}
|
||||
# ...
|
||||
|
||||
See {DOCS_BASE}/setup/homeserver.html
|
||||
"#
|
||||
@@ -128,11 +126,10 @@ Check the well-known document at "{well_known_uri}"
|
||||
Check the well-known document at "{well_known_uri}"
|
||||
Make sure Synapse has delegated auth enabled:
|
||||
|
||||
experimental_features:
|
||||
msc3861:
|
||||
enabled: true
|
||||
issuer: {issuer:?}
|
||||
# ...
|
||||
matrix_authentication_service:
|
||||
enabled: true
|
||||
endpoint: {issuer:?}
|
||||
# ...
|
||||
|
||||
If it is not Synapse handling the well-known document, update it to include the following:
|
||||
|
||||
@@ -283,70 +280,50 @@ Error details: {e}
|
||||
),
|
||||
}
|
||||
|
||||
// Try to reach the admin API on an unauthorized endpoint
|
||||
let server_version = hs_api.join("/_synapse/admin/v1/server_version")?;
|
||||
let result = http_client.get(server_version.as_str()).send_traced().await;
|
||||
match result {
|
||||
Ok(response) => {
|
||||
let status = response.status();
|
||||
if status.is_success() {
|
||||
info!(r#"✅ The Synapse admin API is reachable at "{server_version}"."#);
|
||||
} else {
|
||||
error!(
|
||||
r#"❌ A Synapse admin API endpoint at "{server_version}" replied with {status}.
|
||||
Make sure MAS can reach the admin API, and that the homeserver is running.
|
||||
"#
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(e) => error!(
|
||||
r#"❌ Can't reach the Synapse admin API at "{server_version}".
|
||||
Make sure MAS can reach the admin API, and that the homeserver is running.
|
||||
|
||||
Error details: {e}
|
||||
"#
|
||||
),
|
||||
}
|
||||
|
||||
// Try to reach an authenticated admin API endpoint
|
||||
let background_updates = hs_api.join("/_synapse/admin/v1/background_updates/status")?;
|
||||
// Try to reach an authenticated MAS API endpoint
|
||||
let mas_api = hs_api.join("/_synapse/mas/is_localpart_available")?;
|
||||
let result = http_client
|
||||
.get(background_updates.as_str())
|
||||
.bearer_auth(&admin_token)
|
||||
.get(mas_api.as_str())
|
||||
.bearer_auth(&secret)
|
||||
.send_traced()
|
||||
.await;
|
||||
match result {
|
||||
Ok(response) => {
|
||||
let status = response.status();
|
||||
if status.is_success() {
|
||||
// We intentionally omit the required 'localpart' parameter
|
||||
// in this request. If authentication is successful, Synapse
|
||||
// returns a 400 Bad Request because of the missing
|
||||
// parameter. If authentication fails, Synapse will return a
|
||||
// 403 Forbidden. If the MAS integration isn't enabled,
|
||||
// Synapse will return a 404 Not found.
|
||||
if status == StatusCode::BAD_REQUEST {
|
||||
info!(
|
||||
r#"✅ The Synapse admin API is reachable with authentication at "{background_updates}"."#
|
||||
r#"✅ The Synapse MAS API is reachable with authentication at "{mas_api}"."#
|
||||
);
|
||||
} else {
|
||||
error!(
|
||||
r#"❌ A Synapse admin API endpoint at "{background_updates}" replied with {status}.
|
||||
r#"❌ A Synapse MAS API endpoint at "{mas_api}" replied with {status}.
|
||||
Make sure the homeserver is running, and that the MAS config has the correct `matrix.secret`.
|
||||
It should match the `admin_token` set in the Synapse config.
|
||||
It should match the `secret` set in the Synapse config.
|
||||
|
||||
experimental_features:
|
||||
msc3861:
|
||||
enabled: true
|
||||
issuer: {issuer}
|
||||
# This must exactly match the secret in the MAS config:
|
||||
admin_token: {admin_token:?}
|
||||
matrix_authentication_service:
|
||||
enabled: true
|
||||
endpoint: {issuer:?}
|
||||
# This must exactly match the secret in the MAS config:
|
||||
secret: {secret:?}
|
||||
|
||||
And in the MAS config:
|
||||
|
||||
matrix:
|
||||
homeserver: "{matrix_domain}"
|
||||
endpoint: "{hs_api}"
|
||||
secret: {admin_token:?}
|
||||
secret: {secret:?}
|
||||
"#
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(e) => error!(
|
||||
r#"❌ Can't reach the Synapse admin API at "{background_updates}".
|
||||
r#"❌ Can't reach the Synapse MAS API at "{mas_api}".
|
||||
Make sure the homeserver is running, and that the MAS config has the correct `matrix.secret`.
|
||||
|
||||
Error details: {e}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user