~3 min read
Verify sessions
After verification, Qyzar sets cookies on your domain. Before checkout, account changes, or similar actions, ask Qyzar if that session is still valid.
Cookies (set by the browser SDK)
When connect/verify succeeds, ConnectVerifier (inside Qyzar) calls setConnectSessionCookies on your origin:
qyzar_session_id— session id (Elasticsearch document id)qyzar_session_token— session JWT
Heartbeats via connect/reverify refresh the 15-minute cookie expiry. Read values on the client with getConnectSessionId() / getConnectSessionToken() from @tnuser/qyzar-client.
Browser — read session for your own API
"use client";
import {
getConnectSessionId,
getConnectSessionToken,
} from "@tnuser/qyzar-client";
async function callProtectedApi() {
const sessionId = getConnectSessionId();
const sessionToken = getConnectSessionToken();
if (!sessionId || !sessionToken) {
throw new Error("Not verified yet");
}
return fetch("/api/checkout", {
method: "POST",
credentials: "include", // sends qyzar_session_* cookies
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ sessionId, sessionToken }), // optional if route uses Cookie header
});
}Next.js App Router example
lib/qyzar.ts — one shared server client
import { QyzarServer } from "@tnuser/qyzar-server";
export const qyzar = new QyzarServer({
apiBaseUrl: process.env.QYZAR_API_URL!,
resolveProjectSecret: async () => process.env.QYZAR_PROJECT_SECRET!,
});app/api/checkout/route.ts — protect a route
import { cookies } from "next/headers";
import { NextResponse } from "next/server";
import { qyzar } from "@/lib/qyzar";
export async function POST() {
const projectId = process.env.NEXT_PUBLIC_QYZAR_PROJECT_ID!;
const cookieStore = await cookies();
const cookieHeader = cookieStore
.getAll()
.map((c) => `${c.name}=${c.value}`)
.join("; ");
const result = await qyzar.verifySessionFromCookies(projectId, cookieHeader);
if (!result.valid) {
return NextResponse.json({ error: "Please verify first" }, { status: 401 });
}
// Safe to run checkout logic — result.sessionId, result.deviceId available
return NextResponse.json({ ok: true });
}Express-style example
middleware on protected routes
app.post("/api/checkout", async (req, res) => {
const projectId = process.env.QYZAR_PROJECT_ID;
const cookieHeader = req.headers.cookie ?? "";
try {
const result = await qyzar.verifySessionFromCookies(projectId, cookieHeader);
if (!result.valid) {
return res.status(401).json({ error: result.error ?? "Invalid session" });
}
// proceed…
return res.json({ ok: true });
} catch (e) {
return res.status(500).json({ error: "Verification failed" });
}
});When you already have id + token
import { getConnectSessionId, getConnectSessionToken } from "@tnuser/qyzar-client";
// client
const sessionId = getConnectSessionId()!;
const sessionToken = getConnectSessionToken()!;
// server
const result = await qyzar.verifySession(projectId, {
sessionId,
sessionToken,
});
if (result.valid) {
console.log(result.deviceId, result.lastVerify);
}Raw HTTP
GET with Cookie header
const url = new URL("https://apisecure.qyzar.eu/projects/client/session-verify");
url.searchParams.set("projectId", projectId);
const res = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${projectSecret}`,
Accept: "application/json",
Cookie: req.headers.cookie,
},
});
const data = (await res.json()).data;
// data.valid === true → okClient token vs session
Client tokens let the SDK connect. Session verification is what your own API uses to trust the visitor. See client tokens for reminting a bound JWT after cookies exist.
