In this section, you’re going to implement signup and login functionality that allows your users to authenticate against your GraphQL server.
User modelThe first thing you need is a way to represent user data in the database. You can achieve that by adding a User type to your Prisma datamodel.
You also want to add a relation between the User and the already existing Link type to express that Links are posted by Users.
You’re adding a new relation field called postedBy to the Link type that points to a User instance. The User type then has a links field that’s a list of Links. This is how you express a one-to-many relationship using SDL.
After every change you’re making to the datamodel file, you need to redeploy the Prisma API to apply your changes and migrate the underlying database schema.
This now updated the Prisma API. You also need to update the auto-generated Prisma client so that it can expose CRUD methods for the newly added User model.
Right now, it is a bit annoying that you need to explicitly run prisma generate every time you’re migrating your database with prisma deploy. To make that easier in the future, you can configure a post-deployment hook that gets invoked every time after you ran prisma deploy.
The Prisma client will now automatically be regenerated upon a datamodel change.
Remember the process of schema-driven development? It all starts with extending your schema definition with the new operations that you want to add to the API - in this case a signup and login mutation.
Next, go ahead and add the AuthPayload along with a User type definition to the file.
The signup and login mutations behave very similar. Both return information about the User who’s signing up (or logging in) as well as a token which can be used to authenticate subsequent requests against your GraphQL API. This information is bundled in the AuthPayload type.
After extending the schema definition with the new operations, you need to implement resolver functions for them. Before doing so, let’s actually refactor your code a bit to keep it more modular!
You’ll pull out the resolvers for each type into their own files.
Next, move the implementation of the feed resolver into Query.js.
This is pretty straighforward. You’re just reimplementing the same functionality from before with a dedicated function in a different file. The Mutation resolvers are next.
Let’s use the good ol’ numbered comments again to understand what’s going on here - starting with signup.
signup mutation, the first thing to do is encrypting the User’s password using the bcryptjs library which you’ll install soon.prisma client instance to store the new User in the database.APP_SECRET. You still need to create this APP_SECRET and also install the jwt library that’s used here.token and the user in an object that adheres to the shape of an AuthPayload object from your GraphQL schema.Now on the login mutation:
User object, you’re now using the prisma client instance to retrieve the existing User record by the email address that was sent along as an argument in the login mutation. If no User with that email address was found, you’re returning a corresponding error.token and user again.Let’s go and finish up the implementation.
Next, you’ll create a few utilities that are being reused in a few places.
The APP_SECRET is used to sign the JWTs which you’re issuing for your users.
The getUserId function is a helper function that you’ll call in resolvers which require authentication (such as post). It first retrieves the Authorization header (which contains the User’s JWT) from the context. It then verifies the JWT and retrieves the User’s ID from it. Notice that if that process is not successful for any reason, the function will throw an exception. You can therefore use it to “protect” the resolvers which require authentication.
Right now, there’s one more minor issue. You’re accessing a request object on the context. However, when initializing the context, you’re really only attaching the prisma client instance to it - there’s no request object yet that could be accessed.
Instead of attaching an object directly, you’re now creating the context as a function which returns the context. The advantage of this approach is that you can attach the HTTP request that carries the incoming GraphQL query (or mutation) to the context as well. This will allow your resolvers to read the Authorization header and validate if the user who submitted the request is eligible to perform the requested operation.
post mutationBefore you’re going to test your authentication flow, make sure to complete your schema/resolver setup. Right now the post resolver is still missing.
Two things have changed in the implementation compared to the previous implementation in index.js:
getUserId function to retrieve the ID of the User. This ID is stored in the JWT that’s set at the Authorization header of the incoming HTTP request. Therefore, you know which User is creating the Link here. Recall that an unsuccessful retrieval of the userId will lead to an exception and the function scope is exited before the createLink mutation is invoked. In that case, the GraphQL response will just contain an error indicating that the user was not authenticated.userId to connect the Link to be created with the User who is creating it. This is happening through a nested object write.There’s one more thing you need to do before you can launch the GraphQL server again and test the new functionality: Ensuring the relation between User and Link gets properly resolved.
Notice how we’ve omitted all resolvers for scalar values from the User and Link types? These are following the simple pattern that we saw at the beginning of the tutorial:
Link: {
id: parent => parent.id,
url: parent => parent.url,
description: parent => parent.description,
}However, we’ve now added two fields to our GraphQL schema that can not be resolved in the same way: postedBy on Link and links on User. These fields need to be explicitly implemented because our GraphQL server can not infer where to get that data from.
In the postedBy resolver, you’re first fetching the Link using the prisma client instance and then invoke postedBy on it. Notice that the resolver needs to be called postedBy because it resolves the postedBy field from the Link type in schema.graphql.
You can resolve the links relation in a similar way.
Awesome! The last thing you need to do now is use the new resolver implementations in index.js.
That’s it, you’re ready to test the authentication flow! 🔓
The very first thing you’ll do is test the signup mutation and thereby create a new User in the database.
Note that you can “reuse” your Playground from before if you still have it open - it’s only important that you’re restarting the server so the changes you made to the implementation are actually applied.
Whenever you’re now sending a query/mutation from that tab, it will carry the authentication token.

When your server receives this mutation, it invokes the post resolver and therefore validates the provided JWT. Additionally, the new Link that was created is now connected to the User for which you previously sent the signup mutation.
To verify everything worked, you can send the following login mutation:
mutation {
login(
email: "alice@prisma.io"
password: "graphql"
) {
token
user {
email
links {
url
description
}
}
}
}
This will return a response similar to this:
{
"data": {
"login": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJjanBzaHVsazJoM3lqMDk0NzZzd2JrOHVnIiwiaWF0IjoxNTQ1MDYyNTQyfQ.KjGZTxr1jyJH7HcT_0glRInBef37OKCTDl0tZzogekw",
"user": {
"email": "alice@prisma.io",
"links": [
{
"url": "www.graphqlconf.org",
"description": "An awesome GraphQL conference"
}
]
}
}
}
}