KaroKar secures its API with JSON Web Tokens (JWT) viaDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Codefied-CodePix/Karokar-backend/llms.txt
Use this file to discover all available pages before exploring further.
@nestjs/jwt and passport-jwt. Every request to a protected endpoint must carry a signed JWT in the Authorization header. The token encodes both the caller’s identity (userId) and their organizational scope (organizationId) — together these two claims drive every authorization and multi-tenancy decision made at the API boundary.
JWT Payload Shape
The JWT payload must conform to theJwtPayload interface defined in src/shared/types/authenticated-request.interface.ts:
The standard JWT subject claim. Used as the fallback
userId when the explicit userId field is absent.Explicit user identifier. When present, takes precedence over
sub. The OrganizationContextInterceptor normalises both fields into a single AuthenticatedUser shape before handlers run.The organization the caller is acting on behalf of. This claim is required on every protected request. Requests without it will receive
401 Unauthorized.Passing the Token
Include the JWT as a Bearer token in theAuthorization header on every request:
Example — Create a Booking
Example — Retrieve a Booking
Organization Context Resolution
Before any guard or handler runs, theOrganizationContextInterceptor normalises the request. Its full implementation is:
- Reads the decoded JWT payload from
request.user(populated by Passport after signature verification). - If
organizationIdis present in the payload, it is promoted torequest.organizationIdso downstream guards and handlers can read it without inspecting the raw JWT shape. - If the payload only carries a
subclaim (no explicituserId), the interceptor normalisesrequest.userinto anAuthenticatedUserusingsubas theuserId.
The interceptor does not throw on missing claims — it simply skips normalisation when
organizationId is absent. Identity validation and rejection occur in the PermissionGuard on protected routes.Permission Guard
Protected routes are decorated with@RequirePermission('some.permission'). The PermissionGuard enforces access control on every such route:
Guard Logic — Step by Step
Read the required permission
The guard uses NestJS’s
Reflector to read the permission string set by the @RequirePermission decorator on the handler or controller class. If no permission is set, the guard returns true immediately — the route is publicly accessible.Extract identity claims
userId is read from request.user.userId. organizationId is read first from request.organizationId (set by the interceptor), falling back to request.user.organizationId in the raw JWT payload.Validate identity completeness
If either
userId or organizationId cannot be resolved, a 401 Unauthorized exception is thrown. This happens when the JWT is missing, expired, or lacks the required claims.Permission Naming Convention
Following ADR-010 and ADR-007, permissions are named as<domain>.<action> strings — not role names:
Public vs. Protected Endpoints
Endpoints that are not decorated with@RequirePermission are publicly accessible — the guard returns true without evaluating any claims. Integrators should check individual endpoint documentation to confirm whether authentication is required.
Even on public endpoints, the
OrganizationContextInterceptor still runs. If a valid JWT is present in the Authorization header, request.organizationId will be populated — this is useful for endpoints that behave differently for authenticated vs. anonymous callers.Authorization Service — Integration Required
Environment Configuration
The JWT signing secret is configured via theJWT_SECRET environment variable (see .env.example):
Future Authentication Support
ADR-010 designates Phase 01 authentication as JWT-only (web and mobile clients). Future phases are planned to add OAuth 2.0, OpenID Connect, SAML, and Enterprise SSO support. The API design is intentionally structured so these authentication layers can be added without requiring changes to resource endpoints or authorization logic.
Error Reference
| Scenario | HTTP Status | Cause |
|---|---|---|
Missing Authorization header on a protected route | 401 Unauthorized | No JWT supplied |
| JWT is expired or signature is invalid | 401 Unauthorized | Passport rejects the token before the guard runs |
JWT missing userId/sub or organizationId | 401 Unauthorized | Guard cannot resolve identity claims |
Permission check returns false | 403 Forbidden | User lacks the required permission in their organization |
AuthorizationService.can() not implemented | 500 Internal Server Error | Stub throws NotImplementedException |