Skip to content

Instantly share code, notes, and snippets.

@thuyanduong
Last active February 8, 2023 16:41
Show Gist options
  • Save thuyanduong/6f9566b706f68e3b6fef215ce0e8bbfe to your computer and use it in GitHub Desktop.
Save thuyanduong/6f9566b706f68e3b6fef215ce0e8bbfe to your computer and use it in GitHub Desktop.
Backend Registration, Log-in and Auth

What is the difference between Registration, Log-in, and Authentication?

0. Review and Refactor

  • GET /robots
  • GET /users/:id
  • How do we NOT send back the password in the response?
  • What happens if we request a user that does not exist?
// Refactor response to NOT send back the password
static async getSingleUserFromDB(userId){
  const query = await pool.query("SELECT id, username, bio FROM users WHERE id = $1", [userId])
  return query.rows[0]
}
// Refactor code to return a 404 if the user doesn't exist in our DB
async function getSingleUser (req, res) {
  const userId = req.params.id
  const user = await UserModel.getSingleUserFromDB(userId) //async
  if(user){
    const usersRobots = await UserModel.getUsersRobotsFromDB(userId)
    res.send({user, usersRobots})
  }else{
    res.sendStatus(404)
  }
}

1. Building out Registration

  • We are going to build out the route POST /users/register.
  • What should be in the body of the request?
  • What should our server respond with if the registration was successful?
  • What should our server respond with if the registration was unsuccessful?
//userRouter.js
router.post('/register', registerUser)
//index.js
app.use(express.json())
//userController.js
async function registerUser (req, res) {
  let {username, bio, password} = req.body 
  try{
    const createdUser = await UserModel.createUserinDB(username, bio, password)
    res.send(createdUser)
  }catch(e){
    res.status(400).send(e)
  }
}
//userModel.js
static async createUserinDB(username, bio, password){
  let query = await pool.query(
    "INSERT INTO users (username, bio, password)VALUES ($1, $2, $3) RETURNING id, username, bio;", 
    [username, bio, password]
  )
  return query.rows[0]
}

2. Building out Log-in

  • We are going to build out the route POST /users/login.
  • Why a POST and not a GET request?
  • What should be in the body of the request?
  • What should our server respond with if the login was successful?
  • What should our server respond with if the login was unsuccessful?
//userRouter.js
router.post('/login', loginUser)
//userController.js
async function loginUser(req, res){
  let {username, password} = req.body 
  const foundUser = await UserModel.loginUser(username, password)
  if(foundUser){
    res.send(foundUser)
  }else{
    res.status(401).send("invalid username or password")
  }
}
//userModel.js
static async loginUser(username, password){
  let query = await pool.query(
    "SELECT * FROM users WHERE username = $1 AND password = $2", 
    [username, password]
  )
  return query.rows[0]
}

3. Building out Secure Authentication

  • We will npm install bcrypt.
  • Bcrypt Documentation
  • bcrypt.hashSync(plaintextPassword, numOfHashRounds) will take a plaintext password and return it hashed.
  • bcrypt.compareSync(plaintextPassword, hash) will return a boolean (true or false) is the password matches the hash!
const bcrypt = require('bcrypt')
// seeds/data.js
await knex('users').insert([
  {username: 'caston', bio: 'My name is Caston!', password: bcrypt.hashSync('123', 10)},
  {username: 'jowel', bio: 'I am Jowel!', password: bcrypt.hashSync('456', 10)},
  {username: 'ana', bio: 'Ana here!', password: bcrypt.hashSync('789', 10)}
]);
// userController.js
async function registerUser (req, res) {
  let {username, bio, password} = req.body 
  let hashedPassword = bcrypt.hashSync(password, 10)
  try{
    const createdUser = await UserModel.createUserinDB(username, bio, hashedPassword)
    res.send(createdUser)
  }catch(e){
    res.status(400).send(e)
  }
}

async function loginUser(req, res){
  let {username, password} = req.body 
  const foundUser = await UserModel.loginUser(username)
  if(foundUser && bcrypt.compareSync(password, foundUser.password)){
    res.send(foundUser)
  }else{
    res.status(401).send("invalid username or password")
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment