Skip to content

Instantly share code, notes, and snippets.

@OlivierJM
Last active May 27, 2019 16:58
Show Gist options
  • Select an option

  • Save OlivierJM/c873e650b678d1be80ecff310bbe3b31 to your computer and use it in GitHub Desktop.

Select an option

Save OlivierJM/c873e650b678d1be80ecff310bbe3b31 to your computer and use it in GitHub Desktop.
demo on how to perform basic authentication and authorization in graphql
const { ApolloServer, gql } = require("apollo-server");
const jwt = require("jsonwebtoken");
const mongoose = require("mongoose");
const bcrypt = require("bcrypt");
const pick = require("lodash").pick;
// configure the user collection
const userSchema = mongoose.Schema({
email: String,
password: String
});
const User = mongoose.model("User", userSchema);
// connect to mongodb here
mongoose.Promise = global.Promise;
mongoose.connect(
`mongodb://${process.env.USER}:${
process.env.PASS
}@ds261716.mlab.com:61716/user-test`,
{ useNewUrlParser: true }
);
// Construct a schema, using GraphQL schema language
const typeDefs = gql`
type Query {
user: User
}
type Mutation {
register(email: String, password: String): User!
login(email: String, password: String): String!
}
type User {
email: String
password: String
}
`;
// keep this secret in a safe env and make it as strong as possible
const SECRET = "createaverystrongsec34!retthatalsoincludes2423412wdsa324e34e";
// Provide resolver functions for your schema fields
const resolvers = {
Query: {
user(root, args, { user }) {
return user;
},
users(root, args, { user }) {
// check if is logged before giving them other user's info
if (!user) {
throw new Error("You are not logged in to access this information ");
}
return User.find({});
}
},
Mutation: {
register: async (root, args) => {
const user = User();
// we will get the email and password from the args object
user.email = args.email;
user.password = await bcrypt.hash(args.password, 12);
// save the user to the db
return user.save();
},
login: async (root, args, context) => {
// check if the user exists
const user = await User.findOne({ email: args.email });
if (!user) {
throw new Error("No user found ");
}
// check if the password matches the hashed one we already have
const isValid = await bcrypt.compare(args.password, user.password);
if (!isValid) {
throw new Error("Incorrect password ");
}
// sign in the user
// if the user exist then create a token for them
const token = await jwt.sign(
{
user: pick(user, ["_id", "email"])
},
SECRET,
// this token will last for a day, but you can change it
// check the jsonwebtoken for more on this
{ expiresIn: "1d" }
);
return token;
}
}
};
const server = new ApolloServer({
typeDefs,
resolvers,
// you can catch all the request in the context
context: async ({ req }) => {
const token = await req.headers["authentication"];
let user;
try {
user = await jwt.verify(token, SECRET);
console.log(`${user.user} user`);
} catch (error) {
console.log(`${error.message} caught`);
}
// the user and secret we are passing here is what we access in every resolver
return {
user,
SECRET
};
}
});
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment