Auth
Connection auth - upgrade()
The upgrade function in src/hooks.ws.js runs on every new WebSocket connection. Return user data to attach to the connection, or false to reject it.
// src/hooks.ws.js
export function upgrade({ cookies }) {
const session = validateSession(cookies.session_id);
if (!session) return false;
return { id: session.userId, name: session.name };
} Whatever you return is available as ctx.user in all live() functions.
Per-module auth - guard()
Export a _guard from any src/live/ file. It runs before every function in that file.
// src/live/admin.js
import { live, guard, LiveError } from 'svelte-realtime/server';
export const _guard = guard((ctx) => {
if (ctx.user?.role !== 'admin')
throw new LiveError('FORBIDDEN', 'Admin only');
});
export const deleteUser = live(async (ctx, userId) => {
await db.users.delete(userId);
}); Both functions in this file require admin access.
Composable guards
Chain multiple guards. They run in order, and earlier ones can enrich ctx for later ones:
export const _guard = guard(
(ctx) => {
if (!ctx.user) throw new LiveError('UNAUTHORIZED');
},
(ctx) => {
ctx.permissions = lookupPermissions(ctx.user.id);
},
(ctx) => {
if (!ctx.permissions.includes('write'))
throw new LiveError('FORBIDDEN');
}
); Per-function auth
Check ctx.user inside any live() function:
export const deleteItem = live(async (ctx, id) => {
if (!ctx.user) throw new LiveError('UNAUTHORIZED');
if (ctx.user.role !== 'admin') throw new LiveError('FORBIDDEN');
await db.items.delete(id);
}); Stream access control
Use the access option on streams to filter events per connection:
export const notifications = live.stream('notifications', async (ctx) => {
return db.notifications.forUser(ctx.user.id);
}, {
merge: 'crud',
access(ctx, event, data) {
return data.userId === ctx.user.id;
}
}); Only events where access returns true are sent to that client.
Global middleware
Use live.middleware() for cross-cutting auth:
import { live, LiveError } from 'svelte-realtime/server';
live.middleware(async (ctx, next) => {
if (!ctx.user) throw new LiveError('UNAUTHORIZED');
return next();
}); Under the hood, upgrade() runs inside the adapter’s WebSocket handshake. See svelte-adapter-uws WebSocket docs for the full connection lifecycle.
Was this page helpful?