Skip to content

Integration

Next.js Customer Auth Integration

Build embedded Lamba customer auth in Next.js with console credentials, HttpOnly cookies, request fields, response fields, and scoped Customer API reads.

Choose this when

Use this path when your Next.js App Router product owns the sign-in UI and wants Lamba to provide customer identity, scoped sessions, Project roles, and Customer API reads.

This guide uses the public customer hosts only:

  • https://test.id.uselamba.com or https://id.uselamba.com for auth and session operations
  • https://test.api.uselamba.com or https://api.uselamba.com for Customer API reads

Before you start

You need:

  • a Lamba Workspace
  • a Lamba Project
  • the selected environment, usually test while integrating
  • a Next.js App Router app
  • one server route for each auth action your UI exposes

Do not send console-only workspace, project, or environment headers from your product. Public customer requests are scoped by the bearer token and by POST /v1/sessions/switch-context.

Get credentials from Console

Open the Lamba console and use the top Workspace / Project selector first. Then open the selected Project and environment you are integrating.

Credentials and configuration values
ValueConsole sourceEnv varUsed for
Auth base URLChoose Sandbox or Production from the console environment badgeLAMBA_CUSTOMER_AUTH_BASE_URLCalls to `/v1/auth/*`, `/v1/sessions/switch-context`, and `/connect/*`
API base URLSame selected environment as the auth base URLLAMBA_CUSTOMER_API_BASE_URLCalls to `/v1/me/*` and `/v1/admin/*`
Workspace IDTop Workspace selectorLAMBA_CUSTOMER_WORKSPACE_IDOptional immediate switch into one Workspace after login
Project IDTop Project selectorLAMBA_CUSTOMER_PROJECT_IDOptional immediate switch into one Project after login
App Client IDIntegration > App ClientsLAMBA_CLIENT_IDOnly needed if this Next.js app also performs OIDC hosted auth

Configure environment variables

LAMBA_CUSTOMER_AUTH_BASE_URL=https://test.id.uselamba.com
LAMBA_CUSTOMER_API_BASE_URL=https://test.api.uselamba.com
LAMBA_CUSTOMER_WORKSPACE_ID=<workspace-id>
LAMBA_CUSTOMER_PROJECT_ID=<project-id>
LAMBA_CUSTOMER_ENV=test
LAMBA_SESSION_COOKIE=lamba_access_token
LAMBA_REFRESH_COOKIE=lamba_refresh_token

Use production hosts and production credentials only after the sandbox flow works end to end.

Make the first request

Start with password login if your Project has password auth enabled. Your browser posts to your own Next.js route. That route calls Lamba server-side and stores returned tokens in HttpOnly cookies.

POSThttps://test.id.uselamba.com/v1/auth/login/password
Auth
None for the initial login request
Used for
Turns customer credentials into Lamba customer session tokens
// src/lib/lamba-customer.ts
import "server-only";

export async function customerAuthFetch(path: string, init?: RequestInit) {
  return fetch(`${process.env.LAMBA_CUSTOMER_AUTH_BASE_URL}${path}`, {
    cache: "no-store",
    headers: { "content-type": "application/json", ...(init?.headers ?? {}) },
    ...init,
  });
}

export async function customerApiFetch(path: string, accessToken: string) {
  return fetch(`${process.env.LAMBA_CUSTOMER_API_BASE_URL}${path}`, {
    cache: "no-store",
    headers: { authorization: `Bearer ${accessToken}` },
  });
}
// src/app/api/auth/login/password/route.ts
import { cookies } from "next/headers";
import { NextResponse } from "next/server";
import { customerAuthFetch } from "@/lib/lamba-customer";

export async function POST(request: Request) {
  const payload = await request.json();
  const response = await customerAuthFetch("/v1/auth/login/password", {
    method: "POST",
    body: JSON.stringify(payload),
  });
  const body = await response.json();

  if (!response.ok) {
    return NextResponse.json(body, { status: response.status });
  }

  const cookieStore = await cookies();
  cookieStore.set("lamba_access_token", body.access_token, {
    httpOnly: true,
    secure: true,
    sameSite: "lax",
    path: "/",
  });
  cookieStore.set("lamba_refresh_token", body.refresh_token, {
    httpOnly: true,
    secure: true,
    sameSite: "lax",
    path: "/",
  });

  return NextResponse.json({ ok: true });
}

