Authentication
PlayMesh does not implement authentication. It provides a hook where your application authenticates the incoming connection and returns a user ID. If the hook throws, the connection is rejected.
ℹWithout an onAuthenticate hook, sessions are anonymous — the socket ID is used as userId.
The hook
mesh.onAuthenticate(async request => {
// request.token — shortcut for request.auth.token
// request.auth — full auth payload from the client
// request.headers — HTTP handshake headers
// request.address — client IP
const user = await authService.verifyToken(request.token);
return {
userId: user.id, // required
data: { role: user.role }, // optional — available on session.data
};
});
JWT example
import jwt from 'jsonwebtoken';
mesh.onAuthenticate(async request => {
const token = request.token;
if (!token) throw new Error('Token required');
const payload = jwt.verify(token, process.env.JWT_SECRET!) as { sub: string; role: string };
return { userId: payload.sub, data: { role: payload.role } };
});
Sending auth from the client
// Static token
const client = new PlayMeshClient({
url: 'https://game.example.com',
auth: { token: 'eyJhbGci...' },
});
// Dynamic — refreshed on each reconnect
const client = new PlayMeshClient({
url: 'https://game.example.com',
auth: async () => ({ token: await authService.getToken() }),
});
Admission
After authentication, the admission hook decides which instances the new session joins. The framework then automatically joins the session before the client connection resolves.
mesh.onAdmission(async request => {
const player = await db.players.findById(request.userId);
return {
instances: [
'world/city-center',
`guild/${player.guildId}`,
'social/global-chat',
],
};
});
✦References can be "domainId/instanceId" paths or bare instance IDs (unique across all domains).
Manual assignment
mesh.onSessionCreate(async session => {
const player = await db.players.findById(session.userId);
const zone = mesh.domain('world').instance(player.currentZone);
await session.join(zone);
if (player.guildId) {
const guild = mesh.domain('guild').instance(player.guildId);
await session.join(guild);
}
});
Connection flow
1. Client connects with auth payload
2. onAuthenticate hook — verify token, return userId
3. Session created
4. onSessionCreate hooks run
5. onConnect hooks run
6. onAdmission hook — return instance list
7. Session joins each instance (join hooks fire)
8. playmesh:session event sent to client
9. client.connect() resolves with SessionInfo
Error handling
try {
await client.connect();
} catch (error) {
console.error('Auth failed:', error.message);
}
client.onError(error => {
if (error.scope === 'connection') showAuthError(error.message);
});