From 56c884b40ff6358a7d73401a5a0cb8640d81f571 Mon Sep 17 00:00:00 2001 From: isshaddad Date: Thu, 23 Apr 2026 13:13:42 -0400 Subject: [PATCH] docs: document auth.withAuth scoped authentication helper --- docs/management/authentication.mdx | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/docs/management/authentication.mdx b/docs/management/authentication.mdx index e7d36663423..1a32f3bc01c 100644 --- a/docs/management/authentication.mdx +++ b/docs/management/authentication.mdx @@ -158,3 +158,31 @@ await envvars.update("proj_1234", "preview", "DATABASE_URL", { value: "your_preview_database_url", }); ``` + +### Scoped authentication with `auth.withAuth` + +`auth.withAuth` runs a callback with a temporary API client configuration, then restores the previous configuration when the callback resolves or rejects. It's useful when a single process needs to make calls across multiple Trigger.dev projects or environments without mutating the global config manually. + +```ts +import { auth, runs } from "@trigger.dev/sdk"; + +const projectBRuns = await auth.withAuth( + { accessToken: process.env.TRIGGER_SECRET_KEY_PROJECT_B }, + async () => { + return runs.list({ limit: 10 }); + }, +); +``` + +Any SDK call inside the callback uses the overridden token. Calls outside the callback continue to use whatever was set by `configure` (or picked up from `TRIGGER_SECRET_KEY`). + + + Avoid `auth.withAuth` as a per-request authentication strategy on long-running servers. Use it + only for sequential, non-overlapping scopes. + + +#### How scoping actually works + +Despite looking block-scoped, `auth.withAuth` stores the overridden configuration in a process-wide global (not [AsyncLocalStorage](https://nodejs.org/api/async_context.html)). It saves the previous config, installs the new one globally, runs the callback, and restores the previous config in a `finally`. This means sequential, non-overlapping usage is safe, but concurrent usage is not — if two `auth.withAuth` calls overlap (for example inside `Promise.all` with different tokens, or across concurrent request handlers on a long-running server) both will share whichever configuration was installed most recently, and SDK calls in one scope can silently use the other scope's token. + +A fix using async context isolation is tracked in [issue #3298](https://github.com/triggerdotdev/trigger.dev/issues/3298).