Session Delegation

Early Access

Session Transfer Token · Custom Token Exchange with a distinct actor · act claim identifies the delegating agent

Architecture & Token Flow
Session Delegation flow diagram
1. Agent signs in
2. Pick customer + mint STT
3. Redeem as customer
4. Delegated session
Support Agent (Actor)

Sign in as the support agent. Their own ID token becomes the actor_token in the token-exchange call that mints a Session Transfer Token for a different (customer) user.

Seeded demo account — this demo uses its own fixed users, not the shared test user from the rest of the suite

email support.agent@atko.email

password SessionDelegation!Demo2026

Sign in as Support Agent

Fixed 2-hour lifetime

Non-configurable. Ephemeral cookie, cleared on browser close. The access token shares the same 2-hour ceiling — there is no idle-timeout extension.

No MFA / consent mid-session

If the delegated login would normally trigger MFA, consent, or an enrollment prompt, the request fails with interaction_required instead of prompting.

Single-level actor only

A Session Transfer Token accepts exactly one actor. Nested delegation is rejected — contrast with the OBO demo’s multi-level act chain for ordinary token exchange.

Must log out first — domain-wide

If any session already exists on this Auth0 domain — the actor’s own, not just the target user’s — the delegation attempt fails with an error page asking for logout first. Try the button below to see it.

Security Implications

Strengths

  • Impersonation is audited by construction, not by convention — setActor() is mandatory (omitting it 400s the token-exchange call), so every delegated session carries an act claim naming the actor, and Auth0 emits dedicated tenant log codes (sdel, sdeleacft, sdelsa, and their f-prefixed failure counterparts) that include the actor's sub for free.
  • No refresh tokens are ever issued for a delegated session and the access/ID token share a hard, non-configurable 2-hour ceiling — there is no long-lived credential to leak, unlike a copied password or a standing service credential.
  • session_transfer.enforce_cascade_revocation ties the delegated session's fate to the underlying grant, and the domain-wide "must log out first" rule means a delegated session can never silently coexist with another active session on the same domain.

Risks & Considerations

  • The Session Transfer Token is a bearer credential for the 60-second window it's valid — same class of risk as native-to-web's STT, but the blast radius is a full impersonated session as an arbitrary target user chosen by the actor, not just the actor's own session bridged to a new device.
  • delegation.allow_delegated_access is opt-in per target client with no Dashboard toggle — a target app that's missing it doesn't error visibly, it just falls back to the login page, with only a `w`-level tenant log entry marking what happened. Easy to miss in a demo click-through, and just as easy to miss in a real audit if no one is watching that log line specifically.
  • Side-effect suppression (no last-login/login-count updates, no welcome emails, no auto-created user grants) can look like nothing happened at all in places an admin expects an audit trail — the actual record lives in the dedicated log codes and the act claim, not in the places a normal login would leave a trace.
  • Single-level actor nesting is enforced by Auth0, but that only bounds this specific mechanism — nothing stops a target application from itself performing a further OBO-style exchange using the delegated access token, which would reintroduce a multi-level chain outside Auth0's own visibility.

Hardening Checklist

  • Alert on the specific log codes (sdel/sdeleacft/sdelsa and their fdel* failure counterparts) rather than generic login events — a spike in the fdel* codes is a more specific signal than a generic failed-login spike.
  • Treat the `w`-level allow_delegated_access warning as a configuration-drift alarm, not a routine log line — it means a delegation attempt was silently blocked, which is either a bug or a probe.
  • Same IP-binding lesson as cross-domain-sso: a server-mediated /oauth/token call needs Trust Token Endpoint IP Header enabled on the minting client and the real actor IP forwarded via auth0-forwarded-for, or the device-binding check silently binds to the server's own IP instead.
  • Allowlist which applications can be delegation targets deliberately (delegation.allow_delegated_access per client) — don't default it on tenant-wide just to avoid the silent-fallback failure mode.