Server-Side GraphQL in Next.js

Testing the Authentication Routes

Scott Moss

Scott Moss

Superfilter AI
Server-Side GraphQL in Next.js

Check out a free preview of the full Server-Side GraphQL in Next.js course

The "Testing the Authentication Routes" Lesson is part of the full, Server-Side GraphQL in Next.js course featured in this preview video. Here's what you'd learn in this lesson:

Scott explains how to configure the global context to retrieve the current user if an authorization header is set. He demonstrates how to add a context property to the Apollo server configuration and writes a function that retrieves the user from the authorization header.


Transcript from the "Testing the Authentication Routes" Lesson

>> Scott Moss: One of the last things we need to do is we just need to configure our global context to get the current user if a authorization header is set. So it's attached to the context. So we can then use it in all our resolvers, which is necessary for the me query, which is expecting a user on the context object so it can return it.

So let's do that. We can go to our route.ts in the GraphQL file. We can go down to where we are making a new Apollo server, I'm sorry, a new handler. And then that object that I had there, you can pass in a context property, which runs a function and returns some things.

So let's do that. So in this object, we're gonna pass a context property. So I run a function here. It's gonna be async.
>> Scott Moss: And basically, you get access to the request object here. Basically the whole point of this is, hey, this function runs before the server executes.

I think it runs after validation, though. So assuming the query you sent is validated, then this runs, and then your resolver start to run. So I believe this runs after validation. I could be wrong, but I'm pretty sure it does. But either way, it runs before your resolvers do, which is the most important part.

So the whole strategy here is, use this function, get user from token, pass in the request headers, the authorization header, and then get the optional user. Don't enforce it, this might be null, and that's fine. We don't wanna enforce it. If we said, cool, not user, throw error, then no one could ever sign in or sign up, cuz this runs before that, right?

So we don't wanna enforce it, we just wanna try to get it. So, get, what is it called? GetUserFromToken, req.headers.get. Headers is a set, so you have to do a get method on it. Get the authorization header, that's where the client is sending the token, or just default to an empty string.

And then just return an object with the requests and the optional user, possible user.
>> Scott Moss: So there we go. So now our app is bulletproof, nobody can hack us, we're good. So let's try it. Let's go back to our Apollo server, make sure nothing is broken. Looks like, nice, I'm glad we saw this.

I've been trying to, yes. Okay, so look, look at this, mutation.signup defined, and resolvers were not in schema. So that's so great that it said that, cuz check this out. In my resolvers, I called this signup, right?
>> Speaker 2: Right.
>> Scott Moss: You probably already caught this, you're probably, what is he doing?

But in my mutation, it's called createUser, right? So I gotta change one of them. And I like that. You cannot make a resolver for something that doesn't exist in your schema, and it will scream at you until you do it, right? So I'm gonna go change my resolver too.

Check up above, you may already have it. Do I? I think. Let's see.
>> Speaker 2: No.
>> Scott Moss: No, yeah, I don't have it. Yeah, it would be kinda mutation, yep. So I'm gonna call this createUser. And I think it's like, okay, cool, that works. So that's beautiful. I can't tell you how many times I've built API's like, why is this not working, or this or that.

And it's like, I just named it something different or weird, or I've registered this route before this route. So this route never ran, or something weird like that. You'll have any of those problems with GraphQL. The order in which your resolvers run are dependent on the query that is sent.

You have no control. The GraphQL resolvers have no control or idea on how the order of the resolvers are going to run, because the resolvers respond to the query that is coming in. So anyway, let's sign up. So if you got your database credentials, you got all that stuff, good to go.

You pushed your database scheme up when we first started to Turso, you should be able to create a user. So let's create a user. I'm going to say, cool. I need at least the token here, I need the ID. Let me get the email. For my inputs, I'm gonna do email and password.

Let me get rid of this old one that I have here. So let's give it a email.
>> Scott Moss: I'm gonna say,, and the password is bigcat, cuz he's a bigcat. And let's run this.
>> Scott Moss: Boom, so you can see right here, I was able to create a user.

Here's my adjacent web token, here's my id, here's my email.
>> Scott Moss: If I try to do this again, given the database constraints, I'm going to most likely get an error. There we go, I tried to run this again. Like I said, GraphQL does a try-catch over your whole app.

