fix(auth): resolve JWT InvalidSignatureError and improve frontend UX
Some checks failed
CI / lint-and-test (push) Has been cancelled

- Fix auth by using idToken fallback when accessToken audience mismatches
- Add PyJWT verification with audience-aware token selection in frontend
- Source health: track last_attempt_time and error status per source
- Frontend: fix modal outside x-data scope, add circular-safe JSON stringify
- Frontend: support multi-select service filter with All/None toggles
- Frontend: improve filter layout into organized rows
- Frontend: fix text overflow and result pill colors (success/succeeded)
- Intune: normalize application actors (auditActorType=Application)
- Add cache-control middleware for HTML/API responses
- Update tests for multi-service filtering and source health
This commit is contained in:
2026-04-16 11:32:45 +02:00
parent ed310a06de
commit 82bafc06c9
12 changed files with 350 additions and 103 deletions

View File

@@ -46,6 +46,7 @@ class FetchAuditLogsResponse(BaseModel):
class SourceHealthResponse(BaseModel):
source: str
last_fetch_time: str | None = None
last_attempt_time: str | None = None
status: str

View File

@@ -28,9 +28,11 @@ def _actor_display(actor: dict, resolved: dict = None, owners=None) -> str:
user = actor.get("user", {}) or {}
sp = actor.get("servicePrincipal", {}) or {}
app = actor.get("app", {}) or {}
application = actor.get("application", {}) or {}
upn = user.get("userPrincipalName") or user.get("mail")
display = user.get("displayName")
app_display = app.get("displayName")
app_display = app.get("displayName") or application.get("displayName")
app_id = app.get("id") or application.get("id")
if display and upn and display != upn:
return f"{display} ({upn})"
@@ -41,6 +43,7 @@ def _actor_display(actor: dict, resolved: dict = None, owners=None) -> str:
or app_display
or sp.get("displayName")
or sp.get("appId")
or app_id
or actor.get("ipAddress")
or user.get("id")
or sp.get("id")
@@ -164,7 +167,8 @@ def normalize_event(e):
display_conf = display_mapping.get(category) or display_mapping.get("default", {})
actor_field_pref = display_conf.get("actor_field", "actor_display")
actor_label_text = display_conf.get("actor_label", "User")
default_actor_label = "Application" if (actor.get("application") or actor.get("app")) else "User"
actor_label_text = display_conf.get("actor_label", default_actor_label)
if actor_field_pref == "actor_upn" and actor_upn:
display_actor_value = actor_upn