Files
Devon HudsonandClaude Opus 5.5 ba7438322b Add a POST /api/admin/v1/invite-guests admin endpoint
Mints a single-use, passwordless registration token for each guest,
pinned to their address and username and expiring after
`guest_invites.invite_lifetime`, and schedules their invite emails. The
links are only ever mailed to the guests, so the response carries a
count rather than the tokens.

Everything is validated before anything is minted, and the batch is
committed as a whole, so a rejected request sends no email at all. Each
invite goes through the registration policy as `POST /register` will
check it, so an invite the guest form would refuse is a 400 naming the
invite and every violation. The policy sees an empty requester, as the
request comes from the inviter's homeserver rather than the guest. A
username that is already taken is refused up front, rather than emailed
out as a link nobody can register with. Addresses are deduplicated
ignoring case before the usernames are checked, keeping the first entry,
so a repeated address never counts as a username given twice.

The caller sends the room name and the inviter on the inviter's behalf,
so the endpoint doesn't trust them. The room name and the inviter's
display name are stripped of control characters, including the
bidirectional controls `char::is_control` misses, and truncated before
they are stored in the job payload. The inviter's Matrix ID is never
truncated, so it can't show a server it isn't from: it is kept whole if
it is valid under the historical grammar, and left out otherwise.

The room ID is checked as `/open-room` checks it, and is only recorded
on the span once it is valid.

The endpoint answers 404 while guest invites are disabled. The check is
in the handler, as the admin router doesn't see the configuration.
`guest_invites.enabled` turns it on, and requires `client_room_url`.
`/open-room` keeps using `client_room_url` while the endpoint is
disabled, so that links already sent keep working.

`invite_lifetime` is a positive number of seconds that fits in a `u32`,
so MAS refuses a zero or negative lifetime at startup, and adding it to
the current time can't overflow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 19:57:12 +00:00
..

About this documentation

This documentation is intended to give an overview of how the matrix-authentication-service (MAS) works, both from an admin perspective and from a developer perspective.

MAS is an OAuth 2.0 and OpenID Provider server for Matrix. It has been created to support the migration of Matrix to an OpenID Connect (OIDC) based authentication layer as per MSC3861.

The documentation itself is built using mdBook. A hosted version is available at https://element-hq.github.io/matrix-authentication-service/.

How the documentation is organized

This documentation has four main sections: