Working with Cookies
Type-safe cookie handling for web applications
Encore.ts provides type-safe cookie handling for your API endpoints. Cookies are commonly used for session management, personalization, and tracking. This guide explains how to use cookies in different contexts within your Encore.ts application.
Where Cookies Can Be Used
Cookies can be utilized in three main contexts within Encore.ts:
- Auth handler parameters: Access cookies during authentication
- Response cookies: Set cookies to be sent back to clients
- Request cookies: Access cookies sent by clients
Using Cookies in Auth Handlers
Cookies can be used in authentication handlers:
import { Cookie, Gateway } from "encore.dev/api";
import { authHandler } from "encore.dev/auth";
// Define auth parameters with cookies
interface AuthParams {
sessionId: Cookie<"sessionId">;
}
// Auth handler that uses cookies
const auth = authHandler<AuthParams, User>(async ({ sessionId }) => {
return validateAndGetUser(sessionId.value);
});
// Configure the gateway with the auth handler
export const gateway = new Gateway({
authHandler: auth,
});
Setting Cookies in Responses
You can set cookies in your API responses by including them in your response type:
import { api, Cookie } from "encore.dev/api";
// Define a response type with a cookie
interface LoginResponse {
user: UserData;
sessionId: Cookie<"sessionId">;
}
// Create an API endpoint that sets a cookie
export const login = api<LoginParams, LoginResponse>({
method: "POST",
path: "/login",
expose: true,
}, async (params): Promise<LoginResponse> => {
// Authenticate user
const user = await authenticateUser(params.username, params.password);
const sessionId = generateSessionId();
// Store session
await storeSession(sessionId, user.id);
// Return response with cookie
return {
user,
sessionId: {
value: sessionId,
httpOnly: true,
secure: true,
sameSite: "Strict",
maxAge: 60 * 60 * 24 * 7, // 7 days
}
};
});
Using Cookies in Requests
When creating API endpoints, you can access cookies sent by the client by defining them in your parameter type:
import { api } from "encore.dev/api";
// Define a request type with a cookie
interface Params {
language?: Cookie<"language">;
}
// Create an API endpoint that uses the cookie
export const get = api<Params, { msg: string }>(
{
method: "GET",
path: "/user/profile",
expose: true,
},
async ({ language }) => {
// Access the cookie value
const lang = language?.value ?? "en";
return { msg: `your language: ${lang}` };
},
);
Typed Cookie Values
Encore.ts allows you to specify the type of cookie values for improved type safety. By default, cookie values are strings, but you can define cookies with different data types. If you omit the type parameter, Encore.ts will automatically use string
as the type.
Available Cookie Types
You can use the following types for cookie values:
string
: Text data (default when generic parameter is omitted)number
: Numeric valuesboolean
: True/false valuesDate
: Date objects
How to Specify Cookie Types
When defining cookies, you can specify the type using the generic parameter:
interface UserPreferences {
// Cookies with different types
userId: Cookie<number, "userId">;
darkMode: Cookie<boolean, "darkMode">;
lastVisit: Cookie<Date, "lastVisit">;
language: Cookie<string, "language">;
// Using omitted type parameter (implicitly string)
theme: Cookie<"theme">;
}
export const savePreferences = api<UserPreferences, void>({
method: "POST",
path: "/user/preferences",
expose: true,
}, async (params) => {
// Type-safe access to cookie values
const userId = params.userId.value; // number
const isDarkMode = params.darkMode.value; // boolean
const lastVisit = params.lastVisit.value; // Date
const language = params.language.value; // string
const theme = params.theme.value; // string (implicitly typed)
// Save preferences...
});
Cookie Options
When setting cookies, you can configure various options:
- expires: Sets an expiration date
- maxAge: Sets the cookie lifetime in seconds
- domain: Specifies which domains can receive the cookie
- path: Limits the cookie to a specific path
- secure: Only sends the cookie over HTTPS
- httpOnly: Makes the cookie inaccessible to JavaScript
- sameSite: Controls when cookies are sent with cross-site requests
"Strict"
: Only sent in same-site requests"Lax"
: Sent with same-site requests and top-level navigations"None"
: Sent with all requests (requiressecure: true
)
- partitioned: Creates a partitioned cookie using the CHIPS model
Generated client
The generated Encore.ts client does not explicitly handle cookies. Instead, it relies on the browser's built-in cookie handling. When using the client in browser environments, cookies will be automatically included in requests and stored from responses.
For cross-site requests, you need to configure the client to include credentials:
// Create a client that includes credentials (cookies) for cross-site requests
const client = new Client(Local, { requestInit: { credentials: "include" } });
Best Practices
- Use
httpOnly: true
for cookies containing sensitive data - Set
secure: true
for production environments - Configure appropriate
sameSite
settings based on your requirements - Use the
maxAge
orexpires
options to limit cookie lifetime
By following these guidelines, you can effectively leverage cookies in your Encore.ts applications while maintaining security and type safety.