comms: mint guest tokens via MAS login
This commit is contained in:
parent
b86800cd6d
commit
59305ca27c
@ -7,7 +7,7 @@ Core flow
|
|||||||
- Synapse is the homeserver; MAS fronts login, Synapse serves client/server APIs.
|
- Synapse is the homeserver; MAS fronts login, Synapse serves client/server APIs.
|
||||||
- Element Web provides the main UI; Element Call embeds LiveKit for group video.
|
- Element Web provides the main UI; Element Call embeds LiveKit for group video.
|
||||||
- LiveKit handles SFU media; Coturn provides TURN for NAT traversal.
|
- LiveKit handles SFU media; Coturn provides TURN for NAT traversal.
|
||||||
- matrix-guest-register provides guest accounts + guest sessions (no Keycloak).
|
- matrix-guest-register provisions MAS guest accounts and performs MAS password login to mint device-bound guest tokens (no Keycloak).
|
||||||
|
|
||||||
Operational jobs
|
Operational jobs
|
||||||
- mas-db-ensure-job: ensures MAS database role/database + secret in comms.
|
- mas-db-ensure-job: ensures MAS database role/database + secret in comms.
|
||||||
|
|||||||
@ -21,8 +21,6 @@ data:
|
|||||||
MAS_ADMIN_CLIENT_ID = os.environ["MAS_ADMIN_CLIENT_ID"]
|
MAS_ADMIN_CLIENT_ID = os.environ["MAS_ADMIN_CLIENT_ID"]
|
||||||
MAS_ADMIN_CLIENT_SECRET_FILE = os.environ.get("MAS_ADMIN_CLIENT_SECRET_FILE", "/etc/mas/admin-client/client_secret")
|
MAS_ADMIN_CLIENT_SECRET_FILE = os.environ.get("MAS_ADMIN_CLIENT_SECRET_FILE", "/etc/mas/admin-client/client_secret")
|
||||||
MAS_ADMIN_SCOPE = os.environ.get("MAS_ADMIN_SCOPE", "urn:mas:admin")
|
MAS_ADMIN_SCOPE = os.environ.get("MAS_ADMIN_SCOPE", "urn:mas:admin")
|
||||||
SESSION_TTL_SEC = int(os.environ.get("SESSION_TTL_SEC", "43200"))
|
|
||||||
|
|
||||||
RATE_WINDOW_SEC = int(os.environ.get("RATE_WINDOW_SEC", "60"))
|
RATE_WINDOW_SEC = int(os.environ.get("RATE_WINDOW_SEC", "60"))
|
||||||
RATE_MAX = int(os.environ.get("RATE_MAX", "30"))
|
RATE_MAX = int(os.environ.get("RATE_MAX", "30"))
|
||||||
_rate = {} # ip -> [window_start, count]
|
_rate = {} # ip -> [window_start, count]
|
||||||
@ -126,21 +124,30 @@ data:
|
|||||||
user = payload.get("data") or {}
|
user = payload.get("data") or {}
|
||||||
return status, user.get("id")
|
return status, user.get("id")
|
||||||
|
|
||||||
def _create_session(admin_token, user_id, scope):
|
def _set_password(admin_token, user_id, password):
|
||||||
status, payload = _admin_api(
|
status, _payload = _admin_api(
|
||||||
admin_token,
|
admin_token,
|
||||||
"POST",
|
"POST",
|
||||||
"/personal-sessions",
|
f"/users/{parse.quote(user_id)}/set-password",
|
||||||
{
|
{"password": password},
|
||||||
"actor_user_id": user_id,
|
|
||||||
"human_name": "guest session",
|
|
||||||
"scope": scope,
|
|
||||||
"expires_in": SESSION_TTL_SEC,
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
if status != 201:
|
return status in (200, 204)
|
||||||
return None
|
|
||||||
return (payload.get("data", {}).get("attributes", {}) or {}).get("access_token")
|
def _login_password(username, password):
|
||||||
|
payload = {
|
||||||
|
"type": "m.login.password",
|
||||||
|
"identifier": {"type": "m.id.user", "user": f"@{username}:{SERVER_NAME}"},
|
||||||
|
"password": password,
|
||||||
|
}
|
||||||
|
status, data = _json(
|
||||||
|
"POST",
|
||||||
|
f"{MAS_BASE}/_matrix/client/v3/login",
|
||||||
|
body=payload,
|
||||||
|
timeout=20,
|
||||||
|
)
|
||||||
|
if status != 200:
|
||||||
|
return None, None
|
||||||
|
return data.get("access_token"), data.get("device_id")
|
||||||
|
|
||||||
def _set_display_name(access_token, user_id, displayname):
|
def _set_display_name(access_token, user_id, displayname):
|
||||||
_json(
|
_json(
|
||||||
@ -235,9 +242,12 @@ data:
|
|||||||
if not mas_user_id or not localpart:
|
if not mas_user_id or not localpart:
|
||||||
raise RuntimeError("add_user_failed")
|
raise RuntimeError("add_user_failed")
|
||||||
|
|
||||||
access_token = _create_session(admin_token, mas_user_id, "urn:matrix:client:api:*")
|
password = secrets.token_urlsafe(18)
|
||||||
|
if not _set_password(admin_token, mas_user_id, password):
|
||||||
|
raise RuntimeError("set_password_failed")
|
||||||
|
access_token, device_id = _login_password(localpart, password)
|
||||||
if not access_token:
|
if not access_token:
|
||||||
raise RuntimeError("session_failed")
|
raise RuntimeError("login_failed")
|
||||||
try:
|
try:
|
||||||
_set_display_name(access_token, f"@{localpart}:{SERVER_NAME}", displayname)
|
_set_display_name(access_token, f"@{localpart}:{SERVER_NAME}", displayname)
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -248,7 +258,7 @@ data:
|
|||||||
resp = {
|
resp = {
|
||||||
"user_id": f"@{localpart}:{SERVER_NAME}",
|
"user_id": f"@{localpart}:{SERVER_NAME}",
|
||||||
"access_token": access_token,
|
"access_token": access_token,
|
||||||
"device_id": "guest_device",
|
"device_id": device_id or "guest_device",
|
||||||
"home_server": SERVER_NAME,
|
"home_server": SERVER_NAME,
|
||||||
}
|
}
|
||||||
return self._send_json(200, resp)
|
return self._send_json(200, resp)
|
||||||
|
|||||||
@ -47,8 +47,6 @@ spec:
|
|||||||
value: http://matrix-authentication-service:8081/api/admin/v1
|
value: http://matrix-authentication-service:8081/api/admin/v1
|
||||||
- name: SYNAPSE_BASE
|
- name: SYNAPSE_BASE
|
||||||
value: http://othrys-synapse-matrix-synapse:8008
|
value: http://othrys-synapse-matrix-synapse:8008
|
||||||
- name: SESSION_TTL_SEC
|
|
||||||
value: "43200"
|
|
||||||
- name: MATRIX_SERVER_NAME
|
- name: MATRIX_SERVER_NAME
|
||||||
value: live.bstein.dev
|
value: live.bstein.dev
|
||||||
- name: RATE_WINDOW_SEC
|
- name: RATE_WINDOW_SEC
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user