# Authentication Refer to the lesson for the code syntax. ## Backend ### Models - A user should be able to input something unique to be able to sign up and log in. - We can rely on email or username. - We will store a hashed-salted password in our User collection in the database. ### Sign up - This is your first encounter with a new user. - We need to get the user email or username, password and all the informations necessary in your application. - Verify that the informations provided are valid / safe based on your criterions - The unique username/mail, should be unique (and valid), you should not be able to find an existing entry in your database. - The password should be safe. - If those criterions are passed, generate a salt using bcrypt, then generate a hashed version of the user password. - Create the user in your database. ### Log in - The user came back. He/She likes your website. - Still, we need them to prove their identity, we need their username/email and a password. - If we can't find anyone with this username/email, the user provided some wrong credential, warn them. - If we find someone, we need to check if the password they provided match the one hashed in our database. - If it does not, warn them. - Everything looks fine, we need to generate a token so that the user can remain logged in. - A token is composed of 3 elements: - Payload: The id of the user or it's username. Avoid Sensible informations - Secret: A random secret string unique to our server - Options: The encryption used and the expiration time. - Send that token to the client. ### How does the Token is sent from the client? #### Postman - We recover the token from logging in and put it in the Authorization headers of the Request. - It is generally prefixed with `Bearer YourTokenHere` #### Frontend - When logging in the frontend (React) receive the token and we store it in the localStorage. - When we make a request to the backend on a protected route, we need to send the token with the request. ### How do I protect a route? - You need to create a middleware - Here is a breakdown of the isAuthenticated middleware seen in class: - Get the token from the authorization headers. - No token ? Not allowed. - Verify the token using `jsonwebtoken` package. - Verify will throw an Error if the token is not valid. - **Save the user id located in the payload on the Request object**. - next() #### Usage of a middleware to protect a route. - We can do some wide protection or individual protection. **Wide protection** We use the middleware in the global scope, all the routes below it are now protected. ```javascript= // Not protected router.use('/auth', ...) router.use('/public', ...) // middleware router.use(isAuthenticated) // Need to be authenticated router.use('/user', ...) // ... router.use(isAdmin) // Need to be an admin router.use('/dashboard', ...) // ... ``` **Individual protection** Some routes might need some punctual protection. ```javascript= router.post("/vote", isAdminOrAlumni, ...) ``` > An admin or an Alumni can post on this route, a student cannot. ### Route usage - Knowing who the logged in user is allow us sometime to not need some extra informations. - To update a ressource, we used to need the id of the ressource which we wanted to update, typically in the `params` of the url. - Usually a user can only update something which belong to him. By going through the isAuthenticated middleware we know who the user is. **Before** ```javascript= router.patch("/profile/:id", isAuthenticated, async (req, res, next) => { try { User.findByIdAndUpdate(req.params.id, ...) // ... } catch (error) { next(error) } }) ``` > Anyone with a lot of time to loose can update any profile. **After** ```javascript= router.patch("/profile", isAuthenticated, async (req, res, next) => { try { User.findByIdAndUpdate(req.user._id, ...) // ... } catch (error) { next(error) } }) ``` > The user can only update the profile associated to his token (statistically, his profile then.)