jeremydaly / jeremydaly/lambda-api
Watch out for setCookie and clearCookie opts, as clearCookie mutates opts instance
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 1.5k
- Forks
- 127
- Avg merge
- 31m
- Merged PRs (30d)
- 2
Description
Hi!
Lambda-api is a great package and has been really helpful in our one single backend lambda architecture 🚀
Today, I faced a really hard to debug issue and I though passing the information here if it helps anyone else. I was running our app with SAM CLI and everything worked like a charm, but when I deployed to AWS lambda, it worked in really weird way.
The problem was that I had somewhat the following structure:
const cookieOptions: CookieOptions = {
sameSite: 'Lax',
secure: true,
httpOnly: true,
}
// And pseudo authentication
api.post('/login', async (req,res) => {
// Do login stuff
res.setCookie('authcookie', sessionId, cookieOpts).json({ message: "Authenticated" })
})
api.post('/logout', async (req,res) => {
// Do logout stuff
res.clearCookie('authcookie', cookieOpts).json({ message: "Logged out" })
})
It worked locally like a charm. But when it was deployed to AWS Lambda, it worked like this:
- Login - OK you get a cookie
- Logout - OK cookie gets evicted
- Login - FAILS and no cookie is set
- After some time, it starts to work again, for once 😂
After some weird debugging I found out that the third call gets correct cookie, but with expiration set to -1, so the browser thinks that yes, unset the cookie.
Obvious reason for this is that response.clearCookie call mutates the given opts instance:
After the first response.clearCookie call my opts instance was mutated to contain expiration: -1 field and calls to response.setCookie after that naturally included the expiration.
The reason why it works after some time in AWS lambda is that runtime spins up a new sandbox and then it works again, for once 😄, because opts instance is not mutated and no one has logged out. Locally SAM CLI fires a whole new sandbox for each request and thus it worked locally with no issues.
You can easily work around this for example by wrapping opts in function:
const cookieOptions = (): CookieOptions => ({
sameSite: 'Lax',
secure: true,
httpOnly: true,
})
It surely took me some time to figure out what is going on 😄 I don't think this is mentioned in documentation. I think I can work out a PR for this if this is something that should be fixed - in code or with documentation.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in lib/response.js at lines 221-224 and inspect how clearCookie handles the supplied options object. Reproduce the login, logout, and login sequence with shared cookie options, then verify that clearing a cookie does not affect later setCookie calls; document the behavior if the implementation is intentionally unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, javascript
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100