So the server didn't break, but GraphQL caught the error and said, hey, this is the error that we caught. We're just gonna just throw it to you real quick. So this is coming straight from the database, right? I could catch this error and do something with it, but by default, your server is still good to go.

And what's even crazier, this might blow your mind if you built a lot of APIs. It still gave me a 200 even though it errored out. Right, because GraphQL always does a 200. Even if there's an error, there's always a post request, it's always a 200. Doesn't matter if there's an error or not, because it doesn't care, it doesn't need to.

It would rather just tell you what the error is in the payload than the status code. Which, to be fair, if you really think about how you build applications, status codes are important. But if you're building a really sophisticated application, you're also sending back some context about the error and the payload itself to your client, and you're using that as well.

So mostly status codes are for machines or other applications like browsers where they actually log different things in different colors. They know what to put a red X next to on the network tab and things like that, depending on the status code. But if your app is consuming the response and you needed more control of the error, you're most likely gonna get to the point where you're sending back context about the error in the payload.

Anyway, GraphQL just takes that to the next step and say, forget status codes, your error is gonna be here.
>> Scott Moss: Cool, so we got that. Let's try signin. So now I'm gonna try signin. I'm just going to remove that, go back to my mutation. I'm gonna click signin.

I'm gonna get the same thing, give me the token, give me the ID. The inputs should exactly be the same, except for it renamed them for me. Let's see, it renamed it to signinInput2, has already had an input down there. So I'm gonna rename it back myself. Well, I'm just gonna get rid of it, actually.

So let's get rid of the second one.
>> Scott Moss: There we go, and then name this to input.
>> Scott Moss: There we go. So now I'm gonna try to sign in with the same email and password, and I should get back the same thing I got on sign up, which is a token and a ID.

And then just to be sure, give me the email as well. So I'll try to sign in, there we go. Now we signed in. We have the token, the ID, and things like that. So once you get to this point going forward, because every query and mutation we make from here on out is gonna require a user to be signed in.

You will no longer be able to use this app to interact with your GraphQL API unless you supply a JSON Web Token. So I highly recommend that you create a user, just take the JSON Web Token like this. I'm just gonna copy it. If you go down here to Headers, you click on Headers.

You can make a New Header.
>> Scott Moss: Click on Header Key, click Authorization. For value, put the word bearer, space, your token. And now that's always gonna be there. So now every GraphQL request you make is gonna be this user. So this is necessary because we will be locking down every single mutation and query going forward.

So now we're able to do that, let's actually check out the application to make sure we can sign in. So let's do that. So I'm gonna open up a new tab, go to localhost 3000.
>> Scott Moss: Might already be signed in yet cuz I already have a bunch of stuff in my database and I have a JSON Web Token here.

Let me delete my JSON Web Token.
>> Scott Moss: Where's that? There it is. Delete that, and refresh the page. Should kick me to sign in, there it is. Let this go away, there we go. So now I'm going to try to sign in with the same credentials that I had over here, which was,
>> Scott Moss: For me, it was Darryl app and my bigcat password.

So I'm just gonna copy that, go back to it, see if I can sign in. I think this should work as far as signing in. And yeah, there we go. So this error is because we haven't made the query to get the issues, we're gonna make that next, but I'm able to sign in and get to the app.

So you should be at this point where you can sign in to the app. If assuming you created a user in the Apollo server, if you did not create a user in Apollo server, you need to go to /signup and do that here, right? So just to show you that, if I go to /signup, I can sign up here with, or anything@.

>> Scott Moss: And then whatever password I want, and I should be able to Signup. And that works too. The last thing we wanna check is just to make sure that the me query works. So I'm gonna go back to the Apollo server, get rid of all of this.

This only works if you add that header here. You have to add that header here cuz it won't know who me is if you're not signed in.
>> Scott Moss: So I'm gonna say, give me a query, give me me, give me an email, run that. There you go, that's me, I'm Darryl.

>> Scott Moss: Cool, any questions on this stuff?
>> Scott Moss: Okay, cool, so what we'll do next is, we're gonna get to the point where we can create the issues, get the issues, edit the issues. And if you have time, we will delete the issue. So full crud, and as far as UI goes, that's this button.

So I click this button, I type something in here, type something in here. I want it to actually work and create. Right now it's not cuz it's not even hooked up. So we need to do something there. So that's what we're gonna do next.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now