Skip to content

Integration

OIDC Integration

Connect Lamba as an OpenID Connect provider with discovery, App Client credentials, Authorization Code + PKCE, token validation, JWKS caching, and Customer API session exchange.

Choose this when

Use this path when your product or identity middleware needs a standards-based OpenID Connect integration with Lamba.

Use OIDC if you are configuring:

  • a web app with Authorization Code + PKCE
  • a backend callback that exchanges authorization codes
  • an identity middleware that reads discovery metadata
  • token validation and JWKS caching
  • branded issuer domains later

Before you start

Create an App Client for the Project and environment you are integrating. Public clients must use PKCE. Confidential clients can exchange tokens server-side with a client secret.

Public hosts:

EnvironmentIssuer / auth hostCustomer API host
Sandboxhttps://test.id.uselamba.comhttps://test.api.uselamba.com
Productionhttps://id.uselamba.comhttps://api.uselamba.com

Get credentials from Console

Credentials and configuration values
ValueConsole sourceEnv varUsed for
IssuerEnvironment badge plus auth hostLAMBA_OIDC_ISSUERDiscovery, token validation, and redirect construction
Client IDIntegration > App Clients > Client IDLAMBA_CLIENT_IDOIDC audience and OAuth client identifier
Client secretSecretIntegration > App Clients > Create or Rotate secretLAMBA_CLIENT_SECRETConfidential server-side token exchange only
Redirect URIIntegration > App Clients > Edit > Redirect URIsLAMBA_REDIRECT_URIExact callback URL registered for the client
Workspace and Project IDsTop Workspace / Project selectorLAMBA_WORKSPACE_ID and LAMBA_PROJECT_IDCustomer API session exchange after OIDC login

Configure environment variables

LAMBA_OIDC_ISSUER=https://test.id.uselamba.com
LAMBA_CUSTOMER_API_BASE=https://test.api.uselamba.com
LAMBA_CLIENT_ID=<app-client-id>
LAMBA_CLIENT_SECRET=<confidential-client-secret-if-used>
LAMBA_REDIRECT_URI=http://localhost:3000/auth/callback
LAMBA_WORKSPACE_ID=<workspace-id>
LAMBA_PROJECT_ID=<project-id>
LAMBA_ENV=test

Make the first request

Start with discovery. Your OIDC library should read this document and use its endpoint values instead of hardcoding token and JWKS URLs.

GEThttps://test.id.uselamba.com/.well-known/openid-configuration
Auth
None
Used for
Finds issuer, authorize, token, userinfo, and JWKS endpoints
curl -s https://test.id.uselamba.com/.well-known/openid-configuration

The public token endpoint is /connect/token, and public JWKS is exposed at /.well-known/jwks.json through the discovery document.

Then send users through Authorization Code + PKCE.

GET https://test.id.uselamba.com/connect/authorize
  ?response_type=code
  &client_id=<app-client-id>
  &redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Fcallback
  &scope=openid%20profile%20email
  &code_challenge=<base64url-sha256>
  &code_challenge_method=S256
  &state=<opaque-state>
  &nonce=<opaque-nonce>

Exchange the code:

await fetch(`${process.env.LAMBA_OIDC_ISSUER}/connect/token`, {
  method: 'POST',
  headers: { 'content-type': 'application/x-www-form-urlencoded' },
  body: new URLSearchParams({
    grant_type: 'authorization_code',
    client_id: process.env.LAMBA_CLIENT_ID!,
    code,
    redirect_uri: process.env.LAMBA_REDIRECT_URI!,
    code_verifier,
  }),
});

Request fields

Discovery has no request body. Authorization and token exchange use these fields:

Request and response fields
FieldTypeRequiredMeaningNotes
client_idstringRequiredApp Client ID from the selected Project.-
redirect_uriURIRequiredCallback URL registered on the App Client.No wildcards. Must match exactly.
scopespace-separated stringRequiredOIDC claims and access requested by the app.Start with `openid profile email`.
statestringRequiredCSRF protection value bound to the local browser session.-
noncestringRequiredReplay protection value validated against the ID token.-
code_verifierstringRequiredOriginal PKCE verifier sent only to `/connect/token`.Do not send this in the authorize URL.
client_secretstringConditionalConfidential client secret for server-side exchange.Never ship to browser or mobile public clients.

Response fields

Discovery response fields:

Request and response fields
FieldTypeRequiredMeaningNotes
issuerURIRequiredExpected issuer for tokens from this environment or branded auth domain.-
authorization_endpointURIRequiredWhere browser login starts.-
token_endpointURIRequiredWhere authorization codes and refresh tokens are exchanged.-
userinfo_endpointURIRequiredOIDC user info endpoint when used by your middleware.-
jwks_uriURIRequiredPublic signing keys for token validation.Cache by `kid` and refresh on unknown key once.

Token response fields:

Request and response fields
FieldTypeRequiredMeaningNotes
access_tokenstringRequiredBearer token returned by the auth host.-
id_tokenJWTConditionalOIDC identity token containing claims for the login.-
refresh_tokenstringConditionalCredential for rotating the session when issued.-
expires_innumberRequiredAccess token lifetime in seconds.-
token_typestringRequiredBearer token type.-

Validate tokens

Validate:

  • iss equals the discovery issuer exactly
  • aud contains your Client ID
  • exp and nbf are valid with bounded clock skew
  • nonce matches the original browser auth request
  • JWT signature validates against the discovery jwks_uri

For branded auth domains, the expected issuer is the branded host returned by discovery, not id.uselamba.com.

Enter Customer API context

OIDC signs the user in on the auth host. The Customer API should receive a scoped customer session token after context switch.

curl -X POST "$LAMBA_OIDC_ISSUER/v1/sessions/switch-context" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "workspaceId": "<workspace-id>",
    "projectId": "<project-id>",
    "environment": "test"
  }'

Then call:

curl "$LAMBA_CUSTOMER_API_BASE/v1/me/context" \
  -H "Authorization: Bearer $CUSTOMER_SESSION_TOKEN"

Done when

Done when

  • Discovery returns endpoints from the same issuer your app uses.
  • Authorize requests include state, nonce, and PKCE.
  • Token exchange succeeds with the matching redirect URI and verifier.
  • Your app validates issuer, audience, expiry, nonce, and signature.
  • Customer API calls use a scoped session returned by switch-context.

Troubleshooting

ErrorMeaningAction
invalid_grantCode/verifier invalid, expired, or reusedRestart login and create a new verifier
redirect_uri_mismatchRedirect URI mismatchFix Integration > App Clients > Edit > Redirect URIs
invalid_clientClient auth failedConfirm Project/environment and rotate secret if needed
Signature validation failureToken signature invalidRefresh JWKS once, then fail closed
Unknown kidSigning key was rotated or cache is staleRefresh jwks_uri and retry validation once
  • Hosted Auth Integration: /docs/quickstart/hosted-auth
  • OAuth/OIDC Security: /docs/reference/oauth-oidc-security
  • Auth and Session Contracts: /docs/reference/auth-session-contracts
  • Customer API request and response contract: /docs/quickstart/customer-api