My own realtime chat with react, graphql and postgresql [part 2-Authentication]
Tags: graphql, node, postgres, authentication
Published: 2020-10-16 16:21:03

So, in this second part ([First part](https://dev.to/dalejan/your-own-realtime-chat-with-react-graphql-and-postgresql-4mj8)) we are going to configure our backend to allow us sign up and sign in into our chat app!

In our users.js file we have to do a little bit more than before:
####Users
*./sql/users.js*
```javascript
const bcrypt = require("bcryptjs"); 
const crypto = require("crypto"); 
const db = require("../db.js"); 
```
`bcrypt` is a hashing function that we will use to safely store the users passwords.
And `crypto` provide us  cryptographic functionality that we will use to tokenize the user session.

```javascript
const signup = (user) => {
  return hashPassword(user.password)
    .then((hashedPassword) => {
      delete user.password;
      user.password_digested = hashedPassword;
    })
    .then(() => createToken())
    .then((token) => (user.token = token))
    .then(() => createUser(user))
    .then((user) => {
      delete user.password_digested;
      return user;
    })
    .catch((err) => {
      console.log(err);
      return err;
    });
};

const hashPassword = (password) => {
  return new Promise((resolve, reject) =>
    bcrypt.hash(password, 10, (err, hash) => {
      err ? reject(err) : resolve(hash);
    })
  );
};

const createToken = () => {
  return new Promise((resolve, reject) => {
    crypto.randomBytes(16, (err, data) => {
      err ? reject(err) : resolve(data.toString("base64"));
    });
  });
};

const createUser = (user) => {
  return db
    .raw(
      "INSERT INTO users ( usr, name, password_digested, token, type) VALUES (?, ?, ?, ?, ?) RETURNING  usr, name, type, token",
      [user.usr, user.name, user.password_digested, user.token, user.type]
    )
    .then((data) => data.rows[0]);
};
```
So basically we've create an signup-flow. Lets break down that code a litle.

1. In the `signup` funciton im hoping to recive a user object that is composed by username, password and type.

2. Then we hash the password in the `hashPassword` function, which uses [bcrypt.hash()](https://www.npmjs.com/package/bcrypt) to salt and hash the user password.

3. After that, we now can delete the user password from our records and only care about the hashedPassword. So at this moment we start to create an user object based on the model defined at the migrations models.

4. Then we create a token for this session with `createToken` function, that uses [crypto.randomBytes()](https://nodejs.org/api/crypto.html#crypto_crypto) to get a base64 string. We also add this attribute to the user object.

5. Finally we use `createUser` to... well, order some pizza. This function uses the db knex object to insert into the users table that user object we've been composing.

Now we are building the signin-flow:

```javascript
const signin = (userReq) => {
  let user;
  return findUser(userReq.usr)
    .then((foundUser) => {
      user = foundUser;
      return checkPassword(userReq.password, foundUser);
    })
    .then((res) => createToken())
    .then((token) => updateUserToken(token, user))
    .then(
      () => {
        delete user.password_digested;
        return user;
      },
      (err) => {
        return "User not found, please verify the fields";
      }
    )
    .catch((err) => {
      console.log(err);
      return "Cannot signin, please get in touch with the admin";
    });
};


const findUser = (usr) => {
  console.log(usr);
  return db
    .raw("SELECT * FROM users WHERE usr = ?", [usr])
    .then((data) => data.rows[0]);
};

const checkPassword = (reqPassword, foundUser) => {
  return new Promise((resolve, reject) =>
    bcrypt.compare(
      reqPassword,
      foundUser.password_digested,
      (err, response) => {
        if (err) {
          reject(err);
        } else if (response) {
          resolve(response);
        } else {
          reject(new Error("Verify your password"));
        }
      }
    )
  );
};

const updateUserToken = (token, user) => {
  return db
    .raw("UPDATE users SET token = ? WHERE usr = ? RETURNING  usr, token", [
      token,
      user.usr,
    ])
    .then((data) => data.rows[0]);
};
```
**Lets break it down!**

1. In the `signin` function i hope to get as a parameter an user object composed by username and password.

2. Using sql queries in the `findUser` function we can get the user that is stored (if it exists).

3. Then with the `checkPassword` function we can verify if there is a match between the password stored and the one the user is trying. This is posible thanks to `bcrypt.compare` function.

4. After that we use again the `createToken` function to tokenize the current session, and then we use `updateUserToken` to change the token stored.

5. Finally we send a response of the user authenticated but without his hashed password.

Ok so we've created our signin signup flow, now we can access this functions by exporting them:

```javascript
module.exports = {
  signin,
  signup,
  findUser,
};

```

In the [next part](https://dev.to/dalejan/my-own-realtime-chat-with-react-graphql-and-postgresql-part-3-graphql-schemas-491g) we'll be setting our graphql schemas and subscription to fetch messages and signin and signup usign graphql!