Cookies let the browser remember a session between requests. The cookie holds an opaque token; the server decides which user it belongs to.
In this example, we'll sign in, protect our todos, and sign out.
Use the session-checking hook from the hooks and locals example. These routes need a server adapter, not this site's static adapter. Disable prerendering with export const prerender = false in their +page.js files.
These examples use a few async helpers from your own src/lib/server/auth.js module. They're not built into SvelteKit:
verifyCredentials(email, password) uses a trusted password-hashing library to verify a stored password hash, returning { id, name } or null. Don't store plaintext passwords or use a fast general-purpose hash for passwords.
createSession(userId) generates a new cryptographically random, unpredictable opaque token, persists its hash, user ID, and expiry, and returns { token, expiresAt }, where expiresAt is a Date.
getUserFromSession(token) hashes the token, looks up the session, checks expiry and revocation, and returns the user or null.
revokeSession(token) revokes the persisted session; a missing or unknown token is harmless.
Read the form on the server. Check that both fields are strings and nonempty before verifying credentials.
Return a generic error for invalid credentials. Never return the password to the page.
A new session remembers the verified user. The cookie expiry matches the persisted session expiry.
Keep SvelteKit's origin checks for form POSTs enabled, serve production over HTTPS, and rate-limit login attempts. httpOnly doesn't prevent all attacks: a session token is a credential, so never expose it in page data or logs.