USER-WP-0039: show account-site and Authelia uid on the account page (NK-WP-0051-T03)
The Identity section now names both session uids on separate lines and marks a mismatch, using the existing server-side Authelia /api/state lookup. Unknown Authelia uid reads 'not signed in / unknown'. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 1041694@bnt-lap001 Assistant-Session: 7af0bb68-ac4a-4ce3-8639-24ddd84c0b52
This commit is contained in:
parent
71feaf391b
commit
80f5870ebb
3 changed files with 159 additions and 10 deletions
|
|
@ -142,7 +142,10 @@ class PortalApplication:
|
|||
def __call__(self, environ: Mapping[str, Any], start_response: StartResponse) -> Iterable[bytes]:
|
||||
correlation_id = environ.get("HTTP_X_REQUEST_ID") or f"corr_{secrets.token_hex(12)}"
|
||||
navigation_token = _ACCOUNT_NAVIGATION.set("")
|
||||
cache_token = _REQUEST_CACHE.set({})
|
||||
# The cookie header stays in the per-request cache only so the
|
||||
# Authelia uid can be looked up once while rendering; it is never
|
||||
# rendered or logged.
|
||||
cache_token = _REQUEST_CACHE.set({"cookie_header": str(environ.get("HTTP_COOKIE", ""))})
|
||||
browser_token = _BROWSER_REQUEST.set(
|
||||
"text/html" in str(environ.get("HTTP_ACCEPT", ""))
|
||||
and not str(environ.get("PATH_INFO", "/")).startswith("/api/")
|
||||
|
|
@ -2321,17 +2324,47 @@ Use the login name they provide; it may differ from your display name.</p></sect
|
|||
"<p>You are not signed in.</p>"
|
||||
f"{level}</section>"
|
||||
)
|
||||
name = escape(actor.preferred_username or actor.subject)
|
||||
verification = "Verified by your identity provider" if actor.assurance else "Verification pending"
|
||||
return (
|
||||
'<section aria-labelledby="login-state"><h2 id="login-state">Identity</h2>'
|
||||
f"<p>Signed in as <strong>{name}</strong>.</p>"
|
||||
"<p>This session is for the account site. An application can keep its own session.</p>"
|
||||
+ self._session_uids(actor)
|
||||
+ "<p>This session is for the account site. An application can keep its own session.</p>"
|
||||
f"{level}"
|
||||
f"<p>{escape(verification)}</p>"
|
||||
'<p><a href="/security">Password and one-time code help</a></p></section>'
|
||||
)
|
||||
|
||||
def _session_uids(self, actor: Any) -> str:
|
||||
"""Name the account-site uid and the Authelia uid on separate lines.
|
||||
|
||||
NK-WP-0051-T03 (contract: net-kingdom docs/sign-in-diagnosis.md).
|
||||
Only the two uids are shown; the Authelia uid comes from the existing
|
||||
server-side /api/state lookup and is never guessed.
|
||||
"""
|
||||
account_uid = actor.preferred_username or actor.subject
|
||||
authelia_uid = self._netkingdom_name()
|
||||
lines = (
|
||||
'<dl class="session-uids">'
|
||||
"<dt>Account site session <code>uid</code></dt>"
|
||||
f'<dd data-session="account-site"><strong>{escape(account_uid)}</strong></dd>'
|
||||
"<dt>Authelia session <code>uid</code> (shared NetKingdom sign-in)</dt>"
|
||||
+ (
|
||||
f'<dd data-session="authelia"><strong>{escape(authelia_uid)}</strong></dd>'
|
||||
if authelia_uid
|
||||
else '<dd data-session="authelia">not signed in / unknown</dd>'
|
||||
)
|
||||
+ "</dl>"
|
||||
)
|
||||
if authelia_uid and authelia_uid != account_uid:
|
||||
lines += (
|
||||
'<p role="alert" class="session-uid-mismatch"><strong>These sessions differ.</strong> '
|
||||
f"Applications that use the shared NetKingdom sign-in, such as OpenBao, "
|
||||
f"will continue as <strong>{escape(authelia_uid)}</strong>, "
|
||||
f"not <strong>{escape(account_uid)}</strong>.</p>"
|
||||
+ self._identity_switch_help()
|
||||
)
|
||||
return lines
|
||||
|
||||
@staticmethod
|
||||
def _is_exception_account(actor: Any, memberships: tuple[Any, ...]) -> bool:
|
||||
if {"tenant-admin", "platform-operator", "platform-root"}.intersection(actor.roles):
|
||||
|
|
@ -2526,9 +2559,13 @@ Use the login name they provide; it may differ from your display name.</p></sect
|
|||
if "netkingdom_name" in cache:
|
||||
return cache["netkingdom_name"]
|
||||
name: str | None = None
|
||||
if environ is not None and self.identity_lookup is not None:
|
||||
cookie_header = (
|
||||
str(environ.get("HTTP_COOKIE", "")) if environ is not None
|
||||
else cache.get("cookie_header")
|
||||
)
|
||||
if cookie_header is not None and self.identity_lookup is not None:
|
||||
try:
|
||||
found = self.identity_lookup.username(str(environ.get("HTTP_COOKIE", "")))
|
||||
found = self.identity_lookup.username(cookie_header)
|
||||
except Exception:
|
||||
found = None
|
||||
if is_identity_name(found):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue