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
| Provider | Use it for | Where the token comes from |
|---|---|---|
StaticTokenAuth | Server code, scripts, scheduled jobs | A fixed API token or OAuth access token |
CallbackAuth | Tokens that expire and need a refresh, custom session stores | Your function, called before every request |
supabaseAuth | A browser app whose users sign in to the same Nodaro instance | The user's live session, refreshed automatically |
| Your own object | Anything else | Any object with a getToken() method |
Tokens you can use
| Token | Looks like | Who it acts as | Get it from |
|---|---|---|---|
| API token | ndr_ followed by 64 hex characters | You | Settings › API Tokens in Nodaro |
| OAuth access token | ndr_app_ followed by 64 hex characters | A user who approved your app | The OAuth code exchange, client.oauth.exchangeCode() |
| Session token | A signed-in session | The signed-in user | The 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
supabaseAuthorCallbackAuth.
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): AuthReads 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) })cookieDomainapplies only when the page's host is that domain or one of its subdomains. On any other host, such aslocalhostor 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-jsand@supabase/ssrto 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
supabaseAuthare 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
Related
Client
OAuth and developer apps
OAuth apps
Authentication
Errors
Last updated on
Client
Create a Nodaro SDK client with createClient, set its base URL, auth, timeout and workspace, and find every resource the client exposes.
Errors
Every error the Nodaro TypeScript SDK throws, with its HTTP status, code and fields, and what to do about credits, rate limits, conflicts and failed jobs.