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

122
assets/css/login.css Normal file
View file

@ -0,0 +1,122 @@
/* M365 Login login screen button */
.m365-login {
--m365-bg: #2f2f2f;
--m365-bg-hover: #1a1a1a;
--m365-color: #ffffff;
--m365-border: #2f2f2f;
--m365-radius: 4px;
margin: 0 0 16px;
}
.m365-login--below {
background: #fff;
padding: 0 24px 26px;
margin: -1px 0 0;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
border: 1px solid #c3c4c7;
border-top: 0;
}
body.m365-login-attached #loginform {
border-bottom: 0;
box-shadow: none;
}
.m365-login--above {
background: #fff;
padding: 24px;
margin: 20px 0 0;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
border: 1px solid #c3c4c7;
}
.m365-login--above .m365-login__divider {
margin: 22px 0 0;
}
.m365-login__divider {
position: relative;
text-align: center;
margin: 0 0 22px;
color: #646970;
font-size: 13px;
line-height: 1;
}
.m365-login__divider::before {
content: "";
position: absolute;
left: 0;
right: 0;
top: 50%;
height: 1px;
background: #dcdcde;
}
.m365-login__divider span {
position: relative;
background: #fff;
padding: 0 12px;
text-transform: lowercase;
}
.m365-login__button {
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
box-sizing: border-box;
width: 100%;
min-height: 44px;
padding: 10px 16px;
background: var(--m365-bg);
color: var(--m365-color);
border: 1px solid var(--m365-border);
border-radius: var(--m365-radius);
font-size: 15px;
font-weight: 600;
line-height: 1.3;
text-decoration: none;
cursor: pointer;
transition: background-color 0.15s ease, box-shadow 0.15s ease, transform 0.1s ease;
}
.m365-login__button:hover,
.m365-login__button:focus {
background: var(--m365-bg-hover);
color: var(--m365-color);
text-decoration: none;
}
.m365-login__button:focus {
outline: none;
box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--m365-bg-hover);
}
.m365-login__button:active {
transform: translateY(1px);
}
.m365-login__icon {
flex: 0 0 auto;
width: 20px;
height: 20px;
display: block;
background: #fff;
padding: 3px;
box-sizing: content-box;
border-radius: 2px;
}
.m365-login__label {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.m365-login--shortcode {
padding: 0;
border: 0;
background: transparent;
max-width: 360px;
}