Basic Auth based Connection
This guide explains how to connect to a WebSocket server (wss://itsochvts.com/api/socket) that requires Basic Authentication and a session token. It includes handling reconnection, parsing messages, and cleanly closing the connection.
Steps to Follow
- Generate Session Token using basic auth
- Use Session token to initialize socket
- Handle socket connection
1. Generate a Session Token
- Uses Basic Auth to request a session token.
- Sends a POST request with an expiration query param.
- Returns the raw token string.
const generateToken = async () => {
const response = await fetch(`https://itsochvts.com/api/session/token`, {
method: "POST",
headers: {
Authorization: `Basic ${Buffer.from(
`${authorization.user}:${authorization.password}`
).toString("base64")}`,
},
body: new URLSearchParams({ expiration: "2026-10-10T09:04:51Z" }),
});
const responseText = await response.text();
return responseText;
};
2. Initialize Connection
- Generates token and session token.
- Starts WebSocket connection using the session token.
async function initSocket() {
console.log("[WS] Connecting to WebSocket...");
const token = await generateToken(); // Step 1
if (!token) {
process.exit(1);
}
console.log("[WS] Start Connection...");
connectWebSocket(token); // Step 3
}
3. Handling Socket connection
- Connects to the WebSocket using the session token.
- Handles open, message, close, and error events.
- Parses device, position, and event data from incoming messages.
function connectWebSocket(token: string): void {
socket = new WebSocket(`wss://itsochvts.com/api/socket?token=${token}`);
socket.on("open", () => {
console.log("[WS] Connected");
reconnectAttempts = 0;
socket?.send(JSON.stringify({ logs: includeLogs }));
});
socket.on("message", (data: WebSocket.Data) => {
try {
const parsed: ParsedMessage = JSON.parse(data.toString());
if (parsed.type === "pong") return;
if (parsed.devices) console.log("[WS] Devices:", parsed.devices);
if (parsed.positions) console.log("[WS] Positions:", parsed.positions);
if (parsed.events && !features.disableEvents) {
console.log("[WS] Events:", parsed.events);
}
} catch (err) {
console.error("[WS] Parse Error:", err);
}
});
socket.on("close", (code: number) => {
console.warn("[WS] Closed:", code);
socket = null;
if (code !== 4000) {
scheduleReconnect();
}
});
socket.on("error", (err: Error) => {
console.error("[WS] Error:", err);
if (socket?.readyState !== WebSocket.CLOSED) {
socket?.close();
}
});
}
Reconnecting
- Implements exponential backoff for reconnection attempts.
- Prevents infinite retries beyond the maximum allowed attempts.
function scheduleReconnect(): void {
if (reconnectAttempts >= maxReconnectAttempts) return;
const delay: number = Math.min(30000, 1000 * 2 ** reconnectAttempts);
console.log(`[WS] Reconnecting in ${delay / 1000}s...`);
setTimeout(() => {
reconnectAttempts++;
if (isSocketDisconnected()) {
initSocket();
}
}, delay);
}
function isSocketDisconnected(): boolean {
return !socket || socket.readyState === WebSocket.CLOSED;
}
Stop Connection
- Closes the connection after 15 seconds using custom code 4000.
- Simulates a logout for demo/testing purposes.
function logout(): void {
if (
socket?.readyState === WebSocket.OPEN ||
socket?.readyState === WebSocket.CONNECTING
) {
socket.close(4000);
}
}
//stop connection after 15 sec
setTimeout(() => {
logout();
console.log("[WS] Logged out");
}, 15000);
Full code
Using Nodejs and Typescript
import dotenv from "dotenv";
import WebSocket from "ws";
dotenv.config();
interface Features {
disableEvents: boolean;
}
interface ParsedMessage {
type?: string;
devices?: any[];
positions?: any[];
events?: any[];
}
const authorization = {
user: process.env.USER || "demo@trackon-gps.com",
password: process.env.PASSWORD || "demo123",
};
let socket: WebSocket | null = null;
let includeLogs: boolean = true;
let features: Features = { disableEvents: false };
let reconnectAttempts: number = 0;
const maxReconnectAttempts: number = 10;
//Step 1: Generate a session token using the API
const generateToken = async () => {
const response = await fetch(`https://itsochvts.com/api/session/token`, {
method: "POST",
headers: {
Authorization: `Basic ${Buffer.from(
`${authorization.user}:${authorization.password}`
).toString("base64")}`,
},
body: new URLSearchParams({ expiration: "2026-10-10T09:04:51Z" }),
});
const responseText = await response.text();
return responseText;
};
//Step 2: Initialize the WebSocket connection using the token
async function initSocket() {
console.log("[WS] Connecting to WebSocket...");
const token = await generateToken(); //get token
if (!token) {
process.exit(1);
}
console.log("[WS] Session token Generated");
connectWebSocket(token as string);
}
//Step 3: Connect to WebSocket using the session token
function connectWebSocket(token: string): void {
socket = new WebSocket(`wss://itsochvts.com/api/socket?token=${token}`);
socket.on("open", () => {
console.log("[WS] Connected");
reconnectAttempts = 0;
if (includeLogs) {
socket?.send(JSON.stringify({ logs: includeLogs }));
}
});
socket.on("message", (data: WebSocket.Data) => {
try {
const parsed: ParsedMessage = JSON.parse(data.toString());
if (parsed.type === "pong") return;
if (parsed.devices) {
//handle devices
console.log("[WS] Devices:", parsed.devices);
}
if (parsed.positions) {
//handle positions
console.log("[WS] Positions:", parsed.positions);
}
if (parsed.events && !features.disableEvents) {
//handle events
console.log("[WS] Events:", parsed.events);
}
} catch (err) {
console.error("[WS] Parse Error:", err);
}
});
socket.on("close", (code: number) => {
console.warn("[WS] Closed:", code);
socket = null;
if (code !== 4000) {
scheduleReconnect();
}
});
socket.on("error", (err: Error) => {
console.error("[WS] Error:", err);
if (socket?.readyState !== WebSocket.CLOSED) {
socket?.close();
}
});
}
function isSocketDisconnected(): boolean {
return !socket || socket.readyState === WebSocket.CLOSED;
}
// Reconnecting to socket on failure with exponential backoff
function scheduleReconnect(): void {
if (reconnectAttempts >= maxReconnectAttempts) return;
const delay: number = Math.min(30000, 1000 * 2 ** reconnectAttempts);
console.log(`[WS] Reconnecting in ${delay / 1000}s...`);
setTimeout(() => {
reconnectAttempts++;
if (isSocketDisconnected()) {
initSocket();
}
}, delay);
}
// Simulate logout after 15 seconds
function logout(): void {
if (
socket?.readyState === WebSocket.OPEN ||
socket?.readyState === WebSocket.CONNECTING
) {
socket.close(4000);
}
}
setTimeout(() => {
logout();
console.log("[WS] Logged out");
}, 15000);
//run the socket connection
initSocket();