Appearance
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.