Creating JSON Web Tokens using graphQL, MongoDB and express.js

Aniket Kambli
Udgama Blog
Published in
4 min readMar 31, 2020

Authentication is an important part of any application, we do not want anyone unauthenticated to come and access our website. Also the resources provided by the application should be accessible only by the authorized users and not anyone. Suppose you work in a company then if you are in the Human Resource department, you should only be authorized to use the data and tools of that particular department and not of others such as finance or marketing. In this blog, I will show you how to create a JWT token that authenticates a user and checks if the user is present in our database or not.

Introduction to JSON Web Tokens(JWT):

JSON Web token is a secure and encrypted format used for transferring data between two devices.

JSON web tokens are encoded tokens which consist of three parts, the header which contains information like the type of the token and the algorithm used. The payload section consists of information of the user like name, email, if he/she is admin or not and so on. The third part is the signature which is a combination of the header, payload and the secret key which was used to encode the token.

Encoded JSON token

So now that you have a basic idea of what are JSON token let’s get our hands dirty and start coding.

This is what my App.js looks like in this I am connecting to my MongoDB database and importing all my models and resolvers.

const express = require("express");
const bodyParser = require("body-parser");
const graphqlHttp = require("express-graphql");
var mongoose = require("mongoose");
const isAuth = require("./middleware/is-auth");
const app = express();
const graphQlSchema = require("./graphql/schema/index");
const graphQlResolvers = require("./graphql/resolvers/index");
app.use(bodyParser.json());
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS");
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
if (req.method === "OPTIONS") {
return res.sendStatus(200);
}
next();
});
app.use(isAuth);
app.use(
"/graphql",
graphqlHttp({
schema: graphQlSchema,
rootValue: graphQlResolvers,
graphiql: true
})
);
mongoose
.connect(
`mongodb+srv://${process.env.MONGO_USER}:${@cluster0-mmato.mongodb.net">process.env.MONGO_PASSWORD}@cluster0-mmato.mongodb.net/${process.env.MONGO_DB}?retryWrites=true&w=majority`,
{ useNewUrlParser: true, useUnifiedTopology: true }
)
.then(() => {
app.listen(5000);
})
.catch(err => {
console.log(err);
});

This is what my graphQL schema looks like, it consist of an employee who has email and password and my AuthData which has a token field that we will use for storing JWT tokens.

const { buildSchema } = require("graphql");module.exports = buildSchema(`

type Employee{
_id: ID!
email:String!
password: String

}
type AuthData {
employeeId: ID!
token: String!
tokenExpiration: Int!
}
};

This is the login query which we send from our application to create a token.

const requestBody = {
query: `
query {
login(email: "${email}", password: "${pass}") {
employeeId
token

}
}
`,
};
fetch('http://localhost:8000/graphql', {
method: 'POST',
body: JSON.stringify(requestBody),
headers: {
'Content-Type': 'application/json',
},
})
.then(res => {
if (res.status !== 200 && res.status !== 201) {
throw new Error('Failed!');
}
return res.json();
})
.then(resData => {
if (resData.data.login.token) {
props.dispatch({ type: 'TOKEN', payload: resData.data.login.token });
}
console.log(resData);
})
.catch(err => {
console.log(err);
});
console.log(email, pass);

This is the resolver that will resolve our login query which checks if the user is present in our database or not and if yes then it will create a token and return that token to our application which we can further use for authentication and authorization.

login: async ({ email, password }) => {
const employee = await Employee.findOne({ email: email });
if (!employee) {
throw new Error("User does not exist!");
}
const isEqual = await bcrypt.compare(password, employee.password);
if (!isEqual) {
throw new Error("Password is incorrect!");
}
const token = jwt.sign(
{ employeeId: employee.id, email: employee.email },
"keyusedforencodingtoken",
{
expiresIn: "1h"
}
);
return { employeeId: employee.id, token: token, tokenExpiration: 1 };
}

This is how my graphiQL window looks like when I perform a login query and get the token from the graphQL server.

GraphiQL window

Conclusion

JSON web tokens are an easy and effective way of transferring data as they are lightweight and can carry information about the user so the server need not have to query the database again and again for details of the user. JWT is widely used for authorization purposes in many applications.

--

--