toeverything/AFFiNE · error · AuthenticationRequired

authentication_required

authentication_required

Error message

You must sign in first to access this resource.

What it means

Thrown by assertAuthenticated() in the user realtime provider when the caller is not authenticated. The realtime provider registers live queries for user profile/settings rooms, and both require a valid CurrentUser; passing no user (undefined) trips the guard before any subscription is created.

Source

Thrown at packages/backend/server/src/core/user/realtime.ts:24

import { z } from 'zod';

import { AuthenticationRequired, OnEvent, UserNotFound } from '../../base';
import { Feature, Models } from '../../models';
import { sessionUser } from '../auth/service';
import { AvailableUserFeatureConfig } from '../features/types';
import { registerRealtimeLiveQuery } from '../realtime/provider';
import { RealtimePublisher } from '../realtime/publisher';
import { RealtimeRegistry } from '../realtime/registry';
import {
  realtimeUserProfileRoom,
  realtimeUserSettingsRoom,
} from '../realtime/rooms';

const emptyInput = z.object({}).strict();

function assertAuthenticated(user?: { id: string }) {
  if (!user) {
    throw new AuthenticationRequired();
  }
  return user;
}

@Injectable()
export class UserRealtimeProvider
  extends AvailableUserFeatureConfig
  implements OnModuleInit
{
  constructor(
    private readonly models: Models,
    @Optional() private readonly registry?: RealtimeRegistry,
    @Optional() private readonly publisher?: RealtimePublisher
  ) {
    super();
  }

  onModuleInit() {

View on GitHub (pinned to 26c515e050)

Solutions

  1. Ensure the socket is authenticated (token validated) before subscribing to user realtime rooms.
  2. On token expiry, re-authenticate the socket and re-issue the subscription.
  3. Verify the auth guard is wired to the realtime gateway.

Example fix

// before — subscribing before auth confirmed
socket.emit('realtime:subscribe', { room: realtimeUserSettingsRoom(userId) });

// after — wait for auth
await authenticateSocket(socket);
socket.emit('realtime:subscribe', { room: realtimeUserSettingsRoom(userId) });
Defensive patterns

Strategy: validation

Validate before calling

if (!session?.user) { await authenticate(); return; }
subscribe(realtimeUserProfileRoom(session.user.id));

Type guard

function isAuthenticated(user?: { id: string }): user is { id: string } {
  return Boolean(user?.id);
}

Try / catch

try {
  await subscribe(room);
} catch (e) {
  if (e?.code === 'authentication_required') { await reauthenticate(); await subscribe(room); return; }
  throw e;
}

Prevention

When it happens

Trigger: A realtime subscription request for realtimeUserProfileRoom or realtimeUserSettingsRoom arrives without a valid authenticated session (no user attached by the auth guard).

Common situations: Session expired mid-connection; WebSocket connected before login completed; misconfigured guard that lets unauthenticated sockets through to the realtime layer.

Related errors


AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12). Data as JSON: /api/errors/9f533c353710dab7. Report an issue: GitHub.