npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@defakto/spiffe

v0.5.1

Published

SPIFFE-compliant TypeScript SDK with extended workload identity and attestation support

Downloads

484

Readme

@defakto/spiffe

npm License: Apache-2.0

⚠️ WARNING: Active Development

This SDK is in active development and the API is not yet stable. Breaking changes may occur with every version until we reach 1.0.0. Pin to exact versions and review the changelog carefully before upgrading.

A TypeScript SDK for SPIFFE workload identity. It ships three clients that share the same API surface:

  • WorkloadAPIClient — smart wrapper that automatically selects the right underlying client based on options or environment variables. Use this as your default import in any environment.
  • LocalWorkloadAPIClient — connects to a local SPIFFE agent (SPIRE or compatible) via Unix socket or TCP. Use this directly in traditional server or container environments where a SPIFFE agent runs alongside the workload.
  • AttestingWorkloadAPIClient — attests the workload at request time and connects directly to Defakto's cloud endpoint. Use this directly in serverless or ephemeral environments where installing a local agent is not practical.

Installation

npm install @defakto/spiffe
# yarn
yarn add @defakto/spiffe
# pnpm
pnpm add @defakto/spiffe
# bun
bun add @defakto/spiffe

Smart wrapper (WorkloadAPIClient)

WorkloadAPIClient auto-selects the right underlying client. Use it as your default import — you can switch environments by changing environment variables without touching your application code.

Selection logic (priority order)

  1. SPIFFE_ENDPOINT_SOCKET env var set → uses LocalWorkloadAPIClient
  2. DEFAKTO_ATTESTORS env var set → uses AttestingWorkloadAPIClient
  3. Otherwise → throws SpiffeError with code SOCKET_PATH_NOT_CONFIGURED
import { WorkloadAPIClient } from "@defakto/spiffe";

const client = new WorkloadAPIClient();

Environment-driven attestation (DEFAKTO_ATTESTORS)

Set DEFAKTO_ATTESTORS to a comma-separated list of built-in attestor names to auto-instantiate them with default options. Pair with DEFAKTO_TRUST_DOMAIN_ID to set the Defakto endpoint.

| Name | Attestor class | Environment | | ------------------------ | ------------------ | ---------------------- | | aws_external_identity | AwsTokenAttestor | AWS (Lambda, EC2, …) | | azure_managed_identity | AzureMSIAttestor | Azure Managed Identity | | gcp_service_account | GcpIITAttestor | Google Cloud | | github | GithubAttestor | GitHub Actions |

# Serverless AWS Lambda — no code changes needed
DEFAKTO_ATTESTORS=aws_external_identity
DEFAKTO_TRUST_DOMAIN_ID=td-0000000
// Application code stays the same in every environment
const client = new WorkloadAPIClient();

Unrecognised names throw SpiffeError with code NO_ATTESTORS_CONFIGURED.


Standard SPIFFE (LocalWorkloadAPIClient)

LocalWorkloadAPIClient speaks the standard SPIFFE Workload API gRPC protocol. It works with any compliant SPIFFE agent (e.g. SPIRE).

Connection options

