Authorization
pluv.io uses JWTs to authorize access to rooms on a new connection. To generate a JWT, you will need to setup an authentication endpoint to determine if the user should have access to the room.
The examples below will use express, but so long as you can create an http endpoint that can return text responses, these should still be relevant.
Enable authorization on io
Set the authorize
property on your createIO
config to enable authorization on your io instance.
1// server/io.ts23import { createIO } from "@pluv/io";4import { platformNode } from "@pluv/platform-node";5import { z } from "zod";67export const io = createIO({8 authorize: {9 // If required is false, users can authenticate for a room to10 // attach an identity to their presence. Otherwise they will be11 // anonymous.12 required: true,13 // The secret for generating your JWT14 secret: process.env.PLUV_AUTH_SECRET!,15 // The shape of your user object. `id` must always be required.16 user: z.object({17 id: z.string(),18 // Here is an additional field we wish to add.19 name: z.string(),20 }),21 },22 platform: platformNode(),23});2425export type AppPluvIO = typeof io;
Setup an authorization endpoint
To add custom authorization, you'll need to define an http endpoint to return a JWT from.
1// server/server.ts23import express from "express";4import Http from "http";5import { io } from "./io";67const PORT = 3000;89const app = express();10const server = Http.createServer();1112app.get("/api/authorize", async (req, res) => {13 const room = req.query.room as string;1415 // ... Implement your custom authorization here1617 const token = await io.createToken({18 room,19 user: {20 id: "abc123",21 name: "leedavidcs",22 },23 });2425 return res.send(token).status(200);26});2728server.listen(PORT, () => {29 console.log(`Server is listening on port: ${port}`);30});
Connect to your authorization endpoint
Now that we have our endpoint defined, connect our frontend client to our authorization endpoint.
1// frontend/io.ts23import { createClient } from "@pluv/react";4import type { AppPluvIO } from "server/io";56const client = createClient<AppPluvIO>({7 // Specify your auth endpoint here8 // Set to `true` if you have authorization on your io instance, and you9 // want to use the default of (room) => `/api/pluv/authorize?room=${room}`10 // This is the default from `createPluvHandler`11 authEndpoint: (room) => `http://localhost:3000/api/authorize?room=${room}`,12 // ...13});
How to use POST requests
1// frontend/io.ts23import { createClient } from "@pluv/react";4import type { AppPluvIO } from "server/io";56const client = createClient<AppPluvIO>({7 authEndpoint: (room) => ({8 url: "http://localhost:3000/api/authorize",9 // You can use fetch options as well like so10 options: {11 method: "POST",12 body: JSON.stringify({ room }),13 },14 }),15 // ...16});
Add token to room registration
When the frontend receives a JWT from your authorization endpoint, it will add that token as a token
query parameter to your websocket connection request. To use this token, pass the token into io.room.register
on your server.
1import express from "express";2import Http from "http";3import WebSocket from "ws";4import { io } from "./io";56const PORT = 3000;78const app = express();9const server = Http.createServer();10const wsServer = new WebSocket.Server({ server });1112const parseRoomId = (url: string): string => {13 /* get room from req.url */14};1516const parseToken = (url: string): string => {17 /* get token from query parameters of req.url */18};1920wsServer.on("connection", async (ws, req) => {21 const roomId = parseRoomId(req.url);22 const token = parseToken(req.url);2324 // Pass in the token from query params25 await room.register(ws, { token });26});2728app.get("/api/authorize", async (req, res) => {29 const room = req.query.room as string;3031 // ... Implement your custom authorization here3233 const token = await io.createToken({34 room,35 user: {36 id: "abc123",37 name: "leedavidcs",38 },39 });4041 return res.send(token).status(200);42});4344server.listen(PORT, () => {45 console.log(`Server is listening on port: ${port}`);46});