Add 'README-mobile-oidc-bridge-readme.docx' and 'README-mobile-oidc-bridge-readme.md'.

This commit is contained in:
2026-09-27 17:43:44 +02:00
parent c7ce9f50ac
commit 37cab43f2c
2 changed files with 691 additions and 0 deletions
+691
View File
@@ -0,0 +1,691 @@
# Mattermost OIDC Mobile Bridge
## Zweck
Diese Dokumentation beschreibt die Installation und Konfiguration der `mobile-bridge` aus dem Projekt `mattermost-oidc` für eine native Mattermost-Mobile-App.
Die Bridge wird benötigt, wenn Mattermost für die Anmeldung das Plugin `mattermost-oidc` verwendet, die native Mobile-App aber den eingebauten Mattermost-OpenID-Endpunkt erwartet. Die Bridge verändert Mattermost selbst nicht. Sie fängt nur zwei HTTP-Endpunkte ab:
- `/api/v4/config/client`
- `/oauth/openid/mobile_login`
Für die native Mattermost-App wird in der Client-Konfiguration `EnableSignUpWithOpenId=true` signalisiert. Der Mobile-Login wird anschließend zum `mattermost-oidc`-Plugin umgeleitet.
Web- und Desktop-Clients bleiben unverändert.
## Versions- und Umgebungsvariablen
Die Anleitung ist bewusst versionsunabhängig aufgebaut. Vor Beginn werden die für die jeweilige Installation gültigen Versionen, URLs und Pfade einmal in der aktuellen Root-Shell gesetzt. Die nachfolgenden Befehle verwenden diese Variablen.
```bash
export MM_VER="11.7.11"
export MM_OIDC_VER="0.6.1"
export MM_SITE_URL="https://mm.nd.digital"
export MM_SRC_BASE="/usr/local/src/mattermost-oidc"
export MM_OIDC_REPO="https://github.com/server-camp/mattermost-oidc-plugin.git"
export MM_OIDC_SRC="${MM_SRC_BASE}/mattermost-oidc-plugin-${MM_OIDC_VER}"
export MM_UPSTREAM="http://127.0.0.1:8065"
export MM_BRIDGE_LISTEN="127.0.0.1:8066"
export MM_BRIDGE_BIN_DIR="/usr/local/sbin"
export MM_BRIDGE_BIN="${MM_BRIDGE_BIN_DIR}/mattermost-oidc-mobile-bridge-${MM_OIDC_VER}"
export MM_BRIDGE_LINK="${MM_BRIDGE_BIN_DIR}/mattermost-oidc-mobile-bridge"
```
`MM_VER` dokumentiert die aktuell eingesetzte Mattermost-Version. Für Download und Build der Bridge ist insbesondere `MM_OIDC_VER` relevant. Bei einer späteren Aktualisierung wird die gewünschte Version im Variablenblock geändert und der Ablauf mit dem neuen Release wiederholt.
Die hier beschriebene Installation wurde mit den oben beispielhaft eingetragenen Versionen getestet. Weitere Rahmenbedingungen waren Debian 13, nginx als Reverse Proxy, Mattermost auf `127.0.0.1:8065`, die Mobile Bridge auf `127.0.0.1:8066` und Keycloak als OIDC-Provider.
Die Bridge benötigt **kein eigenes OIDC-Client-Secret**. Client-ID, Client-Secret und Kommunikation mit dem OIDC-Provider bleiben Aufgabe des `mattermost-oidc`-Plugins.
## Funktionsweise
Der relevante Ablauf ist:
```text
Mattermost Mobile App
|
| GET /api/v4/config/client
v
nginx
|
+--> mobile-bridge :8066
|
+--> Mattermost :8065
|
+--> bei Mobile User-Agent:
EnableSignUpWithOpenId=true
Mobile App
|
| /oauth/openid/mobile_login?redirect_to=mmauth://callback
v
nginx
|
+--> mobile-bridge :8066
|
+--> 302 /plugins/mattermost-oidc/oauth2/connect
?mobile_redirect=mmauth://callback
|
v
Keycloak
|
v
/plugins/mattermost-oidc/oauth2/callback
|
v
mmauth://callback
|
v
Mattermost App
```
Alle anderen Requests, insbesondere REST, WebSocket, Dateien und `/plugins/...`, gehen weiterhin direkt an Mattermost.
## Voraussetzungen
Vor Installation der Bridge müssen folgende Bedingungen erfüllt sein:
1. Das Plugin `mattermost-oidc` ist installiert und aktiviert.
2. Der normale OIDC-Web-Login funktioniert bereits vollständig.
3. Der OIDC-Provider ist korrekt eingerichtet.
4. Die bestehende Redirect-URI des Plugins funktioniert:
`<SiteURL>/plugins/mattermost-oidc/oauth2/callback`
5. nginx leitet die normale Mattermost-Site bereits auf `127.0.0.1:8065` weiter.
6. Go ist zum Bauen der Bridge verfügbar.
Die benötigte Go-Version ist nicht in dieser Anleitung fest verdrahtet. Nach dem Download wird sie direkt aus `mobile-bridge/go.mod` abgelesen. Falls die Debian-Standardversion nicht ausreicht, kann eine passende Go-Version beispielsweise aus den Debian-Backports verwendet werden.
## 1. Quellcode herunterladen
Das Repository wird versionsbezogen unter `MM_SRC_BASE` abgelegt. Dadurch können mehrere Release-Stände parallel vorhanden sein und die Herkunft einer installierten Binary bleibt nachvollziehbar.
Arbeitsverzeichnis anlegen:
```bash
mkdir -p "$MM_SRC_BASE"
```
Gewünschten Release-Tag direkt in ein versionsbezogenes Verzeichnis klonen:
```bash
git clone --branch "v${MM_OIDC_VER}" --depth 1 \
"$MM_OIDC_REPO" \
"$MM_OIDC_SRC"
```
Ausgecheckten Stand kontrollieren:
```bash
cd "$MM_OIDC_SRC"
git status
git describe --tags --exact-match
```
Bei einem direkt ausgecheckten Release-Tag ist ein `detached HEAD` normal. `git describe --tags --exact-match` sollte `v${MM_OIDC_VER}` ausgeben.
Die Mobile Bridge befindet sich anschließend unter:
```text
${MM_OIDC_SRC}/mobile-bridge
```
## 2. Go installieren
Benötigte Go-Version aus dem Release ermitteln:
```bash
awk '/^go / {print "benötigte Go-Version:", $2}' \
"$MM_OIDC_SRC/mobile-bridge/go.mod"
```
Installierte Version prüfen:
```bash
go version
```
Falls die vorhandene Go-Version nicht ausreicht, eine passende Version installieren. Unter Debian 13 kann - sofern `trixie-backports` bereits konfiguriert ist - beispielsweise verwendet werden:
```bash
apt install -t trixie-backports golang-go
```
Danach erneut prüfen:
```bash
go version
```
## 3. Mobile Bridge bauen
In das Bridge-Verzeichnis wechseln:
```bash
cd "$MM_OIDC_SRC/mobile-bridge"
```
Binary bauen:
```bash
go build -o mobile-bridge .
```
Ergebnis kontrollieren:
```bash
file mobile-bridge
ls -lh mobile-bridge
```
## 4. Bridge vor der Installation manuell testen
Port 8066 sollte zunächst frei sein:
```bash
ss -lntp | grep ':8066'
```
Die Bridge testweise nur auf Loopback starten:
```bash
LISTEN="$MM_BRIDGE_LISTEN" UPSTREAM="$MM_UPSTREAM" ./mobile-bridge
```
Die Bindung an `127.0.0.1` ist beabsichtigt. Die Bridge muss nicht direkt aus dem Internet erreichbar sein; nginx ist der öffentliche Einstiegspunkt.
### Mobile Client-Konfiguration testen
In einem zweiten Terminal:
```bash
curl -s -A 'Mattermost Mobile/' \
http://127.0.0.1:8066/api/v4/config/client |
grep -o '"EnableSignUpWithOpenId":"[^"]*"'
```
Erwartet:
```text
"EnableSignUpWithOpenId":"true"
```
Mit einem Browser-User-Agent:
```bash
curl -s -A 'Mozilla/5.0' \
http://127.0.0.1:8066/api/v4/config/client |
grep -o '"EnableSignUpWithOpenId":"[^"]*"'
```
Bei der dokumentierten Konfiguration war das Ergebnis:
```text
"EnableSignUpWithOpenId":"false"
```
Damit ist sichergestellt, dass die Änderung nur für die Mobile-App erfolgt.
### Mobile-Login-Redirect testen
```bash
curl -si \
'http://127.0.0.1:8066/oauth/openid/mobile_login?redirect_to=mmauth%3A%2F%2Fcallback' |
head -20
```
Erwartet wird HTTP 302 mit einem `Location`-Header in Richtung:
```text
/plugins/mattermost-oidc/oauth2/connect?mobile_redirect=mmauth%3A%2F%2Fcallback
```
Danach den manuellen Prozess mit `Ctrl-C` beenden.
## 5. Binary versionsbezogen installieren
Die gebaute Bridge wird mit ihrer Plugin-/Bridge-Version im Dateinamen unter `/usr/local/sbin` installiert. Ein stabiler Symlink ohne Versionsnummer zeigt auf die aktuell aktive Binary. Dadurch kann ein Update oder Rollback durch Umschalten des Symlinks erfolgen, während die systemd-Unit unverändert bleibt.
Binary installieren:
```bash
install -o root -g root -m 755 \
mobile-bridge \
"$MM_BRIDGE_BIN"
```
Stabilen Symlink auf diese Version setzen:
```bash
ln -sfn "$(basename "$MM_BRIDGE_BIN")" "$MM_BRIDGE_LINK"
```
Ergebnis kontrollieren:
```bash
ls -l "$MM_BRIDGE_BIN" "$MM_BRIDGE_LINK"
readlink -f "$MM_BRIDGE_LINK"
```
Beispiel für Version `0.6.1`:
```text
/usr/local/sbin/mattermost-oidc-mobile-bridge-0.6.1
/usr/local/sbin/mattermost-oidc-mobile-bridge -> mattermost-oidc-mobile-bridge-0.6.1
```
## 6. systemd-Service einrichten
Datei anlegen:
```text
/etc/systemd/system/mattermost-oidc-mobile-bridge.service
```
Inhalt:
```ini
[Unit]
Description=Mattermost OIDC Mobile Bridge
After=network.target mattermost.service
Requires=mattermost.service
[Service]
Type=simple
User=mattermost
Group=mattermost
Environment=LISTEN=127.0.0.1:8066
Environment=UPSTREAM=http://127.0.0.1:8065
ExecStart=/usr/local/sbin/mattermost-oidc-mobile-bridge
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
```
`ExecStart` verweist bewusst auf den versionsunabhängigen Symlink. Bei einem Update muss die Unit-Datei deshalb nicht geändert werden.
Konfiguration laden und prüfen:
```bash
systemctl daemon-reload
systemd-analyze verify /etc/systemd/system/mattermost-oidc-mobile-bridge.service
```
Dienst zunächst nur starten:
```bash
systemctl start mattermost-oidc-mobile-bridge.service
```
Status prüfen:
```bash
systemctl status mattermost-oidc-mobile-bridge.service
ss -lntp | grep ':8066'
```
Erwartet wird ein Listener ausschließlich auf:
```text
127.0.0.1:8066
```
Nach erfolgreichem End-to-End-Test den Autostart aktivieren:
```bash
systemctl enable mattermost-oidc-mobile-bridge.service
```
Kontrolle:
```bash
systemctl is-enabled mattermost-oidc-mobile-bridge.service
systemctl is-active mattermost-oidc-mobile-bridge.service
```
Erwartet:
```text
enabled
active
```
## 7. nginx konfigurieren
In der dokumentierten Installation ist die aktive Konfiguration:
```text
/etc/nginx/sites-available/mm.nd.digital.conf
```
mit Symlink unter `sites-enabled`.
Vor der Änderung ein Backup der realen Datei anlegen, nicht nur des Symlinks.
Vor den allgemeinen Mattermost-`location`-Blöcken werden zwei Exact-Match-Locations eingefügt:
```nginx
# Mattermost OIDC Mobile Bridge
location = /api/v4/config/client {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:8066;
}
location = /oauth/openid/mobile_login {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:8066;
}
```
Die vorhandenen WebSocket- und Catch-all-Locations bleiben unverändert und zeigen weiterhin direkt auf Mattermost.
Die Exact-Match-Locations sind wichtig: Nur diese beiden Endpunkte sollen über die Bridge laufen.
Konfiguration prüfen:
```bash
nginx -t
```
Bei erfolgreicher Prüfung:
```bash
systemctl reload nginx
```
## 8. Öffentliche Endpunkte testen
### Mobile User-Agent
```bash
curl -s -A 'Mattermost Mobile/' \
${MM_SITE_URL}/api/v4/config/client |
grep -o '"EnableSignUpWithOpenId":"[^"]*"'
```
Erwartet:
```text
"EnableSignUpWithOpenId":"true"
```
### Browser User-Agent
```bash
curl -s -A 'Mozilla/5.0' \
${MM_SITE_URL}/api/v4/config/client |
grep -o '"EnableSignUpWithOpenId":"[^"]*"'
```
Bei der dokumentierten Installation:
```text
"EnableSignUpWithOpenId":"false"
```
### Mobile Login
```bash
curl -si \
"${MM_SITE_URL}/oauth/openid/mobile_login?redirect_to=mmauth%3A%2F%2Fcallback" |
head -20
```
Erwartet wird HTTP 302 auf den Connect-Endpunkt des OIDC-Plugins.
## 9. End-to-End-Test mit der Mattermost-App
In der nativen Mattermost-App:
1. Server aus `MM_SITE_URL` hinzufügen (im dokumentierten Beispiel `https://mm.nd.digital`).
2. Die App muss zusätzlich zur normalen Anmeldung einen Button **Log in with OIDC** anzeigen.
3. OIDC-Login auswählen.
4. Bei Keycloak anmelden.
5. Nach erfolgreicher Authentifizierung muss die App über `mmauth://callback` zurückkehren.
6. Team und Channels müssen anschließend geladen werden.
## 10. Wichtiger Sonderfall: Default Team und erlaubte E-Mail-Domains
Das `mattermost-oidc`-Plugin kann neu angelegte OIDC-Benutzer automatisch einem **Default Team** hinzufügen.
In der dokumentierten Installation ist im Plugin konfiguriert:
```text
Default Team: nd
```
Das Team `nd` erlaubt jedoch nur Benutzer mit einer bestimmten E-Mail-Domain:
```text
nd-online.de
```
Beim Test wurde ein OIDC-Benutzer mit einer anderen Domain erfolgreich angelegt und authentifiziert, konnte aber nicht automatisch dem Team `nd` hinzugefügt werden. Mattermost protokollierte sinngemäß:
```text
Failed to add user to default team
The user cannot be added as the domain associated with the account is not permitted.
```
Das Fehlerbild in der Mobile-App war:
```text
Konnte nicht geladen werden
```
Das Profil des angemeldeten Benutzers war trotzdem erreichbar. Ursache war **nicht die Mobile Bridge und nicht der OIDC-Token**, sondern die fehlende Team-Mitgliedschaft.
### Diagnose
Team-Domain aus PostgreSQL nur lesend prüfen:
```bash
su - postgres -c \
"psql -d mattermost -c \"SELECT name, displayname, type, allowopeninvite, alloweddomains FROM teams WHERE name='nd';\""
```
Alternativ in der System Console:
```text
User Management
-> Teams
-> ND
-> Team Management
-> Only specific email domains can join this team
```
Wenn ein Testbenutzer aus einer anderen Domain verwendet wird, sollte die Domain-Beschränkung **nicht dauerhaft aufgeweicht** werden.
Für den dokumentierten Test wurde die zusätzliche Testdomain kurzzeitig in der kommagetrennten Domainliste zugelassen, der Testbenutzer administrativ zum Team hinzugefügt und die Domainliste anschließend wieder auf den ursprünglichen Wert zurückgesetzt.
## 11. Logs und Fehlersuche
### Bridge
Status:
```bash
systemctl status mattermost-oidc-mobile-bridge.service
```
Journal:
```bash
journalctl -u mattermost-oidc-mobile-bridge.service
```
Für eine gezielte Fehlersuche kann die Bridge mit `DEBUG=1` betrieben werden. Dies sollte nur bei Bedarf aktiviert werden, da dann beobachtete User-Agents protokolliert werden.
### Mattermost
```bash
journalctl -u mattermost.service
```
Bei OIDC-Problemen insbesondere nach Meldungen mit folgenden Begriffen suchen:
```text
oidc
mobile
session
mattermost-oidc
```
### Typische Fehlerbilder
**Kein OIDC-Button in der App**
Prüfen:
- `mattermost-oidc` ist aktiviert.
- Web-OIDC funktioniert.
- `/api/v4/config/client` wird für Mobile User-Agents über die Bridge geleitet.
- `EnableSignUpWithOpenId` ist für `Mattermost Mobile/` auf `true`.
- nginx wurde nach der Änderung erfolgreich neu geladen.
**OIDC-Button erscheint, Login startet nicht korrekt**
Prüfen:
- `/oauth/openid/mobile_login` liefert HTTP 302.
- Ziel ist `/plugins/mattermost-oidc/oauth2/connect`.
- nginx routet exakt diesen Endpunkt auf Port 8066.
**Login bei Keycloak erfolgreich, App lädt aber kein Team**
Prüfen:
- Wurde der Benutzer in Mattermost angelegt?
- Ist der Benutzer Mitglied eines Teams?
- Ist im OIDC-Plugin ein `Default Team` konfiguriert?
- Verhindert `AllowedDomains` des Teams das automatische Hinzufügen?
## 12. Umgebungsvariablen der Bridge
Die Bridge unterstützt laut Projekt-README folgende Variablen:
| Variable | Standard | Zweck |
|---|---|---|
| `LISTEN` | `:8066` | Listen-Adresse |
| `UPSTREAM` | `http://127.0.0.1:8065` | Mattermost-Upstream |
| `PLUGIN_CONNECT_PATH` | `/plugins/mattermost-oidc/oauth2/connect` | Connect-Endpunkt des Plugins |
| `PLUGIN_CONFIG_PATH` | `/plugins/mattermost-oidc/api/v1/config` | öffentliche Plugin-Konfiguration |
| `MOBILE_UA_MATCH` | `Mattermost Mobile/` | Erkennung der nativen App |
| `OPENID_BUTTON_TEXT` | leer / automatisch | optionaler fester Button-Text |
| `OPENID_BUTTON_COLOR` | leer / automatisch | optionale feste Button-Farbe |
| `DEBUG` | leer | bei `1` User-Agent-Logging |
In der dokumentierten Installation werden nur `LISTEN` und `UPSTREAM` explizit gesetzt. Die übrigen Werte bleiben auf den Defaults.
## 13. Update der Bridge
Für ein Update wird die neue Version zunächst im Variablenblock als `MM_OIDC_VER` gesetzt. `MM_OIDC_SRC` und `MM_BRIDGE_BIN` ergeben sich daraus automatisch. Die bisherige versionsbezogene Binary bleibt zunächst erhalten.
Beispiel: Variablenblock mit der gewünschten neuen Version erneut setzen und anschließend den Release wie in Abschnitt 1 herunterladen. Danach:
```bash
cd "$MM_OIDC_SRC/mobile-bridge"
go build -o mobile-bridge .
```
Neue versionsbezogene Binary installieren:
```bash
install -o root -g root -m 755 \
mobile-bridge \
"$MM_BRIDGE_BIN"
```
Vor dem Umschalten kontrollieren:
```bash
file "$MM_BRIDGE_BIN"
ls -lh "$MM_BRIDGE_BIN"
```
Symlink atomar auf die neue Version umstellen und Dienst neu starten:
```bash
ln -sfn "$(basename "$MM_BRIDGE_BIN")" "$MM_BRIDGE_LINK"
systemctl restart mattermost-oidc-mobile-bridge.service
systemctl is-active mattermost-oidc-mobile-bridge.service
readlink -f "$MM_BRIDGE_LINK"
```
Danach die HTTP-Tests und einen Mobile-Login erneut durchführen. Die alte versionsbezogene Binary sollte erst entfernt werden, wenn der neue Stand erfolgreich getestet wurde.
## 14. Rollback
Soll die Bridge wieder entfernt werden:
1. Die beiden Exact-Match-`location`-Blöcke aus nginx entfernen.
2. `nginx -t` ausführen.
3. nginx neu laden.
4. Bridge stoppen und deaktivieren.
5. Optional Unit-Datei und Binary entfernen.
### Rollback auf eine vorherige Bridge-Version
Solange die vorherige versionsbezogene Binary noch vorhanden ist, genügt es, den Symlink zurückzusetzen und den Dienst neu zu starten. Beispiel:
```bash
ln -sfn mattermost-oidc-mobile-bridge-<vorherige-version> \
/usr/local/sbin/mattermost-oidc-mobile-bridge
systemctl restart mattermost-oidc-mobile-bridge.service
readlink -f /usr/local/sbin/mattermost-oidc-mobile-bridge
```
### Bridge vollständig entfernen
```bash
systemctl disable --now mattermost-oidc-mobile-bridge.service
rm -f /etc/systemd/system/mattermost-oidc-mobile-bridge.service
systemctl daemon-reload
rm -f /usr/local/sbin/mattermost-oidc-mobile-bridge
# Versionsbezogene Binaries bei Bedarf anschließend gezielt entfernen.
```
Das `mattermost-oidc`-Plugin und der normale Web-OIDC-Login können dabei unverändert weiterbetrieben werden.
## 15. Sicherheitsaspekte
- Die Bridge nur auf `127.0.0.1:8066` binden.
- Port 8066 nicht öffentlich in der Firewall freigeben.
- Nur die beiden benötigten Exact-Match-Endpunkte über nginx zur Bridge leiten.
- Keine OIDC-Secrets in die systemd-Unit eintragen; die Bridge benötigt keine.
- Client Secret und andere Zugangsdaten nicht in Dokumentationen oder Logs übernehmen.
- Nach Änderungen an OIDC immer Web- und Mobile-Login testen.
- Team-Domain-Beschränkungen nicht nur für einen Test dauerhaft erweitern.
## 16. Abschlusskontrolle
Nach einer vollständigen Installation sollten folgende Prüfungen erfolgreich sein:
```bash
systemctl is-enabled mattermost-oidc-mobile-bridge.service
systemctl is-active mattermost-oidc-mobile-bridge.service
ss -lntp | grep ':8066'
nginx -t
```
Zusätzlich:
```text
Mobile UA -> EnableSignUpWithOpenId=true
Browser UA -> unveränderte Mattermost-Konfiguration
mobile_login -> HTTP 302 zum mattermost-oidc-Plugin
Web-OIDC -> funktioniert
Mobile-OIDC -> funktioniert
Team/Channels -> werden in der App geladen
```