Harden bearer auth: constant-time compare, hashed at rest, authoritative actor_id

Fixes two live authz bugs in omnigraph-server:

- Bearer-token lookup previously used HashMap::get, which compares keys with
  Eq and short-circuits on the first differing byte — a network-observable
  timing oracle for brute-forcing tokens. Tokens are now stored as SHA-256
  digests and compared with subtle::ConstantTimeEq, iterating every entry
  unconditionally so total work is independent of which slot matches. Raw
  token bytes no longer live in server memory after startup.

- authorize_request now overwrites PolicyRequest.actor_id from the
  authenticated session instead of trusting the handler-supplied field,
  which previously defaulted to "" via unwrap_or_default(). The empty
  string can no longer reach Cedar as a policy subject even if a future
  refactor drops the None check.

External API of AppState constructors is unchanged — tokens still enter as
Vec<(String, String)> and are hashed on the way in.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
andrew 2026-04-17 21:40:51 +03:00
parent e926c925d6
commit c338e80180
5 changed files with 152 additions and 7 deletions

2
Cargo.lock generated
View file

@ -4597,6 +4597,8 @@ dependencies = [
"serde_json",
"serde_yaml",
"serial_test",
"sha2",
"subtle",
"tempfile",
"tokio",
"tower",