Can Vercel OIDC federation replace the keys in your environment variables?

  • Isaac
    Isaac
    AI Systems Engineer

Vercel OIDC federation gives every build, function and linked development machine a short-lived token signed by Vercel, which AWS, Google Cloud, Azure or your own API can trust in place of a long-lived key. Vercel's own services accept the same token, so on Vercel a model call through AI Gateway or a Sandbox microVM needs no stored key at all. That is how we run it. The monogram.io site assistant holds no AI Gateway key, and Monogram Tools reaches Vercel Sandbox on the deployment's token.

What is Vercel OIDC federation?

Vercel acts as an OpenID Connect identity provider for your projects. It issues a JWT whose subject names the team, the project and the environment, in the form owner:[TEAM]:project:[PROJECT]:environment:[ENV]. A cloud provider configured to trust Vercel's issuer can check those claims and hand back credentials that expire on their own. Nothing long-lived is copied into Vercel's environment variables, and you can grant production different access from preview.

The token reaches your code in three ways. A build gets it as VERCEL_OIDC_TOKEN. A function gets it on each request in the x-vercel-oidc-token header. A developer gets one written to .env.local by vercel env pull.

How do you connect Vercel to AWS, GCP or Azure without keys?

Each provider has its own exchange, and Vercel documents all three.

  • AWS: Register Vercel as an OIDC provider in IAM, write a role trust policy that checks the aud and sub claims, and pass awsCredentialsProvider({ roleArn }) from @vercel/oidc-aws-credentials-provider to the AWS SDK client. It calls AssumeRoleWithWebIdentity for you.
  • Google Cloud: Create a Workload Identity Federation pool and an OIDC provider pointed at Vercel's issuer, and map google.subject to assertion.sub. Create a service account with the roles your code needs, then grant the Service Account User role on it to the pool's principal for each Vercel project and environment, ending in subject/owner:[TEAM]:project:[PROJECT]:environment:[ENV]. In code, google-auth-library's ExternalAccountClient exchanges the Vercel token and impersonates that service account.
  • Azure: Pass getVercelOidcToken() from @vercel/oidc to a ClientAssertionCredential.

When an AWS call is refused as not authorized, the usual cause is a mismatch between the token's sub or aud and the trust policy. Decode the token and compare the two strings before changing anything else. The issuer mode matters here too. Team mode, which Vercel recommends, puts your team slug in the issuer URL, and global mode does not.

How do we use it?

On a deployment, the site assistant on monogram.io and Atlas, the agent inside Monogram Tools, reach AI Gateway on the OIDC token, and the assistant's project carries no Gateway key at all. The rest of Monogram Tools falls back to the same token whenever no explicit Gateway key is set. Vercel Sandbox, where Monogram Tools builds decks and runs media jobs, authenticates the same way in production. Our calls to Vercel Connect for Slack tokens authenticate with the deployment's OIDC token, the SDK's default on Vercel. On a client platform, the production apps reach Google Cloud Storage with no stored key: the Vercel OIDC token is federated through Google's workload identity.

Why does my VERCEL_OIDC_TOKEN stop working after 12 hours?

Because the development token expires after 12 hours by design. Function tokens for preview and production expire after two hours, and each request brings a current one, so a running deployment never needs a redeploy to refresh it. The token on your laptop is a copy that vercel env pull wrote, so code that reads the variable directly sees it expire. getVercelOidcToken() from @vercel/oidc, which the AI SDK's Gateway provider calls, refreshes an expired development token on its own; anything else needs vercel env pull again.

Can you cache the OIDC token?

No. Vercel's reference says to call getVercelOidcToken() at request time, never at module level inside a function, and not to cache the result, because the token arrives with the request and expires. In Monogram Tools, an image client that uses the token builds a new client per call and reads the token at that moment, rather than holding one across warm invocations.

What tripped us up?

An empty key beat a valid token. In our project, vercel env pull wrote AI_GATEWAY_API_KEY="" because no explicit key was set. Our Gateway client falls back from an explicit key to the OIDC token, and with the nullish ?? operator an empty string counts as present, which would fail every call while a valid token sat in the next variable. We use || for that fallback, and the reason is written into the code.

Where OIDC stops

  • Renaming a team or project changes the claims. A trust policy written against the old names will refuse the new ones, so add both before you rename.
  • Off Vercel there is no token. External CI or another host needs its own identity, such as a Vercel access token for Vercel's APIs or that platform's own OIDC for your cloud.
  • Cloud federation lives or dies on the trust policy. For AWS, Google Cloud or Azure, follow Vercel's documented recipe for that cloud and test the exchange on the target account before relying on it.

FAQ

Does the OIDC token refresh in production?

Yes. Functions receive a current token on each request, so you never redeploy to refresh it.

Do I need an AI Gateway API key on Vercel?

No. The AI SDK uses the OIDC token when no key is set. Keep a key only for callers outside Vercel.

Which token lives longest?

Development tokens last 12 hours, function tokens two hours, build tokens one hour.

Can I call getVercelOidcToken() at the top of a module?

Not inside a Vercel Function. The token arrives with the request, so call it in the handler.

We build on Next.js and Vercel for clients; see Next.js and Vercel development, Vercel and AWS.

Vendor references: OIDC federation, OIDC reference, AWS, Google Cloud, Azure, AI Gateway OIDC.