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:
friloo 2026-09-22 14:30:53 +00:00
parent 1517e7e3bc
commit 1202283eda
No known key found for this signature in database
20 changed files with 2241 additions and 517 deletions

View file

@ -576,3 +576,145 @@
.m365-card code {
font-size: 12px;
}
/* Group picker */
.m365-group-results {
margin-top: 10px;
border: 1px solid var(--m365-border);
border-radius: 8px;
max-height: 320px;
overflow-y: auto;
background: #fff;
}
.m365-group-results.is-error {
border-color: #f0b8bd;
background: #fcf0f1;
}
.m365-group-results__status {
margin: 0;
padding: 12px 14px;
color: var(--m365-muted);
}
.m365-group-result {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 10px 14px;
border-bottom: 1px solid #f0f0f1;
}
.m365-group-result:last-child {
border-bottom: 0;
}
.m365-group-result__meta {
min-width: 0;
display: flex;
flex-wrap: wrap;
align-items: baseline;
gap: 4px 10px;
}
.m365-group-result__meta code {
font-size: 11px;
color: var(--m365-muted);
background: transparent;
padding: 0;
}
.m365-group-result__meta em {
display: block;
width: 100%;
font-style: normal;
color: var(--m365-muted);
font-size: 12px;
}
.m365-group-result__type {
font-size: 11px;
padding: 1px 8px;
border-radius: 999px;
background: #f0f6fc;
color: #0a4b78;
}
.m365-group-list {
margin: 0;
padding: 0;
list-style: none;
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.m365-group-list.is-empty::before {
content: attr(data-empty);
color: var(--m365-muted);
font-size: 13px;
}
.m365-group-chip {
display: inline-flex;
align-items: center;
gap: 8px;
margin: 0;
padding: 6px 6px 6px 12px;
background: #f0f6fc;
border: 1px solid #c5d9ed;
border-radius: 999px;
font-size: 13px;
max-width: 100%;
}
.m365-group-chip__name {
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.m365-group-chip__id {
font-size: 11px;
color: var(--m365-muted);
background: transparent;
padding: 0;
}
.m365-group-chip__remove {
appearance: none;
border: 0;
background: #fff;
color: #b32d2e;
width: 22px;
height: 22px;
border-radius: 50%;
line-height: 1;
font-size: 16px;
cursor: pointer;
}
.m365-group-chip__remove:hover {
background: #b32d2e;
color: #fff;
}
/* Fallback link */
.m365-fallback {
margin-top: 8px;
padding: 16px;
border: 1px dashed #c3c4c7;
border-radius: 8px;
background: #fafafa;
}
.m365-fallback .description {
margin: 4px 0 8px;
}
.m365-fallback .m365-copy {
margin-bottom: 8px;
}

View file

@ -120,3 +120,17 @@ body.m365-login-attached #loginform {
background: transparent;
max-width: 360px;
}
/* Button-only mode: the password form is hidden until the fallback key is used. */
body.m365-button-only #loginform,
body.m365-button-only #nav {
display: none;
}
body.m365-button-only .m365-login--below,
body.m365-button-only .m365-login--above {
margin-top: 20px;
padding: 26px 24px;
border: 1px solid #c3c4c7;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
}