Request fields

For POST /v1/auth/login/password:

Request and response fields
FieldTypeRequiredMeaningNotes
loginstringRequiredEmail, username, or configured login identifier entered by the customer.Use `email` only if your UI intentionally accepts email-only login.
passwordstringRequiredThe customer password.Send only from your server route or trusted native client flow.
mfaCodestringConditionalOne-time code when the login response requires MFA.Submit after prompting for the configured factor.

For POST /v1/sessions/switch-context after login:

Request and response fields
FieldTypeRequiredMeaningNotes
workspaceIdstringRequiredThe Workspace selected in the Lamba console.Customer-facing copy should call this Workspace, not tenant.
projectIdstringRequiredThe Project that owns this product runtime.Use the selected Project from the console top selector.
environmenttest | prodRequiredThe environment whose auth, roles, domains, and webhooks should apply.Keep sandbox and production sessions separate.

Response fields

Login, refresh, and switch-context responses use the same token shape:

Request and response fields
FieldTypeRequiredMeaningNotes
access_tokenstringRequiredBearer token for the current customer session.Store in an HttpOnly cookie for browser apps.
refresh_tokenstringRequiredCredential used to rotate the customer session.Treat like a password. Do not expose it to client props or localStorage.
refresh_token_expires_atISO-8601 datetimeRequiredWhen the refresh token stops being valid.Restart login before or after this point instead of retrying forever.

GET /v1/me/context is the simplest Customer API proof:

Request and response fields
FieldTypeRequiredMeaningNotes
userobjectRequiredThe signed-in Lamba User profile visible to your product.Includes values such as `id`, `email`, `username`, and `displayName`.
activeWorkspaceobject | nullOptionalWorkspace context after switch-context.Null means the session has not entered a Workspace yet.
activeProjectobject | nullOptionalProject and environment context after switch-context.Use this to confirm your app is pinned to the expected Project.
roleKeysstring[]RequiredProject runtime roles attached to the active session.Use `/v1/me/authorization` for permission-level UI decisions.

Read protected pages

After setting cookies, call the Customer API from server components or route handlers.

// src/app/app/page.tsx
import { cookies } from "next/headers";
import { redirect } from "next/navigation";
import { customerApiFetch } from "@/lib/lamba-customer";

export default async function AppPage() {
  const cookieStore = await cookies();
  const token = cookieStore.get("lamba_access_token")?.value;

  if (!token) {
    redirect("/login");
  }

  const response = await customerApiFetch("/v1/me/context", token);
  if (!response.ok) {
    redirect("/login");
  }

  const context = await response.json();
  return <main>Signed in as {context.user.email}</main>;
}

Done when

Done when

  • A customer can register or log in from your Next.js UI.
  • Access and refresh tokens are stored only in HttpOnly cookies.
  • Optional switch-context returns a scoped session for the expected Workspace, Project, and environment.
  • `GET /v1/me/context` renders on a protected server page.
  • Logout clears your cookies and calls Lamba logout when a token exists.

Troubleshooting

SymptomLikely causeFix
Login succeeds but /v1/me/context is missing Project dataYou did not call POST /v1/sessions/switch-contextCall switch-context with Workspace, Project, and environment after login
401 from Customer APIAccess token is missing, expired, or revokedRefresh once, then restart login if refresh fails
403 from an admin routeThe user session lacks the required Project roleRead /v1/me/authorization and hide or block the action
Cookies exist but the browser still behaves as logged outCookies are not httpOnly, secure, sameSite=lax, or on the correct pathSet cookies from a server route and test over HTTPS outside localhost
Sandbox data appears in productionTest and production environment values were mixedUse separate env files and separate App Clients per environment
  • Hosted Auth Integration: /docs/quickstart/hosted-auth
  • OIDC Integration: /docs/quickstart/oidc
  • Customer API request and response contract: /docs/quickstart/customer-api
  • Error Reference: /docs/reference/errors