Skip to content

With OIDC federation turned on, Vercel signs a short-lived token for each function invocation and attaches it to the incoming request. The Edge SDK presents that token to Aembit as proof of identity, so a function can reach a protected service without holding a long-lived secret in its environment.

This guide covers the parts specific to Vercel. For what the SDK does in general, see the Edge SDK overview.

On the Vercel side, enable OIDC federation on the project and run the function on the Node.js runtime.

In Aembit, configure an Access Policy: Access Policies define, enforce, and audit access between Client and Server Workloads by cryptographically verifying workload identity and contextual factors rather than relying on static secrets.Learn more with these pieces:

  • An OIDC ID Token Trust Provider carrying an Edge SDK Client ID: A structured identifier that Aembit generates when you configure a Trust Provider, encoding your region, tenant, and Trust Provider. It identifies a Trust Provider rather than an individual Client Workload.Learn more.
  • A Client Workload: Client Workloads represent software applications, scripts, or automated processes that initiate access requests to Server Workloads, operating autonomously without direct user interaction.Learn more whose identifier matches a claim in the Vercel token.
  • A Server Workload: Server Workloads represent target services, APIs, databases, or applications that receive and respond to access requests from Client Workloads.Learn more whose Service Endpoint host and port match what your function requests.
  • A Credential Provider: Credential Providers obtain the specific access credentials—such as API keys, OAuth tokens, or temporary cloud credentials—that Client Workloads need to authenticate to Server Workloads.Learn more that returns the credential type your function asks for.

This flow has a setup step the cloud provider methods skip. Aembit verifies the token signature itself, so it needs the public keys from Vercel before the first request can pass. The OIDC Discovery attestation method is the least work. Give it the issuer URL, and Aembit finds the provider configuration and public keys from there.

Read the issuer and audience values off a real token rather than guessing them. Both depend on your Vercel team, so deploy the function once, log the decoded token, and write the iss and aud values you see into the match rules.

Vercel delivers the token in two different places depending on where the code runs.

In production, the token arrives on the request as the x-vercel-oidc-token header. Locally, vercel env pull writes a .env.local file containing VERCEL_OIDC_TOKEN, and vercel dev loads it from there. Handling both keeps one function working in both places:

function resolveToken(request: Request): string {
const header = request.headers.get("x-vercel-oidc-token")?.trim()
if (header) {
return header
}
const env = process.env.VERCEL_OIDC_TOKEN?.trim()
if (env) {
return env
}
throw new Error(
"Missing Vercel OIDC token. Expected the x-vercel-oidc-token header in production, " +
"or VERCEL_OIDC_TOKEN for local development."
)
}

Build the Trust Provider: Trust Providers validate Client Workload identities through workload attestation, verifying identity claims from the workload's runtime environment rather than relying on pre-shared secrets.Learn more and the client inside the handler. The token belongs to a single request, so nothing exists to read at module load time. A client constructed there would capture a token that has already expired, or never existed at all:

import { EdgeClient, trustProviders } from "@aembit/edge-sdk"
const CONFIG = {
baseUrl: "https://<tenant>.ec.<stack>.aembit.io",
clientId: "your-edge-sdk-client-id",
serverHost: "target.example.com",
serverPort: 443,
credentialType: "ApiKey"
}
export async function GET(request: Request) {
const trustProvider = trustProviders.oidcIdToken({
identityToken: () => resolveToken(request)
})
const client = new EdgeClient({
baseUrl: CONFIG.baseUrl,
clientId: CONFIG.clientId,
trustProvider
})
const credential = await client.getCredential({
server: { host: CONFIG.serverHost, port: CONFIG.serverPort },
credentialType: CONFIG.credentialType
})
return Response.json({
credentialType: credential.credentialType,
expiresAt: credential.expiresAt,
dataKeys: Object.keys(credential.data)
})
}

Per-request construction gives up the in-memory token cache that a long-running process would reuse. That trade is correct here, because the identity itself is request-scoped.

The runnable example in the SDK repository carries the full handler.

  1. Set baseUrl to your tenant’s Edge host.

    The form is https://<tenant>.ec.<stack>.aembit.io. Use the final host. A URL that redirects fails against the credentials endpoint instead of following the redirect.

  2. Set clientId to the Edge SDK Client ID from your OIDC ID Token Trust Provider.

  3. Set serverHost and serverPort to the Service Endpoint on your Server Workload.

    These must match what you configured in Aembit exactly. A mismatch returns a response that looks successful but carries no credential.

  4. Set credentialType to the type your Credential Provider returns, such as ApiKey.

If your tenant uses Resource Sets, pass resourceSet to EdgeClient as well.

Pull the environment and start the dev server from the function’s project directory, so Vercel writes its local state and .env.local in the right place:

Terminal window
vercel env pull
vercel dev

Then call the function:

Terminal window
curl "http://localhost:3000/api"

A working flow reports the credential type and the keys in the payload without printing the secret:

{
"credentialType": "ApiKey",
"expiresAt": "2026-03-10T19:19:09.2559713Z",
"dataKeys": ["apiKey"]
}

The function reports a missing token. In production, confirm the project has OIDC federation enabled. Locally, confirm vercel env pull ran in the function’s project directory and that the resulting .env.local contains VERCEL_OIDC_TOKEN.

Aembit returns 401 from the credentials endpoint. Confirm baseUrl is the final Edge host and that it returns no redirect. Then confirm the Trust Provider can validate the signature, and that the iss, aud, and sub match rules line up with the claims in a real token.

You get 200 back, but the credential type is Unknown and dataKeys is empty. The request reached Aembit and failed to match an Access Policy. serverHost and serverPort are the usual cause, followed by credentialType, the token claim matching on the Client Workload, and then resourceSet if your tenant uses one.

  1. Log in to your Aembit Tenant.

  2. Go to the Trust Providers section in the left sidebar.

  3. Select the Trust Provider you want to use for Edge API authentication.

  4. In the TRUST PROVIDER section, find the Edge SDK Client ID field.

  5. Copy the Edge SDK Client ID to use in your authentication requests.

    Aembit UI Trust Provider page