1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2026-01-03 17:02:28 +03:00

Add some documentation as an mdBook

This commit is contained in:
Quentin Gliech
2021-09-24 19:10:17 +02:00
parent 8e34dd3778
commit 4d589b8fa1
15 changed files with 816 additions and 0 deletions

22
book.toml Normal file
View File

@@ -0,0 +1,22 @@
# Documentation for possible options in this file is at
# https://rust-lang.github.io/mdBook/format/config.html
[book]
title = "Matrix Authentication Service"
authors = ["The Matrix.org Foundation C.I.C."]
language = "en"
multilingual = false
src = "docs"
[build]
build-dir = "target/book"
[output.html]
# The URL visitors will be directed to when they try to edit a page
edit-url-template = "https://github.com/matrix-org/synapse/edit/main/{path}"
# The source code URL of the repository
git-repository-url = "https://github.com/matrix-org/matrix-authentication-service"
# The path that the docs are hosted on
site-url = "/matrix-authentication-service/"

3
docs/README.md Normal file
View File

@@ -0,0 +1,3 @@
# About this documentation
This documentation is intended to give an overview of how the `matrix-authentication-service` works, both from a admin perspective as well as from a developper perspective.

24
docs/SUMMARY.md Normal file
View File

@@ -0,0 +1,24 @@
# Summary
# Introduction
- [About this documentation](./README.md)
# Usage
- [Installation](./usage/installation.md)
- [Configuration](./usage/configuration.md)
- [Using the service](./usage/usage.md)
- [Command line tool](./usage/cli/README.md)
- [`config`](./usage/cli/config.md)
- [`database`](./usage/cli/database.md)
- [`manage`](./usage/cli/manage.md)
- [`server`](./usage/cli/server.md)
- [`templates`](./usage/cli/templates.md)
# Development
- [Architecture](./development/architecture.md)
- [Database](./development/database.md)
- [Routing with `warp`](./development/warp.md)
- [Templates]()

View File

