Migrate Matrix auth to appservice (MAS-durable)

Replace password login + password-UIA cross-signing with appservice
as_token auth and MSC4190 device creation, so the bot survives the
Matrix Authentication Service (MAS) migration that removes m.login.password
and UIA.

- internal/bot/client.go: NewClient uses AS_TOKEN, SetAppServiceUserID,
  whoami validation, cryptohelper MSC4190 device create; drop device.json
  (crypto store persists device id); cross-signing best-effort/soft-fail.
- main.go: Config.Password -> ASToken (reads AS_TOKEN).
- internal/util/auth.go: deleted (password login dead in a MAS world).
- Bump mautrix-go v0.28.0 -> v0.28.1.
- registration.yaml.example + README/.env.example: appservice setup docs.
This commit is contained in:
prosolis
2026-07-03 15:12:47 -07:00
parent c07d228be6
commit 48330be3d5
8 changed files with 177 additions and 229 deletions

61
registration.yaml.example Normal file
View File

@@ -0,0 +1,61 @@
# GogoBee appservice registration — MAS-durable auth.
#
# Copy to registration.yaml, fill in the tokens, and register it with your
# homeserver. This replaces the old password login: the as_token is a Synapse-
# level trust relationship, so it never expires and is unaffected by Matrix
# Authentication Service (MAS) removing password login / UIA.
#
# ---------------------------------------------------------------------------
# 1. Generate two independent secrets (do NOT reuse the same value):
# openssl rand -hex 32 # -> as_token
# openssl rand -hex 32 # -> hs_token
#
# 2. Point Synapse at this file in homeserver.yaml:
# app_service_config_files:
# - /path/to/registration.yaml
#
# 3. Restart Synapse, then set AS_TOKEN in GogoBee's .env to the as_token below.
#
# MSC4190 device management (so the bot creates its E2EE device without UIA) is
# opted into per-appservice via the `io.element.msc4190: true` flag at the
# bottom of this file — there is NO homeserver-level flag for it in current
# Synapse. Works even with Matrix Authentication Service (MAS) delegation on:
# Synapse serves PUT /devices for appservice requests regardless of MAS.
# ---------------------------------------------------------------------------
# Unique identifier for this appservice.
id: gogobee
# The token GogoBee sends to the homeserver (Authorization: Bearer <as_token>).
# This is the value that goes in the bot's AS_TOKEN env var.
as_token: "CHANGE_ME_as_token_from_openssl_rand_hex_32"
# The token the homeserver would use to authenticate to the appservice's push
# endpoint. GogoBee uses /sync rather than the push (transaction) model, so it
# is not consumed by the bot — but Synapse still requires it to be set and
# distinct from as_token.
hs_token: "CHANGE_ME_hs_token_from_openssl_rand_hex_32"
# The bot's localpart. Its full user ID is @gogobee:<your-domain>, which must
# match BOT_USER_ID in .env.
sender_localpart: gogobee
# GogoBee uses /sync, not the transaction push API, so this URL is never called.
# Synapse requires the field; null disables push delivery.
url: null
# GogoBee only ever acts as its own @gogobee user. This namespace claims that
# single user ID. Adjust the domain to match your homeserver.
# The bot only needs to ACT AS @gogobee (which already exists), not exclusively
# own the namespace — so exclusive is false to avoid any conflict with the
# existing account.
namespaces:
users:
- exclusive: false
regex: "@gogobee:example\\.com"
aliases: []
rooms: []
# Required for the bot to manage its own E2EE device via MSC4190 (PUT /devices)
# instead of the UIA-gated login flow that MAS removes.
io.element.msc4190: true