You've already forked authentication-service
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:
22
book.toml
Normal file
22
book.toml
Normal 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
3
docs/README.md
Normal 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
24
docs/SUMMARY.md
Normal 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]()
|
||||
84
docs/development/architecture.md
Normal file
84
docs/development/architecture.md
Normal 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.
|
||||
96
docs/development/database.md
Normal file
96
docs/development/database.md
Normal 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
91
docs/development/warp.md
Normal 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
40
docs/usage/cli/README.md
Normal 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
35
docs/usage/cli/config.md
Normal 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
|
||||
```
|
||||
11
docs/usage/cli/database.md
Normal file
11
docs/usage/cli/database.md
Normal 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
12
docs/usage/cli/manage.md
Normal 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
12
docs/usage/cli/server.md
Normal 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.
|
||||
37
docs/usage/cli/templates.md
Normal file
37
docs/usage/cli/templates.md
Normal 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
212
docs/usage/configuration.md
Normal 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-----
|
||||
```
|
||||
62
docs/usage/installation.md
Normal file
62
docs/usage/installation.md
Normal 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
75
docs/usage/usage.md
Normal 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.
|
||||
Reference in New Issue
Block a user