Skip to content

Commit

Permalink
Setting up auth plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
francisli committed Mar 29, 2024
1 parent bc2407c commit 182b405
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 110 deletions.
59 changes: 39 additions & 20 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@
"author": "",
"license": "ISC",
"dependencies": {
"@fastify/auth": "^4.6.1",
"@fastify/autoload": "^5.8.0",
"@fastify/cookie": "^9.3.1",
"@fastify/secure-session": "^7.1.0",
"@fastify/sensible": "^5.5.0",
"@fastify/session": "^10.7.0",
"@prisma/client": "^5.10.2",
"bcrypt": "^5.1.1",
"dotenv": "^16.4.5",
"fastify": "^4.26.1",
"fastify-cli": "^6.1.1",
"fastify-plugin": "^4.5.1",
"http-status-codes": "^2.3.0",
"nodemailer": "^6.9.12"
},
"devDependencies": {
Expand Down
38 changes: 38 additions & 0 deletions server/plugins/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import fp from 'fastify-plugin';

// the use of fastify-plugin is required to be able
// to export the decorators to the outer scope

export default fp(async function (fastify, _opts) {
// set up secure encrypted cookie-based sessions
await fastify.register(import('@fastify/secure-session'), {
key: Buffer.from(process.env.SESSION_SECRET_KEY, 'hex'),
cookie: {
httpOnly: true,
sameSite: true,
secure: true,
},
});
// add a user object reference to the request instance
fastify.decorateRequest('user', null);
// add a hook to check for a signed in user on every request
fastify.addHook('onRequest', async (request, _reply) => {
// first check cookie-based session
const id = request.session.get('userId');
if (id) {
const user = await fastify.prisma.user.findUnique({ where: { id } });
if (user) {
request.user = user;
} else {
// session data is invalid, delete
request.session.delete();
}
}
});
// onRequest handler to be used to ensure a user is logged in
fastify.decorate('requireUser', async (request, reply) => {
if (!request.user) {
reply.unauthorized();
}
});
});
48 changes: 0 additions & 48 deletions server/plugins/auth/auth.js

This file was deleted.

86 changes: 46 additions & 40 deletions server/routes/api/v1/auth/local.js
Original file line number Diff line number Diff line change
@@ -1,50 +1,56 @@
import bcrypt from 'bcrypt';

// could be reimplamented with fastify-passport
export default async function (fastify, _opts) {
// add a login route that returns a login page
fastify.get('/login', (_request, reply) => {
// currently only redirects to login page
reply.redirect('/login');
});

// add a login route that handles the actual login
fastify.post('/login', async (request, reply) => {
const { email, password } = request.body;
try {
const user = await fastify.prisma.user.findUnique({ email });
if (!user) {
reply.status(401);
reply.send('No user with that email');
return;
}

const result = await bcrypt.compare(password, user.password);
if (!result) {
reply.status(401);
reply.send('Invalid password');
return;
fastify.post(
'/login',
{
// schema template for fastify-swagger
schema: {
body: {
type: 'object',
required: ['email', 'password'],
properties: {
email: { type: 'string', format: 'email' },
password: { type: 'string' },
},
},
response: {
200: {
type: 'object',
properties: {
id: { type: 'string' },
firstName: { type: 'string' },
lastName: { type: 'string' },
email: { type: 'string', format: 'email' },
role: { type: 'string' },
createdAt: { type: 'string' },
},
},
},
},
},
async (request, reply) => {
const { email, password } = request.body;
try {
const user = await fastify.prisma.user.findUnique({ email });
if (!user) {
return reply.notFound();
}
const result = await bcrypt.compare(password, user.password);
if (!result) {
return reply.unauthorized();
}
request.session.set('userId', user.id);
} catch (error) {
return error;
}
return (request.session.authenticated = true);
} catch (error) {
reply.status(500);
reply.send('Internal Server Error');
}
});
},
);

// add a logout route
fastify.get('/logout', (request, reply) => {
if (request.session.authenticated) {
request.session.destroy((err) => {
if (err) {
reply.status(500);
reply.send('Internal Server Error');
} else {
reply.redirect('/');
}
});
} else {
reply.redirect('/');
}
request.session.delete();
reply.send();
});
}

0 comments on commit 182b405

Please sign in to comment.