Nodaro Docs
DocumentationNode ReferenceModelsAI Agents (MCP)DevelopersSelf-hostingResearch
TypeScript SDK

Authentication

Choose how the Nodaro SDK authenticates, with StaticTokenAuth, CallbackAuth or supabaseAuth, and share one browser login across your subdomains.

An auth provider tells the Nodaro SDK which token to send. Before every request, the client calls the provider's getToken() and sends the result as Authorization: Bearer <token>. When the provider returns null, the request is sent without the header, as an anonymous request.

Choose a provider

ProviderUse it forWhere the token comes from
StaticTokenAuthServer code, scripts, scheduled jobsA fixed API token or OAuth access token
CallbackAuthTokens that expire and need a refresh, custom session storesYour function, called before every request
supabaseAuthA browser app whose users sign in to the same Nodaro instanceThe user's live session, refreshed automatically
Your own objectAnything elseAny object with a getToken() method

Tokens you can use

TokenLooks likeWho it acts asGet it from
API tokenndr_ followed by 64 hex charactersYouSettings › API Tokens in Nodaro
OAuth access tokenndr_app_ followed by 64 hex charactersA user who approved your appThe OAuth code exchange, client.oauth.exchangeCode()
Session tokenA signed-in sessionThe signed-in userThe Nodaro sign-in, through supabaseAuth
  • An API token is a permanent credential with no spending cap. It works until you deactivate or delete it, so keep it on a server. See API authentication for limits and rate settings.
  • An OAuth access token carries only the scopes the user approved. Use it when your app acts for other people. See OAuth.
  • On a self-hosted Community edition install, the app does not offer API tokens. Sign in and use your session token instead, with supabaseAuth or CallbackAuth.

The Auth interface

interface Auth {
  getToken(): Promise<string | null>
}

Any object with this shape can be the auth option of createClient. The three providers below implement it.

StaticTokenAuth

new StaticTokenAuth(token: string)

Wraps one fixed token. Use it when the token does not change while your process runs: an API token, or an OAuth access token your server obtained through the authorization-code flow.

Prop

Type

import { createClient, StaticTokenAuth } from "@nodaro/sdk"

const client = createClient({
  baseUrl: "https://app.nodaro.ai",
  auth: new StaticTokenAuth(process.env.NODARO_TOKEN!),
})

CallbackAuth

new CallbackAuth(fn: () => string | null | Promise<string | null>)

Calls your function before every request and sends the token it returns. The function can be synchronous or asynchronous. Return null to send the request without a token.

Prop

Type

Use it to refresh tokens, to read a custom session store, or to rotate credentials:

import { createClient, CallbackAuth } from "@nodaro/sdk"

const client = createClient({
  baseUrl: "https://app.nodaro.ai",
  auth: new CallbackAuth(async () => {
    const session = await sessionStore.read()
    if (!session) return null
    if (Date.now() > session.expiresAt - 60_000) {
      await refresh(session)
    }
    return session.accessToken
  }),
})

supabaseAuth(supabase)

supabaseAuth(supabase: SupabaseLikeClient): Auth

Reads the signed-in user's token from a Supabase v2 client before every request. Use it in a browser app whose users sign in to the same Nodaro instance, for example your own frontend for a self-hosted install. The Nodaro editor uses the same provider. Because the token is read live, a refreshed session is picked up automatically.

Prop

Type

import { createClient, supabaseAuth } from "@nodaro/sdk"
import { createClient as createSupabase } from "@supabase/supabase-js"

const supabase = createSupabase(
  import.meta.env.VITE_SUPABASE_URL,
  import.meta.env.VITE_SUPABASE_ANON_KEY,
)

const client = createClient({
  baseUrl: import.meta.env.VITE_API_URL ?? "",
  auth: supabaseAuth(supabase),
})

When nobody is signed in, the request is sent without a token.

createSharedSupabaseClient(options)

import { createSharedSupabaseClient } from "@nodaro/sdk/supabase"

createSharedSupabaseClient<Db = any>(options: {
  url: string
  anonKey: string
  cookieDomain?: string
}): SupabaseClient<Db>

Creates a browser Supabase client that keeps the session in cookies instead of local storage. With cookieDomain, several apps on sibling subdomains share one login: a user who signs in on one is signed in on all of them, and signing out anywhere signs out everywhere.

Prop

Type

import { createClient, supabaseAuth } from "@nodaro/sdk"
import { createSharedSupabaseClient } from "@nodaro/sdk/supabase"

const supabase = createSharedSupabaseClient({
  url: SUPABASE_URL,
  anonKey: SUPABASE_ANON_KEY,
  cookieDomain: ".example.com",
})

const client = createClient({ baseUrl: "", auth: supabaseAuth(supabase) })
  • cookieDomain applies only when the page's host is that domain or one of its subdomains. On any other host, such as localhost or a preview URL, cookies stay on the current host, so local development keeps a separate session per origin.
  • On the first load, an existing session in local storage moves into the cookie and the old entry is removed. A user who was already signed in stays signed in. Expired sessions are discarded.
  • This export lives at the separate path @nodaro/sdk/supabase, so the main package does not depend on Supabase. Install @supabase/supabase-js and @supabase/ssr to use it.

Scopes and missing permissions

An OAuth access token carries the scopes the user approved, such as workflows:read or workflows:execute. The reference page of each resource names the scope its methods need. When a token lacks one, the method throws a ForbiddenError whose missingScope names it:

import { ForbiddenError } from "@nodaro/sdk"

try {
  await client.workflows.run(workflowId)
} catch (err) {
  if (err instanceof ForbiddenError && err.missingScope) {
    requestConsentFor([err.missingScope]) // send the user through OAuth again
  } else {
    throw err
  }
}

API tokens and session tokens are not limited by scopes. See Errors for every error class.

Browser rules

  • Never ship an API token to a browser. Anyone can read it from the page, and it acts as you.
  • OAuth tokens in the browser work only from origins listed in your developer app's allowedOrigins. See OAuth and developer apps.
  • Session tokens from supabaseAuth are not checked against that list.
  • Keep secrets on the server. The OAuth code exchange needs your client secret, so run client.oauth.exchangeCode() only in server code.

Frequently asked questions

Last updated on

On this page