# 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:

1. **Auth handler parameters**: Access cookies during authentication
2. **Response cookies**: Set cookies to be sent back to clients
3. **Request cookies**: Access cookies sent by clients

## Using Cookies in Auth Handlers

Cookies can be used in authentication handlers:

```ts
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:

```ts
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:

```ts
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 values
- `boolean`: True/false values
- `Date`: Date objects

### How to Specify Cookie Types

When defining cookies, you can specify the type using the generic parameter:

```ts
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 (requires `secure: 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:

```ts
// Create a client that includes credentials (cookies) for cross-site requests
const client = new Client(Local, { requestInit: { credentials: "include" } });
```

## Best Practices

1. Use `httpOnly: true` for cookies containing sensitive data
2. Set `secure: true` for production environments
3. Configure appropriate `sameSite` settings based on your requirements
4. Use the `maxAge` or `expires` 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.
