Skip to main content

Cookie Helper

Model-written

contextclaimmethodsetupresultanalysislimitation

Cookie Helper

Cookie Helper manages cookies: set, parse, delete for regular and signed

The Cookie Helper provides an easy interface to manage cookies, enabling developers to set, parse, and delete cookies seamlessly.The Cookie Helper provides an easy interface to manage cookies, enabling developers to set, parse, and delete cookies seamlessly.Cookie Helper manages cookies, enabling set, parse and delete seamlessly It wraps cookie handling so developers avoid manual header workCookie Helper manages cookies, enabling set, parse and delete seamlesslyCookie Helper

Import

import { Hono } from 'hono'
import {
  deleteCookie,
  getCookie,
  getSignedCookie,
  setCookie,
  setSignedCookie,
  generateCookie,
  generateSignedCookie,
} from 'hono/cookie'

Usage

Regular cookies

app.get('/cookie', (c) => {
  setCookie(c, 'cookie_name', 'cookie_value')
  const yummyCookie = getCookie(c, 'cookie_name')
  deleteCookie(c, 'cookie_name')
  const allCookies = getCookie(c)
  // ...
})

Signed cookies

Signed cookies need await because WebCrypto HMAC SHA-256 signing is async

NOTE: Setting and retrieving signed cookies returns a Promise due to the async nature of the WebCrypto API, which is used to create HMAC SHA-256 signatures.NOTE: Setting and retrieving signed cookies returns a Promise due to the async nature of the WebCrypto API, which is used to create HMAC SHA-256 signatures.Signed cookie operations return a Promise due to async WebCrypto HMAC SHA-256 signatures are created through the asynchronous WebCrypto APISigned cookie operations return a Promise due to async WebCryptoSigned cookie

app.get('/signed-cookie', (c) => {
  const secret = 'secret' // make sure it's a large enough string to be secure

  await setSignedCookie(c, 'cookie_name0', 'cookie_value', secret)
  const fortuneCookie = await getSignedCookie(
    c,
    secret,
    'cookie_name0'
  )
  deleteCookie(c, 'cookie_name0')
  // `getSignedCookie` will return `false` for a specified cookie if its signature fails verification
  const allSignedCookies = await getSignedCookie(c, secret)
  // ...
})

Note

getSignedCookie distinguishes two cases. A cookie that has a signature but fails verification returns false. A cookie that does not have a valid signature format is treated as not being a signed cookie at all and returns undefined — the same as when the cookie is not present. This rule applies both when retrieving a single cookie by name and when retrieving all signed cookies. Since both false and undefined are falsy, if (!value) handles both cases.A cookie that has a signature but fails verification returns false. A cookie that does not have a valid signature format is treated as not being a signed cookie at all and returns undefined — the same as when the cookie is not present.Bad signature returns false; invalid format returns undefined Both are falsy, so if (!value) covers both the verification failure and absenceBad signature returns false; invalid format returns undefinedBad signature

generateCookie and generateSignedCookie produce cookie strings without setting headers

generateCookie and generateSignedCookie functions allow you to create cookie strings directly without setting them in the response headers.generateCookie and generateSignedCookie functions allow you to create cookie strings directly without setting them in the response headers.generateCookie and generateSignedCookie create cookie strings directly They skip setting response headers, so output must be applied manuallygenerateCookie and generateSignedCookie create cookie strings directlycookie strings

generateCookie

// Basic cookie generation
const cookie = generateCookie('delicious_cookie', 'macha')
// Returns: 'delicious_cookie=macha; Path=/'

// Cookie with options
const cookie = generateCookie('delicious_cookie', 'macha', {
  path: '/',
  secure: true,
  httpOnly: true,
  domain: 'example.com',
})

generateSignedCookie

generateSignedCookie awaits a secret and optionally sets cookie options

// Basic signed cookie generation
const signedCookie = await generateSignedCookie(
  'delicious_cookie',
  'macha',
  'secret chocolate chips'
)

// Signed cookie with options
const signedCookie = await generateSignedCookie(
  'delicious_cookie',
  'macha',
  'secret chocolate chips',
  {
    path: '/',
    secure: true,
    httpOnly: true,
  }
)

Note: Unlike setCookie and setSignedCookie, these functions only generate the cookie strings. You need to manually set them in headers if needed.Note: Unlike setCookie and setSignedCookie, these functions only generate the cookie strings. You need to manually set them in headers if needed.These functions only generate cookie strings, not set headers You must manually place the generated strings into headers yourselfThese functions only generate cookie strings, not set headerscookie strings

Options

setCookie & setSignedCookie

setCookie and setSignedCookie accept domain, expires, httpOnly, maxAge, path and more

  • domain: string
  • expires: Date
  • httpOnly: boolean
  • maxAge: number
  • path: string
  • secure: boolean
  • sameSite: 'Strict' | 'Lax' | 'None'
  • priority: 'Low' | 'Medium' | 'High'
  • prefix: secure | 'host'
  • partitioned: boolean

Example:Example:setCookie and setSignedCookie accept many cookie options Options like path, secure, domain, maxAge, expires and sameSite are passed in an objectsetCookie and setSignedCookie accept many cookie optionscookie options

// Regular cookies
setCookie(c, 'great_cookie', 'banana', {
  path: '/',
  secure: true,
  domain: 'example.com',
  httpOnly: true,
  maxAge: 1000,
  expires: new Date(Date.UTC(2000, 11, 24, 10, 30, 59, 900)),
  sameSite: 'Strict',
})

