How to use JWT with SvelteKit and Strapi

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello hello youtube my name is braden gerard and welcome back to another one of my youtube tutorial videos today we're going to talk about two things first we're going to talk about how we can set up a felt kit project in the current beta now that it's maturing a couple things have changed so we're going to go over and i'll point out some of those differences from previous videos that i've made and then on the other side we're going to also talk about how we can do authentication using a json web token so i've done a previous video on cookies and today we're going to look specifically at json web tokens and we're going to use strappy as a content management system that provides us this json web token to our felt kit application and then we'll use the front end bits of svelt kit to create a front end for our application it's going to be very basic login to say a profile authenticated screen and we'll set up that login and show you how to use that json web token that gets sent back from strappy to communicate with the content management system in a secure way so without talking more let's jump into the video and we'll take a look at how we can do this okay so first we're going to make a directory like always for our project we'll call this one sveltkit jwt and then we'll change into that directory and we will do an npm init spelt at next which will generate us a default felt kit project yes proceed okay do we want the demo app or just a skeleton project i think i'm going to go with a skeleton project for this one uh do you want typescript we'll say no yes no prettier no all right now let's change directory oh sorry no we're already there so now we can actually do an npm install to install our default libraries and now we should be able to unpm run dev and we have our skeleton project up and running and there it is okay so now that we have that skeleton project up and running we can start working on the code to sort of implement a very quick login form so if i go back over to visual studio code here let me just open up that project so felt jwt and we are going to go into our source folder and then we have our routes so at the top level of our routes we want to create a new file which will be our layout and so we'll call this underscore underscore layout dot svelt now notice this is a new sort of way of naming your files or convention for naming the theme files template files so that's how it's been changed in the beta from the original version of sveltkit that was sort of pre-beta where we had the at symbol so i had some comments on that just clarifying there this is how you now name your layouts so in this layout we're going to create a navigation and in that navigation we're going to have uh three things so we'll have a home which will go to forward slash and then we will have a login so that'll go to our login page and then we will also have a profile so what we're going to do is if they are logged in then they should be able to see their profile link and if they're not then they won't see this profile link so we'll add some logic to that later on now in here we are going to add the slot okay and that's where our rest of our project will get inserted or the rest the rest of the files we entered into our layout so our html files here so anything that's in our index here now should be added inside of this slot um so if i save that and over here we'll now see that is my project not running anymore hold on okay i have an error here uh let me see it looks like i might name this wrong why do i have an e at the end i don't know okay is it gonna like that better there we go okay so back over here like i was saying now we have our uh menu here okay we can just add some really quick styling to that so inside of here let's create a style tag and we'll say give our a links a margin on the right of 10 pixels and just spread them out a little bit there we go um okay so let me zoom the browser a little for you guys so you guys can see this better there we go um so we have our menu here and it takes us to our different pages which currently don't exist so we get this 404 from the browser so let's go over and actually first handle that so let's create an error page okay so if for some reason a page fails to load we can have our own custom error pages in this felt kit so inside of our routes folder here we'll make a new file and we'll call it underscore underscore oops underscore underscore air dot svelt okay and then this can be the page that we show whenever there's an error so what we could do is we could just get the actual error and display it in the page so to do that we would create our script context equals module because we want this to get the air before the page loads and then inside of that we just export the function of load and inside of that we receive an object and we're going to take out the air and the status from that object and then inside of this function we need to return our props which will have that error inside of the object that we return from props so we have that object and we're going to return we'll call it a title props and then inside of there we're going to say status so whatever the error status is and then the actual error message so air dot message and then we can have another back tick here and there so we return the string with the status and whatever the error message is as it props so then that means that in our page we can simply get that props so we can say export let title to get the props and then we would put it into our page we'll put it in an h1 tag title and then if i go to a page that doesn't exist here i go over to login we get the air 404 and we get the not found message forward slash login okay so now we have sort of our own custom error handling page so that's how you would set up your layout and your air so these are sort of two things you want to set up with most projects sort of off the get-go you can also create nested layouts so if i wanted to have say a subset of pages under my profile where i said okay so we have profile and then inside of there we have an index.felt okay so that's my profile page and then inside of there we also have maybe like a contacts or something i don't know if you want to have a different layout for these profile pages then you can actually create a new layout inside of that folder and this will be a nested layout so what will happen is this layout will be inserted into the outer layout and then everything inside of this profile folder will be then inserted into this layout okay so you can nest your layouts like that so we could have another slot here and above that we could put you know so you're in your profile so we could just say welcome to your profile and then that will display at the top of every profile page you should put this inside of like an h1 or something and that'll display um inside of every profile page so that we don't have to add it to every page it'll just display there um so if we go to forward slash profile um we have that index page there now so we're not getting a 404 and it says welcome to your profile even though i haven't actually added anything to this index page um so down here let's put the person's name so we'll just say braden make that maybe an h2 and then we'll make this name dynamic once we actually log in and have the information but we're just setting up sort of like a roughed out profile page right now and then you know if i go to the contacts page so that would be forward slash profile forward slash contacts you can see that we still have that welcome to your profile but instead we would have whatever the content is of that contacts page so we could say like your contacts right and then it would show that on the contacts page so that's how you would do a nested layout again with a double underscore so back here we're going back to our index and currently we just have um welcome to sveltkit um visit blah blah blah that's fine we'll leave that as our index for now we need to make a login page so let's make a new folder and call that login and inside of there we want to make a new file and we'll call that index.felt and then inside of there we want to actually create our form so let's create a form actually we don't even need a form let's just create a couple inputs so we'd have an input type equals text because this is sorry email okay and then we would have another input where the type is equal to text now this is going to be the username input and we'll name this one as the email input and we'll add a placeholder to both of them enter your username same for this one placeholder equals enter your email and then on our final input we would have the password and then inside of there we'll have a placeholder that says enter your password and then down here we will make a button and we'll just say login i'm making a registration form so so we don't need both the email and username so we could just take one so for now let's just set it to the person's username so we'll get rid of the email and just put the username in since we're just going to manually create the user inside of strappy and we just to save time we don't have to do all of the registration type equals password name password okay so if i save that and then we go to our login page we have this very basic form let's just add a let's just wrap this inside of a div and in there we will just put some padding on top of it so that um it's not super tight to the menu so we'll do a style div margin top 20 pixels okay um so we have this login form where we put in our username and we put in our password and then we log in so i think we've pretty much stubbed out everything that we need now we have our home we have our login we have our profile which will be dynamic and only visible if we're logged in and yeah i think that's good so now we're going to basically connect to strappy so let's look at how we can set up strappy quickly and then use that as our back end okay so getting started with strappy is fairly easy all we have to do is go npx create strappy app and then the name of it so we'll call this one svelt kit trappy and then we'll just start with the quick start setup so if we run that that will bootstrap a strappy project for us and then we can run our strappy oh i'm in the wrong version of node so this is a little note strappy only works on node 14 right now so i just have to open up if you're on an m1 mac like i am you have to open up a rosetta terminal and then let me just zoom this again for you guys [Applause] and then you have to change your node version to 14 so i'm currently uh nvm in the node 16. so i'd have to do nvmus-lts because 14 is still the current lts version and now that i'm using node 14 i should be able to use strappy no problem mpx create strappy app spelt kit strappy and dash dash quick start so by default strappy will set up a project and it just uses sqlite as the database locally on your machine and you can work from the admin panel inside of strappy using that sqlite database so we'll log in to the admin panel with our admin user that'll get us to set up right away and then we'll create a user account with the user permissions plugin so dropy has a plugin that basically will set up all the user permission stuff for you so that you can just create users inside of strappy and then log in with them there's also a process to actually register a user from the front end if you wanted to do that but we're not going to go through all that today just to keep things you know quick so that we're just looking at how to deal with the json web token that strappy provides us after we've logged in so now that our project is building here it should be done in a minute all we'll have to do is say npm run develop and then we'll be able to start working with our strappy admin and we're almost done okay there we go actually strappy will start up on its own for us um once it's done installing so we don't even have to run npm run develop but typically that's how you would start it up later on is if you wanted to run your strappy project just npm run develop so strappy has opened up here in the other window for me let me just bring that over so you guys can see that and it launches on the default strappy url which is that local host forward slash or 1337 forward slash admin so i just need to set up my default admin account in strappy and that is going to take me one second sure use that password and then let's start so this is what the default strappy admin panel looks like uh what we want to do is we want to go to plugins and we want to do the roles and permissions plug-in right here you guys can't see that i don't think hold on uh roles and permissions here so if i click on that oh sorry it's already installed so it's installed by default actually so we just need to go to settings and then under the user and permissions plugin we go to roles and by default they've set up an authenticated role for us and a public role for us so that's really all we need so if i go over here to users and i add a new user i can create a username so let's say braden gerard my email and my password so we'll just use let me just use a simple one so that i don't forget it okay my password and i'm going to do i need to confirm my email uh no and do i need to be blocked no okay save okay now i have a user right here um sorry i should say confirm to on that's basically just so i don't have to confirm my email um save my email has been confirmed good so my account should be good to go now um so what i have to do is i have to do a login request to actually log in and get the json web token for this user account so let's just minimize this again and let's go back to our code for also minimize that for our salt kit front end um so if i go back to that code we can now create a login function so let's go over here and let's do a couple things first we want our requests to sort of be handled elsewhere so that we're not always writing out all the fetch request logic to create requests and then secondly we want our our token to be stored whenever we do get it back so we'll make a lib folder inside of our source here and inside of that lib folder we're going to create a file and that file will just name it [Music] we'll call it request utils so new file request underscore util dot js oops okay and inside of this request utils file the first thing we're going to do is make a little helper function that will allow us to retrieve something from our browser's local storage so we'll just call it browser get and then inside of that method it will take the function will take a key which is the key of what we want to get and then we will say if the browser exists const item will be equal to local storage dot get item by the key and then we will if we actually find an item so if item i return json.parse the item if it's there return the item as a json object and otherwise if the browser doesn't exist we return null or if for some reason it can't find an item now to use this if browser here what we have to do is import from felt kit so import browser from uh the helper methods in sveltkit app forward slash environment helper helper functions and then we have this browser variable which tells us if we're actually in the browser or not so whether it's a front end being executed on the front end which it always should be and then we'll also do the same for a browser set so we'll just copy and paste this browser set except instead of just a key we want a key and a value if the browser exists we'll do local storage dot set item and we don't need to have any response here and we'll say key and value and that's all we have to do okay so we have our browser set in our browser get so let's actually implement our request util here which will make use of those browser set and browser get helper methods so inside of our request util function it's going to be a post request so we'll call it export async function host and then it will be fetch so we're going to pass in the fetch from wherever we are importing it and then we're going to say the url that we want to make the fetch request to and then also the body of the fetch request because this is a post type um then we will handle our errors so first we'll set up a little air boolean here we'll check whether we need a custom error or not which i'll get to in a minute then we will do a try around everything that we're doing let's create an empty headers object that we'll store our headers in we're going to make this a little bit robust so that if the body that we pass in is an instance of form data so if it's actually coming from a form then we will set our sorry if it's not coming from a form then we will set our content type equal to application forward slash json and we will also set our body equal to [Applause] json.stringify body just so that we have that ready to go over the wire we need to get our token here that we're going to send in our request so we'll say token equals browser get and then we'll just get our jwt well that's what we'll call our token and if we have a token so if the token actually comes back from our browser get method then we will set our headers authorization equal to bearer the space plus the token and this is how we're going to use our json web token to authorize with strappy because strappy looks for that authorization header with a bearer and then the token is set as a bearer type now the last thing that we have to do is make the request so let's say const result is equal to a weight fetch and then we will put our url in here and then we will have our object in our request here so the method the type that we want to send so this is going to be a post request and then we will have the body and then we will have the headers okay now when we get that request back so the response we want to check if the response dot okay so if the response is okay but we're going to say not so if the response is not okay then we want to do something else so let's create a new try catch block and we will say const data is equal to await res.json and then we will say const air is equal to data dot message at zero dot messages at zero so let's get that error message out of the request or at least the first error message and then we're gonna say that this is a custom error make that equal to true and then we're going to throw the object so we're going to throw an id so air dot id we're going to throw a message air dot messages or message sorry um and then we'll catch here so if for some reason we can't actually get the json out of the air and that throws in air itself then we'll say console we'll just console.log it because we don't know what the heck is going on and we'll just throw the air and then we will say return so if we don't if the response is okay then we'll just say return response and then we will add our catch here in case our first request just something happens and we don't even get a response at all so then in our cache we'll say console.log the air and we'll say throw custom air so if we've already created our own error and throwing it we're going to check that that custom error is so if we did set throw a custom error here i don't want to throw the default there so we'll check if there's a custom error and if there is a custom error then we're going to say air and if there is not a custom error because that'll be the customary that i'm throwing here then if there's not a custom error then i'm just going to send a message and that message will be an unknown error has occurred if we don't really know what is going on with the air and that needs to be inside of a block and we'll give it an id we'll just actually set that id to an empty string and we'll give it a message with that that unknown error has occurred and we'll throw that object so now in our app we can always expect this format for an error object we can expect an id of some sort uh with a message um as our air handling it's just a little bit of basic air handling for post requests um we'd probably want similar uh error handling for like a get request or something like that um but we can look at that later uh it's probably not gonna be needed for this app but there's our post request we've handled the airs um now if our post request succeeds um one thing that we're going to be doing on login is we're going to be storing that json web token so that we can then get it back from our browser um so let's go back over to i guess we're going to actually need this browser set as well so we'll export that from this request details as well and we'll export posts from this request you to this file so let's export this one whoops browser set export function browser set there we go and browser get we can just leave internal for now that's fine i don't think we'll need it so if we go back over to our index here we're going to add a click listener to our button so on our button we'll say on click will be equal to and then we'll just say handle login and then we will have our script up here and we'll say function handle login so we need to import our import post from app invite or sorry not environment from lib forward slash request utils and then we need to say this will be actually an async function and then we say await post and then we need to pass it our fetch pass it the url that we want to go to so we're going to go into http forces forward slash local host 1337 forward slash and then with strappy where we want to go for the login is you want to go to forward slash auth forward slash local and that will be where you can actually log into the website so forward slash off forward slash local and then we need to pass it the body so the body of our request is going to be an identifier which is going to be either their email or their username in this case we are taking a username so username and the password which is going to be called password so we can just leave that like that so that's our body and then fetch your body that's all we needed for our post request okay and then we want to get our response so let's say const json equals so that's going to be our json response and then if if the json web token is there which it should be uh we'll just console.log it for now just to see if we're actually getting our json.jwt back okay um oh come on prettier i don't want my semicolons okay um username and now we need to one thing we have to do is say let user name and let password and then we need to bind those here to our inputs we'll say bind and then we want to bind the value of this field into the username and then same for this field we want to say bind the value into password okay so we've got our username and password on here and it looks like i've got some formatting going on but that's fine and when we click this it submits handle login which takes that username and password and requests a login and we should get a json web token back so if i everything's still running here and i go to login let's uh check out what's going to be logged out here so we'll go to our console all right yeah that's fine okay so let me just clear this so we can see what we got going on here uh username braden girard password is the password that i put in strappy okay and we're getting a readable state locked am i not hold on let's go to my request utils what am i returning here oh i'm not actually getting the json out of it first that's an issue okay so what i actually want to return here if the result is okay we're still gonna do a try okay um and then we're gonna do a catch so there was a mistake here in my post handler um i do need to get the json out so we're gonna say const.json equals await res.json because i was only doing that if there was an error to get the error message out of the json so i still need to do it here and if everything goes good here then we can just return the json um but if there's an error here then we're going to console.log the air uh and well it wouldn't have been a customary because we haven't even got here yet so we're just gonna go uh return earth row and then we're just gonna throw that unknown air again so we'll say ide we don't know what this error is there's better ways to handle this stuff i'm just giving you guys a basic example to show you that we're at least abstracting out this error logic and this request logic and unknown air has occurred alright so let's just leave it like that for now um but we're actually getting the json back now which is what i was expecting the first time around so let's call this json now and then we can just say json.jwt i believe let's console log it just to make sure that's what we're getting and we will log in and when we log in there we go so there's our jwt so json is this and jwt is this so if we say j.json.jwt it'll give us the json web token perfect so let's go back up here and also import from our request utils we're going to import [Music] the set browser i think that's what we called it a browser set sorry browser set and then down here if we get the json web token on login we're going to say browser set and we're going to we called it jwt i believe and the json.jwt so we're saving that into the browser and now anytime we make a request a post request at least so far we've set it up only for post but it's going to get that json web token where are we here it's going to get that json web token out of the browser and it's going to use that in the authorization header to create stuff on our api okay um so if we go back here um well we should when we log in we should see that our browser storage um gets a entry here from our site so let's log in now and let's see what did we get in the console hey that all ran a web let me set browser set let's just refresh this in our local storage there's the gwt that we just saved okay so it's there now so now when we access our profile we can pull down our name from our profile and we can do that by using the jwt okay so let's do a get request on our profile let's go over to our profile index.felt okay so we'll add a [Music] script tag here at the top of our profile and we will say let name and then in there we will put name instead of braden and we'll get this name from our api so [Music] because we need to use the json web token from our browser we can't actually use the context module load function and pull it in as a props because that will be run on the server side and we don't have access to the browser there so a workaround for this for now this is the way i've been doing it at least it's just to use the on mount function from svelt and that will run on the client side so we can simply import the on mount from svelte and then in here we can say on mount async and inside of this on mount function we can say const result equals await fetch we know we have access to fetch here and then we're going to go http cold forward slash local host now i'm doing this here again this would be much better to abstract out into that request details that we made for a get request i just haven't written that all i don't want to do all the air handling because this video is getting fairly long so i'll just do it here very [Music] quickly and this video is getting very long so i'll just do it here very quickly localhost 1337. uh forward slash users forward slash me that'll get my user's information and then inside of this we also need to send a headers with the authorization so we have authorization and then inside of that authorization we're going to send bearer sorry the headers this should be an object that is object and then inside of authorization we want to send bearer space and then we need to get our token so plus local storage dot get item jwt okay this is how you would do it if we weren't doing it inside of this request utils because in this request details we actually made some things here to check if the browser is being used a little more robust we do a get in a set here and we're setting it up as a post we could also set up another one of these functions as a get and then we can just import that and run it here but for the sake of this tutorial i'm just going to do it really quickly here and show you how you would do it as just like a one off right so i do my looks.get my jwt and put that in the header and then i should be able to make this request to strappy on this protected route so i can show you guys if i just go to this route on strappy so i'll just go to localhost 1337 forward slash users forward slash me it's going to tell me that i got a 400 bad request no authorization header was found okay so i can't normally access that but because we're passing in that token here in this fetch we should get a proper response and i'm not going to err handle for this we're just going to do it on the fly we're going to say const json equals res.json and then we'll just console.log for now our json so we can see where our uh name is sitting so if i go here and we go to profile okay and let's look at our console.log we're getting unhandled function invalid header name authorization okay uh six okay so authorization what did we do wrong here authorization did i make my bad there we go um we didn't need the colon and here's our promise uh so we're when we're logging this we're gonna oh because i'm not waiting here so i need to await this because we're getting a promise back right now and if i say that there it is there is our users information we get all the information back including the name so we can simply here say name is equal to json.name and if we save that welcome to your profile brayden look at that we now have a login working if we were if we wanted this to redirect to like an error page uh what you could do here is when you do get an error you would send you would do a go-to using the sveltkit go to and send them over to your unauthorized error page or something like that i think i showed that in one of my other videos i think i showed it in the cookie video so i'm not going to redo that but that's what you would do here to send an errand send them to a different page but yeah to wrap up this we have our home we have our login and we have our profile okay and we get our profile information here when we're logged in if we weren't to logged in so let's go over here and just clear our local storage so we don't have that web that json web token if we try to get our profile information it's going to be undefined right and in the background here we're actually getting an error we're getting a 401 so i could be grabbing that 401 right here and then sending them over to an unauthorized page if if we don't want them to be to even see anything here right they're not going to get any of the data but it still shows them like a broken page which we wouldn't want to do in a proper user experience so you would send them over to an unauthorized page or send them back to the login page all right but then if we log in and if i log in with my password that i set up now i should also have this redirecting over to the profile once we log in but we can see now that i'm logged in because i've done my login and the json web token is now stored and if i go over to profile it's going to show me my name thanks for sticking around for another one of my youtube tutorial videos today we looked at json web tokens and we also looked at how we can set up sveltkit in the current beta as far as a front end that is married to a back end with a headless content management system like strappy i hope you enjoyed the video if you want to see more content like this more spelt kit videos more headless cms type development videos definitely subscribe to the channel because i'll have a whole bunch coming up in the future i try to release weekly so you guys can get that content that's nice and fresh and uh yeah if you like this video give it a thumbs up because it helps youtube show to other people like yourself thanks have a great day [Music] you
Info
Channel: Brayden Girard
Views: 3,230
Rating: 5 out of 5
Keywords: web development, svelte, strapi
Id: WgX87HDrAss
Channel Id: undefined
Length: 44min 38sec (2678 seconds)
Published: Sun May 30 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.