Files
mattermost/README-mobile-oidc-bridge-readme.md

19 KiB

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.

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:

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:

mkdir -p "$MM_SRC_BASE"

Gewünschten Release-Tag direkt in ein versionsbezogenes Verzeichnis klonen:

git clone --branch "v${MM_OIDC_VER}" --depth 1 \
  "$MM_OIDC_REPO" \
  "$MM_OIDC_SRC"

Ausgecheckten Stand kontrollieren:

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:

${MM_OIDC_SRC}/mobile-bridge

2. Go installieren

Benötigte Go-Version aus dem Release ermitteln:

awk '/^go / {print "benötigte Go-Version:", $2}' \
  "$MM_OIDC_SRC/mobile-bridge/go.mod"

Installierte Version prüfen:

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:

apt install -t trixie-backports golang-go

Danach erneut prüfen:

go version

3. Mobile Bridge bauen

In das Bridge-Verzeichnis wechseln:

cd "$MM_OIDC_SRC/mobile-bridge"

Binary bauen:

go build -o mobile-bridge .

Ergebnis kontrollieren:

file mobile-bridge
ls -lh mobile-bridge

4. Bridge vor der Installation manuell testen

Port 8066 sollte zunächst frei sein:

ss -lntp | grep ':8066'

Die Bridge testweise nur auf Loopback starten:

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:

curl -s -A 'Mattermost Mobile/' \
  http://127.0.0.1:8066/api/v4/config/client |
  grep -o '"EnableSignUpWithOpenId":"[^"]*"'

Erwartet:

"EnableSignUpWithOpenId":"true"

Mit einem Browser-User-Agent:

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:

"EnableSignUpWithOpenId":"false"

Damit ist sichergestellt, dass die Änderung nur für die Mobile-App erfolgt.

Mobile-Login-Redirect testen

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:

/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:

install -o root -g root -m 755 \
  mobile-bridge \
  "$MM_BRIDGE_BIN"

Stabilen Symlink auf diese Version setzen:

ln -sfn "$(basename "$MM_BRIDGE_BIN")" "$MM_BRIDGE_LINK"

Ergebnis kontrollieren:

ls -l "$MM_BRIDGE_BIN" "$MM_BRIDGE_LINK"
readlink -f "$MM_BRIDGE_LINK"

Beispiel für Version 0.6.1:

/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:

/etc/systemd/system/mattermost-oidc-mobile-bridge.service

Inhalt:

[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:

systemctl daemon-reload
systemd-analyze verify /etc/systemd/system/mattermost-oidc-mobile-bridge.service

Dienst zunächst nur starten:

systemctl start mattermost-oidc-mobile-bridge.service

Status prüfen:

systemctl status mattermost-oidc-mobile-bridge.service
ss -lntp | grep ':8066'

Erwartet wird ein Listener ausschließlich auf:

127.0.0.1:8066

Nach erfolgreichem End-to-End-Test den Autostart aktivieren:

systemctl enable mattermost-oidc-mobile-bridge.service

Kontrolle:

systemctl is-enabled mattermost-oidc-mobile-bridge.service
systemctl is-active mattermost-oidc-mobile-bridge.service

Erwartet:

enabled
active

7. nginx konfigurieren

In der dokumentierten Installation ist die aktive Konfiguration:

/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:

# 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:

nginx -t

Bei erfolgreicher Prüfung:

systemctl reload nginx

8. Öffentliche Endpunkte testen

Mobile User-Agent

curl -s -A 'Mattermost Mobile/' \
  ${MM_SITE_URL}/api/v4/config/client |
  grep -o '"EnableSignUpWithOpenId":"[^"]*"'

Erwartet:

"EnableSignUpWithOpenId":"true"

Browser User-Agent

curl -s -A 'Mozilla/5.0' \
  ${MM_SITE_URL}/api/v4/config/client |
  grep -o '"EnableSignUpWithOpenId":"[^"]*"'

Bei der dokumentierten Installation:

"EnableSignUpWithOpenId":"false"

Mobile Login

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:

Default Team: nd

Das Team nd erlaubt jedoch nur Benutzer mit einer bestimmten E-Mail-Domain:

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äß:

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:

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:

su - postgres -c \
  "psql -d mattermost -c \"SELECT name, displayname, type, allowopeninvite, alloweddomains FROM teams WHERE name='nd';\""

Alternativ in der System Console:

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:

systemctl status mattermost-oidc-mobile-bridge.service

Journal:

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

journalctl -u mattermost.service

Bei OIDC-Problemen insbesondere nach Meldungen mit folgenden Begriffen suchen:

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:

cd "$MM_OIDC_SRC/mobile-bridge"
go build -o mobile-bridge .

Neue versionsbezogene Binary installieren:

install -o root -g root -m 755 \
  mobile-bridge \
  "$MM_BRIDGE_BIN"

Vor dem Umschalten kontrollieren:

file "$MM_BRIDGE_BIN"
ls -lh "$MM_BRIDGE_BIN"

Symlink atomar auf die neue Version umstellen und Dienst neu starten:

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:

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

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:

systemctl is-enabled mattermost-oidc-mobile-bridge.service
systemctl is-active mattermost-oidc-mobile-bridge.service
ss -lntp | grep ':8066'
nginx -t

Zusätzlich:

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