The RequestUser interface represents authenticated user information attached
to a ZuploRequest. This interface is used when
authentication policies validate and identify users.
The subject identifier (unique user ID) from the authentication token.
sub: string;
ts
data
Additional user data of generic type TUserData.
data: TUserData;
ts
Usage
The user property is available on ZuploRequest after successful
authentication:
import { ZuploContext, ZuploRequest } from "@zuplo/runtime";export default async function handler( request: ZuploRequest, context: ZuploContext,) { // Check if user is authenticated if (!request.user) { return new Response("Unauthorized", { status: 401 }); } // Access user information const userId = request.user.sub; const userData = request.user.data; context.log.info("Request from user", { userId }); return new Response(`Hello, user ${userId}!`);}
ts
Type-Safe User Data
You can define custom types for user data:
import { ZuploContext, ZuploRequest, RequestUser } from "@zuplo/runtime";// Define your user data structureinterface MyUserData { email: string; roles: string[]; organizationId: string; permissions?: string[];}// Use typed requesttype MyRequest = ZuploRequest<{ UserData: MyUserData;}>;export default async function handler( request: MyRequest, context: ZuploContext,) { if (!request.user) { return new Response("Unauthorized", { status: 401 }); } // TypeScript knows the shape of user.data const { email, roles, organizationId } = request.user.data; if (!roles.includes("admin")) { return new Response("Forbidden: Admin role required", { status: 403 }); } return new Response(`Welcome admin ${email} from org ${organizationId}`);}
ts
Common Authentication Patterns
JWT Authentication
When using JWT authentication policies, the user data typically includes claims
from the token:
For API key authentication, user data might include consumer information:
// After API key validationrequest.user = { // The subject of the consumer sub: "consumer-id-123", data: { // The metadata you set when creating the consumer customerId: "123", plan: "premium", },};
ts
Working with User Data
Role-Based Access Control
import { ZuploContext, ZuploRequest } from "@zuplo/runtime";interface UserWithRoles { roles: string[]; permissions?: string[];}export function requireRole(role: string) { return async function handler( request: ZuploRequest<{ UserData: UserWithRoles }>, context: ZuploContext, ) { if (!request.user) { return new Response("Unauthorized", { status: 401 }); } const { roles } = request.user.data; if (!roles.includes(role)) { context.log.warn("Access denied", { userId: request.user.sub, requiredRole: role, userRoles: roles, }); return new Response(`Forbidden: ${role} role required`, { status: 403, }); } // User has required role, continue processing return null; // Continue to next handler };}// Usage in a routeexport const adminOnly = requireRole("admin");