Add Entra group restriction, button-only mode and detailed README
Groups: a Graph-backed picker on the Security tab (search by name or paste object IDs) stores allowed group IDs. During sign-in membership is read from the ID token's groups claim when present, otherwise verified through Microsoft Graph checkMemberGroups (transitive). Verification failures refuse the sign-in. Button-only mode: hides the password form and the lost-password link and rejects password sign-ins on wp-login.php via the authenticate filter. A generated, rate-limited fallback key re-enables the form for 30 minutes per browser; M365_LOGIN_DISABLE_BUTTON_ONLY switches the mode off from wp-config.php. Also: new German-language README with sequence diagram, settings reference, troubleshooting and hook examples; readme.txt external services section now covers Microsoft Graph; translations updated. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JJxAHYdMfKPoN4koRc4Ci2
This commit is contained in:
parent
1517e7e3bc
commit
1202283eda
20 changed files with 2241 additions and 517 deletions
414
README.md
414
README.md
|
|
@ -1,94 +1,394 @@
|
|||
# M365 Login für WordPress
|
||||
<div align="center">
|
||||
|
||||
Ein schlankes, sicherheitsorientiertes WordPress-Plugin, das einen **„Login mit Microsoft“-Button** auf die
|
||||
Anmeldeseite (`wp-login.php`) setzt. Bestehende WordPress-Benutzer melden sich mit ihrem Microsoft 365 /
|
||||
Entra-ID-Konto an. Der gemeinsame Schlüssel ist die **E-Mail-Adresse** – es werden keine Benutzer angelegt.
|
||||
<img src=".wordpress-org/icon.svg" width="96" height="96" alt="">
|
||||
|
||||
> Plugin-Slug / Text Domain: `m365-login` · Lizenz: GPL-2.0-or-later · PHP ≥ 7.4 · WordPress ≥ 6.0
|
||||
# M365 Login
|
||||
|
||||
## Funktionen
|
||||
**Anmeldung an WordPress mit dem Microsoft 365 / Entra ID-Konto – sicher, schlank, gestaltbar.**
|
||||
|
||||
- **Button auf der Login-Seite** – Text, Icon (Microsoft-Logo oder eigenes Bild aus der Mediathek), Hintergrund-,
|
||||
Hover-, Text- und Rahmenfarbe, Eckenradius und Position (über/unter dem Formular) sind im Backend einstellbar,
|
||||
mit Live-Vorschau und Farb-Presets.
|
||||
- **Aufgeräumte Einstellungsseite** unter *Einstellungen → M365 Login* mit Redirect-URI zum Kopieren,
|
||||
Tenant-Verbindungstest und 5-Schritte-Anleitung.
|
||||
- **Kein Provisioning**: Anmeldung nur, wenn ein WordPress-Benutzer mit derselben E-Mail-Adresse existiert.
|
||||
- **Shortcode** `[m365_login_button redirect="/mein-konto/"]` für eigene Login-Seiten.
|
||||
- Vollständig übersetzbar, deutsche Übersetzung enthalten.
|
||||
[](https://wordpress.org/)
|
||||
[](https://www.php.net/)
|
||||
[](LICENSE)
|
||||
[](https://github.com/friloo/wp-m365-login/actions/workflows/ci.yml)
|
||||
[](docs/wordpress-org-einreichung.md)
|
||||
|
||||
## Sicherheit
|
||||
<img src=".github/assets/button-preview.svg" width="720" alt="Login-Seite mit Microsoft-Button, Farb-Presets und Sicherheitsmerkmalen">
|
||||
|
||||
| Maßnahme | Umsetzung |
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## Inhalt
|
||||
|
||||
- [Auf einen Blick](#auf-einen-blick)
|
||||
- [So funktioniert es](#so-funktioniert-es)
|
||||
- [Installation](#installation)
|
||||
- [Einrichtung in Microsoft Entra ID](#einrichtung-in-microsoft-entra-id)
|
||||
- [Einstellungen im Backend](#einstellungen-im-backend)
|
||||
- [Verbindung](#verbindung)
|
||||
- [Button](#button)
|
||||
- [Sicherheit](#sicherheit)
|
||||
- [Gruppen-Beschränkung](#gruppen-beschränkung)
|
||||
- [Nur-Button-Modus & Fallback](#nur-button-modus--fallback)
|
||||
- [Sicherheitskonzept](#sicherheitskonzept)
|
||||
- [Shortcode & Hooks](#shortcode--hooks)
|
||||
- [Fehlerbehebung](#fehlerbehebung)
|
||||
- [Entwicklung](#entwicklung)
|
||||
- [Einreichung bei WordPress.org](#einreichung-bei-wordpressorg)
|
||||
- [FAQ](#faq)
|
||||
- [Lizenz](#lizenz)
|
||||
|
||||
---
|
||||
|
||||
## Auf einen Blick
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| Authorization Code Flow **mit PKCE (S256)** | Tokens laufen ausschließlich Server-zu-Server, nie durch den Browser. |
|
||||
| **State & Nonce** | Einmalig, 10 Minuten gültig, per HttpOnly/SameSite-Cookie an den Browser gebunden (CSRF-/Replay-Schutz, verhindert Login-CSRF). |
|
||||
| **ID-Token-Prüfung** | Signatur gegen Microsofts JWKS (RS256, Schlüssel-Rollover wird abgefangen), Issuer, Audience, Tenant, `exp`/`nbf`/`iat`, Nonce. `alg=none`/HMAC werden abgelehnt. |
|
||||
| **Tenant-Pinning** | Bei konfigurierter Tenant-GUID werden Tokens anderer Tenants abgewiesen. |
|
||||
| **Konto-Bindung** | Beim ersten Login wird die unveränderliche Microsoft-Objekt-ID am Benutzer gespeichert; spätere Logins mit gleicher E-Mail, aber anderer Identität werden abgelehnt. |
|
||||
| **Domain-Allowlist** | Optional nur bestimmte E-Mail-Domains zulassen. |
|
||||
| **Client Secret verschlüsselt** | AES-256-GCM, Schlüssel aus den WordPress-Salts abgeleitet; wird nie wieder angezeigt. |
|
||||
| **WordPress-Standards** | Capability-Checks, Nonces, Sanitizing aller Eingaben, Escaping aller Ausgaben, `wp_safe_redirect`, keine externen Assets. |
|
||||
| 🔑 **Login per Microsoft** | Ein Klick auf der Anmeldeseite, Anmeldung bei Microsoft, zurück in WordPress – fertig. |
|
||||
| 📧 **Zuordnung über die E-Mail-Adresse** | Es werden **keine Benutzer angelegt**. Nur wer schon ein WordPress-Konto mit derselben E-Mail hat, kommt rein. |
|
||||
| 🎨 **Gestaltbarer Button** | Text, Icon (Microsoft-Logo oder eigenes Bild), Farben, Hover-Farbe, Rahmen, Eckenradius, Position – mit Live-Vorschau und Presets. |
|
||||
| 👥 **Entra-Gruppen** | Optional nur Mitglieder ausgewählter Gruppen zulassen. Gruppen werden direkt im Backend gesucht und ausgewählt. |
|
||||
| 🚪 **Nur-Button-Modus** | Passwortfelder ausblenden und Passwort-Logins sperren – mit geheimem Fallback-Link als Notausgang. |
|
||||
| 🛡️ **Sicher by default** | OpenID Connect + PKCE, Signaturprüfung, Tenant-Pinning, Konto-Bindung, verschlüsseltes Secret. |
|
||||
| 🌍 **Übersetzbar** | Englische Basis, deutsche Übersetzung (du & Sie) enthalten. |
|
||||
| 📦 **WordPress.org-ready** | readme.txt, Lizenz, Uninstall, Plugin Check in CI, Build-Script. |
|
||||
|
||||
## Installation & Einrichtung
|
||||
---
|
||||
|
||||
1. Ordner in `wp-content/plugins/` legen (oder ZIP aus `bin/build-zip.sh` hochladen) und aktivieren.
|
||||
2. *Einstellungen → M365 Login* öffnen und die **Redirect-URI** aus der Seitenleiste kopieren
|
||||
(`https://deine-seite.tld/m365-login/callback`).
|
||||
3. Im [Microsoft Entra Admin Center](https://entra.microsoft.com/) → **App-Registrierungen → Neue Registrierung**:
|
||||
- Name frei wählbar, z. B. „WordPress Login“.
|
||||
- Kontotypen: *Nur Konten in diesem Organisationsverzeichnis* (Single Tenant).
|
||||
- Plattform **Web**, Redirect-URI einfügen.
|
||||
4. Auf der Übersichtsseite **Anwendungs-ID (Client)** und **Verzeichnis-ID (Mandant)** kopieren und im Plugin eintragen.
|
||||
5. **Zertifikate & Geheimnisse → Neuer geheimer Clientschlüssel** – den *Wert* (nicht die ID) ins Plugin eintragen.
|
||||
Ablaufdatum notieren; abgelaufene Secrets müssen erneuert werden.
|
||||
6. **Tokenkonfiguration → Optionalen Anspruch hinzufügen → ID → `email`** (empfohlen). Die delegierten
|
||||
Berechtigungen `openid`, `profile`, `email` sind standardmäßig vorhanden.
|
||||
7. Speichern. Der Button erscheint auf `wp-login.php`; Gestaltung im Tab **Button**.
|
||||
## So funktioniert es
|
||||
|
||||
Stelle sicher, dass die E-Mail-Adressen der WordPress-Benutzer mit denen in Microsoft 365 übereinstimmen.
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant B as Browser
|
||||
participant WP as WordPress<br/>(M365 Login)
|
||||
participant MS as Microsoft Entra ID
|
||||
participant G as Microsoft Graph<br/>(optional)
|
||||
|
||||
## Entwickler-Hooks
|
||||
B->>WP: Klick auf „Login mit Microsoft“
|
||||
WP->>WP: state, nonce, PKCE-Verifier erzeugen<br/>State-Cookie setzen (HttpOnly)
|
||||
WP-->>B: Redirect zu Microsoft (code_challenge, state, nonce)
|
||||
B->>MS: Anmeldung beim Microsoft-Konto
|
||||
MS-->>B: Redirect zurück mit code + state
|
||||
B->>WP: /m365-login/callback?code=…&state=…
|
||||
WP->>WP: State einmalig einlösen, Cookie prüfen
|
||||
WP->>MS: Code + code_verifier + Client Secret (Server-zu-Server)
|
||||
MS-->>WP: ID-Token
|
||||
WP->>MS: Signaturschlüssel (JWKS, gecacht)
|
||||
WP->>WP: Signatur, Issuer, Audience, Tenant, exp, Nonce prüfen
|
||||
opt Gruppen-Beschränkung aktiv
|
||||
WP->>G: checkMemberGroups(oid, erlaubte Gruppen)
|
||||
G-->>WP: Treffer / kein Treffer
|
||||
end
|
||||
WP->>WP: Benutzer per E-Mail suchen, Objekt-ID abgleichen
|
||||
WP-->>B: WordPress-Session, Redirect ins Dashboard
|
||||
```
|
||||
|
||||
Tokens laufen ausschließlich zwischen deinem Server und Microsoft. Der Browser sieht nur einen Autorisierungscode, der ohne den serverseitigen PKCE-Verifier und das Client Secret wertlos ist.
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
**Variante A – manuell (empfohlen, solange das Plugin nicht im Verzeichnis ist)**
|
||||
|
||||
```bash
|
||||
git clone https://github.com/friloo/wp-m365-login.git
|
||||
cd wp-m365-login
|
||||
bash bin/build-zip.sh # erzeugt build/m365-login.zip
|
||||
```
|
||||
|
||||
Dann in WordPress unter *Plugins → Installieren → Plugin hochladen* das ZIP hochladen und aktivieren.
|
||||
Alternativ den Repo-Inhalt als Ordner `m365-login` nach `wp-content/plugins/` kopieren.
|
||||
|
||||
**Variante B – WordPress.org** (nach der Freigabe): *Plugins → Installieren → „M365 Login“*.
|
||||
|
||||
> **Voraussetzungen:** WordPress ≥ 6.0, PHP ≥ 7.4 mit OpenSSL-Erweiterung, HTTPS auf der Website (Microsoft akzeptiert `http://` nur für `localhost`).
|
||||
|
||||
---
|
||||
|
||||
## Einrichtung in Microsoft Entra ID
|
||||
|
||||
<details open>
|
||||
<summary><strong>Schritt für Schritt (ca. 5 Minuten)</strong></summary>
|
||||
|
||||
1. **Redirect-URI kopieren.** In WordPress *Einstellungen → M365 Login* öffnen; die URI steht in der Seitenleiste
|
||||
(`https://deine-seite.tld/m365-login/callback`, bei einfachen Permalinks `https://deine-seite.tld/?m365-login=callback`).
|
||||
2. **App registrieren.** [Microsoft Entra Admin Center](https://entra.microsoft.com/) → *App-Registrierungen → Neue Registrierung*
|
||||
- Name: z. B. „WordPress Login“
|
||||
- Unterstützte Kontotypen: **Nur Konten in diesem Organisationsverzeichnis** (Single Tenant)
|
||||
- Umleitungs-URI: Plattform **Web**, URI aus Schritt 1
|
||||
3. **IDs übernehmen.** Auf der Übersichtsseite **Anwendungs-ID (Client)** und **Verzeichnis-ID (Mandant)** kopieren → in WordPress eintragen.
|
||||
4. **Client Secret erstellen.** *Zertifikate & Geheimnisse → Neuer geheimer Clientschlüssel* → den **Wert** (nicht die Geheimnis-ID) in WordPress eintragen.
|
||||
Das Ablaufdatum notieren – abgelaufene Secrets müssen erneuert werden.
|
||||
5. **E-Mail-Claim aktivieren** (empfohlen). *Tokenkonfiguration → Optionalen Anspruch hinzufügen → ID → `email`*.
|
||||
6. **Speichern** und mit *Tenant testen* prüfen, ob Microsoft erreichbar ist.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Zusätzlich für die Gruppen-Beschränkung</strong></summary>
|
||||
|
||||
Damit das Backend Gruppen suchen und beim Login die Mitgliedschaft prüfen kann, braucht die App-Registrierung
|
||||
**Anwendungsberechtigungen** (nicht delegiert) für Microsoft Graph, jeweils mit **Administratorzustimmung**:
|
||||
|
||||
| Berechtigung | Wofür |
|
||||
| --- | --- |
|
||||
| `GroupMember.Read.All` | Gruppen im Backend suchen |
|
||||
| `User.Read.All` | Mitgliedschaft beim Login prüfen (`checkMemberGroups`, inkl. verschachtelter Gruppen) |
|
||||
|
||||
`Directory.Read.All` deckt beides ab, ist aber weiter gefasst.
|
||||
|
||||
**Ohne Graph-Berechtigungen** geht es auch: Unter *Tokenkonfiguration → Gruppenanspruch hinzufügen* den `groups`-Claim
|
||||
für ID-Tokens aktivieren (am besten *Der Anwendung zugewiesene Gruppen* oder *Sicherheitsgruppen*). Dann prüft das Plugin die
|
||||
Mitgliedschaft direkt im Token. Gruppen-IDs lassen sich im Backend auch von Hand einfügen. Bei mehr als 200 Gruppen pro
|
||||
Benutzer liefert Microsoft keinen `groups`-Claim mehr („Overage“); dann greift das Plugin automatisch auf Graph zurück.
|
||||
|
||||
</details>
|
||||
|
||||
Wichtig: Jeder Benutzer, der sich per Microsoft anmelden soll, braucht in WordPress **dieselbe E-Mail-Adresse** wie in Microsoft 365.
|
||||
|
||||
---
|
||||
|
||||
## Einstellungen im Backend
|
||||
|
||||
*Einstellungen → M365 Login* – drei Tabs, ein Formular, ein Speichern-Button.
|
||||
|
||||
### Verbindung
|
||||
|
||||
| Feld | Beschreibung |
|
||||
| --- | --- |
|
||||
| Verzeichnis-ID (Tenant) | GUID des Tenants (empfohlen, aktiviert Tenant-Pinning) oder `organizations` / `common` / `consumers`. |
|
||||
| Anwendungs-ID (Client) | GUID der App-Registrierung. |
|
||||
| Client Secret | Wird verschlüsselt gespeichert und nie wieder angezeigt. Leer lassen = behalten. |
|
||||
| Kontoauswahl | `select_account` (Standard), `none` (bestehende Microsoft-Sitzung nutzen) oder `login` (immer Anmeldedaten verlangen). |
|
||||
| Tenant testen | Lädt die OpenID-Konfiguration des Tenants – prüft ID und ausgehende Verbindung. |
|
||||
|
||||
### Button
|
||||
|
||||
| Option | Beschreibung |
|
||||
| --- | --- |
|
||||
| Button-Text | Standard „Sign in with Microsoft“ / „Login mit Microsoft“ (max. 80 Zeichen). |
|
||||
| Trennlinien-Text | Standard „or“ / „oder“; leer = keine Trennlinie. |
|
||||
| Icon | Microsoft-Logo (eingebettet) oder eigenes Bild aus der Mediathek (PNG, SVG, JPG, WebP). Ein-/ausblendbar. |
|
||||
| Farben | Hintergrund, Hintergrund (Hover), Text, Rahmen – mit Farbwähler. |
|
||||
| Eckenradius | 0–50 px. |
|
||||
| Position | Unter dem Login-Formular (Standard) oder darüber. |
|
||||
| Presets | Microsoft dunkel, Microsoft hell, Azure-Blau, WordPress-Blau. |
|
||||
|
||||
Alles wird live in der Vorschau angezeigt, bevor du speicherst.
|
||||
|
||||
### Sicherheit
|
||||
|
||||
| Option | Standard | Beschreibung |
|
||||
| --- | --- | --- |
|
||||
| Konto an Microsoft-Objekt-ID binden | an | Beim ersten Login wird die `oid` gespeichert; danach muss sie übereinstimmen. Schützt vor Übernahme, wenn eine E-Mail-Adresse in Microsoft neu vergeben wird. |
|
||||
| UPN-Fallback | an | Fehlt der `email`-Claim, wird der User Principal Name verwendet, sofern er eine gültige E-Mail-Adresse ist. |
|
||||
| Angemeldet bleiben | aus | 14-Tage-Session statt Browser-Session. |
|
||||
| Erlaubte E-Mail-Domains | leer | Kommagetrennte Liste, z. B. `contoso.com, contoso.de`. |
|
||||
|
||||
### Gruppen-Beschränkung
|
||||
|
||||
Im Tab *Sicherheit* → **Erlaubte Entra-Gruppen**:
|
||||
|
||||
1. Gruppenname eintippen (oder Objekt-ID einfügen) → *Suchen*.
|
||||
2. Treffer mit *Hinzufügen* übernehmen – sie erscheinen als Chips mit Name und ID.
|
||||
3. Speichern. Ab jetzt darf sich nur anmelden, wer in **mindestens einer** dieser Gruppen ist (verschachtelte Mitgliedschaften zählen).
|
||||
|
||||
Prüfreihenfolge beim Login:
|
||||
|
||||
1. Enthält das ID-Token einen `groups`-Claim → Abgleich direkt im Token.
|
||||
2. Sonst (oder bei Overage) → Microsoft Graph `checkMemberGroups`.
|
||||
3. Schlägt beides fehl → **Anmeldung abgelehnt** (fail closed), Meldung „Gruppenmitgliedschaft konnte nicht geprüft werden“.
|
||||
|
||||
Leere Liste = keine Beschränkung.
|
||||
|
||||
### Nur-Button-Modus & Fallback
|
||||
|
||||
Im Tab *Sicherheit* → **Button-only mode**:
|
||||
|
||||
- Blendet Benutzername/Passwort-Felder und den „Passwort vergessen?“-Link aus.
|
||||
- **Sperrt Passwort-Logins** über `wp-login.php` serverseitig – nicht nur per CSS.
|
||||
- Application Passwords, REST API und XML-RPC sind nicht betroffen.
|
||||
- Wird erst aktiv, wenn die Verbindung vollständig konfiguriert ist.
|
||||
|
||||
**Fallback (Notausgang):** Beim Speichern erzeugt das Plugin einen geheimen Schlüssel und zeigt den Fallback-Link an:
|
||||
|
||||
```
|
||||
https://deine-seite.tld/wp-login.php?m365_fallback=AbC…xYz
|
||||
```
|
||||
|
||||
Wer den Link öffnet, sieht für **30 Minuten in diesem Browser** wieder das normale Formular und kann sich mit Passwort anmelden.
|
||||
Der Schlüssel landet nicht im Cookie (nur ein HMAC davon), Fehlversuche werden pro IP gedrosselt (10 Versuche / 15 Minuten),
|
||||
und über die Checkbox *Neuen Schlüssel beim Speichern erzeugen* lässt er sich jederzeit rotieren.
|
||||
|
||||
**Notschalter ohne Backend-Zugang:** In `wp-config.php`
|
||||
|
||||
```php
|
||||
// Button z. B. nur für eine bestimmte Domain anzeigen
|
||||
add_filter( 'm365_login_show_button', fn( $show ) => $show && 'intranet.example.com' === $_SERVER['HTTP_HOST'] );
|
||||
define( 'M365_LOGIN_DISABLE_BUTTON_ONLY', true );
|
||||
```
|
||||
|
||||
// domain_hint an Microsoft senden
|
||||
schaltet den Modus komplett ab. Alternativ das Plugin-Verzeichnis per FTP umbenennen.
|
||||
|
||||
> ⚠️ Vor dem Aktivieren sicherstellen, dass dein eigenes Admin-Konto per Microsoft funktioniert, und den Fallback-Link sicher ablegen.
|
||||
|
||||
---
|
||||
|
||||
## Sicherheitskonzept
|
||||
|
||||
| Bedrohung | Gegenmaßnahme |
|
||||
| --- | --- |
|
||||
| Abfangen von Tokens im Browser | Authorization Code Flow **mit PKCE (S256)**; ID-Token wird serverseitig geholt, `response_mode=query` ohne Token. |
|
||||
| CSRF / Login-CSRF | `state` ist zufällig (256 Bit), **einmalig** verwendbar, 10 Min. gültig und per HttpOnly-/SameSite-Cookie an den startenden Browser gebunden. |
|
||||
| Token-Replay | `nonce` wird im ID-Token geprüft und mit dem State-Datensatz verworfen. |
|
||||
| Gefälschte Tokens | Signaturprüfung gegen Microsofts JWKS (`RS256` only; `alg=none`/HMAC werden abgelehnt), Schlüssel-Rollover wird automatisch nachgeladen. `iss`, `aud`, `tid`, `exp`, `nbf`, `iat` werden geprüft. |
|
||||
| Fremde Tenants | Bei konfigurierter Tenant-GUID **Tenant-Pinning**; sonst Issuer-Konsistenz mit `tid`. |
|
||||
| Kontoübernahme per E-Mail-Recycling | **Bindung an die Objekt-ID** (`oid`) beim ersten Login. |
|
||||
| Unbefugte Konten | Kein Provisioning, optionale Domain-Allowlist, optionale Gruppen-Beschränkung (fail closed). |
|
||||
| Secret-Diebstahl aus der Datenbank | AES-256-GCM, Schlüssel per HKDF aus `AUTH_KEY`/`SECURE_AUTH_KEY`; ohne `wp-config.php` ist der Datensatz wertlos. |
|
||||
| Offene Redirects | `redirect_to` läuft durch `wp_validate_redirect`, alle Redirects über `wp_safe_redirect`. |
|
||||
| Fehler-Reflektion | Fehlermeldungen sind Codes → feste, übersetzte Texte; Details nur ins Log (`WP_DEBUG_LOG`). |
|
||||
| Rate Limiting Fallback-Key | 10 Fehlversuche pro IP / 15 Min. |
|
||||
|
||||
Die Klassen für JWT-Prüfung und Verschlüsselung haben isolierte Tests (manipulierte Signaturen, abgelaufene Tokens, falsche Audience/Tenant/Issuer, `alg=none`, fremde Schlüssel).
|
||||
|
||||
---
|
||||
|
||||
## Shortcode & Hooks
|
||||
|
||||
**Shortcode** für eigene Login-Seiten:
|
||||
|
||||
```
|
||||
[m365_login_button redirect="/mein-konto/"]
|
||||
```
|
||||
|
||||
**Filter & Actions**
|
||||
|
||||
```php
|
||||
// Button z. B. nur im Intranet zeigen
|
||||
add_filter( 'm365_login_show_button', function ( $show ) {
|
||||
return $show && 'intranet.example.com' === $_SERVER['HTTP_HOST'];
|
||||
} );
|
||||
|
||||
// domain_hint mitschicken, damit Microsoft direkt die Firmenanmeldung zeigt
|
||||
add_filter( 'm365_login_authorize_params', function ( $params ) {
|
||||
$params['domain_hint'] = 'contoso.com';
|
||||
return $params;
|
||||
} );
|
||||
|
||||
// Login zusätzlich anhand der Claims verbieten (z. B. Gruppenmitgliedschaft)
|
||||
// E-Mail vor dem Lookup umschreiben (z. B. Alias-Domain)
|
||||
add_filter( 'm365_login_match_email', function ( $email, $claims ) {
|
||||
return str_replace( '@alt.contoso.com', '@contoso.com', $email );
|
||||
}, 10, 2 );
|
||||
|
||||
// Eigene Zusatzprüfung nach allen Plugin-Checks
|
||||
add_filter( 'm365_login_allow_user', function ( $allowed, WP_User $user, array $claims ) {
|
||||
return $allowed && ! empty( $claims['groups'] );
|
||||
return $allowed && ! in_array( 'subscriber', $user->roles, true );
|
||||
}, 10, 3 );
|
||||
|
||||
// Nach erfolgreichem Login, z. B. Anzeigenamen synchronisieren
|
||||
add_action( 'm365_login_success', function ( WP_User $user, array $claims ) {
|
||||
// z. B. Anzeigenamen synchronisieren
|
||||
if ( ! empty( $claims['name'] ) ) {
|
||||
wp_update_user( array( 'ID' => $user->ID, 'display_name' => $claims['name'] ) );
|
||||
}
|
||||
}, 10, 2 );
|
||||
|
||||
// Redirect-URI anpassen (z. B. hinter einem Reverse Proxy)
|
||||
add_filter( 'm365_login_redirect_uri', fn( $uri ) => 'https://www.example.com/m365-login/callback' );
|
||||
```
|
||||
|
||||
Weitere: `m365_login_match_email` (E-Mail vor dem Lookup anpassen).
|
||||
---
|
||||
|
||||
## Fehlerbehebung
|
||||
|
||||
| Meldung auf der Login-Seite | Ursache & Lösung |
|
||||
| --- | --- |
|
||||
| *Microsoft login is not configured yet.* | Tenant-ID, Client-ID oder Secret fehlt. |
|
||||
| *The login request expired or was invalid.* | State abgelaufen (> 10 Min.), Cookie blockiert oder Seite doppelt geladen. Erneut versuchen; Cookies für die Domain erlauben. |
|
||||
| *Could not complete the sign-in with Microsoft.* | Token-Tausch fehlgeschlagen – meist falsches/abgelaufenes Client Secret oder Redirect-URI stimmt nicht exakt mit Entra überein. Details im Log. |
|
||||
| *The Microsoft sign-in could not be verified.* | ID-Token abgelehnt (Tenant, Audience, Signatur). Tenant-ID prüfen; Serverzeit prüfen (NTP). |
|
||||
| *Your Microsoft account did not provide an e-mail address.* | `email`-Claim fehlt und UPN-Fallback ist aus oder UPN ist keine E-Mail. Claim in der Tokenkonfiguration hinzufügen. |
|
||||
| *No WordPress account exists for your Microsoft e-mail address.* | E-Mail in WordPress stimmt nicht mit Microsoft überein. |
|
||||
| *This WordPress account is linked to a different Microsoft account.* | Objekt-ID weicht ab. Wenn gewollt (neues Microsoft-Konto): User-Meta `_m365_login_oid` beim Benutzer löschen. |
|
||||
| *… not a member of a group that is allowed …* | Benutzer ist in keiner der ausgewählten Gruppen. |
|
||||
| *Your group membership could not be verified.* | Graph nicht erreichbar oder Berechtigung fehlt (`User.Read.All`) – oder `groups`-Claim aktivieren. |
|
||||
|
||||
Logging: Mit `WP_DEBUG` und `WP_DEBUG_LOG` schreibt das Plugin Fehlerdetails mit Präfix `[M365 Login]` nach `wp-content/debug.log`. Es werden nie Tokens oder Secrets geloggt.
|
||||
|
||||
---
|
||||
|
||||
## Entwicklung
|
||||
|
||||
```bash
|
||||
composer install # PHPCS + WordPress Coding Standards
|
||||
composer lint # php -l über alle Dateien
|
||||
composer phpcs # Coding-Standards-Prüfung
|
||||
bash bin/build-zip.sh # build/m365-login.zip für Upload/Einreichung
|
||||
python3 bin/compile-mo.py # languages/*.po → *.mo
|
||||
```
|
||||
m365-login.php Plugin-Header & Bootstrap
|
||||
includes/
|
||||
class-m365-login.php Verdrahtung der Komponenten
|
||||
class-m365-login-settings.php Defaults, Sanitizing, Redirect-URI, Fallback-Key
|
||||
class-m365-login-crypto.php AES-256-GCM für das Client Secret
|
||||
class-m365-login-jwt.php RS256-Verifikation, JWKS → PEM
|
||||
class-m365-login-auth.php OAuth-Flow, Callback, Benutzerzuordnung, Nur-Button-Modus
|
||||
class-m365-login-graph.php Client-Credentials-Token, Gruppensuche, checkMemberGroups
|
||||
class-m365-login-button.php Ausgabe auf wp-login.php, Shortcode
|
||||
class-m365-login-admin.php Einstellungsseite, AJAX
|
||||
assets/ CSS/JS für Login-Seite und Backend (unminifiziert)
|
||||
languages/ .pot, de_DE, de_DE_formal
|
||||
bin/ build-zip.sh, make-pot.py, compile-mo.py
|
||||
docs/ Einreichungs-Checkliste
|
||||
```
|
||||
|
||||
Die GitHub-Actions-Pipeline (`.github/workflows/ci.yml`) führt Syntax-Check (PHP 7.4–8.4), PHPCS und den
|
||||
offiziellen **WordPress Plugin Check** aus.
|
||||
```bash
|
||||
composer install # PHPCS + WordPress Coding Standards + PHPCompatibility
|
||||
composer lint # php -l für alle Dateien
|
||||
composer phpcs # Coding-Standards-Prüfung (phpcs.xml.dist)
|
||||
python3 bin/make-pot.py # Strings extrahieren (oder: wp i18n make-pot . languages/m365-login.pot)
|
||||
python3 bin/compile-mo.py # .po → .mo
|
||||
bash bin/build-zip.sh # build/m365-login.zip
|
||||
```
|
||||
|
||||
Die CI (`.github/workflows/ci.yml`) prüft Syntax unter PHP 7.4–8.4, führt PHPCS aus und lässt den offiziellen
|
||||
**WordPress Plugin Check** über das Build-Verzeichnis laufen.
|
||||
|
||||
---
|
||||
|
||||
## Einreichung bei WordPress.org
|
||||
|
||||
Siehe [docs/wordpress-org-einreichung.md](docs/wordpress-org-einreichung.md) für die vollständige Checkliste.
|
||||
Das Plugin bringt alles mit, was das Review-Team verlangt: `readme.txt` mit *External services*-Abschnitt, GPL-Lizenz,
|
||||
`uninstall.php`, eindeutige Präfixe, keine externen Assets, Übersetzungen, Verzeichnis-Icon. Die komplette Checkliste
|
||||
(inkl. Slug-/Marken-Hinweisen und SVN-Schritten nach der Freigabe) steht in
|
||||
**[docs/wordpress-org-einreichung.md](docs/wordpress-org-einreichung.md)**.
|
||||
|
||||
---
|
||||
|
||||
## FAQ
|
||||
|
||||
<details>
|
||||
<summary><strong>Kann ich Benutzer automatisch anlegen lassen?</strong></summary>
|
||||
Nein, bewusst nicht. Der Admin entscheidet, wer ein Konto hat. Wer Auto-Provisioning braucht, kann es über den Hook <code>m365_login_allow_user</code> nicht nachrüsten – das wäre ein anderes Sicherheitsmodell.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Funktioniert es mit privaten Microsoft-Konten (outlook.com)?</strong></summary>
|
||||
Ja, Tenant auf <code>consumers</code> oder <code>common</code> stellen. Microsoft erlaubt dann keine Query-Strings in Redirect-URIs, deshalb müssen sprechende Permalinks aktiv sein (Callback ohne <code>?</code>).
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Multisite?</strong></summary>
|
||||
Ja. Einstellungen gelten pro Site; der Benutzer muss Mitglied der Site (oder Super-Admin) sein.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Was passiert beim Deinstallieren?</strong></summary>
|
||||
Einstellungen, Caches (Transients) und die pro Benutzer gespeicherte Objekt-ID werden entfernt – auch in Multisite.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><strong>Ich habe mich ausgesperrt.</strong></summary>
|
||||
Fallback-Link öffnen. Kein Link zur Hand? <code>define( 'M365_LOGIN_DISABLE_BUTTON_ONLY', true );</code> in die <code>wp-config.php</code> oder den Plugin-Ordner per FTP umbenennen.
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
## Lizenz
|
||||
|
||||
GPL-2.0-or-later – siehe [LICENSE](LICENSE).
|
||||
GPL-2.0-or-later – siehe [LICENSE](LICENSE). „Microsoft“, „Microsoft 365“ und das Microsoft-Logo sind Marken der Microsoft Corporation;
|
||||
das Plugin ist ein unabhängiges Community-Projekt und steht in keiner Verbindung zu Microsoft.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue