Add M365 Login plugin: Microsoft Entra ID sign-in for existing users

Adds a WordPress plugin that places a customisable "Sign in with
Microsoft" button on wp-login.php and signs existing users in via the
OpenID Connect authorization code flow with PKCE. Users are matched by
e-mail address only; no accounts are created.

Security: single-use state/nonce bound to an HttpOnly cookie, ID token
signature verification against Microsoft's JWKS (RS256 only) with
issuer/audience/tenant/expiry/nonce checks, optional tenant pinning,
account binding to the Microsoft object ID, e-mail domain allow-list,
client secret encrypted at rest (AES-256-GCM).

Admin: settings screen with connection, button and security tabs, live
button preview, colour presets, media-library icon picker, redirect URI
copy button and tenant connectivity test.

Packaging for WordPress.org: readme.txt with External services section,
GPL-2.0 license, uninstall.php, POT + German translations, .distignore,
build script, PHPCS config and CI running Plugin Check.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJxAHYdMfKPoN4koRc4Ci2
This commit is contained in:
Friederich Loheide 2026-09-22 14:21:10 +00:00
commit 3e3e87b399
No known key found for this signature in database
35 changed files with 5413 additions and 0 deletions

94
README.md Normal file
View file

@ -0,0 +1,94 @@
# M365 Login für WordPress
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.
> Plugin-Slug / Text Domain: `m365-login` · Lizenz: GPL-2.0-or-later · PHP ≥ 7.4 · WordPress ≥ 6.0
## Funktionen
- **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.
## Sicherheit
| Maßnahme | Umsetzung |
| --- | --- |
| 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. |
## 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**.
Stelle sicher, dass die E-Mail-Adressen der WordPress-Benutzer mit denen in Microsoft 365 übereinstimmen.
## Entwickler-Hooks
```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'] );
// domain_hint an Microsoft senden
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)
add_filter( 'm365_login_allow_user', function ( $allowed, WP_User $user, array $claims ) {
return $allowed && ! empty( $claims['groups'] );
}, 10, 3 );
add_action( 'm365_login_success', function ( WP_User $user, array $claims ) {
// z. B. Anzeigenamen synchronisieren
}, 10, 2 );
```
Weitere: `m365_login_match_email` (E-Mail vor dem Lookup anpassen).
## 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
```
Die GitHub-Actions-Pipeline (`.github/workflows/ci.yml`) führt Syntax-Check (PHP 7.48.4), PHPCS und den
offiziellen **WordPress Plugin Check** aus.
## Einreichung bei WordPress.org
Siehe [docs/wordpress-org-einreichung.md](docs/wordpress-org-einreichung.md) für die vollständige Checkliste.
## Lizenz
GPL-2.0-or-later siehe [LICENSE](LICENSE).