Nest.js Browser Cookie based authentication with Passport JWT

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
next year's got a ton of attention in the past few years and the main reason is that they have built really good system that supports the Legacy Express GS for middlewares and pretty much entire code bases and also build a modular microservice logic dependency injection style code base that pretty much can be extendable multiple teams even at the same time today we are going to look how to make cookie based Json web token authentication for an SGS that is going to be a separate module for an SGS you can plug it on your existing application or that could be even a separate repository inside your organization so let's get into it we are starting a fresh new project to demonstrate how cookie authentication will work and how we can make it as a separate module so let just make a new messages application and we will name this cookie Json web token so we are going to use npm and an installation in progress so after installation is completed I'm gonna use the webstorm to open up this project so I'm using webstorm as a main code editor for but you can use of course vs code whichever available for you this is a standard Mass JS application and we can run our server by typing npm Run start Dev and we'll have the swipe server running so in this application right now we should add a separate Logic for having this hello endpoint under the authentication and whenever we have a cookie that has the Json web token authentication then we should proceed further sending the Hello message otherwise it should be 401 unauthenticated response to get started first of all we will need to install a couple of packages that we'll use later on and one of them is obviously the cookie parser cookie parser which is extended by Nest GS but originally that was developed for express.js so it's almost the same middleware and we're going to import that secondly we will use the passport and passport Json web token also to include the passport.js InTune SGS project we have to have the nest passport after having those packages installed first of all let's enable the configuration for having the SGS cookie parser so we will just make sure that we have cookie parser and we are going to make sure that we are using cookie parser so this enables us to essentially parse and process cookies from a browser request and of course we also have to have installed types which is not mandatory but sometimes the editor is just complain a lot when you don't have installed package types so after having this installed we can make sure that the actual cookies will be parsed from a requested browser and we can use the request cookie object inside our controller to see whether we have a properly formatted stuff as a cookies there or not so for that I'm gonna use the standard directive of request inside the nest GS this will give us the request object that we can use for an SGS after having this written down to log the cookies itself from given request object we can now test this directly inside of our browser I'll just spin up the nest GS server and inside our browser I'll try to refresh now if you can see we got back an empty object because at the moment we don't have any cookies in our browser so if I'm gonna add a cookie here by inserting the localhost 3000 let's say I'm adding a test cookie with the value something and when I do refresh cookie is persisted and we got back response from the server and the cookies contain what we have actually said inside our browser so this is the the most important part of this entire project rest is just Json web token implementation that you can use whatever you like even without the cookies with just plain authorization headers but let's continue on uh building an actual Json web token process here so what we have to do now is to generate a new model called called out I'm gonna use Nest GS command G module out and this will create our authentication module and will automatically add it to the list of the modules here inside our main file so we don't have to do anything else other than making this module besides this authentication module inside we will have a separate file called gvt strategy which is going to be a Json web token strategy class that extends the password Json web token that we can use to essentially parse the cookies and get back our response so for that let's create the class Json web token strategy which extends the passport strategy and for giving we have to give an actual strategy here which is going to be a Json web passport Json web token strategy class extended from passport Json web token here and it has a strategy class in it here we have also missing these types for passport gvt so we we are going to install it now because that that will help us to avoid type conflicts and it will actually bring the correct types now that we have extended the class we have to write also Constructor function which is coming from the passport strategy and for that we have to use the super function which is from a passport strategy again and here we also have the extract Json web token which is a generic function that extracts the Json web token either from a barrier token or from Json web token prefix depending on your use case and here we have one little problem that this Json Webster web token extractor essentially tries to get always from headers or from other sources but not from cookies and for that we have to add a separate or private function which essentially tries to user token uh which is named for that either from cookies or it returns a null just to proceed on on a second like header part of it so this goes in a way that if we don't have a Json web token inside our cookies we'll try to get it from our headers this way we'll support both and because we are not going to use a configuration service at the moment you can use a simple secret key essentially to just add it but in the production of course you're gonna add the configuration service and the most important part here is that we have to make this code as an injectable to bring this component to our main module it seems I'm getting this error underlined here which says that this password strategy is a callable function seems it is not a interface reference but instead of function so essentially this passport strategy returns back an instance type with the new so that's what extendable for typescript so the rest of the code base is essentially implemented already by passport.js and the nest.js passport extensions we just have to include this as a module provider and adding a passport strategy here we have to export of course yeah exporting password strategy and then importing that here now we have the we have the passport Json web token strategy already imported let's try to start our server let's see if all types compiled yes everything is fine the only part is that we are missing an actual passport.js import which will give the middleware access to Natural passport.js functionality and for that we have to install another package which is named The Nest GS Json web token this is essentially a wrapper around a standard Json web token library that handles all of the parsing and processing of Json web tokens to the object and the encryption process so here inside the authentication module we have to support the Imports and we have to import already the passport module which should be registered which should be registered as a default strategy Json web token and without any sessions because we don't need a session here it's everything under the cookie and another part is that we have to include Json web token which we have to register which we have to register with the Secret the same secret that we have here the configuration that in general that is going to be a configuration but right now uh we don't care that much and we can set the sign options which uh which should be expiring in one hour so this is generally fine we don't really need anything else other than this very simple configuration and with this we actually have pretty much everything that could support potentially the authentication process itself but we are missing a key part which is a guard to guard a specific endpoint with the Json web token checking and sending the 401 unauthorized error or getting back the rest of the functionality with the context of what is user and what is the use user object contain and for that let's make another file name that as quart and with these cards we have to make another injectable export class Json web token Court which extends extends the out card named Duty so now whenever we have the implementation of some controller or route inside an SGS we can essentially Safeguard this with the user guards Json web token and that will essentially execute this strategy to get back and check whether we have a correct Json web token if yes then we can proceed with the standard validate function if not then it will throw an error but here we are missing an actual validate function which should in theory return back user information if our payload contains that so but because like we don't have any authentication checking things going on here so we can essentially make a standard payload response with saying that like assuming that our payload will contain sub which is a user ID and username inside the same payload but that's just assumption to make things a lot easier let's just return a single user ID which we will include inside payload as a user ID so here uh we have to already like check whether we have a user in database but because we don't have any all any of that we just have to validate if Json web token is correct using this wrapper functions if yes then we'll just send back wherever we have just to make sure that we get get back the same payload that we have in our cookie Json web token strategy the last part is to safeguard our controller with the Json web token user guards or you can do this for the single path as well let's try it with entire control controller and here we have the user guard developer by Nest GS coming by default and we can essentially assign that to a Json web token guard to make sure that our request that comes from browser contains the cookie information that we need so now let's start our server and we will see that when we reload the browser we we get an authorized message meaning that we probably don't have a Json web token cookie here that qualifies all of the parameters that we need and the same happens actually when I'm wrapping a single function here which is get hello but the next function might be just without it meaning that this one will be a private endpoint and this one is going to be public endpoint and let's name this properly so now when I go into a private endpoint I get the same or message but when I go to public everything works so the last part here is to add another endpoint that will generate our Json web token without needing all of that complicated stuff for the login process first of all let's make our Json web token secret as a exportable static parameter just so that we can use uh use that for the for importing that in inside the rest of our application that's not pretty but that's uh the easiest way now I I don't want to go into having the entire uh configuration setup now so we can use gbt Secret TMP and this is for and for you to understand that this is just a temporary so we will just use this variable across our application wherever we need our secret because we already have enabled our Json web token strategy so I'm gonna create a new controller here called the out controller TS this controller essentially will be our kind of login and logout logic and I'm gonna make injectable export class alt controller so this is going to be an actual authentication controller we will have the endpoints written here and for basic usage uh what we're gonna do is to add a Json web token service and because we already have the authentication model enabled and Json web token module loaded here for from next next gsgvt token we can use Json web token service to sign and send back a response to our services so what we're gonna do we add another endpoint here which could be get like we don't care that much let's make these controller seems and the controller is going to be with the out prefix and let's make this login so this is what we are going to send back to the client it is just a username and ID that is going to be our Json web token payload and by signing this we send back our by signing this we send back our access token that is going to be as well imported as a cookie from our format now we should import our authentication controller here as a standard controller and that should be it we should be able now to get back the uh authenticated cookie let's just restart our server and try out our new out login and point oops out login yes as you can see we got back a proper version of our Json web token now what we're gonna do is to set user token cookie variable with the Json web token that we just got and that should be enough to get back a proper response but now since we are getting again unauthorized this seems to be issue that we named wrong the bearer token so let's go back here inside Json web token strategy and seems yes we have to have a barrier token instead of a Json web token you can change this a bit tweak okay we get back and again an issue let's see if we have everything in place yes we have a user token where barrier is our Json web token now let's try again here to see what's going on so we have Json web token strategy I'm gonna set here a console log to see if we actually getting back a proper cookies here in the private mode this is the process of debugging that yes we get back proper Json web token now let's see what's what's going on then oh okay so because we don't have any barrier extraction here we just kind of clean up user token and expect to get back only user tokens so we don't need this Bearer this Bearer is required for an HTTP authorization header but with cookies that should be pretty much without the variable so now you can see that we have a public endpoint and private endpoint both of them working and now when I try to remove this user token the public still works but the private will be 401. now let's try to log in again out login and copy over the user token here try reloading again and this is now works so the next thing the most important part here is that whenever we make a login request we actually have to set that cookie directly instead of trying to set that from the browser because that's usually how it's going to work when user tries to log in we don't have to inject that cookie from the browser or from browser JavaScript that should happen from the server because API usually will have a separate subdomain so we have to insert that for a cross domain access even within the same domain name space for that inside this controller in login controller I'm going to use the standard dropper function called res and this response actually can be passed through this response object will be the only part where we will essentially Force set the cookie cookies that set and this user token is going to be assigned [Music] this user token is going to be signed Json web token and we also can tweak a bit the parameters how this going to work here we can set the expire time when this cookie should expire this should be pretty much ready to go and now when we restart our server let's fix the es link this sometimes breaks so now we have the user token let's remove it and try to log in again go to out login now we got internal server okay so cannot read properties of undefined reading set okay so we don't have cookies here okay so this is not a standard store yeah we have to set a rest cookie as a standard function so yeah this this was uh from the old Express version so after having this set let's try again and now you can see that I reloaded the page authentication login and got back the user token and whenever we hit next we already have the user token available here so the last part will be the making an actual log out screen which is going to be a simple function that essentially cleans the cookie but not with the clear function instead it is going to be setting a cookie this is the best best way of doing it instead of having separate functions we actually have to set expires now this alerts browser to essentially remove this cookie right after this request because it kind of counts that this cookie should be already expired so now we have to make sure that we are just setting the empty string and the options will be expired and we can go back again to out log out now we have removed user cookie as you can see it's quite easy to manipulate the next nest.js code and also having this type of cookie based authentication makes you quite flexible on deploying API on a separate subdomain and your web application on Main subdomain and even use in Sub sub multiple sub domains across many devices but using the same API using the same cookie based authentication which means front-end developers don't have to care about cookies they just have to send a request and whenever they have a properly formatted request after login the cookies will be sent directly to API endpoint and they don't have to manage the state of user login
Info
Channel: Tigran Tech
Views: 2,781
Rating: undefined out of 5
Keywords: Tigran, JavaScript, TypeScript, Node.js, microservice, cloud server
Id: UQEQHPwQJdg
Channel Id: undefined
Length: 30min 10sec (1810 seconds)
Published: Thu Jul 27 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.