Skip to content

Authentication ​

A session belongs to one side: a trader token on a staff path answers auth.invalid_terminal.

Browser terminals ​

With auth: { type: "session" } the sign-in sets HttpOnly cookies the code never sees. The SDK keeps the csrf_token from the answer and sends it as X-CSRF-Token on every POST, PUT, PATCH and DELETE. After a page reload it reads the hst_admin_csrf / hst_trader_csrf cookie, or the token from auth.me().

ts
const staff = new Staff({ baseUrl: "", auth: { type: "session" } })
await staff.auth.login({ login: 1000, password, terminal: "admin" })   // or "manager"

const trader = new Trader({ baseUrl: "", auth: { type: "session" } })
await trader.auth.login({ login: 1001, password, terminal: "web" })

Serve the web app from an allowed origin (API_ALLOWED_ORIGINS) or from the gateway's host: the cookies are SameSite=Strict.

Apps and API clients ​

With auth: { type: "jwt" } the SDK stores access_token and refresh_token and sends Authorization: Bearer …. Memory is the default store; give it your own (secure storage, a file, localStorage):

ts
const trader = new Trader({
  baseUrl: "https://api.example.com",
  auth: {
    type: "jwt",
    storage: {
      get: (k) => localStorage.getItem(k),
      set: (k, v) => (v === null ? localStorage.removeItem(k) : localStorage.setItem(k, v)),
    },
  },
  deviceId: "install-7f3c",
})
await trader.auth.login({ login: 1001, password, terminal: "api" })

Staying signed in ​

The access token lives 15 minutes by default. When a call answers auth.session_expired, the SDK calls auth/refresh once (other calls wait for it) and repeats the call. If the refresh fails, the tokens are cleared and onSessionEnd runs:

ts
new Staff({ baseUrl: "", auth: { type: "session" }, onSessionEnd: () => router.push("/login") })

One-time codes ​

ts
import { NoviqaError } from "@hybrid-solutions-09/noviqa-sdk"

try {
  await staff.auth.login({ login, password, terminal: "admin" })
} catch (e) {
  if (e instanceof NoviqaError && e.code === "auth.otp_required") {
    const otp = await askForCode()
    await staff.auth.login({ login, password, terminal: "admin", otp })
  } else throw e
}

Restricted sessions ​

Check the session after sign-in:

ts
const me = await staff.auth.me()
if (me.must_change_password) {
  await staff.auth.changePassword({ current_password, new_password })  // every session ends: sign in again
}
if (me.must_enrol_otp) {
  const { uri } = await staff.auth.otpEnrol()     // show uri as a QR code
  await staff.auth.otpConfirm({ code })           // the session becomes full
}

Until then every other call answers auth.password_change_required or auth.otp_enrol_required, and the live socket refuses the session.

Sign out ​

auth.logout() ends the session and the SDK forgets its tokens.