// Signed cookies
await setSignedCookie(
  c,
  'fortune_cookie',
  'lots-of-money',
  'secret ingredient',
  {
    path: '/',
    secure: true,
    domain: 'example.com',
    httpOnly: true,
    maxAge: 1000,
    expires: new Date(Date.UTC(2000, 11, 24, 10, 30, 59, 900)),
    sameSite: 'Strict',
  }
)

deleteCookie

deleteCookie takes path, secure, domain options and returns the deleted value

  • path: string
  • secure: boolean
  • domain: string

Example:Example:deleteCookie accepts path, secure and domain options These options must match how the cookie was originally set for deletion to workdeleteCookie accepts path, secure and domain optionsdeleteCookie options

deleteCookie(c, 'banana', {
  path: '/',
  secure: true,
  domain: 'example.com',
})

deleteCookie returns the deleted value:deleteCookie returns the deleted value:deleteCookie returns the deleted value The removed cookie's value is captured so callers can inspect what was deleteddeleteCookie returns the deleted valuedeleted value

const deletedCookie = deleteCookie(c, 'delicious_cookie')

__Secure- and __Host- prefix

Prefix option verifies and sets __Secure- and __Host- cookie names

The Cookie helper supports __Secure- and __Host- prefixes for cookie names.The Cookie helper supports __Secure- and __Host- prefixes for cookie names.Cookie helper supports __Secure- and __Host- name prefixes These prefixes enforce security constraints on how the cookie is setCookie helper supports __Secure- and __Host- name prefixes__Secure- prefixes

If you want to verify if the cookie name has a prefix, specify the prefix option.If you want to verify if the cookie name has a prefix, specify the prefix option.Specify the prefix option to verify cookie name prefixes getCookie and getSignedCookie take the prefix value as an extra argument when readingSpecify the prefix option to verify cookie name prefixesprefix option

const securePrefixCookie = getCookie(c, 'yummy_cookie', 'secure')
const hostPrefixCookie = getCookie(c, 'yummy_cookie', 'host')

const securePrefixSignedCookie = await getSignedCookie(
  c,
  secret,
  'fortune_cookie',
  'secure'
)
const hostPrefixSignedCookie = await getSignedCookie(
  c,
  secret,
  'fortune_cookie',
  'host'
)

Also, if you wish to specify a prefix when setting the cookie, specify a value for the prefix option.Also, if you wish to specify a prefix when setting the cookie, specify a value for the prefix option.Set the prefix option when setting prefixed cookies Passing prefix secure or host applies the matching prefix to the cookie nameSet the prefix option when setting prefixed cookiesprefix option

setCookie(c, 'delicious_cookie', 'macha', {
  prefix: 'secure', // or `host`
})

await setSignedCookie(
  c,
  'delicious_cookie',
  'macha',
  'secret choco chips',
  {
    prefix: 'secure', // or `host`
  }
)

Following the best practices

Hono throws on violated cookie best practices like long maxAge

A New Cookie RFC (a.k.a cookie-bis) and CHIPS include some best practices for Cookie settings that developers should follow.A New Cookie RFC (a.k.a cookie-bis) and CHIPS include some best practices for Cookie settings that developers should follow.New Cookie RFC and CHIPS define cookie best practices These specifications describe settings developers should follow for securityNew Cookie RFC and CHIPS define cookie best practicescookie best practices

  • RFC6265bis-13
    • Max-Age/Expires limitation
    • __Host-/__Secure- prefix limitation
  • CHIPS-01
    • Partitioned limitation

Hono is following the best practices. The cookie helper will throw an Error when parsing cookies under the following conditions:Hono is following the best practices. The cookie helper will throw an Error when parsing cookies under the following conditions:Hono follows best practices and throws on violations when parsing Errors surface under the listed conditions such as missing secure or oversized maxAgeHono follows best practices and throws on violations when parsingHono follows

  • The cookie name starts with __Secure-, but secure option is not set.
    The cookie name starts with __Secure-, but secure option is not set.
    __Secure- name without secure option throws an Error The secure attribute is mandatory for cookies carrying that prefix
    __Secure- name without secure option throws an Error
    __Secure- name
  • The cookie name starts with __Host-, but secure option is not set.
    The cookie name starts with __Host-, but secure option is not set.
    __Host- name without secure option throws an Error Host-prefixed cookies must be marked secure to be accepted
    __Host- name without secure option throws an Error
    __Host- name
  • The cookie name starts with __Host-, but path is not /.
    The cookie name starts with __Host-, but path is not /.
    __Host- name with non-slash path throws an Error The __Host- prefix requires the cookie path to be exactly slash
    __Host- name with non-slash path throws an Error
    __Host- path
  • The cookie name starts with __Host-, but domain is set.
    The cookie name starts with __Host-, but domain is set.
    __Host- name with domain set throws an Error Host-prefixed cookies must not carry a domain attribute
    __Host- name with domain set throws an Error
    __Host- domain
  • The maxAge option value is greater than 400 days.
    The maxAge option value is greater than 400 days.
    maxAge greater than 400 days throws an Error The RFC caps cookie lifetime at 400 days
    maxAge greater than 400 days throws an Error
    maxAge limit
  • The expires option value is 400 days later than the current time.
    The expires option value is 400 days later than the current time.
    expires more than 400 days ahead throws an Error The same 400-day lifetime cap applies to the expires option
    expires more than 400 days ahead throws an Error
    expires limit