Advanced GraphQL, v2 GraphQL Auth Approaches
Transcript from the "GraphQL Auth Approaches" Lesson
>> So many ways to off, couple ways here in is probably more than this but these are the three biggest ones. One is, outside of graph QL. So in our case, we're using an Apollo server. Apollo server can also be used as a middleware attached to an existing Express server.
[00:00:16] Or it can be the other way around, where you attach Express middleware to an Apollo server. So either way, that means you could be running some type of Logic outside the Apollo server on your server. So when I say outside of GraphQL an example and that is if you have Apollo server any GraphQL server running as no where on Express server, you might do the authentication logic and in the middle where before your execution of a GraphQL server.
[00:00:42] And then, you'll find some way to pass that to the GraphQL execution. So that's one way you can do it. Another way is, when you're creating the context object in GraphQL. So the context object is when you initialize the server, like what we just did when we created new Apollo server.
[00:00:59] You could add a method there, that creates the context object that's passed to every single resolver. That's a place where you could also do authentication, you could say, I'm about to create the context, which by the way, it gets initialized every single request that that context object gets created every single request.
[00:01:14] So during that creation, you could say I'm going to go ahead and do some type of authentication or authorization here. The last one is the obvious one, which is just inside the resolvers. All the resolvers are encapsulated, they only know about themselves, they're the small little functions that do one thing.
[00:01:30] They're responsible for resolving one value for one field. So there's nothing stopping you from just saying, I'll just check for off every in every single resolver that needs it, and you're good to go. So those are the three different ways. But based off the what I said before here, a good system and these three different ways.
[00:01:48] We're going to talk about some of the pros and cons of how these different approaches might fit into a really good off system and which ones you might want to use and, and why. So talking about outside of graph QL, using something like Express middleware before the GraphQL Server executes, so that's the example that I gave you.
[00:02:07] The downside of this is, it completely locks down all your GraphQL queries and mutations, because you're outside the server. So I've done this before and basically what you get into is like, all right? Everything GraphQL related is authenticated, everything that is not authenticated an't be GraphQL related. So, you either make regular routes on the express server, or you literary make a whole another GraphQL server next to the authenticated server and that was not authenticated.
[00:02:36] I've seen that happen before. Either way, it's probably not the best approach. It doesn't really tie well into the flexibility of GraphQL of being able to access things on a field level and stuff like that. So I would say probably, stay away from this one. In any scenario, if you want to lock down the entire API, I would probably still stay away from this approach.
[00:02:57] Because there is extra complexity of passing the alt information to the GraphQL execution. And express is not that big of a deal cuz you could just, in the middle of nowhere, you can just attach something to the request body. And in the request body, you can use that in the context and you can figure things out.
[00:03:12] But in other sort of implementations, this might not be as simple of passing some outside information into the execution context of GraphQL. So there's always extra complexity there. And that's always going to be a point of fault. So I recommend not doing that approach at all, unless you have a really good reason.
[00:03:30] Like for instance, your graph kill server is dynamically generated based off something in your database. So therefore, you do need to authenticate before your server executes. So like we actually do that in our example, there's we actually can't even run a graphical server, unless we authenticate you first.
[00:03:46] So that might be an extreme example where you would have to do something like that. So when creating the context object, the second approach, so you can use the context creation function when creating your Apollo server. Again, I can just go back to show you what I'm talking about when I when I mentioned that, if you don't remember what that is.
[00:04:01] That's basically here and Apollo server, you can use this context method like this. And whatever you return here is going to be an object that gets passed as the third argument to every single resolver. So every resolver is going to get a context objects, like here. And that object is going to be whatever you return, here.
[00:04:19] And this object is computed every single request. It's never the same and unless it is, and you can also be asynchronous. So, you can do pretty much whatever you want in here. You also get access to things like the request object from in this case express. So you do some pretty crazy stuff in here.
[00:04:37] This is what I'm talking about. When I say Context object,so like I said, you can access the incoming request to determine authentication. So if your authentication is like a WT, and you're using the authentication header, that's the perfect place to grab it. And then there really is no extra work that passes to the graph qL resolvers because whatever you return, gets passed in with the execution for free.
[00:04:59] So there's no trying to figure out how do we get this authentication info down to the execution of graph ql. You not have to worry about, just return the objects, you're good to go. So, also you have the ability to lock down the entire schema if you want to.
[00:05:13] This is why I said if you do want to lock down the entire graphical API, I still wouldn't use the first approach of doing outside of graph kill. I will just do it here, because you can also lock down the entire graph qL API here. You can just say, I'm not gonna return object was gonna throw an error because you're your unauthenticated.
[00:05:29] And that's probably a better approach than doing it outside. The last one that I mentioned was basically inside the resolvers. This one just has a whole bunch of cons. I actually can't think of anything good other than, that it's the simplest to implement because it's the most natural one.
[00:05:43] It's I think this is what most people do when they first use graph QL they fall in love with the resolvers. And then they realize that the resolvers can do anything and the resolvers are like super huge resolvers. And as they get better and understand graph QL more, they try to find a way to keep the resolvers skinny.
[00:06:00] So a lot of people just put everything in the resolver, authentication, authorization, transactions. I mean whatever you want, you stored in resolver. And that's kinda how it starts out, before you start figuring out different patterns. So I think because of that it's the simplest to implement, but it is really the hardest to reuse.
[00:06:15] Because you have that authentication, logic authorization logic tied up with the business logic. And to me, that's just too much. Those are separation of concerns, there are two different systems, the business logic doesn't need to know about the authentication logic and vice versa. As you just assume something, like it should just to just like if you were to lock down the whole GraphQL server.
[00:06:36] That graphQL execution assumes that whoever is accessing it is always authenticated, they're always authorized, they don't have to do the check or the resolvers will work the same way. They should already assume that they're good to go, they shouldn't have to worry about hold on now are you allowed to do what I'm about to do?
[00:06:52] That's shouldn't be their job, they should just do what they need to do, and that's it. So I almost always recommend not adding authentication and authorization this way. So it's not, not a good thing.