wp-m365-login/assets/css/admin.css
friloo 8766927123
Add certificate authentication, in-app setup guides and security audit
Certificate (RFC 7523 client assertion) as an alternative to the client
secret: one-click generation of a 3072-bit RSA key pair with a
self-signed certificate, .cer download (public part only), own PEM
upload with validation, expiry display, encrypted key storage. Both the
authorization code exchange and the Graph client-credentials request
use the selected method. Step-by-step guides for secret, certificate
and the app registration are shown in the settings.

Security audit (docs/security-audit.md) and fixes:
- Multi-tenant mode ignored the unverified email claim: matching now
  uses the UPN only, or the email claim when xms_edov is true.
- Login starts are rate limited per client (30 per 10 minutes).
- Optional trusted proxy header for client IPs
  (M365_LOGIN_CLIENT_IP_HEADER / filter).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJxAHYdMfKPoN4koRc4Ci2
2026-09-22 15:04:32 +00:00

947 lines
15 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* M365 Login settings screen */
.m365-admin {
--m365-accent: #0078d4;
--m365-accent-dark: #106ebe;
--m365-border: #dcdcde;
--m365-muted: #646970;
--m365-radius: 10px;
max-width: 1180px;
}
.m365-admin h1 {
font-size: 22px;
font-weight: 600;
line-height: 1.2;
margin: 0 0 4px;
padding: 0;
}
.m365-admin__header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
flex-wrap: wrap;
margin: 12px 0 20px;
}
.m365-admin__brand {
display: flex;
align-items: center;
gap: 16px;
}
.m365-admin__brand p {
margin: 0;
color: var(--m365-muted);
}
.m365-admin__logo {
display: inline-flex;
align-items: center;
justify-content: center;
width: 52px;
height: 52px;
background: #fff;
border: 1px solid var(--m365-border);
border-radius: 12px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
}
.m365-admin__logo svg {
width: 26px;
height: 26px;
}
.m365-admin__status {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 6px 12px;
border-radius: 999px;
font-size: 13px;
font-weight: 500;
background: #fcf0e4;
color: #8a4b00;
}
.m365-admin__status.is-ok {
background: #e6f4ea;
color: #1e6b31;
}
.m365-admin__status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: currentColor;
}
/* Tabs */
.m365-admin__tabs {
display: flex;
gap: 4px;
border-bottom: 1px solid var(--m365-border);
margin-bottom: 20px;
}
.m365-admin__tab {
appearance: none;
background: none;
border: 0;
border-bottom: 2px solid transparent;
margin-bottom: -1px;
padding: 10px 14px;
font-size: 14px;
font-weight: 500;
color: var(--m365-muted);
cursor: pointer;
}
.m365-admin__tab:hover {
color: #1d2327;
}
.m365-admin__tab.is-active {
color: var(--m365-accent);
border-bottom-color: var(--m365-accent);
}
.m365-admin__tab:focus-visible {
outline: 2px solid var(--m365-accent);
outline-offset: -2px;
border-radius: 4px;
}
.m365-admin__panel {
display: none;
}
.m365-admin__panel.is-active {
display: block;
}
/* Layout */
.m365-admin__layout {
display: grid;
grid-template-columns: minmax(0, 1fr) 340px;
gap: 20px;
align-items: start;
}
@media (max-width: 1024px) {
.m365-admin__layout {
grid-template-columns: 1fr;
}
}
.m365-admin__actions {
margin-top: 20px;
}
/* Cards */
.m365-card {
background: #fff;
border: 1px solid var(--m365-border);
border-radius: var(--m365-radius);
padding: 24px;
margin-bottom: 20px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
}
.m365-card--accent {
border-color: #b6d7f2;
background: linear-gradient(180deg, #f3f9fe 0%, #fff 100%);
}
.m365-card--muted {
background: #f6f7f7;
}
.m365-card__title {
font-size: 15px;
font-weight: 600;
margin: 0 0 6px;
}
.m365-card__intro {
margin: 0 0 20px;
color: var(--m365-muted);
}
/* Fields */
.m365-field {
margin-bottom: 20px;
}
.m365-field:last-child {
margin-bottom: 0;
}
.m365-field > label,
.m365-field__label {
display: block;
font-weight: 600;
margin-bottom: 6px;
}
.m365-field input[type="text"],
.m365-field input[type="url"],
.m365-field input[type="password"],
.m365-field select,
.m365-field textarea {
width: 100%;
max-width: 100%;
border-radius: 6px;
min-height: 36px;
}
.m365-field .regular-text {
width: 100%;
}
.m365-field__row {
display: flex;
gap: 8px;
align-items: center;
}
.m365-field__row > input {
flex: 1 1 auto;
}
.m365-field__row .button {
flex: 0 0 auto;
min-height: 36px;
display: inline-flex;
align-items: center;
}
.m365-field .description {
margin-top: 6px;
}
.m365-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0 20px;
}
.m365-grid--4 {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
@media (max-width: 782px) {
.m365-grid,
.m365-grid--4 {
grid-template-columns: 1fr;
}
}
.m365-check {
display: inline-flex;
gap: 8px;
align-items: flex-start;
margin: 8px 0 0;
}
.m365-check--block {
display: flex;
padding: 14px 16px;
border: 1px solid var(--m365-border);
border-radius: 8px;
margin: 0 0 12px;
cursor: pointer;
}
.m365-check--block:hover {
border-color: #b6d7f2;
background: #fbfdff;
}
.m365-check--block input {
margin-top: 3px;
}
.m365-check--block strong {
display: block;
font-weight: 600;
}
.m365-check--block em {
display: block;
font-style: normal;
color: var(--m365-muted);
margin-top: 2px;
}
.m365-inline-result {
margin-top: 10px;
padding: 10px 12px;
border-radius: 6px;
font-size: 13px;
background: #f0f6fc;
border: 1px solid #c5d9ed;
}
.m365-inline-result.is-success {
background: #e6f4ea;
border-color: #a6d8b2;
}
.m365-inline-result.is-error {
background: #fcf0f1;
border-color: #f0b8bd;
}
.m365-inline-result code {
display: block;
margin-top: 4px;
font-size: 12px;
word-break: break-all;
}
.m365-warning {
margin: 12px 0 0;
padding: 10px 12px;
border-radius: 6px;
background: #fcf0e4;
color: #8a4b00;
font-size: 13px;
}
.m365-toggle-secret .dashicons {
line-height: 1;
vertical-align: middle;
}
.m365-link-danger {
color: #b32d2e;
}
/* Preview */
.m365-preview {
margin-bottom: 24px;
}
.m365-preview__label {
display: block;
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--m365-muted);
margin-bottom: 8px;
}
.m365-preview__stage {
display: flex;
justify-content: center;
padding: 32px 24px;
background: #f0f0f1 radial-gradient(circle at 1px 1px, #dcdcde 1px, transparent 0);
background-size: 16px 16px;
border: 1px solid var(--m365-border);
border-radius: 8px;
}
.m365-login--preview {
width: 272px;
background: #fff;
border: 1px solid #c3c4c7;
padding: 24px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
--m365-bg: #2f2f2f;
--m365-bg-hover: #1a1a1a;
--m365-color: #fff;
--m365-border: #2f2f2f;
--m365-radius: 4px;
}
.m365-login--preview .m365-login__divider {
position: relative;
text-align: center;
margin: 0 0 22px;
color: #646970;
font-size: 13px;
line-height: 1;
}
.m365-login--preview .m365-login__divider::before {
content: "";
position: absolute;
left: 0;
right: 0;
top: 50%;
height: 1px;
background: #dcdcde;
}
.m365-login--preview .m365-login__divider span {
position: relative;
background: #fff;
padding: 0 12px;
}
.m365-login--preview .m365-login__divider.is-hidden {
display: none;
}
.m365-login--preview .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;
transition: background-color 0.15s ease;
}
.m365-login--preview .m365-login__button:hover {
background: var(--m365-bg-hover);
color: var(--m365-color);
}
.m365-login--preview .m365-login__button:focus {
box-shadow: none;
outline: none;
}
.m365-login--preview .m365-login__icon,
.m365-login--preview #m365-preview-icon img,
.m365-login--preview #m365-preview-icon svg {
width: 20px;
height: 20px;
display: block;
background: #fff;
padding: 3px;
box-sizing: content-box;
border-radius: 2px;
}
.m365-login--preview #m365-preview-icon.is-hidden {
display: none;
}
.m365-login--preview .m365-login__label {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* Icon picker */
.m365-icon-picker {
display: flex;
gap: 16px;
align-items: flex-start;
margin-top: 12px;
}
.m365-icon-picker__thumb {
flex: 0 0 64px;
width: 64px;
height: 64px;
display: flex;
align-items: center;
justify-content: center;
background: #fff;
border: 1px solid var(--m365-border);
border-radius: 8px;
}
.m365-icon-picker__thumb img,
.m365-icon-picker__thumb svg {
max-width: 36px;
max-height: 36px;
}
.m365-icon-picker__controls {
flex: 1 1 auto;
}
.m365-icon-picker__controls .m365-field__row {
margin-top: 8px;
}
/* Colour pickers */
.m365-field .wp-picker-container {
display: block;
}
.m365-field .wp-picker-container .wp-color-result.button {
margin: 0;
min-height: 36px;
border-radius: 6px;
}
.m365-range-value {
font-weight: 400;
color: var(--m365-muted);
margin-left: 6px;
}
.m365-field input[type="range"] {
width: 100%;
margin-top: 10px;
accent-color: var(--m365-accent);
}
/* Presets */
.m365-presets {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
margin-top: 8px;
}
.m365-presets .m365-field__label {
width: 100%;
}
.m365-preset {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 6px 12px 6px 8px;
background: #fff;
border: 1px solid var(--m365-border);
border-radius: 999px;
cursor: pointer;
font-size: 13px;
}
.m365-preset:hover {
border-color: var(--m365-accent);
}
.m365-preset span {
width: 16px;
height: 16px;
border-radius: 50%;
border: 1px solid rgba(0, 0, 0, 0.08);
}
/* Sidebar */
.m365-copy {
display: flex;
gap: 8px;
align-items: center;
margin-top: 8px;
}
.m365-copy code {
flex: 1 1 auto;
padding: 8px 10px;
font-size: 12px;
background: #fff;
border: 1px solid var(--m365-border);
border-radius: 6px;
word-break: break-all;
}
.m365-copy__button {
flex: 0 0 auto;
}
.m365-steps {
margin: 0;
padding-left: 20px;
}
.m365-steps li {
margin-bottom: 8px;
line-height: 1.5;
}
.m365-list {
margin: 8px 0 0;
padding-left: 18px;
list-style: disc;
}
.m365-list li {
margin-bottom: 6px;
line-height: 1.5;
}
.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;
}
/* Auth method switch */
.m365-method {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
margin-bottom: 20px;
}
@media (max-width: 782px) {
.m365-method {
grid-template-columns: 1fr;
}
}
.m365-method__option {
display: flex;
gap: 10px;
align-items: flex-start;
padding: 14px 16px;
border: 1px solid var(--m365-border);
border-radius: 8px;
cursor: pointer;
background: #fff;
}
.m365-method__option:hover {
border-color: #b6d7f2;
}
.m365-method__option.is-selected {
border-color: var(--m365-accent);
box-shadow: 0 0 0 1px var(--m365-accent);
background: #fbfdff;
}
.m365-method__option input {
margin-top: 3px;
}
.m365-method__option strong {
display: block;
font-weight: 600;
}
.m365-method__option em {
display: block;
font-style: normal;
color: var(--m365-muted);
margin-top: 2px;
font-size: 12px;
}
.m365-method__badge {
display: inline-block;
margin-left: 6px;
padding: 1px 8px;
border-radius: 999px;
font-size: 11px;
font-weight: 600;
background: #e6f4ea;
color: #1e6b31;
vertical-align: middle;
}
.m365-auth-panel {
display: none;
}
.m365-auth-panel.is-active {
display: block;
}
/* Certificate box */
.m365-cert {
border: 1px solid var(--m365-border);
border-radius: 8px;
padding: 16px;
background: #fafafa;
margin-bottom: 16px;
}
.m365-cert__grid {
display: grid;
grid-template-columns: max-content minmax(0, 1fr);
gap: 6px 16px;
font-size: 13px;
margin: 8px 0 12px;
}
.m365-cert__grid dt {
color: var(--m365-muted);
}
.m365-cert__grid dd {
margin: 0;
word-break: break-all;
}
.m365-cert__grid code {
background: #fff;
border: 1px solid var(--m365-border);
border-radius: 4px;
padding: 2px 6px;
font-size: 12px;
}
.m365-cert__actions {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
}
.m365-cert__empty {
color: var(--m365-muted);
margin: 0 0 12px;
}
.m365-cert__status {
display: inline-block;
padding: 2px 10px;
border-radius: 999px;
font-size: 12px;
font-weight: 600;
}
.m365-cert__status.is-ok {
background: #e6f4ea;
color: #1e6b31;
}
.m365-cert__status.is-warn {
background: #fcf0e4;
color: #8a4b00;
}
.m365-cert__status.is-bad {
background: #fcf0f1;
color: #8a2424;
}
.m365-field textarea.m365-pem {
font-family: Consolas, Monaco, monospace;
font-size: 12px;
min-height: 120px;
}
/* Guides */
.m365-guide {
border: 1px solid var(--m365-border);
border-radius: 8px;
background: #fff;
margin-top: 16px;
}
.m365-guide > summary {
cursor: pointer;
padding: 12px 16px;
font-weight: 600;
list-style: none;
display: flex;
align-items: center;
gap: 8px;
}
.m365-guide > summary::-webkit-details-marker {
display: none;
}
.m365-guide > summary::before {
content: "▸";
color: var(--m365-accent);
transition: transform 0.15s ease;
}
.m365-guide[open] > summary::before {
transform: rotate(90deg);
}
.m365-guide__body {
padding: 0 16px 16px;
border-top: 1px solid #f0f0f1;
}
.m365-guide__body ol {
margin: 12px 0 0;
padding-left: 22px;
}
.m365-guide__body li {
margin-bottom: 10px;
line-height: 1.55;
}
.m365-guide__body li strong {
font-weight: 600;
}
.m365-guide__body code {
font-size: 12px;
}
.m365-guide__note {
margin: 12px 0 0;
padding: 10px 12px;
border-radius: 6px;
background: #f0f6fc;
border: 1px solid #c5d9ed;
font-size: 13px;
}
.m365-guide__warn {
margin: 12px 0 0;
padding: 10px 12px;
border-radius: 6px;
background: #fcf0e4;
border: 1px solid #f0c28a;
color: #6b3a00;
font-size: 13px;
}
.m365-warning--strong {
background: #fcf0f1;
color: #8a2424;
border: 1px solid #f0b8bd;
}