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
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
Cookie Generation
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
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/Expireslimitation__Host-/__Secure-prefix limitation
- CHIPS-01
Partitionedlimitation
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-, butsecureoption is not set.The cookie name starts with__Secure-, butsecureoption 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-, butsecureoption is not set.The cookie name starts with__Host-, butsecureoption 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-, butpathis not/.The cookie name starts with__Host-, butpathis 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-, butdomainis set.The cookie name starts with__Host-, butdomainis 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
maxAgeoption value is greater than 400 days.ThemaxAgeoption value is greater than 400 days.maxAge greater than 400 days throws an Error The RFC caps cookie lifetime at 400 daysmaxAge greater than 400 days throws an ErrormaxAge limit - The
expiresoption value is 400 days later than the current time.Theexpiresoption 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 optionexpires more than 400 days ahead throws an Errorexpires limit