@@ -0,0 +1,84 @@
# Architecture
The service is meant to be easily embeddable, with only a dependency to a database.
It is also meant to stay lightweight in terms of resource usage and easily scalable horizontally.
## Workspace and crate split
The whole repository is a [Cargo Workspace](https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html) that includes multiple crates under the `/crates` directory.
This includes:
- `oauth2-types`: Useful structures and types to deal with OAuth 2.0/OpenID Connect endpoints. This might end up published as a standalone library as it can be useful in other contexts.
- `mas-config`: Configuration parsing and loading
- `mas-core`: Main logic, includes templates, database interactions and HTTP routes
- `mas-cli`: Command line utility, main entry point
## Important crates
The project makes use of a few important crates.
### Async runtime: `tokio`
[Tokio](https://tokio.rs/) is the async runtime used by the project.
The choice of runtime does not have much impact on most of the code.
It has an impact when:
- spawning asynchronous work (as in "not awaiting on it immediately")
- running CPU-intensive tasks. They should be ran in a blocking context using `tokio::task::spawn_blocking`. This includes password hashing and other crypto operations.
- when dealing with shared memory, e.g. mutexes, rwlocks, etc.
### Logging: `tracing`
Logging is handled through the [`tracing`](https://docs.rs/tracing/*/tracing/) crate.
It provides a way to emit structured log messages at various levels.
```rust
use tracing::{info, debug};
info!("Logging some things");
debug!(user = "john", "Structured stuff");
```
`tracing` also provides ways to create spans to better understand where a logging message comes from.
In the future, it will help building OpenTelemetry-compatible distributed traces to help with debugging.
`tracing` is becoming the standard to log things in Rust.
By itself it will do nothing unless a subscriber is installed to -for example- log the events to the console.
The CLI installs [`tracing-subcriber`](https://docs.rs/tracing-subscriber/*/tracing_subscriber/) on startup to log in the console.
It looks for a `RUST_LOG` environment variable to determine what event should be logged.
### Error management: `thiserror` / `anyhow`
[`thiserror`](https://docs.rs/thiserror/*/thiserror/) helps defining custom error types.
This is especially useful for errors that should be handled in a specific way, while being able to augment underlying errors with additional context.
[`anyhow`](https://docs.rs/anyhow/*/anyhow/) helps dealing with chains of errors.
It allows for quickly adding additional context around an error while it is being propagated.
Both crates work well together and complement each other.
### Database interactions: `sqlx`
Interactions with the database are done through [`sqlx`](https://github.com/launchbadge/sqlx), an async, pure-Rust SQL library with compile-time check of queries.
It also handles schema migrations.
### Web framework: `warp`
[`warp`](https://docs.rs/warp/*/warp/) is an easy, macro-free web framework.
Its composability makes a lot of sense when implementing OAuth 2.0 endpoints, because of the need to deal with a lot of different scenarios.
### Templates: `tera`
[Tera](https://tera.netlify.app/) was chosen as template engine for its simplicity as well as its ability to load templates at runtime.
The builtin templates are embedded in the final binary through some macro magic.
The downside of Tera compared to compile-time template engines is the possibility of runtime crashes.
This can however be somewhat mitigated with unit tests.
### Crates from *RustCrypto*
The [RustCrypto team](https://github.com/RustCrypto) offer high quality, independent crates for dealing with cryptography.
The whole project is highly modular and APIs are coherent between crates.

View File

@@ -0,0 +1,96 @@
# Database
Interactions with the database goes through `sqlx`.
It provides async database operations with connection pooling, migrations support and compile-time check of queries through macros.
## Compile-time check of queries
To be able to check queries, `sqlx` has to introspect the live database.
Usually it does so by having the database available at compile time, but to avoid that we're using the `offline` feature of `sqlx`, which saves the introspection informatons as a flat file in the repository.
Preparing this flat file is done through `sqlx-cli`, and should be done everytime the database schema or the queries changed.
```sh
# Install the CLI
cargo install sqlx-cli --no-default-features --features postgres
cd crates/core/ # Must be in the mas-core crate folder
export DATABASE_URL=postgresql:///matrix_auth
cargo sqlx prepare
```
## Migrations
Migration files live in the `migrations` folder in the `mas-core` crate.
```sh
cd crates/core/ # Again, in the mas-core crate folder
export DATABASE_URL=postgresql:///matrix_auth
cargo sqlx migrate run # Run pending migrations
cargo sqlx migrate revert # Revert the last migration
cargo sqlx migrate add -r [description] # Add new migration files
```
Note that migrations are embedded in the final binary and can be run from the service CLI tool.
## Writing database interactions
A typical interaction with the database look like this:
```rust
pub async fn lookup_session(
executor: impl Executor<'_, Database = Postgres>,
id: i64,
) -> anyhow::Result<SessionInfo> {
sqlx::query_as!(
SessionInfo, // Struct that will be filled with the result
r#"
SELECT
s.id,
u.id as user_id,
u.username,
s.active,
s.created_at,
a.created_at as "last_authd_at?"
FROM user_sessions s
INNER JOIN users u
ON s.user_id = u.id
LEFT JOIN user_session_authentications a
ON a.session_id = s.id
WHERE s.id = $1
ORDER BY a.created_at DESC
LIMIT 1
"#,
id, // Query parameter
)
.fetch_one(executor)
.await
// Providing some context when there is an error
.context("could not fetch session")
}
```
Note that we pass an `impl Executor` as parameter here.
This allows us to use this function from either a simple connection or from an active transaction.
The caveat here is that the `executor` can be used only once, so if an interaction needs to do multiple queries, it should probably take an `impl Acquire` to then acquire a transaction and do multiple interactions.
```rust
pub async fn login(
conn: impl Acquire<'_, Database = Postgres>,
username: &str,
password: String,
) -> Result<SessionInfo, LoginError> {
let mut txn = conn.begin().await.context("could not start transaction")?;
// First interaction
let user = lookup_user_by_username(&mut txn, username)?;
// Second interaction
let mut session = start_session(&mut txn, user).await?;
// Third interaction
session.last_authd_at =
Some(authenticate_session(&mut txn, session.id, password).await?);
// Commit the transaction once everything went fine
txn.commit().await.context("could not commit transaction")?;
Ok(session)
}
```

91
docs/development/warp.md Normal file
View File

@@ -0,0 +1,91 @@
# `warp`
Warp has a pretty unique approach in terms of routing.
It does not have a central router, rather a chain of filters composed together.
It encourages writing reusable filters to handle stuff like authentication, extracting user sessions, starting database transactions, etc.
Everything related to `warp` currently lives in the `mas-core` crate:
- `crates/core/src/`
- `handlers/`: The actual handlers for each route
- `oauth2/`: Everything related to OAuth 2.0/OIDC endpoints
- `views/`: HTML views (login, registration, account management, etc.)
- `filters/`: Reusable, composable filters
- `reply/`: Composable replies
## Defining a new endpoint
We usually keep one endpoint per file and use module roots to combine the filters of endpoints.
This is how it looks like in the current hierarchy at time of writing:
- `mod.rs`: combines the filters from `oauth2`, `views` and `health`
- `oauth2/`
- `mod.rs`: combines filters from `authorization`, `discovery`, etc.
- `authorization.rs`: handles `GET /oauth2/authorize` and `GET /oauth2/authorize/step`
- `discovery.rs`: handles `GET /.well-known/openid-configuration`
- ...
- `views/`
- `mod.rs`: combines the filters from `index`, `login`, `logout`, etc.
- `index.rs`: handles `GET /`
- `login.rs`: handles `GET /login` and `POST /login`
- `logout.rs`: handles `POST /logout`
- ...
- `health.rs`: handles `GET /health`
All filters are functions that take their dependencies (the database connection pool, the template engine, etc.) as parameters and return an `impl warp::Filter<Extract = (impl warp::Reply,)>`.
```rust
// crates/core/src/handlers/hello.rs
// Don't be scared by the type at the end, just copy-paste it
pub(super) fn filter(
pool: &PgPool,
templates: &Templates,
cookies_config: &CookiesConfig,
) -> impl Filter<Extract = (impl Reply,), Error = Rejection> + Clone + Send + Sync + 'static {
// Handles `GET /hello/:param`
warp::path!("hello" / String)
.and(warp::get())
// Pass the template engine
.and(with_templates(templates))
// Extract the current user session
.and(optional_session(pool, cookies_config))
.and_then(get)
}
async fn get(
// Parameter from the route
parameter: String,
// Template engine
templates: Templates,
// The current user session
session: Option<SessionInfo>,
) -> Result<impl Reply, Rejection> {
let ctx = SomeTemplateContext::new(parameter)
.maybe_with_session(session);
let content = templates.render_something(&ctx)?;
let reply = html(content);
Ok(reply)
}
```
And then, it can be attached to the root handler:
```rust
// crates/core/src/handlers/mod.rs
use self::{health::filter as health, oauth2::filter as oauth2, hello::filter as hello};
pub fn root(
pool: &PgPool,
templates: &Templates,
config: &RootConfig,
) -> impl Filter<Extract = (impl Reply,), Error = Rejection> + Clone + Send + Sync + 'static {
health(pool)
.or(oauth2(pool, templates, &config.oauth2, &config.cookies))
// Attach it here, passing the right dependencies
.or(hello(pool, templates, &config.cookies))
}
```

40
docs/usage/cli/README.md Normal file
View File

@@ -0,0 +1,40 @@
# Command line tool
The command line interface provides subcommands that helps running the service.
## Logging
The overall log level of the CLI can be changed via the `RUST_LOG` environment variable.
Default log level is `info`.
Valid levels from least to most verbose are `error`, `warn`, `info`, `debug` and `trace`.
## Global flags
### `--config`
Sets the configuration file to load.
It can be repeated multiple times to merge multiple files together.
---
```
mas-cli
USAGE:
mas-cli [OPTIONS] [SUBCOMMAND]
FLAGS:
-h, --help Print help information
-V, --version Print version information
OPTIONS:
-c, --config <CONFIG>... Path to the configuration file [default: config.yaml]
SUBCOMMANDS:
config Configuration-related commands
database Manage the database
help Print this message or the help of the given subcommand(s)
manage Manage the instance
server Runs the web server
templates Templates-related commands
```

35
docs/usage/cli/config.md Normal file
View File

@@ -0,0 +1,35 @@
# `config`
Helps dealing with the configuration
## `config check`
Check the validity of configuration files.
```console
$ mas-cli config check --config=config.yaml
INFO mas_cli::config: Configuration file looks good path=["config.yaml"]
```
## `config dump`
Dump the merged configuration tree.
```console
$ mas-cli config dump --config=first.yaml --config=second.yaml
---
oauth2:
# ...
```
## `config generate`
Generate a sample configuration file.
It generates random signing keys (`.oauth2.keys`) and the cookie encryption secret (`.cookies.secret`).
```console
$ mas-cli config generate > config.yaml
INFO generate: mas_config::oauth2: Generating keys...
INFO generate:rsa: mas_config::oauth2: Done generating RSA key
INFO generate:ecdsa: mas_config::oauth2: Done generating ECDSA key
```

View File

@@ -0,0 +1,11 @@
# `database`
Run database-related operations
## `database migrate`
Run the pending database migrations
```
$ mas-cli database migrate
```

12
docs/usage/cli/manage.md Normal file
View File

@@ -0,0 +1,12 @@
# `manage`
Includes admin-related subcommands.
## `manage register <username> <password>`
Register a new user
```console
$ mas-cli manage register johndoe hunter2
INFO mas_cli::manage: User registered user=User { id: 2, username: "johndoe" }
```

12
docs/usage/cli/server.md Normal file
View File

@@ -0,0 +1,12 @@
# `server`
Runs the authentication service.
```
$ mas-cli server
INFO mas_cli::server: Starting task scheduler
INFO mas_core::templates: Loading builtin templates
INFO mas_cli::server: Listening on http://0.0.0.0:8080
```
A `--migrate` flag can be set to automatically run pending database migrations on startup.

View File

@@ -0,0 +1,37 @@
# `templates`
Helps customizing templates.
## `templates save <path>`
Save the builtin template in the specified folder.
```console
$ mas-cli templates save ./templates
INFO mas_core::templates: Wrote template path="./templates/login.html"
INFO mas_core::templates: Wrote template path="./templates/register.html"
INFO mas_core::templates: Wrote template path="./templates/index.html"
INFO mas_core::templates: Wrote template path="./templates/reauth.html"
INFO mas_core::templates: Wrote template path="./templates/form_post.html"
INFO mas_core::templates: Wrote template path="./templates/error.html"
INFO mas_core::templates: Wrote template path="./templates/base.html"
```
By default this command won't overwrite existing files, but this behavior can be changed by adding the `--overwrite` flag.
## `templates check <path>`
Check the validity of the templates in the specified folder.
It compiles the templates and then renders them with different contexts.
```console
$ mas-cli templates check ./templates
INFO mas_core::templates: Loading builtin templates
INFO mas_core::templates: Loading templates from filesystem path=./templates/**/*.{html,txt}
INFO mas_core::templates::check: Rendering template name="login.html" context={"csrf_token":"fake_csrf_token","form":{"fields_errors":{},"form_errors":[],"has_errors":false}}
INFO mas_core::templates::check: Rendering template name="register.html" context={"__UNUSED":null,"csrf_token":"fake_csrf_token"}
INFO mas_core::templates::check: Rendering template name="index.html" context={"csrf_token":"fake_csrf_token","current_session":{"active":true,"created_at":"2021-09-24T13:26:52.962135085Z","id":1,"last_authd_at":"2021-09-24T13:26:52.962135316Z","user_id":2,"username":"john"},"discovery_url":"https://example.com/.well-known/openid-configuration"}
...
```
Builtin templates are still loaded by default when running this command, but this can be skipped by adding the `--skip-builtin` flag.

212
docs/usage/configuration.md Normal file
View File

@@ -0,0 +1,212 @@
# Configuration
The service needs some configuration to work.
This includes random, private keys and secrets.
A sample configuration file can be generated using `mas-cli config generate`.
```sh
mas-cli config generate > config.yaml
mas-cli config check --config=config.yaml
# if --config is omitted, it will try to load `config.yaml`
# in the current working directory
mas-cli config check
```
Or, with Docker:
```sh
docker run --rm \
ghcr.io/matrix-org/matrix-authentication-service:main \
config generate > config.yaml
docker run --rm -v `pwd`:/wd \
ghcr.io/matrix-org/matrix-authentication-service:main \
--config=/wd/config.yaml config dump
# or, mounting only the config file and omitting `--config`
docker run --rm -v `pwd`/config.yaml:/config.yaml \
ghcr.io/matrix-org/matrix-authentication-service:main \
config dump
```
Note that with Docker, the config file must be mounted inside the container with `-v/--volume`.
## Minimal configuration
Here is a minimal configuration needed to have the server running.
It is strongly recommended to generate the initial configuration using the `config generate` to have unique secrets and signing keys.
Check the next section to know about each section.
```yaml
# config.yaml
database:
uri: postgresql:///matrix_auth
cookies:
secret: c7e42fb8baba8f228b2e169fdf4c8216dffd5d33ad18bafd8b928c09ca46c718
oauth2:
keys:
- type: rsa
key: |
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7iinu0NXjWP5/
/4OqyqOMI5uLJIHSrYIZLUlWMldtXmNy0c/pan+gxvZogiYx0cNydO/FogNbC4oD
yj7RIF+QcWJ8wcdG94/P+Xs3HFQzIZfwF+78RWQQJ7nQFekXJ1wQSXV4giw9b4XR
YkoVhHlyxyYGBFffO//DtYVto4uHvXVL0M27bV6l1K8VKspF72gb8Vt44V8OX5hT
sEsYW8SjOD1neEoVKiY6XP63cAG9FTB4a4sKkcUqwjrKEYKio/JLujmCl96eLN18
cuqr6XuSDKvuVJtb+ZNLJi61vIOlD8cz3wu37hr3PCUZ+Ko9Ley+QfopJ3WYFxrI
IjQKb0W5AgMBAAECggEBAK87ZfsTfwczPHn1Ed4gAbkL/GaC8hscrJdBzWiRGUfE
DkBW82IydJaR0ePM2EtsqKblxLRxsZj8qzTnYNKe4SxiBZh0p/MTlnjJr+vKuJIe
LY3VjySA4gKGXASmtGlCCa/eM7kqSJQPBIakxHxej+xDULAGluSrd0wy7D2JtvJY
5By+2apILUujBZZU/iUyB2AqK6IrzALo2gTV9Jhun9Wz0k3DXZBGd41v42BhZ+Rx
bHHgpuUTyDQOpKqJ5g1kN4qGlN/CeoontxcE5NOSgtipWeQEuelT8t4eZKHTXBS+
Byd+uFe8oobWRY2crLptX8TZEENH7wX7y2YgNYUbeZECgYEA95YRhDuukcrDiNuF
fOXs+99XFORsKTbtZYwrouc7PI2CYb0I9ezoQMu3dzWIwOTUQHea5qCo/dYzbeED
fNzwPb2zaWaWFbkEWVTOwRewL+NfP+Ek2Nml+dVJm3d35qdIHYV+9gAcI87iCHxA
gqc13ZS4ba+5/vV6OYwNSAeW0TcCgYEAwem1F9zhVVOIReh3JaJLpZn0xuvZs5kN
TzvFXar33LKdulk5liC3L7ZrqspGESU0JC3pANR8PwuNteEEdHnkC5UTEqMf/fxG
j5CObJl+e2CiV2CNbe+3IQ1PKSxopD+Sq65ze7aP2moVZg94mbw4dsN+uY5QEql1
Bmq0b7Wm2I8CgYBOqlDgefIKgqlEF7O/LnLwyFKr4bP4GGqvZC0NMnkg0TmHAoAR
W3ej9tZROyI7X7mMzjPaaVuoY2Gt3Nu11aFDjL2vlJfFSSb3lzmmInepj43ZBxkl
CWpyCfG8QuZG1AnWz266jOhj/DzXQ1tf5+72e2Vp/HaVaruuAzDJHRgvWwKBgAHy
aMEOlKyYpBufk+Kq2HuXKh/9KjhlZv7OqNKh7s8mc/L1BmD9fxlZiYczdLSjXPyo
AVjiyUSQxyF2WucYejOrkX90Z9PS/ppeZy+r8tsmQzsBWyopZ/tK+Op+6aYMhVp3
6+zoDlWxDvnxWdKhUyfOGq2eQiuNzAD+fUVJ25z9AoGARUJ4C87X7vH4QnsIE0g+
ni0xSs8DgSq0v8+cJ7xwyN+NnC6eeU9N2U/m/5anLEM2GFjo4kghLDkC/2urc8dD
UtiisQjWz3O88QHqOvclEAmveuxfCYr/A/CWGdkH3YoK+AXIj3fkwb2Qd//rJ9zL
dT3XPCRatoVKLNKzUGNVcFM=
-----END PRIVATE KEY-----
- type: ecdsa
key: |
-----BEGIN PRIVATE KEY-----
MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgaa7KvLdq72Nb7i7pGm/6
SCW0RAKFcVwz7P9/8Wo2TTShRANCAATlTf0uyezm7riXjZdn1XND00uf4d1tc1jc
V4CiFiDQsDX+3znAGxqhTuoOkVn/G5lwgE1cgTX57r9cyYkso9UY
-----END PRIVATE KEY-----
```
## Configuration sections
### `http`
Controls on what address the server should be listening on
```yaml
http:
address: 0.0.0.0:8080
```
### `cookies`
Configuration related to encrypted cookies
```yaml
cookies:
# Secret key used to encrypt cookies
secret: c7e42fb8baba8f228b2e169fdf4c8216dffd5d33ad18bafd8b928c09ca46c718
```
### `database`
Configure how to connect to the PostgreSQL database.
```yaml
database:
# Full connection string as per
# https://www.postgresql.org/docs/13/libpq-connect.html#id-1.7.3.8.3.6
uri: postgresql://user:password@hostname:5432/database?sslmode=require
# -- OR --
# Separate parameters
host: hostname
port: 5432
#socket:
username: user
password: password
database: database
# Additional parameters for the connection pool
min_connections: 0
max_connections: 10
connect_timeout: 30
idle_timeout: 600
max_lifetime: 1800
```
### `templates`
Allows loading custom templates
```yaml
templates:
# From where to load the templates
# This is relative to the current working directory, *not* the config file
path: /to/templates
# Whether builtin should be loaded or not
builtin: true
```
### `oauth2`
Configuration related to the OAuth 2.0 endpoints
```yaml
oauth2:
# URL where the server should be accessed
issuer: http://localhost:8080/
# List of OAuth 2.0 clients
clients:
# Confidential client
- client_id: first
client_secret: secret
# List of authorized redirect URIs
redirect_uris:
- http://localhost:1234/callback
# Public client, without client_secret
- client_id: second
# Signing keys
keys:
# It needs at least an RSA key to work properly
- type: "rsa"
key: |
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7iinu0NXjWP5/
/4OqyqOMI5uLJIHSrYIZLUlWMldtXmNy0c/pan+gxvZogiYx0cNydO/FogNbC4oD
yj7RIF+QcWJ8wcdG94/P+Xs3HFQzIZfwF+78RWQQJ7nQFekXJ1wQSXV4giw9b4XR
YkoVhHlyxyYGBFffO//DtYVto4uHvXVL0M27bV6l1K8VKspF72gb8Vt44V8OX5hT
sEsYW8SjOD1neEoVKiY6XP63cAG9FTB4a4sKkcUqwjrKEYKio/JLujmCl96eLN18
cuqr6XuSDKvuVJtb+ZNLJi61vIOlD8cz3wu37hr3PCUZ+Ko9Ley+QfopJ3WYFxrI
IjQKb0W5AgMBAAECggEBAK87ZfsTfwczPHn1Ed4gAbkL/GaC8hscrJdBzWiRGUfE
DkBW82IydJaR0ePM2EtsqKblxLRxsZj8qzTnYNKe4SxiBZh0p/MTlnjJr+vKuJIe
LY3VjySA4gKGXASmtGlCCa/eM7kqSJQPBIakxHxej+xDULAGluSrd0wy7D2JtvJY
5By+2apILUujBZZU/iUyB2AqK6IrzALo2gTV9Jhun9Wz0k3DXZBGd41v42BhZ+Rx
bHHgpuUTyDQOpKqJ5g1kN4qGlN/CeoontxcE5NOSgtipWeQEuelT8t4eZKHTXBS+
Byd+uFe8oobWRY2crLptX8TZEENH7wX7y2YgNYUbeZECgYEA95YRhDuukcrDiNuF
fOXs+99XFORsKTbtZYwrouc7PI2CYb0I9ezoQMu3dzWIwOTUQHea5qCo/dYzbeED
fNzwPb2zaWaWFbkEWVTOwRewL+NfP+Ek2Nml+dVJm3d35qdIHYV+9gAcI87iCHxA
gqc13ZS4ba+5/vV6OYwNSAeW0TcCgYEAwem1F9zhVVOIReh3JaJLpZn0xuvZs5kN
TzvFXar33LKdulk5liC3L7ZrqspGESU0JC3pANR8PwuNteEEdHnkC5UTEqMf/fxG
j5CObJl+e2CiV2CNbe+3IQ1PKSxopD+Sq65ze7aP2moVZg94mbw4dsN+uY5QEql1
Bmq0b7Wm2I8CgYBOqlDgefIKgqlEF7O/LnLwyFKr4bP4GGqvZC0NMnkg0TmHAoAR
W3ej9tZROyI7X7mMzjPaaVuoY2Gt3Nu11aFDjL2vlJfFSSb3lzmmInepj43ZBxkl
CWpyCfG8QuZG1AnWz266jOhj/DzXQ1tf5+72e2Vp/HaVaruuAzDJHRgvWwKBgAHy
aMEOlKyYpBufk+Kq2HuXKh/9KjhlZv7OqNKh7s8mc/L1BmD9fxlZiYczdLSjXPyo
AVjiyUSQxyF2WucYejOrkX90Z9PS/ppeZy+r8tsmQzsBWyopZ/tK+Op+6aYMhVp3
6+zoDlWxDvnxWdKhUyfOGq2eQiuNzAD+fUVJ25z9AoGARUJ4C87X7vH4QnsIE0g+
ni0xSs8DgSq0v8+cJ7xwyN+NnC6eeU9N2U/m/5anLEM2GFjo4kghLDkC/2urc8dD
UtiisQjWz3O88QHqOvclEAmveuxfCYr/A/CWGdkH3YoK+AXIj3fkwb2Qd//rJ9zL
dT3XPCRatoVKLNKzUGNVcFM=
-----END PRIVATE KEY-----
- type: "ecdsa"
key: |
-----BEGIN PRIVATE KEY-----
MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgaa7KvLdq72Nb7i7pGm/6
SCW0RAKFcVwz7P9/8Wo2TTShRANCAATlTf0uyezm7riXjZdn1XND00uf4d1tc1jc
V4CiFiDQsDX+3znAGxqhTuoOkVn/G5lwgE1cgTX57r9cyYkso9UY
-----END PRIVATE KEY-----
```

View File

@@ -0,0 +1,62 @@
# Installation
## Requirements
- A PostgreSQL database
- Either:
- A [Rust toolchain](https://www.rust-lang.org/learn/get-started) (recommended for development)
- or [Docker](https://www.docker.com/get-started) (or a compatible container runtime)
## Installing from the source
1. Get the source
```sh
git clone https://github.com/matrix-org/matrix-authentication-service.git
cd matrix-authentication-service
```
2. Compile the CLI
```
cargo build --release
```
3. Grab the built binary
```
cp ./target/release/mas-cli ~/.local/bin # Copy the binary somewhere in $PATH
mas-cli --help # Should display the help message
```
## Running from the Docker image
A Docker image is available here: [`ghcr.io/matrix-org/matrix-authentication-service:main`](https://ghcr.io/matrix-org/matrix-authentication-service:main)
---
```sh
docker run --rm ghcr.io/matrix-org/matrix-authentication-service:main --help
```
```
mas-cli
USAGE:
mas-cli [OPTIONS] [SUBCOMMAND]
FLAGS:
-h, --help Print help information
-V, --version Print version information
OPTIONS:
-c, --config <CONFIG>... Path to the configuration file [default: config.yaml]
SUBCOMMANDS:
config Configuration-related commands
database Manage the database
help Print this message or the help of the given subcommand(s)
manage Manage the instance
server Runs the web server
templates Templates-related commands
```
Note that when running in a Docker environment
---
The next step is to generate the configuration file and tweak it to reach the PostgreSQL database.

75
docs/usage/usage.md Normal file
View File

@@ -0,0 +1,75 @@
# Using the service
## Running
Once the configuration is done, one should run the database migrations by running
```sh
mas-cli database migrate
```
The server can then be started by running
```sh
mas-cli server
```
```
Sep 24 14:42:42.743 INFO mas_cli::server: Starting task scheduler
Sep 24 14:42:42.743 INFO mas_core::templates: Loading builtin templates
Sep 24 14:42:42.752 INFO mas_cli::server: Listening on http://0.0.0.0:8080
```
The server should now be accessible through <http://localhost:8080/>.
**Note**: when running with Docker, the port used by the server should be exposed with the `-p` flag:
```sh
docker run --rm \
-v `pwd`/config.yaml:/config.yaml \
-p 8080:8080 \
ghcr.io/matrix-org/matrix-authentication-service:main \
server
```
## Registering, logging in and out
Through the interface, users are able to create an account by clicking the `Register` button on the top right (or going to [`/register`](http://localhost:8080/register).
They can then end their session by clicking the `Log out` button and log back in.
## Playing around with the playground
The OpenID Foundation hosts a OpenID Connect Playground where one can test logging in through an OIDC provider: https://openidconnect.net/
### Step 1: Add the client to the server config
Add the following section to the server configuration file `config.yaml`:
```yaml
oauth2:
# ...
clients:
- client_id: oidc-playground
client_secret: verysecret
redirect_uris:
- "https://openidconnect.net/callback"
```
### Step 2: Change the playground configuration
- Navigate to [the playground](https://openidconnect.net/)
- Click on "Configuration"
- Server template: *Custom*
- Paste the discovery document URL found on the service homepage (e.g. `http://localhost:8080/.well-known/openid-configuration`)
- Click "Use discovery document" ; it should fill out the authorization, token and token keys endpoints
- Set the OIDC Client ID to `oidc-playground` and the Client Secret to `verysecret` (must match the ones in the configuration)
- Click "Save"
### Step 3: Run the OpenID Connect flow
Start the flow by clicking the "Start" button.
It should redirect the browser to the authentication service.
If a user is already logged in, it should redirect back to the playground immediately.
Follow the flow to see the code exchange happen.
Note that the last step only works if the service is accessible through the internet.