mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-04-10 04:00:52 -04:00
Merge commit from fork
httpOnly (invisible to JS) and secure (https only) are now used. In order to update existing users without requiring them to re-authenticate, each request sets those properties on the cookie. Finally, the maxAge is now 30 days and is also updated on each request. i.e. it's a rolling 30 days. Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
committed by
GitHub
parent
acd5508831
commit
6848da8320
@@ -13,6 +13,8 @@ async function setupServer() {
|
||||
return fastify;
|
||||
}
|
||||
|
||||
const THIRTY_DAYS_IN_SECONDS = 2592000;
|
||||
|
||||
describe('auth', () => {
|
||||
let fastify: FastifyInstance;
|
||||
|
||||
@@ -51,30 +53,11 @@ describe('auth', () => {
|
||||
path: '/',
|
||||
sameSite: 'Lax',
|
||||
domain: COOKIE_DOMAIN,
|
||||
maxAge: token.ttl
|
||||
maxAge: THIRTY_DAYS_IN_SECONDS,
|
||||
httpOnly: true,
|
||||
secure: true
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: Post-MVP sync the cookie max-age with the token ttl (i.e. the
|
||||
// max-age should be the ttl/1000, not ttl)
|
||||
it('should set the max-age of the cookie to match the ttl of the token', async () => {
|
||||
const token = createAccessToken('test-id', 123000);
|
||||
fastify.get('/test', async (req, reply) => {
|
||||
reply.setAccessTokenCookie(token);
|
||||
return { ok: true };
|
||||
});
|
||||
|
||||
const res = await fastify.inject({
|
||||
method: 'GET',
|
||||
url: '/test'
|
||||
});
|
||||
|
||||
expect(res.cookies[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
maxAge: 123000
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('authorize', () => {
|
||||
@@ -250,4 +233,46 @@ describe('auth', () => {
|
||||
expect(res.statusCode).toEqual(200);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onRequest Hook', () => {
|
||||
it('should update the jwt_access_token to httpOnly and secure', async () => {
|
||||
const rawValue = 'should-not-change';
|
||||
fastify.get('/test', (req, reply) => {
|
||||
reply.send({ ok: true });
|
||||
});
|
||||
|
||||
const res = await fastify.inject({
|
||||
method: 'GET',
|
||||
url: '/test',
|
||||
cookies: {
|
||||
jwt_access_token: signCookie(rawValue)
|
||||
}
|
||||
});
|
||||
|
||||
expect(res.cookies[0]).toMatchObject({
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
value: signCookie(rawValue),
|
||||
maxAge: THIRTY_DAYS_IN_SECONDS
|
||||
});
|
||||
|
||||
expect(res.json()).toStrictEqual({ ok: true });
|
||||
expect(res.statusCode).toBe(200);
|
||||
});
|
||||
|
||||
it('should do nothing if there is no jwt_access_token', async () => {
|
||||
fastify.get('/test', (req, reply) => {
|
||||
reply.send({ ok: true });
|
||||
});
|
||||
|
||||
const res = await fastify.inject({
|
||||
method: 'GET',
|
||||
url: '/test'
|
||||
});
|
||||
|
||||
expect(res.cookies).toHaveLength(0);
|
||||
expect(res.json()).toStrictEqual({ ok: true });
|
||||
expect(res.statusCode).toBe(200);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -28,13 +28,26 @@ declare module 'fastify' {
|
||||
}
|
||||
|
||||
const auth: FastifyPluginCallback = (fastify, _options, done) => {
|
||||
const cookieOpts = {
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
maxAge: 2592000 // thirty days in seconds
|
||||
};
|
||||
fastify.decorateReply('setAccessTokenCookie', function (accessToken: Token) {
|
||||
const signedToken = jwt.sign({ accessToken }, JWT_SECRET);
|
||||
void this.setCookie('jwt_access_token', signedToken, {
|
||||
httpOnly: false,
|
||||
secure: false,
|
||||
maxAge: accessToken.ttl
|
||||
});
|
||||
void this.setCookie('jwt_access_token', signedToken, cookieOpts);
|
||||
});
|
||||
|
||||
// update existing jwt_access_token cookie properties
|
||||
fastify.addHook('onRequest', (req, reply, done) => {
|
||||
const rawCookie = req.cookies['jwt_access_token'];
|
||||
if (rawCookie) {
|
||||
const jwtAccessToken = req.unsignCookie(rawCookie);
|
||||
if (jwtAccessToken.valid) {
|
||||
reply.setCookie('jwt_access_token', jwtAccessToken.value, cookieOpts);
|
||||
}
|
||||
}
|
||||
done();
|
||||
});
|
||||
|
||||
fastify.decorateRequest('accessDeniedMessage', null);
|
||||
|
||||
Reference in New Issue
Block a user