@sinequa/atomic

Bearer token

Authenticating with a configured access token — for a service, a script or a plugin — and why previews need a cookie anyway.

An access token configured on the server authorises a fixed set of API methods. Send it and every request is authenticated: no form, no redirect, no session to establish. This is the mode for a service, a scheduled job, a script, or a plugin.

the whole configuration
import { AuthMode } from "@sinequa/atomic";

client.configure({ authMode: AuthMode.bearer(token) });
await client.auth.login();

The token is sent as Authorization: Bearer on every request.

Browser or not: one decision

yes no — Node, a job, a service AuthMode.bearer(token) Is there a browserrendering documents? sessionCookie: true (default)also obtain a session cookie sessionCookie: falseskip the exchange iframes, thumbnails and downloadscannot send an Authorization header

Why a token-based sign-in still wants a cookie

The cookie is not for this library — which authenticates itself on every request. It is for the browser. An <iframe> showing a document preview, the stylesheet and images that preview references, an <img> thumbnail, a download link: none of them can carry an Authorization header. Measured against a live backend, they answer 200 with the cookie and 559 without — so a preview is blank however well your application is authenticated.

What login() does in this mode

Unlike every other mode, it does not look for an existing session first — the token is the credential:

  1. Unless sessionCookie: false, it posts security.webtoken to trade the token for a session cookie.
  2. If the server refuses that exchange, the sign-in continues — this is not fatal.
  3. It then validates the token against a protected endpoint and records the authenticated state explicitly. On this path there is no client token, so isAuthenticated() relies on a stored flag, exactly as token-less ambient SSO does.

A missing or refused token throws, with the reason. There is no fallback screen: a password form for an authentication that has no password is a dead end.

Two deployments

A browser application, and a headless job
src/service.ts
import { AuthMode, createAtomicClient } from "@sinequa/atomic";

/**
 * Headless: no browser, so the cookie exchange buys nothing. Skipping it removes a
 * round trip and an error log on every start-up.
 */
const client = createAtomicClient({
  app: "<your-app>",
  backendUrl: "https://<your-sinequa-server>",
  authMode: AuthMode.bearer(process.env.SINEQUA_TOKEN ?? "", { sessionCookie: false }),
});

await client.initializeConfig();

// Throws if the token is missing or refused — there is nothing to fall back to.
await client.auth.login();

const result = await client.api.query.search({
  name: "<your-query>",
  text: "quarterly report",
  pageSize: 100,
});

console.log(`${result.rowCount} documents`);

A token in front-end code is readable by anyone

Anything shipped to a browser — an environment variable inlined at build time included — is public. Use this mode in a browser only for a token whose rights you are willing to hand to every visitor. Otherwise keep the token server-side and put your own backend in front.

Getting previews to work

If document previews are blank while everything else succeeds, the cookie exchange was refused. The error looks like this, and it is explicit:

errorCode 6
The JSON method 'webtoken' is not allowed by the access token '…' as none of the JSON
method rules allow it.

An access token whitelists the JSON methods it may call, and webtoken — the login method an access token replaces — is often not among them. The fix is on the access token's own rules, not the web application's global list, which is what that message names.

The refusal is logged at debug and the fallback at info, so a supported configuration does not report an error on every boot.

Pitfalls

What's next

On this page