Create a Golang Webserver with jwt authentication using go-fiber 1/2

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome everyone in this video we are going to be creating a goland um quick server um we're just going to be creating our authentication routes and just showing how we can make some routes private public and protect them through um jw3 authentication and we're going to do this all through fiber so stick around [Music] all right so as i said we're going to be making a jwt authentication server in golang so the framework that i'm going to use for the http server is fiber if you are coming from express this um sort of there is the same apis that they use will seem familiar to you and that's very true even though this this is also very similar to some of the other um golang web frameworks this is also very close to fiber so i mean very close to express so we're going to be using this it's super easy to get started with and they have a bunch of other um packages that you can use in conjunction with fiber that just work amazingly so that's why i like prefer fiber and also it's it's pretty fast it's built on top of fast http yeah it's built on top of fast http um so it's just guaranteed to give you some really good performance without you really worrying about anything happening in the future so to get started um i'm just going to copy these go get commands so this is on github.com forward slash go fiber forward slash jwt so i'm just going to copy these go gets first of all um these are the prerequisites that you need to get started um we're going to use go we're going to use um we're going to use docker compose and we are also going to use this vs code marketplace called rest client this is going to help us make http calls um to our server so let's get started so to initialize our goal app we have to say go mod in it we gotta give it a name the convention for the name is pretty much the url for where your code will live if it doesn't really have if you're not really um if you're not really hosting this or certain hosting it's putting this up on github or bitbucket or any other of the repos um this doesn't really matter but um the common convention is the url name so this one will be github.com forward slash floyd jones one forward slash um auth server um yeah so odd server github floyd jones and hit enter so that creates our goal mod in it so go mod in it is like our package.json for all the javascript people i'm just going to help us manage our dependencies so let's get downloading so we'll download golf fiber we will download the required jwt stuff so over here paste it in as well and then finally we need to get the this is the jade the jwt to handle the middleware and this is the jwt that actually does the encryption so finally we paste that down as well and you notice that our go mod file actually grew as well so now let's create our first go file so touch main.go and over here we will have package main and it's just going to have a function main over here so to start our app it's really simple we just say app and we initialize our app to be a fiber dot app over here so this creates our fiber app instance over here so this gives us our app so let's go back to our documentation over here so you see we just say fiber dot new and we get our app so let's change that here save that so that gives us our app over here um it's completing something about something this has to be v2 so that's the first problem over there and actually that fixes that so that gets our app all over here so at the very bottom we're just going to make our app listed on a port so we're going to say appalachian [Music] port 3000 and we're just going to panic if any errors are there so error is equal to if error does not equal to nil we're just going to panic with our error okay so that handles that so now we want to create four routes one for signing up one for logging in one is a protected route and one is a private route so let's do that here it's really simple so we just say app dot um so for our signup route this is gonna be a post request and it's gonna be forward slash sign up and this is just going to be a function over here intellisense will kick in and let's return nil over here return no okay so now i'm just going to copy and paste this three more times one two three so this over here is going to be our login which is also going to be a post this is going to be our private route and this is good let's make this a get request and this is going to be our public route which is also going to be a get request so now let's return some json to show that things are actually working so to do that we can say c dot json and then we can just say fiber dot map i really prefer this way of um setting json bodies and stuff like that um so this will be a success true um path is from um public cool so now let me copy this and paste that in here and i'll change this to private cool so now let's run this to see if it actually works right so go run main.go so that runs our fiber instance over here one thing we're going to do is create a new file called rest.http this is our um this is our vs code plugin that we got our vs code marketplace plugin so let's create a few routes now so the first one we're going to create a get for http call info versus forward slash local host public right and let's just say this is http http forward slash 1.1 and then the next one is going to be the same thing um so to separate our api requests we need to put on three pounds over here and then at the bottom we can put the new one so this is going to be our private and then again go down pound pound pound and then we paste this and then this is going to be our sign up and our sign up is going to be specifically post and then finally we need one for our login over here i'm going to have login both of these are going to have a content type of application json even this one at the bottom over here is going to take in an application a content type of application json okay cool so now let's send a request over here and see what we get we get our request back from our server this is great so this is our server that we have set up we're getting our public when we're hitting this endpoint and then if we hit send request over here we get private private is success true okay cool so we have all of that set up let's now start setting up our sign up route so our sign up route is going to take in an email a name and a password and it's going to save that into our database so that's going to be a struct so what we're going to do is we're going to create a type sign up request and it's going to be a struct and again it's going to be a name string email string password string okay so now um now we just have to parse this in from our body so the way we do that is we just say we initialize a new request first so we say request new sign up request and then we say if error c dot body parser and we pass in our request over here error does not equal nil then we return the error over here cool so that is honestly the same thing we need to do for our login around as well so um i will paste that over there actually i'll save that for later because it's going to be a lot of copy pasting so we get our request over here in what we need to do first is check whether all three parameters are not empty so we'll just say if request.name is equal to that or request.email is equal to that or request a password is equal is is equal to that if that is the case then we will want to return a fiber dot new error and this is going to have a status quo so in this case it's going to be fiber dot um let's see what we got bad request yep bad request and just going to be um invalid sign up credentials cool so now after this point we are sure that all three parameters are filled so now what we need to do is save this info in in the database and then we create a jwt token okay so let's do that so let's create let's start creating our client for our database so for our database client i prefer using xorn or however you pronounce it um out of all the research that i've done for finding the best um the middle ground for the best database client i found xormo over here it supports a bunch of different databases so sqlite postgres cockroach oracle and what's great about this is that it's not only a orm but it's also provides you the capabilities to make raw sql queries which is great you really want to have the flexibility to do both because once your queries get really complex you will need to write them out by hand for the most part writing them out as orm is number one it's complicated and also gets hard to read as compared to just reading an sql statement so to do this we gotta again go get this exam over here so let's go back uh over to our thing over here let's cancel this out and let's get our exo arm over here so now with our database we actually have to make a new directory called data and inside there i'm going to create another folder called data.go cool so over here we're going to have all our database initialization happening so package data versus show the function create db engine and the reason why it's called engine is because um xor calls it engine so i'm going to call it engine as as well okay so cool um what we're going to do now is to create our engine so to do that we need to um first and foremost i'm just going to um copy this over here so this let me delete this so you can see the whole thing this is going to be our connection string that we're going to use so to do that we'll say xorm dot new engine and it's going to take in first the type of database so postgres and then it's going to take in our connection info so our connection info over here is um our host our port our user our password and our database name um right now i put these in you can put these in as well as whatever you you want just make sure they match the um docker compose file that we're going to make later on so this is going to create our engine what else we are going to do first we have to actually engine and error and then we also have to check for our errors so if error does not equal now then i return nil and then the error the reason why it's nil is because we actually want to return two things here we want to return a pointer to our um xorm engine xorm engine and then we also want to return our error so this will be nil and then after that we just want to do engine.ping we want to ping the database to see if there is an actual connection so let's go over here if error is equal to that error does not equal now then we just return now nil and the error and then finally that means our database is good so then we just return our engine and then we return nil over here cool so this creates our engine over here which is great um one thing we're going to do is also create our database model um from our struct so we'll say type user is a struct and it's going to have an id um the id is going to be n64 it's going to have a name which is going to be a string um email which is a string password which is a string cool um so i'll save that one thing cool that x1 has it has the ability to sync your structs with your database tables so um the way we can do that also is if we say if we want to do this after the ping because we want to make sure that there's an actual connection so we say if error equal to engine dot sync or sync 2. sync i forget which one i'm going to stick with sync because that's the one i used before so sync is equal to new user over here just takes a pointer to the user and i'll just say if error does not equal nil then i just return nil and then the error cool so that will sync our database so now all we have to do over here is after we create our app we also have to data dot create engine so this will create and return our engine over here so we say engine error is equal to that and then finally over here at the bottom we say if error does not equal no then we return actually no over here we panic so on the main package we panic um just so it stops executing we put a return as well but panic um stops the execution process and it also returns this factories which is kill all right so we have our engine over here let's just make sure that things are actually actually down so our database so if we clear this over here and we say go run main.go um it says engine declared but not used okay it's being annoying save that let's run this and then it says unknown driver postgres i totally forgot this i forget this every time so to use this also you need to import the um pq library or the postgres library over here so i'm just going to do that and just because the red squiggly lines here means it's not found so what we have to do is go mod tidy and this actually checks everything in your packages it goes sips through all your gold packages and it sees that that's not included and it'll pull it in so now that's good so now we can do go run main.go and over here it says connection reviews because we didn't really set up our database yet but no worries we will do that soon so let's clear this just to make sure it's not messy okay so now we said we're going to save the info into our database so let's do that right now so um what we're going to do is we first need to encrypt our password we don't want to store it as the same text that was sent in from the client we want to encrypt it and then store it into our database just so someone accesses our database they can't see everyone's passwords so to do that we also need another library called bcrypt and i don't think we have it so we'll need to download it um so the the b crypt package over here i'll just go into thing it's called golian.org x crypto so this is all the cryptography functions actually it's not that many but there's a few cryptography functions here we're going to use this to hash our passwords and stuff like that so we can go back over here and we can say go get this and this gets our b crypt package so now we can say over here b crypt dot um what's it called bcrypt.generate from password and this takes in our password but our password as an array of bytes so we have to do array of byte and that's just going to be a request.password cool and uh that's about it and it takes in our cost yes so we'll say decrypt this is just intellisense kick in so we'll say be crypt dot default cost again this is not a cryptography video so if you were to properly make sure your systems are unlocked and in check please do make sure do not trust this default stuff i'm just showing you how to get up and running so if error is equal to that we're just going to err does not equal no we just return the error over here and that should be good enough why is this complaining uh let's see we cannot initialize oh there's two variables okay what is the second one one is an array of bytes and one is an error okay so this is gives us our hash yep this gives us our hash and the error and because the hash we need the hash now on the other scope so we can't really do this um because it actually is it if you declare it like this all the variables over here are only available inside the scope of the if and also the else if you have an else but we are not doing that so we need to pull this out over here into the main scope so we'll do if error is equal to that blah blah blah okay cool so now we have our hashed password so now let's create a new user so new user and it's going to be a pointer to data.user so it's going to the name is going to be from the request.name the email is going to be from the request.email and then the password is going to be from the request.password cool so now all we have to do is save it so to save that xor actually has really useful um readme over here that you can literally just copy and paste so over here all you have to do is insert the struct which is crazy um this is i really like this because you just insert the struct and like the it generates it figures out the name by the name of this truck there are ways to modify the table name to say that hey this truck points to a different table and there's all documentation for that so all of that stuff is covered if you don't have structs that are exactly matching your table names all right cool um so now all we have to do here is just say engine again engine dot insert engine is an undeclared name oh yeah because you have to do this cool engine.insert user and that inserts the user i don't really care if it's truly affected i just care if there's an error because if there's an error um then where there's smoke this fire you know so if there's an error then we actually want to return the error because that's the main thing um so now we return the error so now we have our inserted user into the database all we have to do now is create our jwt token now to create our jwt token i do want to abstract it into a different function because it will be shared between our login route and our sign up route so we say func um jump create um jwt token okay and this is just going to be a user instruct and that's about it and what's it going to return is our string which is going to be our token it's going to also return an n64 which is going to be the expiration time and then finally it's also going to return an error so now over here we can do all the magic that pertains to jhjwts first let's generate our expiration time so time dot now and then if we add about 30 minutes to it again this is configurable up to um the people watching this video how long you want your jwt to be valid for i like um 30 minutes and then we can just say unix there we go so now let's create our token so our token is equal to jwt dot new it's going to be a new jwt and it's going to take a signing signature so we need to do jwt dot um signing signing method is oops the cursor went off signing method is um hs256 so signing method is hs256 over [Music] over here cool so let's see where the gwt is from it should be from yeah it's from golang jwt um actually needs to be from jwt forward slash b4 let me double check that so we want to make sure we're using the latest packages so over here yeah so we're using we need to use v4 for this we're just going to go here and copy this down oops just going to paste that in there cool just to make sure that the res three lines go away again go mod tidy we'll make sure all your dependencies are up to date and then that fixes that cure all right so we generate our token and now let's um modify our claim so we'll do claims is equal to j token token dot claims dot jwt and then assert that to a type and then finally claims um the one claim you want to add in for sure is the user id i do like to store the minimum amount of information about your user in here user id is enough to go to your database and fetch the relevant information so now we can go here and say user dot id and then we say claims is equal to we also want to store the expiration date so that will be exp and then finally our token in the form of string so we just have to be token dot sign um sine string and this is going to be an array of bytes that's going to just be the secret cool so that is it for that and that will sign it and then finally we just want to return the error so if error does not equal it's not equal nil then we return the empty string zero and the error otherwise that means it is successful so we return the token we return the time which is the expiration date and we return nil because there's no error over here cool so that's all we need now so now we just have to use this function over here and say token um token and the error and then we create new things so create jwt and we pass in our user over here a user is a pointer so we do have to do that um what is going on over here no new variables on the left okay that's fine what about you cannot initialize to all this three yep so i'll just say exp over here and what does it say uh oh it's not used okay that's cool so now if error does not mean equal to nil we want to return the error over here and then finally at the very end we just want to return this information so we'll say c dot json and it's going to be a fiber map over here and then finally that map is just going to be our token which is going to just be our token generated from our function it's going to um consist of our expiration date as well so we see exp and then finally it's going to also create our user over here when we pass in our user as well um one thing to note is that this will also return our encrypted password even though it's encrypted you don't want to send back what the encrypted password is to your client so the way we get around that is if we go over here to our password and we create a um struct tag so over here we'll just say json and then we just have to put a hyphen here in the middle and this will tell the json marshaller that hey i don't want you to marshal this just like don't send it out so this is great this is everything we need for the sign up stuff oh the hash we want to store the hash not the actual password and the hash is actually an array of bytes so we need to parse that as a string cool so that fixes it for sign up um login is pre is kind of the same so what i'm going to do is i'm going to copy this from the request down over here and paste that in over here obviously the login request is different so the login request is only going to be the email and the password so i'm going to delete this and i'm going to change this to login capital l login request and then finally i'm just going to put that in there so cool so now this is login request login request does not contain a name so we can delete that cool so now we we've reached a point where we verified that email and password doesn't exist and we return back invalid login credentials um so now we have to fetch our user from our database and compare the passwords so again i love seeing the documentation because this is so easy to do um they're super useful so over here there's a get query for the user so all we have to do is use this function over here something similar to this to get our user so over here we just paste this in for now and what we're going to do is we are going to initialize new user so we're going to say user is equal to new data.user and it's all real pointer so i don't want to give it an address to an address um and then finally we want to check for where the user's email is equal to the request.email sweet so now if error does not equal to nil then we just return the error right to our client um and also if it does not have the user then we also want to return a fiber dot new return spell from return fiber dot new error and it's just going to be a fiber status code of let's say let's say bad requests i think best status bad request is always my default to go to it's a 400 status quo so we're just going to say invalid um login credentials will just be vague because that's the way logins usually work you have to be pretty vague about what actually went wrong um and yeah and then finally that is our user over here and then we just um again encrypt our we get our token so i'm just going to actually copy this over here word for word and just paste that at the bottom and bada bing bada boom that is it so we have now set up our sign up and our login route we've can we've set up our database client as as well and now all we have left is creating our database and making sure that um the tokens are being used correctly so i'm gonna stop the video right here because it's getting quite long we've reached 30 minute mark now if you did enjoy this video please share your support down in the comments section in the next video we're just going to be wrapping this up and i hope to see you there peace
Info
Channel: TDot Code
Views: 1,311
Rating: undefined out of 5
Keywords: golang, go-fiber, jwt, authentication, zero memory allocation, gopher, web server, api
Id: SAsTnFRbGR8
Channel Id: undefined
Length: 29min 53sec (1793 seconds)
Published: Tue Sep 07 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.