Cookies and Sessions
Finch provides two mechanisms for persisting data between HTTP requests: cookies (client-side) and sessions (server-side). Understanding the difference helps you choose the right tool:
- Cookies are stored in the browser and sent with every request. They are suitable for lightweight user preferences (theme, language) that can be safely stored client-side.
- Sessions are stored on the server. Only a session ID is sent to the browser. They are suitable for sensitive data such as the currently logged-in user.
Both are accessible through the rq object inside any controller or route handler.
Cookies
Cookies are key-value string pairs stored in the browser. Finch reads them from incoming Cookie headers and writes them via Set-Cookie response headers.
Read a Cookie
Use rq.getCookie(key, def: defaultValue) to read a cookie. The def parameter specifies what to return if the cookie does not exist:
// Plain cookie — value is stored as-is in the browser
var theme = rq.getCookie('theme', def: 'light');
// Encrypted cookie — value is decrypted server-side before returning
var token = rq.getCookie('auth_token', def: '', safe: true);
Write a Cookie
Use rq.addCookie(key, value) to set a cookie. The cookie is attached to the response:
// Plain cookie
rq.addCookie('theme', 'dark');
// Encrypted cookie — value is encrypted before sending to the browser
rq.addCookie('auth_token', 'abc123', safe: true);
Remove a Cookie
To remove a cookie, Finch sets it with an expired max-age:
rq.removeCookie('theme');
Complete Example
class CookieController extends Controller {
Future<String> showCookie() async {
var value = rq.getCookie('test', def: 'not set');
rq.addParam('cookieValue', value);
return rq.renderView(path: 'example/cookie');
}
Future<String> addCookie() async {
var key = rq.get<String>('key', def: '');
var value = rq.get<String>('value', def: '');
var safe = rq.get<bool>('safe', def: false);
if (key.isNotEmpty) {
rq.addCookie(key, value, safe: safe);
}
return rq.redirect('/example/cookie');
}
}
Sessions
Sessions are managed by Dart's built-in HttpSession. Each visitor receives a unique session ID stored in a browser cookie, but the actual data lives on the server in memory.
Important: The default Dart
HttpSessionis memory-backed. Session data is lost when the server restarts. For production use, consider a persistent session store or store critical data in the database instead.
Read a Session Value
Use rq.getSession(key, def: defaultValue) to read a value. Returns def if the key does not exist:
var userEmail = rq.getSession('user', def: '');
Write a Session Value
Use rq.addSession(key, value) to store a value in the current session:
rq.addSession('user', '[email protected]');
Remove a Session Value
rq.session.remove('user');
Complete Example
A typical login/logout/dashboard flow using sessions:
class SessionController extends Controller {
Future<String> login() async {
var email = rq.get<String>('email', def: '');
var password = rq.get<String>('password', def: '');
if (isValidUser(email, password)) {
// Store the user's email in the session after successful authentication
rq.addSession('user', email);
return rq.redirect('/dashboard');
}
return rq.renderError(401);
}
Future<String> logout() async {
// Remove the user from the session to log them out
rq.session.remove('user');
return rq.redirect('/login');
}
Future<String> dashboard() async {
var email = rq.getSession('user', def: '');
// If no session, the user is not logged in — redirect to login
if (email.isEmpty) return rq.redirect('/login');
rq.addParam('email', email);
return rq.renderView(path: 'pages/dashboard');
}
}
Encrypted Cookies
When safe: true is used, Finch encrypts the cookie value before sending it to the browser and decrypts it when reading. This prevents the user from reading or tampering with the stored value.
The encryption key is taken from FinchConfigs.cookiePassword:
FinchConfigs configs = FinchConfigs(
cookiePassword: env['COOKIE_SECRET'] ?? 'change-this-in-production',
);
// Writing — stored encrypted in browser
rq.addCookie('prefs', '{"theme":"dark"}', safe: true);
// Reading back — Finch decrypts it automatically
var prefs = rq.getCookie('prefs', def: '{}', safe: true);
Security: Use a long, random
cookiePassword. Store it as an environment variable. Never hardcode it or commit it to version control.
Reading Cookies in Templates
You can also read a cookie value directly inside a Jinja template:
{{ $e.getCookie('theme', 'light') }}
Cookies
Read a Cookie
// Plain cookie
var theme = rq.getCookie('theme', def: 'light');
// Encrypted cookie (decrypted using FinchConfigs.cookiePassword)
var token = rq.getCookie('auth_token', def: '', safe: true);
Write a Cookie
// Plain cookie
rq.addCookie('theme', 'dark');
// Encrypted cookie
rq.addCookie('auth_token', 'abc123', safe: true);
Remove a Cookie
rq.removeCookie('theme');
Complete Example
class CookieController extends Controller {
Future<String> showCookie() async {
var value = rq.getCookie('test', def: 'not set');
rq.addParam('cookieValue', value);
return rq.renderView(path: 'example/cookie');
}
Future<String> addCookie() async {
var key = rq.get<String>('key', def: '');
var value = rq.get<String>('value', def: '');
var safe = rq.get<bool>('safe', def: false);
if (key.isNotEmpty) {
rq.addCookie(key, value, safe: safe);
}
return rq.redirect('/example/cookie');
}
}
Sessions
Sessions are server-side and stored in Dart's built-in HttpSession (memory-backed by default).
Read a Session Value
var userEmail = rq.getSession('user', def: '');
Write a Session Value
rq.addSession('user', '[email protected]');
Remove a Session Value
rq.session.remove('user');
Complete Example
class SessionController extends Controller {
Future<String> login() async {
var email = rq.get<String>('email', def: '');
var password = rq.get<String>('password', def: '');
if (isValidUser(email, password)) {
rq.addSession('user', email);
return rq.redirect('/dashboard');
}
return rq.renderError(401);
}
Future<String> logout() async {
rq.session.remove('user');
return rq.redirect('/login');
}
Future<String> dashboard() async {
var email = rq.getSession('user', def: '');
if (email.isEmpty) return rq.redirect('/login');
rq.addParam('email', email);
return rq.renderView(path: 'pages/dashboard');
}
}
Encrypted Cookies
Set safe: true on addCookie / getCookie to encrypt the value. The encryption key is FinchConfigs.cookiePassword.
// Writing
rq.addCookie('prefs', '{"theme":"dark"}', safe: true);
// Reading back
var prefs = rq.getCookie('prefs', def: '{}', safe: true);
Security: Set a strong, unique
cookiePasswordin your.envfile. Never commit the password to version control.
Reading Cookies in Templates
{{ $e.getCookie('theme', 'light') }}