Skip to content

Authentication strategies

Every request your server forwards to Nebulas needs credentials. Which ones depends on who is using your site.

Your situation Strategy Browser needs a token?
Public website, marketing page, anonymous visitors Service account (recommended) or service auth (ROP / client credentials) No
Users already sign in with Auth0 on your site Session No (cookies)
Users sign in with Entra ID and calls should carry their identity Session with Entra On-Behalf-Of No (cookies)
Quick internal tool where people type a login Browser ROP (example) Yes

For a chatbot or a contact form on a public website, pick a service strategy. Your server calls Nebulas as itself, and visitors don’t have to sign in.

No identity provider is involved. Your server signs its own short-lived JWT (RS256, 5-minute TTL) with a private key. Nebulas verifies it with the public key registered on a service account.

src/lib/nebulas.ts
import { configureNebulasServer } from "@gnomondigital/nebulas-kit-core";
configureNebulasServer({
a2aUrl: process.env.A2A_URL,
nebulasApiUrl: process.env.NEBULAS_API_URL,
nebulasApiKey: process.env.NEBULAS_API_KEY,
nebulasProjectId: process.env.NEBULAS_PROJECT_ID,
nebulasAuthStrategy: "service_account",
serviceAccount: {
serviceAccountId: process.env.SERVICE_ACCOUNT_ID ?? "",
keyId: process.env.SERVICE_ACCOUNT_KEY_ID ?? "",
// One of the two:
privateKeyPem: process.env.SERVICE_ACCOUNT_PRIVATE_KEY,
privateKeyPath: process.env.SERVICE_ACCOUNT_PRIVATE_KEY_PATH,
},
});

Setup: create the service account in Admin, give it a role in your organization, and register its public key. Nebulas takes the org from that role. See Service accounts for the steps.

privateKeyPem accepts \n escapes, so the key can sit on a single line in your .env.

With a service strategy, use the WithServiceAuth variants on Next.js. They use whatever nebulasAuthStrategy you configured, and default to Auth0 ROP (authProvider: "auth0") or Entra client credentials (authProvider: "entra").

Route Next.js handler Express
POST /api/a2a createA2AProxyHandlerWithServiceAuth() createA2AExpressRouter(express, { strategy })
GET /api/a2a/config handleA2AConfigNextJsGET(req, { getHeaders: createGetHeadersWithServiceAuth() }) (included in the router)
/api/nebulas-surfaces/* createSurfaceHandlerWithServiceAuth() createNebulasSurfaceRouter(express, { apiKey })

If service auth fails, the handler returns 401 with a hint that names the config block to check.