Implementing Authentication using JWT, Bcrypt and GraphQL Nexus
Tags: graphql, javascript, authentication, tutorial
Published: 2019-05-02 21:13:55

---
title: Implementing Authentication using JWT, Bcrypt and GraphQL Nexus
published: true
description: You’ve finished coding the skeleton for your application, but it’s missing one thing — authentication.
tags: GraphQL, Javascript, Authentication, Tutorial, 
---
You’ve finished coding the skeleton for your application, but it’s missing one thing — authentication. This can be added using [JSON Web Tokens](https://jwt.io/) and Bcrypt. The basis of this tutorial should be similar for most schema construction frameworks, but we will be using [GraphQL Nexus](https://nexus.js.org/). We’re also using [Prisma](https://www.prisma.io/) as our ORM, but any other ORM or database would work.

This tutorial assumes you have knowledge of GraphQL mutations, queries, resolvers, and context- If you don’t know GraphQL, [How to GraphQL](https://howtographql.com/) is a great place to start.

The final application will allow users to create an account and log in by storing and using a JSON Web Token. JWTs are strings that contain information to transfer between parties and are a great way to authenticate users because they can securely store user information and provide a digital signature.

Our application will allow users to log in and register using these JWTs. On the backend, we will create a payload, add a JWT secret, and set up login and signup mutations to properly generate authorization headers. On the frontend, we’ll pass an authorization token into our headers, and set up our queries to get the current logged in user.

#### Backend

#### 1. Installing Our Tools 🛠

First thing’s first, we’ll need to install Bcrypt and JSON Web Tokens!

```
yarn add bcrypt jsonwebtoken
```

Now you’re ready to get started✨

#### 2. Creating our JWT Secret 🗝️

We can set up our JWT secret- in our `config.ts` file, the following was added:

```
export default {  
  ...  
  jwt: {  
    JWT_SECRET: 'super-secret',  
  },  
}
```

#### 3. Creating the Payload 🚚

For us to properly return the token and user information to the requester, we need to set up a payload.

```
export const UserLoginPayload = objectType({  
  name: 'UserLoginPayload',  
  definition: t =&gt; {  
    t.field('user', {  
      type: 'User',  
    })  
    t.string('token')  
  },  
})
```

What we’re doing here is creating an object type named  `userLoginPayload`. We define the type as being able to return our `User` field, along with the token generated when the user registers or logs in.

#### 4. Setting up the Login and Signup Mutations 🚪🚶

To set up user registration and login, we create two new mutation fields, `userLogin` and `userRegister`. We can set the return type to `UserLoginPayload` to return the `User` and a `token`, and our arguments are the username and password collected from a form in the frontend. Here is what the mutations would look like in GraphQL Nexus:

```
export const userLogin = mutationField('userLogin', {  
  type: UserLoginPayload,  
  args: {  
    username: stringArg({ required: true }),  
    password: stringArg({ required: true }),  
  },  
})

export const userRegister = mutationField('userRegister', {  
  type: UserLoginPayload,  
  args: {  
    username: stringArg({ required: true }),  
    password: stringArg({ required: true }),  
  },  
})
```

After this, a resolver is added to the mutations.

```
export const userLogin = mutationField('userLogin', {  
  type: UserLoginPayload,  
  args: {  
    username: stringArg({ required: true }),  
    password: stringArg({ required: true }),  
  },  
  resolve: async (root, args, context, info) =&gt; {  
    try {  
      const { password, ...user } = await context.prisma.user({  
        where: {  
          userName: args.username,  
        },  
      })  
      var validpass = await bcrypt.compareSync(args.password, password)  
      if (validpass) {  
        const token = jwt.sign(user, config.jwt.JWT_SECRET)  
        return {  
          user: user,  
          token,  
        }  
      }  
      return null  
    } catch (e) {  
      console.log(e)  
    }  
  },  
})
```

We’ve added our resolver. This might be a bit overwhelming, so let’s break it up into pieces.

```
const { password, ...user } = await context.prisma.user({  
        where: {  
          userName: args.username,  
        },  
      })
```

Here, we’re trying to get `User` data. `await context.prisma.users({where: {userName: args.username}` gets our `User` information from the database, storing the information in `password, ...user`. We've separated the password so it won't be included in our user variable or the JSON Web Token data, as shown in the next step.

```
var validpass = await bcrypt.compareSync(args.password, password)  
      if (validpass) {  
        const token = jwt.sign(user, config.jwt.JWT_SECRET)  
        return {  
          user: user,  
          token,  
        }  
      }  
      return null
```

We use Bcrypt to compare to see if our password values are equal. If the passwords match, a JWT is generated using our JWT secret from the config file and `user`. (If we didn't separate the password data beforehand, it would have been returned with the user data and stored in the JWT 😱!) Though at last, we're now returning our payload (the `user` data along with the JWT)!

The process for registration is relatively similar.

```
export const userRegister = mutationField('userRegister', {  
  type: UserLoginPayload,  
  args: {  
    username: stringArg({ required: true }),  
    password: stringArg({ required: true }),  
  },  
  resolve: async (root, args, context) =&gt; {  
    try {  
      const existingUser = await context.prisma.user({  
        where: {  
          userName: args.username,  
        },  
      })  
      if (existingUser) {  
        throw new Error('ERROR: Username already used.')  
      }  
      var hash = bcrypt.hashSync(args.password, 10)

      const { password, ...register } = await context.prisma.createUser({  
        userName: args.username,  
        password: hash,  
      })  
      const token = jwt.sign(register, config.jwt.JWT_SECRET)  
      return {  
        user: register,  
        token: token,  
      }  
    } catch (e) {  
      console.log(e)  
      return null  
    }  
  },  
})
```

Let’s break this up again.

```
const existingUser = await context.prisma.user({  
        where: {  
          userName: args.username,  
        },  
      })  
      if (existingUser) {  
        throw new Error('ERROR: Username already used.')  
      }
```

Previously, we queried to see if a username existed. This is relatively the same, only now we are throwing an error if something is returned because each username should be unique.

```
var hash = bcrypt.hashSync(args.password, 10)

      const { password, ...register } = await context.prisma.createUser({  
        userName: args.username,  
        password: hash,  
      })
```

We hash the password passed into the form using bcrypt, passing in the password and the salt length we want to generate. After that, the `createUser` mutation makes a new user with our username and newly hashed password.

```
const token = jwt.sign(register, config.jwt.JWT_SECRET)  
      return {  
        user: register,  
        token: token,  
      }
```

The payload is generated and returned in the same way as the user login.

#### 5. Adding User to the Context 🧮

Our user can now log in and register! Now we can create a query and viewer field to return that information to the frontend.

Let’s start out by adding the current user to the context.

```
export interface Context {  
  prisma: Prisma  
  currentUser: User  
}

export default async ({ req }) =&gt; {  
  const currentUser = await getUser(  
    req.get('Authorization'),  
    config.jwt,  
    prisma,  
  )  
  return {  
    prisma,  
    currentUser  
  }  
}
```

Here, we’re adding the variable `currentUser` of type `User` to be exported from our `Context`. We can use a `getUser` function (we'll go over how to make this function in the next step- in summary, it returns our `User` type) to return our user's information by passing in our token with `req.get('Authorization')` (which fetches our token from our header), our JWT secret, and the Prisma client.

#### 6. Creating a getUser Function 👶

Because we want to query for user information in our application, we need to get our user’s token from the headers.

```
export default async (authorization, secrets, prisma: Prisma) =&gt; {  
  const bearerLength = 'Bearer '.length  
  if (authorization && authorization.length &gt; bearerLength) {  
    const token = authorization.slice(bearerLength)  
    const { ok, result } = await new Promise(resolve =&gt;  
      jwt.verify(token, secrets.JWT_SECRET, (err, result) =&gt; {  
        if (err) {  
          resolve({  
            ok: false,  
            result: err,  
          })  
        } else {  
          resolve({  
            ok: true,  
            result,  
          })  
        }  
      }),  
    )  
    if (ok) {  
      const user = await prisma.user({  
        id: result.id,  
      })  
      return user  
    } else {  
      console.error(result)  
      return null  
    }  
  }  
  return null  
}
```

Let’s go through this step by step.

```
const bearerLength = 'Bearer '.length  
  if (authorization && authorization.length &gt; bearerLength) {  
    const token = authorization.slice(bearerLength)  
    ...  
  }  
  return null  
}
```

Here we have some basic error checking to see if the token is longer than our `Bearer` string- If it is, we can extract the token by slicing off the `Bearer` string.

```
const { ok, result } = await new Promise(resolve =&gt;  
      jwt.verify(token, secrets.JWT_SECRET, (err, result) =&gt; {  
        if (err) {  
          resolve({  
            ok: false,  
            result: err,  
          })  
        } else {  
          resolve({  
            ok: true,  
            result,  
          })  
        }  
      })  
    )
```

Now we are verifying the token with our secret, and resolving our promise with whether the passed in token was valid or not, along with the `result` from our JWT (which is our `user` type).

```
if (ok) {  
      const user = await prisma.user({  
        id: result.id,  
      })  
      return user  
    } else {  
      console.error(result)  
      return null  
    }  
  }
```

Lastly, if the token was valid, we query for the user with the ID we got from our token and return it!

#### 7. Creating a User Query and Viewer Field 🔬

We can create a viewer field and user query so we are able to query for the currently logged in user’s information in our application.

```
t.string('getCurrentUser', {  
  resolve: async (root, args, context, info) =&gt; {  
    return context.prisma.user  
  },  
})
```

We can create a new query, `getCurrentUser`- this returns the value of what we got in our `Context` function, making it so we can now easily query for whatever user is currently logged in!

Lastly, we should add a `viewer` field to our query.

```
t.field('viewer', {  
      type: 'User',  
      nullable: true,  
      resolve: (root, args, context) =&gt; {  
        return context.currentUser  
      },  
    })
```

This simply returns the `currentUser` that we added to our context.

#### Frontend

#### 1. Login and Registration 💎

Now that our backend is complete, we can implement a simple frontend solution using the resolvers we created in the backend.

```
const SIGNUP_MUTATION = gql`  
  mutation UserRegister($username: String!, $password: String!) {  
    userRegister(username: $username, password: $password) {  
      user {  
        id  
        userName  
      }  
      token  
    }  
  }  
`;
```

Here is a simple signup mutation that creates a new user when the form is submitted. We are using the `userRegister` function that we created on the backend, and simply passing in a username and password while returning any desired information.

```
&lt;Mutation  
    mutation={SIGNUP_MUTATION}  
    onCompleted={data =&gt; _confirm(data)}  
  &gt;  
...  
&lt;/Mutation&gt;
```

Next, we can add the signup mutation to our `Mutation` component provided by `react-apollo`. When the mutation is completed, we call the function `_confirm`.

```
_confirm = async data =&gt; {  
  const { token } = data.userLogin;  
  this._saveUserData(token);  
};

_saveUserData = async token =&gt; {  
  try {  
    await AsyncStorage.setItem(AUTH_TOKEN, token);  
  } catch (e) {  
    console.log("ERROR: ", e);  
  }  
};
```

What our `_confirm` function does is take the `data` we were returned from our mutation and extracts the token from it, passing it to `_saveUserData`. This function stores the `token` in `AsyncStorage` (if you're not developing using Native, the token would be stored in `LocalStorage`).

WARNING: As a side note, using localStorage to store our JWT isn’t the best practice in production- you can read more about that [here](https://github.com/howtographql/howtographql/issues/550). 

The process for logging in is extremely similar, we would just swap out our `SIGNUP_MUTATION` with our `LOGIN_MUTATION`.

#### 2. Inserting the token into the header 💯

```
const authLink = setContext(async (_, { headers }) =&gt; {  
  const token = await AsyncStorage.getItem(AUTH_TOKEN);  
  return {  
    headers: {  
      ...headers,  
      authorization: token ? `Bearer ${token}` : ""  
    }  
  };  
});
```

We are using `apollo-link-context`'s `setContext` function to set the headers of our application. We are getting our authorization token from `AsyncStorage` and then storing it in our header.

#### 3. Querying for User Info 🙆

Because of all of our hard work, we can query for the user’s information anywhere we want in the app- Yep, it’s that simple!

```
const GET_USER = gql`  
  query getUser {  
    viewer {  
      id  
    }  
  }  
`;
```

#### Conclusion

And with that, your authentication is now set up! We have now created resolvers to return the desired payload and can query for the current logged in user anywhere in the application. This tutorial was inspired by Spencer Carli’s great tutorial, [GraphQL Authentication with React Native & Apollo](https://medium.com/handlebar-labs/graphql-authentication-with-react-native-apollo-part-1-2-9613aacd80b3) — give it a look if you’d like a more in-depth look on the things we went over in this tutorial. If you have any questions or suggestions, feel free to leave a comment, reach out to us on [Twitter](http://twitter.com/novvumio), or over on [our website] (http://novvum.io). Thank you!