When setting up users for an app there are two things we need to consider:
- Who is the user? This is authentication.
- Given who the user is, what are they able to do/access? This is authorization.
To deal with the first, authentication, we need to set up the following routes. It is very common to put all of these into a router and have that handle an /auth
path (profile works too, I'd just already written this).
- GET
/register
(show the form for sign-up; don't need this route if the form is on another page) - POST
/register
(checks user info, creates a user, and starts a session) - GET
/login
(shows form for login; again, don't need if this is on a different page) - POST
/login
(checks credentials and starts a session) - GET
/logout
(clear the session)
So the paths would be /auth/register
, /auth/login
, /auth/logout
.
You'd define the routes in ./routes/auth.js
and would put the route handlers in ./controllers/auth.js
To deal with the second, authorization, you don't need any new routes. You will just be defining middleware that you will add to certain routes. The middleware will check if the user object is present, and if it is, decide if we want to give that user the authority to perform that action.
For example, in the quotes app, we might say that anyone can see the home page but to see the quotes index, a user needs to log in.
Additionally, we want only the author of a quote to be able to edit it.
// controllers/authorizationController.js
module.exports = {
isLoggedIn(req, res, next) {
if (req.session.user) {
next()
} else {
req.session.error = `Login required`
res.redirect(`/auth/login`)
}
},
isAuthor(req, res, next) {
if (req.session.user.id === res.locals.quote.author_id) {
next()
} else {
req.session.error =`Only the quotes author can edit it.`
res.redirect(`/quotes/${res.locals.quote.id}`)
}
}
}
// routes/quotes.js
router.use(athorizationController.isLoggedIn)
router.get(`/`, quotesController.findAll, viewsController.quotesIndex)
router.get(`/:id`, quotesController.findOne, viewsController.quoteShow)
router.get(`/:id/edit`, quotesController.findOne, authorizationController.isAuthor, viewsController.quoteEdit)