Skip to main content

Auth Helpers

Auth helpers provide pluggable authentication strategies for outbound HTTP requests. They are used by createRemoteTokenIssuer and any other component that needs to authenticate with an external service. All strategies implement the AuthHeaderProvider type:
type AuthHeaderProvider = () => Promise<Record<string, string>>;
A provider returns a dictionary of HTTP headers to attach to outbound requests. The returned object may be empty (for noAuth) or contain one or more headers such as Authorization.

Strategy Comparison

StrategyUse CaseHeaders Returned
noAuth()Local development, trusted networks, public endpointsNone
sharedSecretAuth(name, secret)Internal services with a static API key{ [name]: secret }
signedJwtAuth(issuer, audience)Service-to-service with RS256/HS256 JWT{ Authorization: "Bearer <jwt>" }
oauthClientCredentialsAuth(config)OAuth 2.0 providers (Auth0, Okta, etc.){ Authorization: "Bearer <token>" }

noAuth

Returns empty headers. Use for local development, trusted networks, or public endpoints that do not require authentication.
import { noAuth } from "@key0ai/key0";

const auth = noAuth();
const headers = await auth(); // {}
Signature:
function noAuth(): AuthHeaderProvider;

sharedSecretAuth

Returns a static header with a secret value. Use when both services share a pre-configured API key or internal secret.
import { sharedSecretAuth } from "@key0ai/key0";

const auth = sharedSecretAuth("X-Internal-Auth", process.env.INTERNAL_SECRET);
const headers = await auth(); // { "X-Internal-Auth": "s3cr3t..." }
Signature:
function sharedSecretAuth(headerName: string, secret: string): AuthHeaderProvider;
ParameterTypeDescription
headerNamestringThe HTTP header name to set (e.g. "X-Internal-Auth", "X-API-Key").
secretstringThe secret value to send in the header.

signedJwtAuth

Signs a short-lived JWT using the SDK’s AccessTokenIssuer. Use when the backend validates JWTs signed by your Key0 instance (particularly useful with RS256 key pairs).
import { signedJwtAuth } from "@key0ai/key0";
import { AccessTokenIssuer } from "@key0ai/key0";

const issuer = new AccessTokenIssuer({
  privateKey: process.env.KEY0_PRIVATE_KEY,
  algorithm: "RS256",
});

const auth = signedJwtAuth(issuer, "backend-service", 120);
const headers = await auth(); // { Authorization: "Bearer eyJhbGci..." }
Signature:
function signedJwtAuth(
  issuer: AccessTokenIssuer,
  audience: string,
  ttlSeconds?: number,
): AuthHeaderProvider;
ParameterTypeDefaultDescription
issuerAccessTokenIssuerThe token issuer instance used to sign the JWT.
audiencestringMapped to the resourceId claim in the signed JWT.
ttlSecondsnumber60Token lifetime in seconds. Keep short for service-to-service calls.
The generated JWT includes the following claims:
ClaimValue
sub"key0-service"
jtiRandom UUID
resourceIdThe audience parameter
planId"system"
txHash"system-auth"

oauthClientCredentialsAuth

Fetches an access token from an OAuth 2.0 provider using the Client Credentials grant. Caches the token in memory and automatically re-fetches when it expires (with a 10-second buffer).
import { oauthClientCredentialsAuth } from "@key0ai/key0";

const auth = oauthClientCredentialsAuth({
  tokenUrl: "https://auth.example.com/oauth/token",
  clientId: process.env.CLIENT_ID,
  clientSecret: process.env.CLIENT_SECRET,
  scopes: ["api:access"],
  audience: "https://api.example.com",
});

const headers = await auth(); // { Authorization: "Bearer eyJhbGci..." }
Signature:
function oauthClientCredentialsAuth(config: {
  tokenUrl: string;
  clientId: string;
  clientSecret: string;
  scopes?: string[];
  audience?: string;
}): AuthHeaderProvider;
ParameterTypeRequiredDescription
tokenUrlstringYesThe OAuth token endpoint URL.
clientIdstringYesOAuth client ID.
clientSecretstringYesOAuth client secret.
scopesstring[]NoOAuth scopes to request. Joined with spaces in the scope parameter.
audiencestringNoTarget audience (used by providers like Auth0).
Behavior details:
  • Sends a POST request with Content-Type: application/x-www-form-urlencoded.
  • Expects a JSON response with access_token (string) and expires_in (number, seconds).
  • Caches the token and re-fetches 10 seconds before expiry.
  • 10-second request timeout via AbortController.
  • Throws Key0Error with code INTERNAL_ERROR and HTTP 500 if the token request fails.

createRemoteTokenIssuer

Creates a fetchResourceCredentials callback that delegates token issuance to a remote HTTP endpoint. Use this when your backend (not Key0) is responsible for issuing API keys or custom tokens after payment.
import { createRemoteTokenIssuer } from "@key0ai/key0";
import { oauthClientCredentialsAuth } from "@key0ai/key0";

const issuer = createRemoteTokenIssuer({
  url: "https://api.myapp.com/internal/issue-token",
  timeoutMs: 5000,
  auth: oauthClientCredentialsAuth({
    tokenUrl: "https://auth.myapp.com/token",
    clientId: process.env.CLIENT_ID,
    clientSecret: process.env.CLIENT_SECRET,
  }),
});
Signature:
function createRemoteTokenIssuer(
  config: RemoteTokenIssuerConfig,
): (params: IssueTokenParams) => Promise<TokenIssuanceResult>;

RemoteTokenIssuerConfig

type RemoteTokenIssuerConfig = {
  url: string;
  timeoutMs?: number;
  auth?: AuthHeaderProvider;

  /** @deprecated Use `auth` instead */
  secret?: string;
  /** @deprecated Use `auth` instead */
  headerName?: string;
};
FieldTypeDefaultDescription
urlstringThe backend endpoint to POST to.
timeoutMsnumber10000Request timeout in milliseconds.
authAuthHeaderProviderAuthentication strategy for outbound requests.
secretstringDeprecated. Mapped to sharedSecretAuth(headerName, secret).
headerNamestring"X-Internal-Auth"Deprecated. Header name for the legacy secret option.
Request format: The callback sends a POST with Content-Type: application/json and the IssueTokenParams as the body. Expected response: A JSON object with token (string, required) and optionally tokenType (string, defaults to "Bearer"). Error handling:
ScenarioError CodeHTTP Status
Backend returns non-2xxTOKEN_ISSUE_FAILED502
Response missing token fieldTOKEN_ISSUE_FAILED502
Request times outTOKEN_ISSUE_TIMEOUT504
Network errorTOKEN_ISSUE_FAILED502