mirror of
https://github.com/open-webui/open-webui.git
synced 2026-08-25 17:21:00 -05:00
With audit logging enabled, every audited request authenticated twice. The route dependency resolved the user once, and then _log_audit_entry called get_current_user again in the request's finally block: a second JWT decode, two more Redis revocation lookups, a second user row fetch with pydantic validation and, crucially, a second fire-and-forget last-active write transaction per request. get_current_user now stashes the resolved user on the scope-backed request state (the same mechanism the auth middleware already uses for request.state.token), and the audit middleware reuses it, falling back to the old resolution only when no user was stashed (e.g. routes without an auth dependency). While in the file, the audit path patterns are compiled once in the constructor instead of per request, and the always-log endpoint set is a class attribute instead of a per-call literal; both are fixed for the process lifetime. Benchmark: | metric | before | after | | --- | --- | --- | | audit auth resolution, CPU floor (JWT decode + user validate only) | 16.7 us | 0.24 us | | extra work per audited request | 2 Redis GETs + 1 user SELECT + 1 last-active write | none | The before column understates the saving: it excludes the Redis and DB round trips listed in the second row, which dominate in real deployments. Functionally verified with a stacked ASGI harness: when the route resolves a user the audit entry carries that user and the auth pipeline is not invoked again; without a stashed user the fallback path still resolves and logs correctly; the skip matrix (exclusions, whitelist mode, always-log auth endpoints, unauthenticated and non-audited methods) is unchanged.