# Socket Client Setup & Authentication

### Authentication Mechanism

* For the socket connection to be authenticated, the JWT token must be passed in the `auth` object during the initial handshake.
* The backend verifies this token and attaches the user object to the socket session (`socket.user`).

### Installation

```bash
npm install socket.io-client
# or
yarn add socket.io-client
```

### Initialization Code

To authenticate, you must pass the token in the `auth` field of the configuration object.

#### Basic Setup

```javascript
import { io } from "socket.io-client";

// URL of your backend
const SOCKET_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:4000";

// Retrieve the token from wherever you stored it (e.g., localStorage)
const token = localStorage.getItem("jwt_token");

export const socket = io(SOCKET_URL, {
    path: "/socket.io",
    // need polling as transports for authentication to work
    // connection first polls and later moves to websocket connection
    transports: ["websocket", "polling"],
    auth: {
        token: token, // Sent during the handshake for authentication
    },
    autoConnect: true,
});

socket.on("connect", () => {
    console.log("Connected with ID:", socket.id);
});

socket.on("connect_error", err => {
    console.error("Connection failed:", err.message);
    // If error is 'Unauthorized', handle re-login
});
```

#### React Hook / Context Pattern

In a React or Next.js application, you can update the `auth` token dynamically if the user logs in after the initial connection.

```javascript
// lib/socket.js
import { io } from "socket.io-client";

const SOCKET_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:4000";

export const socket = io(SOCKET_URL, {
    path: "/socket.io",
    transports: ["websocket"],
    autoConnect: false, // We control when to connect
});
```

```javascript
// Updating auth token and connecting
export const connectSocket = (token) => {
    socket.auth = { token };
    socket.connect();
};
```

```javascript
// hooks/useSocket.js
import { useEffect, useState } from "react";
import { socket } from "../lib/socket";

export const useSocket = () => {
    const [isConnected, setIsConnected] = useState(socket.connected);

    useEffect(() => {
        function onConnect() {
            setIsConnected(true);
            console.log("Socket connected");
        }

        function onDisconnect() {
            setIsConnected(false);
            console.log("Socket disconnected");
        }

        socket.on("connect", onConnect);
        socket.on("disconnect", onDisconnect);

        // Retrieve token and connect if available
        const token = localStorage.getItem("jwt_token");
        if (token && !socket.connected) {
            socket.auth = { token };
            socket.connect();
        }

        return () => {
            socket.off("connect", onConnect);
            socket.off("disconnect", onDisconnect);
        };
    }, []);

    return { socket, isConnected };
};
```