The client resolves its endpoint in the following priority order:

  1. Explicit options passed to the constructor.
  2. SPIFFE_ENDPOINT_SOCKET environment variable (supports unix:///path, unix://path, and unix:path prefixes).

If neither is provided, the client throws a SpiffeError with code SOCKET_PATH_NOT_CONFIGURED.

import { LocalWorkloadAPIClient } from "@defakto/spiffe";

// Resolved from SPIFFE_ENDPOINT_SOCKET (throws if not set)
const client = new LocalWorkloadAPIClient();

// Explicit Unix socket
const client = new LocalWorkloadAPIClient({
  transport: "unix",
  socketPath: "/run/spire/agent.sock",
});

// Explicit TCP (e.g. remote SPIRE agent)
const client = new LocalWorkloadAPIClient({
  transport: "tcp",
  address: "spire-agent.internal",
  port: 8081,
  insecureSkipTls: false, // default: false (TLS enabled)
});

X.509 SVID

const svid = await client.x509.getSVID();

console.log("SPIFFE ID:", svid.id.toString()); // spiffe://example.org/service
console.log("Expires at:", svid.expiresAt.toISOString());
// svid.certificates — DER-encoded certificate chain (Uint8Array[])
// svid.privateKey   — CryptoKey

JWT SVID

const jwt = await client.jwt.fetchSVID(["https://api.example.org"]);

console.log("SPIFFE ID:", jwt.id.toString());
console.log("Token:", jwt.token);

Watching X.509 context rotations

The Workload API pushes a new context whenever SVIDs are rotated. watchX509Context returns an async iterable that reconnects automatically if the stream ends cleanly.

// Full context (all SVIDs + trust bundles)
for await (const ctx of client.watchX509Context()) {
  const svid = ctx.defaultSVID();
  console.log("Rotated SVID:", svid.id.toString());

  // ctx.svids   — all SVIDs issued to this workload
  // ctx.bundles — Map<trustDomainName, X509Bundle>
}

// Or watch just the default SVID
for await (const svid of client.x509.watchSVID()) {
  console.log("New SVID expires:", svid.expiresAt.toISOString());
}

Resource cleanup

All clients implement Symbol.asyncDispose for use with await using (TypeScript 5.2+), and expose an explicit close() method.

// Recommended: automatic cleanup via `await using`
await using client = new LocalWorkloadAPIClient();
const svid = await client.x509.getSVID();
// client.close() is called automatically when the block exits

// Manual cleanup
const client = new LocalWorkloadAPIClient();
try {
  const svid = await client.x509.getSVID();
} finally {
  await client.close();
}

Defakto Serverless (AttestingWorkloadAPIClient)

AttestingWorkloadAPIClient is designed for environments where a SPIFFE agent cannot run alongside the workload (AWS Lambda, Google Cloud Run, Azure Container Apps, GitHub Actions, etc.). Instead of relying on a pre-existing agent, it attests the workload inline — collecting cryptographic evidence from the environment on every request — and sends that evidence to Defakto's trust domain server endpoint to obtain SVIDs.

Setting trustDomainId automatically resolves the endpoint to <trustDomainId>.agent.spirl.com:443 over TLS. You can override this with an explicit transport option (same shape as LocalWorkloadAPIClient).

X.509 SVID

const svid = await client.x509.getSVID();

JWT SVID

const jwt = await client.jwt.fetchSVID(["https://api.example.org"]);
console.log("ID:", jwt.id);

Watching X.509 context rotations

The attesting client re-attests and re-fetches the SVID automatically before it expires (at 85% of the remaining lifetime, minimum 1 second interval).

for await (const ctx of client.watchX509Context()) {
  const svid = ctx.defaultSVID();
  console.log("Renewed SVID expires:", svid.expiresAt.toISOString());
}

Built-in attestors

AWS (AwsTokenAttestor)

Attests using a signed JWT from AWS STS (GetWebIdentityToken). Works in any environment with an IAM role attached (Lambda, ECS, EC2, etc.).

import { AttestingWorkloadAPIClient, AwsTokenAttestor } from "@defakto/spiffe";

const client = new AttestingWorkloadAPIClient({
  trustDomainId: "td-0000000",
  attestors: [new AwsTokenAttestor()],
});

const svid = await client.x509.getSVID();
console.log("SPIFFE ID:", svid.id.toString());

Options

| Option | Type | Default | Description | | ------------------ | -------------------- | --------------------------------- | --------------------------------------------------------------- | | audience | string[] | ["urn:defakto:security:server"] | JWT audience (aud claim) | | signingAlgorithm | "RS256" \| "ES384" | "RS256" | STS token signing algorithm | | durationSeconds | number | 60 | Token validity in seconds (60–3600) | | tags | Tag[] | — | Optional custom STS session tags | | stsConfig | STSClientConfig | {} | AWS SDK STS client config (region, credentials, endpoint, etc.) |

const attestor = new AwsTokenAttestor({
  audience: ["my-service"],
  signingAlgorithm: "ES384",
  durationSeconds: 300,
  stsConfig: { region: "eu-west-1" },
});

Azure (AzureMSIAttestor)

Attests using an Azure Managed Identity token. Works on any Azure compute resource with a managed identity assigned (App Service, Container Apps, AKS, VM, etc.).

import { AttestingWorkloadAPIClient, AzureMSIAttestor } from "@defakto/spiffe";

const client = new AttestingWorkloadAPIClient({
  trustDomainId: "td-0000000",
  attestors: [new AzureMSIAttestor()],
});

const svid = await client.x509.getSVID();
console.log("SPIFFE ID:", svid.id.toString());

By default the attestor uses api://AzureADTokenExchange as the audience (a well-known Azure workload identity federation audience). If the managed identity is user-assigned, select it by clientId, principalId, or resourceId:

// System-assigned identity (default)
new AzureMSIAttestor();

// User-assigned identity — select by client ID
new AzureMSIAttestor({ clientId: "00000000-0000-0000-0000-000000000000" });

// User-assigned identity — select by object/principal ID
new AzureMSIAttestor({ principalId: "00000000-0000-0000-0000-000000000000" });

// Custom audience
new AzureMSIAttestor({ audience: "api://my-tenant-id/defakto-server" });

Options

| Option | Type | Default | Description | | ------------- | -------- | ------------------------------ | ---------------------------------------------- | | audience | string | "api://AzureADTokenExchange" | Azure resource URI for the token | | clientId | string | — | Select managed identity by client ID | | principalId | string | — | Select managed identity by object/principal ID | | resourceId | string | — | Select managed identity by MSI resource ID |

At most one of clientId, principalId, resourceId may be set.


GCP (GcpIITAttestor)

Attests using a GCP Instance Identity Token (IIT) fetched from the metadata service. The token is a signed JWT issued by Google that proves the workload is running on a specific GCE instance, Cloud Run service, GKE pod, etc.

import { AttestingWorkloadAPIClient, GcpIITAttestor } from "@defakto/spiffe";

const client = new AttestingWorkloadAPIClient({
  trustDomainId: "td-0000000",
  attestors: [new GcpIITAttestor()],
});

const svid = await client.x509.getSVID();
console.log("SPIFFE ID:", svid.id.toString());

Options

| Option | Type | Default | Description | | ------------------- | -------- | ------------------------------- | ----------------------------------------------- | | audience | string | "urn:defakto:security:server" | Audience for the identity token | | serviceAccount | string | "default" | Service account to fetch the identity token for | | identityTokenHost | string | "metadata.google.internal" | Override the metadata service host |

new GcpIITAttestor({
  audience: "my-defakto-agent",
  serviceAccount: "[email protected]",
});

GitHub Actions (GithubAttestor)

Attests a workload running inside a GitHub Actions job using a GitHub Actions OIDC ID token. The token is a signed JWT issued by GitHub (https://token.actions.githubusercontent.com) that proves the workload is executing in a specific repository, workflow, ref, and environment.

The token is fetched on demand via @actions/core's getIDToken, which calls the GitHub Actions runtime to mint a fresh JWT for the requested audience. The token itself is never read from an environment variable or the filesystem.

The workflow must grant id-token: write permission, e.g.:

permissions:
  id-token: write
  contents: read
import { AttestingWorkloadAPIClient, GithubAttestor } from "@defakto/spiffe";

const client = new AttestingWorkloadAPIClient({
  trustDomainId: "td-0000000",
  attestors: [new GithubAttestor()],
});

const svid = await client.x509.getSVID();
console.log("SPIFFE ID:", svid.id.toString());

Options

| Option | Type | Default | Description | | -------------- | ------------------------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | audience | string | "defakto-github" | Audience (aud claim) requested for the OIDC token; must match the audience the Defakto signer is configured to accept | | fetchIdToken | (audience) => Promise<string> | @actions/core.getIDToken | Override the token fetcher (e.g. for testing). Defaults to GitHub's official Actions toolkit, which mints a fresh JWT on each call |


Custom attestors

Implement the Attestor interface to add any attestation source:

import type { Attestor, AttestationEvidence } from "@defakto/spiffe";
import { readFile } from "node:fs/promises";

class KubernetesAttestor implements Attestor {
  readonly pluginName = "k8s_sat"; // must match what the endpoint expects
  readonly pluginVersion = "1.0.0";

  async collectEvidence(): Promise<AttestationEvidence> {
    const token = await readFile("/var/run/secrets/kubernetes.io/serviceaccount/token");
    return {
      pluginName: this.pluginName,
      pluginVersion: this.pluginVersion,
      payload: token,
    };
  }
}

const client = new AttestingWorkloadAPIClient({
  trustDomainId: "td-0000000",
  attestors: [new KubernetesAttestor()],
});

When multiple attestors are configured, evidence is collected concurrently and all results are sent together in a single request.


Cloud provider credential integration

Once you have a SPIFFE client, you can use a JWT SVID as a proof of identity to obtain native cloud credentials — no long-lived secrets or service account keys needed. The integrations live in separate sub-path exports to keep peer-dependency footprint minimal.

All four integrations self-bootstrap when no source is supplied: they create a WorkloadAPIClient automatically, reading the socket path or attestor config from environment variables. Pass source explicitly only when you need to share an existing client or use AttestingWorkloadAPIClient.

AWS (fromSpiffe)

fromSpiffe returns an AWS credential provider that assumes an IAM role using the SVID as a web identity token. Pass the result to the credentials option of any AWS SDK client.

import { fromSpiffe } from "@defakto/spiffe/aws";
import { S3Client } from "@aws-sdk/client-s3";

// Zero-arg: WorkloadAPIClient created lazily on first credential refresh.
// roleArn can also be set via the AWS_ROLE_ARN environment variable.
const s3 = new S3Client({
  region: "eu-west-1",
  credentials: fromSpiffe({ roleArn: "arn:aws:iam::123456789012:role/my-role" }),
});

AWS credentials are automatically refreshed: whenever the SDK detects the credentials have expired, fromSpiffe fetches a fresh SVID and exchanges it for a new STS session.

roleArn can be omitted when the AWS_ROLE_ARN environment variable is set — useful for ECS task definitions, EC2 instance env, or Kubernetes env injection:

// AWS_ROLE_ARN=arn:aws:iam::123456789012:role/my-role
const s3 = new S3Client({
  region: "eu-west-1",
  credentials: fromSpiffe(),
});

To use an existing SPIFFE client, pass it via source:

import { LocalWorkloadAPIClient } from "@defakto/spiffe";
import { fromSpiffe } from "@defakto/spiffe/aws";

const spiffe = new LocalWorkloadAPIClient();
const credentials = fromSpiffe({
  source: spiffe.jwt,
  roleArn: "arn:aws:iam::123456789012:role/my-role",
});

Options

| Option | Type | Default | Description | | ----------------- | ------------------------- | ------------------------------- | ------------------------------------------------------------------------------------ | | source | JwtSVIDSource | new WorkloadAPIClient().jwt | JWT SVID source; created lazily on first credential refresh if not provided | | roleArn | string | AWS_ROLE_ARN env var | ARN of the IAM role to assume. Falls back to the AWS_ROLE_ARN environment variable | | svidAudience | string \| string[] | "urn:defakto:security:server" | Audience(s) for the JWT SVID — must match the IAM identity provider | | roleSessionName | string | "spiffe-session" | Name for the assumed role session | | providerId | string | — | FQDN of the identity provider (e.g. "graph.facebook.com") | | policyArns | { arn: string }[] | — | Managed session policies | | policy | string | — | Inline session policy JSON | | durationSeconds | number | 3600 | Role session duration in seconds | | clientConfig | Record<string, unknown> | — | Config passed to the inner STS client (region, endpoint, etc.) |


Azure (SPIFFECredential)

SPIFFECredential is an Azure TokenCredential that authenticates using a SPIFFE JWT SVID as a client assertion. It enables workload identity federation: no client secrets or certificates — the SVID proves the workload's identity to Azure AD.

import { SPIFFECredential } from "@defakto/spiffe/azure";
import { BlobServiceClient } from "@azure/storage-blob";

// Zero-arg: WorkloadAPIClient created eagerly in constructor.
// tenantId and clientId can also be set via AZURE_TENANT_ID / AZURE_CLIENT_ID.
const credential = new SPIFFECredential({
  tenantId: "your-tenant-id",
  clientId: "your-app-client-id",
});

const blobClient = new BlobServiceClient(
  "https://mystorageaccount.blob.core.windows.net",
  credential,
);

SPIFFECredential implements the standard TokenCredential interface, so it is a drop-in replacement for DefaultAzureCredential or any other credential type accepted by the Azure SDK.

Environment variable–driven usage — In environments where AZURE_TENANT_ID and AZURE_CLIENT_ID are already injected (AKS, Container Apps, VM env injection), you can omit options entirely:

// AZURE_TENANT_ID and AZURE_CLIENT_ID set in environment
const credential = new SPIFFECredential();

To use an existing SPIFFE client, pass it via source:

import { LocalWorkloadAPIClient } from "@defakto/spiffe";
import { SPIFFECredential } from "@defakto/spiffe/azure";

const spiffe = new LocalWorkloadAPIClient();
const credential = new SPIFFECredential({ source: spiffe.jwt, tenantId: "...", clientId: "..." });

If AZURE_AUTHORITY_HOST is set in the environment (e.g. for sovereign clouds), it is used as the authority host unless credentialOptions.authorityHost is provided explicitly.

Prerequisites in Azure AD:

  1. An app registration (or managed identity) with a federated identity credential configured.
  2. The federated credential's audience must match svidAudience (default: "api://AzureADTokenExchange").
  3. The app must have the required RBAC roles or API permissions.

Options

| Option | Type | Default | Description | | ------------------- | ---------------------------------- | ------------------------------ | ----------------------------------------------------------------------------------- | | source | JwtSVIDSource | new WorkloadAPIClient().jwt | JWT SVID source; created eagerly in constructor if not provided | | tenantId | string | AZURE_TENANT_ID | Azure AD tenant ID | | clientId | string | AZURE_CLIENT_ID | Azure AD application (client) ID | | svidAudience | string \| string[] | "api://AzureADTokenExchange" | Audience(s) for the JWT SVID | | credentialOptions | ClientAssertionCredentialOptions | — | Authority host (falls back to AZURE_AUTHORITY_HOST), logging, retry options, etc. |


GCP (SPIFFEIdentityPoolClient)

SPIFFEIdentityPoolClient exchanges a SPIFFE JWT SVID for a GCP access token via Workload Identity Federation. It extends google-auth-library's IdentityPoolClient, so it can be passed directly as authClient to any Google Cloud SDK library (@google-cloud/storage, @google-cloud/bigquery, etc.).

import { SPIFFEIdentityPoolClient } from "@defakto/spiffe/gcp";
import { Storage } from "@google-cloud/storage";

// Zero-arg: WorkloadAPIClient created eagerly in constructor.
// audience can also be set via the GOOGLE_CLOUD_WORKLOAD_IDENTITY_POOL environment variable.
const gcpClient = new SPIFFEIdentityPoolClient({
  audience:
    "//iam.googleapis.com/projects/123456789/locations/global/" +
    "workloadIdentityPools/my-pool/providers/my-provider",
});

// Pass gcpClient directly as authClient to any Google Cloud SDK library.
const storage = new Storage({ authClient: gcpClient });
const [metadata] = await storage.bucket("my-bucket").getMetadata();
console.log(metadata);

For setups that use service account impersonation, pass serviceAccountImpersonationUrl:

const gcpClient = new SPIFFEIdentityPoolClient({
  audience: "//iam.googleapis.com/projects/.../providers/my-provider",
  serviceAccountImpersonationUrl:
    "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/" +
    "[email protected]:generateAccessToken",
});

Environment variable–driven usage — In environments where GOOGLE_CLOUD_WORKLOAD_IDENTITY_POOL and other GCP variables are already injected (Cloud Run, GKE, etc.), you can omit options entirely:

// GOOGLE_CLOUD_WORKLOAD_IDENTITY_POOL, GOOGLE_CLOUD_PROJECT, etc. set in environment
const gcpClient = new SPIFFEIdentityPoolClient();

To use an existing SPIFFE client, pass it via source:

import { LocalWorkloadAPIClient } from "@defakto/spiffe";
import { SPIFFEIdentityPoolClient } from "@defakto/spiffe/gcp";

const spiffe = new LocalWorkloadAPIClient();
const gcpClient = new SPIFFEIdentityPoolClient({
  source: spiffe.jwt,
  audience: "//iam.googleapis.com/...",
});

If CLOUDSDK_AUTH_IMPERSONATE_SERVICE_ACCOUNT is set to a service account email, the impersonation URL is constructed automatically unless serviceAccountImpersonationUrl is provided explicitly.

Prerequisites in GCP:

  1. A Workload Identity Pool with an OIDC provider configured for your SPIFFE trust domain.
  2. The provider's audience must match svidAudience (defaults to the value of audience).
  3. IAM bindings granting the pool (or the impersonated service account) access to GCP resources.

Options

| Option | Type | Default | Description | | -------------------------------- | -------------------- | ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------- | | source | JwtSVIDSource | new WorkloadAPIClient().jwt | JWT SVID source; created eagerly in constructor if not provided | | audience | string | GOOGLE_CLOUD_WORKLOAD_IDENTITY_POOL | Workload Identity Pool audience string | | svidAudience | string \| string[] | value of audience | Audience(s) for the JWT SVID | | serviceAccountImpersonationUrl | string | constructed from CLOUDSDK_AUTH_IMPERSONATE_SERVICE_ACCOUNT | Service account impersonation URL; env var holds SA email, URL is constructed automatically | | projectId | string | GOOGLE_CLOUD_PROJECT | GCP project ID; required when running outside GCP (Azure, AWS, on-prem) so Cloud SDK clients can skip auto-detect | | universeDomain | string | "googleapis.com" | GCP universe domain; only needed for non-public GCP universes | | quotaProjectId | string | GOOGLE_CLOUD_QUOTA_PROJECT | Project used for quota and billing attribution; defaults to projectId |


Anthropic (identityTokenFromSpiffe)

identityTokenFromSpiffe returns an Anthropic IdentityTokenProvider — a () => Promise<string> callable that the Anthropic SDK invokes to fetch a fresh JWT for OIDC Workload Identity Federation. Pass it to oidcFederationProvider({ identityTokenProvider, ... }) from @anthropic-ai/sdk/lib/credentials/oidc-federation. Each refresh fetches a new JWT SVID — no token files on disk, no static sk-ant-... keys.

import Anthropic from "@anthropic-ai/sdk";
import { oidcFederationProvider } from "@anthropic-ai/sdk/lib/credentials/oidc-federation";
import { identityTokenFromSpiffe } from "@defakto/spiffe/anthropic";

// Zero-arg: WorkloadAPIClient created lazily on first token refresh.
const client = new Anthropic({
  credentials: oidcFederationProvider({
    identityTokenProvider: identityTokenFromSpiffe(),
    federationRuleId: "fdrl_...",
    organizationId: "00000000-0000-0000-0000-000000000000",
    serviceAccountId: "svac_...",
    baseURL: "https://api.anthropic.com",
    fetch,
  }),
});

const message = await client.messages.create({
  model: "claude-sonnet-4-6",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Hello, Claude" }],
});

The Anthropic SDK refreshes its access token on a two-tier schedule (advisory at expiry−120s, mandatory at expiry−30s). On each refresh identityTokenFromSpiffe calls JwtSVIDSource.fetchSVID again, so the underlying SVID is always fresh.

To use an existing SPIFFE client, pass it via source:

import { LocalWorkloadAPIClient } from "@defakto/spiffe";
import { identityTokenFromSpiffe } from "@defakto/spiffe/anthropic";

const spiffe = new LocalWorkloadAPIClient();
const identityTokenProvider = identityTokenFromSpiffe({
  source: spiffe.jwt,
  svidAudience: "https://api.anthropic.com",
});

Prerequisites in the Claude Console:

  1. A registered federation issuer for your SPIFFE trust domain (issuer URL pointing to your SPIRE server's OIDC discovery endpoint).
  2. A federation rule whose audience match (if configured) equals svidAudience.
  3. A service account targeted by the rule, added as a member of the workspace you intend to call the API from.

Options

| Option | Type | Default | Description | | -------------- | -------------------- | ----------------------------- | ----------------------------------------------------------------------- | | source | JwtSVIDSource | new WorkloadAPIClient().jwt | JWT SVID source; created lazily on first token refresh if not provided | | svidAudience | string \| string[] | "https://api.anthropic.com" | Audience(s) for the JWT SVID — must satisfy the federation rule's match |


Error Handling

All errors thrown by this SDK are instances of SpiffeError:

import { SpiffeError, SpiffeErrorCode } from "@defakto/spiffe";

try {
  const svid = await client.x509.getSVID();
} catch (err) {
  if (err instanceof SpiffeError) {
    console.error(err.code, err.message, err.cause);
  }
}

Error codes

| Code | Description | | ---------------------------- | ----------------------------------------------------------- | | INVALID_SPIFFE_ID | Malformed SPIFFE ID string | | INVALID_TRUST_DOMAIN | Malformed trust domain | | BUNDLE_NOT_FOUND | No bundle for the requested trust domain | | SVID_EXPIRED | The SVID has expired | | SVID_INVALID | The SVID is structurally invalid | | SVID_AUDIENCE_MISMATCH | JWT audience does not match | | WORKLOAD_API_UNAVAILABLE | Cannot reach the Workload API endpoint | | WORKLOAD_API_ERROR | Workload API returned an unexpected error | | JWT_PARSE_ERROR | Failed to parse a JWT | | JWT_SIGNATURE_INVALID | JWT signature verification failed | | NO_ATTESTORS_CONFIGURED | AttestingWorkloadAPIClient requires at least one attestor | | ATTESTOR_COLLECTION_FAILED | An attestor failed to collect evidence | | ATTESTATION_FAILED | The endpoint rejected the attestation |


API Reference

Main export (@defakto/spiffe)

| Export | Kind | Description | | ---------------------------- | --------- | ---------------------------------------------------------- | | WorkloadAPIClient | class | Smart wrapper — auto-selects local or attesting client | | LocalWorkloadAPIClient | class | Standard SPIFFE Workload API client (gRPC to local agent) | | AttestingWorkloadAPIClient | class | Defakto attesting client for serverless environments | | AwsTokenAttestor | class | Built-in AWS IAM attestor (uses STS GetWebIdentityToken) | | AzureMSIAttestor | class | Built-in Azure Managed Identity attestor | | GcpIITAttestor | class | Built-in GCP Instance Identity Token attestor | | GithubAttestor | class | Built-in GitHub Actions OIDC attestor | | SpiffeError | class | Error type thrown by the SDK | | SpiffeErrorCode | enum | All possible error codes | | Attestor | interface | Implement to create a custom attestor | | AttestationEvidence | interface | Evidence payload returned by an attestor | | ClientOptions | type | Transport options for LocalWorkloadAPIClient | | AttestingClientOptions | type | Options for AttestingWorkloadAPIClient | | AwsTokenAttestorOptions | type | Options for AwsTokenAttestor | | AzureMSIAttestorOptions | type | Options for AzureMSIAttestor | | GcpIITAttestorOptions | type | Options for GcpIITAttestor | | GithubAttestorOptions | type | Options for GithubAttestor | | GithubIdTokenFetcher | type | Token fetcher signature for GithubAttestor | | X509Context | interface | Snapshot of all X.509 SVIDs and bundles | | X509SVID | interface | An X.509 SVID with certificate chain and private key | | JwtSVID | interface | A JWT SVID |

AWS sub-path (@defakto/spiffe/aws)

| Export | Kind | Description | | ------------------- | -------- | --------------------------------------------------------------------- | | fromSpiffe | function | AWS credential provider using a SPIFFE JWT SVID as web identity token | | FromSpiffeOptions | type | Options for fromSpiffe |

Azure sub-path (@defakto/spiffe/azure)

| Export | Kind | Description | | ------------------------- | ----- | ---------------------------------------------------------------------------------- | | SPIFFECredential | class | Azure TokenCredential backed by a SPIFFE JWT SVID (workload identity federation) | | SPIFFECredentialOptions | type | Options for SPIFFECredential |

GCP sub-path (@defakto/spiffe/gcp)

| Export | Kind | Description | | --------------------------------- | ----- | ------------------------------------------------------------------------ | | SPIFFEIdentityPoolClient | class | GCP auth client using a SPIFFE JWT SVID for Workload Identity Federation | | SPIFFEIdentityPoolClientOptions | type | Options for SPIFFEIdentityPoolClient |

Anthropic sub-path (@defakto/spiffe/anthropic)

| Export | Kind | Description | | -------------------------------- | -------- | --------------------------------------------------------------------------------- | | identityTokenFromSpiffe | function | Anthropic IdentityTokenProvider backed by a SPIFFE JWT SVID (OIDC WIF exchange) | | IdentityTokenFromSpiffeOptions | type | Options for identityTokenFromSpiffe |