Skip to content

Security: Unauthenticated LiveKit JWT generation + missing auth on timesheet endpoints #4270

@lighthousekeeper1212

Description

@lighthousekeeper1212

Summary

Two security issues in the Next.js BFF API layer:

1. Unauthenticated LiveKit JWT Generation (HIGH)

The /api/livekit endpoint generates LiveKit room JWT tokens with full admin privileges for any unauthenticated caller.

File: apps/web/app/api/livekit/route.ts

The endpoint accepts roomName and username query parameters and returns a JWT token with extensive privileges including roomAdmin: true, roomRecord: true, roomCreate: true, roomList: true.

No authentication check is performed - compare with the Jitsi Meet JWT endpoint (/api/auth/meet/jwt/route.ts) which correctly uses `authenticatedGuard`:

```typescript
// SECURE - Jitsi Meet JWT (route.ts line 45)
const { $res, user } = await authenticatedGuard(req, res);

// VULNERABLE - LiveKit JWT (route.ts line 4)
export async function GET(req: NextRequest) {
const room = req.nextUrl.searchParams.get("roomName");
const username = req.nextUrl.searchParams.get("username");
// NO authenticatedGuard call
const at = new AccessToken(apiKey, apiSecret, { identity: username, ttl: '1h' });
at.addGrant({ room, roomJoin: true, roomAdmin: true, roomRecord: true, roomList: true, ... });
}
```

Impact: Any anonymous internet user can join, record, and administrate any LiveKit room.

2. Missing authenticatedGuard on Timesheet Reporting Endpoints (MEDIUM)

Two timesheet reporting routes are missing the authenticatedGuard call that adjacent sibling endpoints have:

  • apps/web/app/api/timesheet/activity/report/route.ts - missing guard
  • apps/web/app/api/timesheet/time-log/report/daily/route.ts - missing guard

Compare with the secure siblings:

  • apps/web/app/api/timesheet/statistics/counts/route.ts - has authenticatedGuard
  • apps/web/app/api/timesheet/time-log/report/daily-chart/route.ts - has authenticatedGuard

Suggested Fix

Add authenticatedGuard to the LiveKit endpoint:

```typescript
import { authenticatedGuard } from '@/core/services/server/guards/authenticated-guard-app';

export async function GET(req: NextRequest) {
const res = new NextResponse();
const { $res, user, access_token } = await authenticatedGuard(req, res);
if (!user) return $res('Unauthorized');

// ... existing token generation, using user identity instead of query param

}
```

Discovery

Found through automated security research comparing auth patterns across API route handlers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions