Last active
May 27, 2019 16:58
-
-
Save OlivierJM/c873e650b678d1be80ecff310bbe3b31 to your computer and use it in GitHub Desktop.
demo on how to perform basic authentication and authorization in graphql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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