mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
feat(chat): join users to rooms on sign-in
This commit is contained in:
18
infrastructure/matrix/element/40-element-config.sh
Normal file
18
infrastructure/matrix/element/40-element-config.sh
Normal file
@@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
# Renders /app/config.json from config.json.tmpl at container start.
|
||||
#
|
||||
# The homeserver URL and server_name differ per environment, and config.json is
|
||||
# read by the browser rather than the build, so baking it into the image would
|
||||
# mean one image per environment. Dropped into /docker-entrypoint.d, which the
|
||||
# upstream nginx entrypoint runs (in lexical order) before starting nginx —
|
||||
# no ENTRYPOINT override, so the image's own startup work still happens.
|
||||
set -eu
|
||||
|
||||
: "${MATRIX_PUBLIC_BASEURL:?MATRIX_PUBLIC_BASEURL is required}"
|
||||
: "${MATRIX_SERVER_NAME:?MATRIX_SERVER_NAME is required}"
|
||||
: "${ELEMENT_PUBLIC_URL:?ELEMENT_PUBLIC_URL is required}"
|
||||
|
||||
envsubst '${MATRIX_PUBLIC_BASEURL} ${MATRIX_SERVER_NAME} ${ELEMENT_PUBLIC_URL}' \
|
||||
< /app/config.json.tmpl > /app/config.json
|
||||
|
||||
echo "element-config: homeserver ${MATRIX_PUBLIC_BASEURL} (${MATRIX_SERVER_NAME})"
|
||||
@@ -5,5 +5,19 @@
|
||||
# Pin the tag; never float on `latest`.
|
||||
FROM ghcr.io/element-hq/element-web:v1.11.108
|
||||
|
||||
COPY config.json /app/config.json
|
||||
COPY config.json.tmpl /app/config.json.tmpl
|
||||
COPY sso.html /app/sso.html
|
||||
# Replaces the upstream manifest, which names the app "Element" and advertises
|
||||
# the Play/App Store builds under related_applications. Those apps cannot log
|
||||
# in here — this deployment has no password login and no SSO provider, only the
|
||||
# JWT handoff from freight-api — so pointing staff at them is a dead end.
|
||||
COPY manifest.json /app/manifest.json
|
||||
COPY 40-element-config.sh /docker-entrypoint.d/40-element-config.sh
|
||||
|
||||
# The image runs as uid 101 (nginx) but ships /app root-owned, so the startup
|
||||
# hook could not write the rendered config without this.
|
||||
USER root
|
||||
RUN chmod +x /docker-entrypoint.d/40-element-config.sh \
|
||||
&& touch /app/config.json \
|
||||
&& chown nginx:nginx /app/config.json
|
||||
USER nginx
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
{
|
||||
"default_server_config": {
|
||||
"m.homeserver": {
|
||||
"base_url": "https://matrix.edr.et",
|
||||
"server_name": "matrix.edr.et"
|
||||
"base_url": "${MATRIX_PUBLIC_BASEURL}",
|
||||
"server_name": "${MATRIX_SERVER_NAME}"
|
||||
}
|
||||
},
|
||||
"brand": "EDR Chat",
|
||||
"permalink_prefix": "https://chat.edr.et",
|
||||
"permalink_prefix": "${ELEMENT_PUBLIC_URL}",
|
||||
"disable_guests": true,
|
||||
"disable_3pid_login": true,
|
||||
"disable_custom_urls": true,
|
||||
"default_theme": "light",
|
||||
"mobile_guide_toast": false,
|
||||
"settingDefaults": {
|
||||
"UIFeature.registration": false
|
||||
}
|
||||
12
infrastructure/matrix/element/manifest.json
Normal file
12
infrastructure/matrix/element/manifest.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "EDR Chat",
|
||||
"short_name": "EDR Chat",
|
||||
"display": "standalone",
|
||||
"theme_color": "#0dbd8b",
|
||||
"start_url": "index.html",
|
||||
"icons": [
|
||||
{ "src": "/vector-icons/150.png", "sizes": "150x150", "type": "image/png" },
|
||||
{ "src": "/vector-icons/300.png", "sizes": "300x300", "type": "image/png" },
|
||||
{ "src": "/vector-icons/1024.png", "sizes": "1024x1024", "type": "image/png" }
|
||||
]
|
||||
}
|
||||
@@ -1,16 +1,23 @@
|
||||
<!doctype html>
|
||||
<!--
|
||||
Element only honours a `?loginToken=` on `/` if `mx_sso_hs_url` is already
|
||||
in localStorage (element-web apps/web/src/Lifecycle.ts attemptTokenLogin,
|
||||
key defined in apps/web/src/BasePlatform.ts). Normally that key is written
|
||||
by Element itself at the start of an SSO redirect; freight-api's SSO
|
||||
handoff skips that redirect (it already knows the homeserver), so this
|
||||
page seeds the key by hand and forwards straight to the login-token URL.
|
||||
Session handoff from freight-api into Element.
|
||||
|
||||
freight-api's chat-sso.service.ts links here as
|
||||
https://chat.edr.et/sso.html?t=<login_token>&hs=<homeserver base_url>.
|
||||
`hs` is passed rather than hardcoded so this file doesn't need to change if
|
||||
MATRIX_PUBLIC_BASEURL ever does.
|
||||
https://chat.edr.et/sso.html#hs=<homeserver>&t=<access_token>&u=<user_id>&d=<device_id>
|
||||
— a fragment, not a query, so the token is never sent to a server and never
|
||||
lands in an access log. location.replace() below drops this URL from history
|
||||
as well, so the token does not survive the redirect.
|
||||
|
||||
The keys written here are the ones Element reads on startup
|
||||
(element-web src/Lifecycle.ts getStoredSessionVars/getStoredToken): the token
|
||||
is looked up in IndexedDB first and falls back to localStorage, which Element
|
||||
then migrates into IndexedDB itself. A plaintext token is accepted —
|
||||
tryDecryptToken returns a string token as-is, and only decrypts when it finds
|
||||
an encrypted payload.
|
||||
|
||||
This replaced a ?loginToken= handoff: POST /_matrix/client/v1/login/get_token
|
||||
is capped at one call per user per minute by a limiter hardcoded in Synapse,
|
||||
so clicking Chat twice in a minute failed.
|
||||
-->
|
||||
<html lang="en">
|
||||
<head>
|
||||
@@ -19,17 +26,23 @@
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
var token = params.get("t");
|
||||
var params = new URLSearchParams(window.location.hash.slice(1));
|
||||
var homeserver = params.get("hs");
|
||||
if (token && homeserver) {
|
||||
localStorage.setItem("mx_sso_hs_url", homeserver);
|
||||
window.location.replace(
|
||||
"/?loginToken=" + encodeURIComponent(token),
|
||||
);
|
||||
var token = params.get("t");
|
||||
var userId = params.get("u");
|
||||
var deviceId = params.get("d");
|
||||
|
||||
if (homeserver && token && userId && deviceId) {
|
||||
localStorage.setItem("mx_hs_url", homeserver);
|
||||
localStorage.setItem("mx_user_id", userId);
|
||||
localStorage.setItem("mx_device_id", deviceId);
|
||||
localStorage.setItem("mx_access_token", token);
|
||||
localStorage.setItem("mx_has_access_token", "true");
|
||||
localStorage.setItem("mx_is_guest", "false");
|
||||
window.location.replace("/");
|
||||
} else {
|
||||
document.body.textContent =
|
||||
"Missing sign-in token. Go back to the EDR backoffice and click Chat again.";
|
||||
"Missing sign-in details. Go back to the EDR backoffice and click Chat again.";
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -42,6 +42,24 @@ federation_domain_whitelist: []
|
||||
enable_registration: false
|
||||
encryption_enabled_by_default_for_room_type: "off"
|
||||
|
||||
# Turning rooms' encryption off above is not enough on its own: Element still
|
||||
# bootstraps cross-signing on a user's first login, and from then on gates
|
||||
# EVERY later login behind "Verify this device" (MatrixChat: crossSigningIsSetUp
|
||||
# -> Views.COMPLETE_SECURITY). Nobody on this deployment can clear that gate —
|
||||
# each SSO click is a brand-new device, so there is never a second verified
|
||||
# device to accept the request, and resetting the identity needs UIA, which
|
||||
# password_config.enabled: false makes impossible.
|
||||
#
|
||||
# This tells Element encryption is off here, so it skips the bootstrap
|
||||
# (shouldSkipSetupEncryption) and the gate is never armed. Only helps accounts
|
||||
# that have no cross-signing keys yet — anyone already bootstrapped keeps
|
||||
# hitting the gate until their keys are cleared.
|
||||
extra_well_known_client_content:
|
||||
io.element.e2ee:
|
||||
default: false
|
||||
force_disable: true
|
||||
secure_backup_required: false
|
||||
|
||||
# Employees authenticate via freight-api's SSO handoff, never a Matrix
|
||||
# password prompt. This is the entire auth story for this deployment.
|
||||
password_config:
|
||||
|
||||
Reference in New Issue
Block a user