C# API Authentication using JWT | .NET Core Authentication

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Awesome

👍︎︎ 1 👤︎︎ u/jogai-san 📅︎︎ Mar 31 2021 🗫︎ replies
Captions
in this video we will build an authentication system using dotnet core before we start building the app i would like to remind you that this video can be combined with other videos so if you want to use c sharp with angular react nexjs view nexjs orswelt i provided some links in the description of this video the combinations are optional so you may watch this video without needing to combine them also make sure to check scalable scripts.com now let's create the goto.net.microsoft.com and click download and download the right version for your machine i downloaded.net core so this is my ide i'm using rider from intellij but you can use visual studio or visual studio code is the same now i'll create a project here and i have dot net cli running in my machine and to create a new project write dot net new and we have a bunch of projects here that we can select i will select the web api here since we'll create an api so dot net new web api and the project is created so now we can see a bunch of files here so i will remove whatever is not necessary so i will remove the weather forecast here and the controller for the weather forecast i'll keep the controller folder i'll remove swagger here so keep everything really simple and that's it so let's try to run this project by running dot net run and we have two ports one is https and one is http so i'll click the http one so nothing is running right now what i will do right now is change this port because our backends they will all have the port 8000 and i will remove the https so the application url here in properties launch settings.json will be http localhost port 8000 and i will restart this and now it's running successfully now let's create a controller so we can see something on the browser i'll create i will call it auth controller here we need to set the namespace i'll call it auth controllers and the classes out controller will extend from controller from microsoft asp.net core mvc and here i will add the method so i will create a public function that returns i action result and i'll call it register and for the moment i will make it a http get so i'll not name it register i will just name it hello and this will return ok ok means successful response and we want to return the message success so let's return this simple endpoint also make sure the controller is an api controller and also let's add the route so for the moment i will make it empty but we will change this and everything is okay so let's see now let's restart and let's click and as we can see this is our first endpoint and now we want to connect with the database so i will open my database right now and i will connect with mysql you may connect with sql server or you may not have this right tab but you can use either mysql workbench sql server or any other tool so in my case my user is root my password is root root and database is youtube c sharp house so i connected with an empty database right now so now let's make migrations to create the table that we need so the user table first let's create the user model i'll create here a folder where is the directory models and inside let's add a class user so we have our user here and now this user will have these properties public int id will set a getter and the setter here and let's do the same for the other other properties we need the string name here email and a password so this is our user now to map this user with the data and to create migrations we have to add some packages so go to nugget.org and here let's search for entity framework and this is the package that we need so we will use a dot net cli here and i will copy this and i will open the terminal close this and run this command except i want to have the version 3.1.0 because the version that the latest version has problems with mysql and i want this version if you're using sql server you may want to add the latest version so we need also entity framework core that design so the entity framework is installed now i want to use it with a command line like this dot net ef if you don't have this command run dot net to install global dot net ef eff so i already installed it so make sure to install this package and we have the net tool set also we need another package which is mysql and what we need here is mysql data entity framework core so copy this and i will paste it here and install it so everything is correct till now now let's uh to add the migration we need first to create a context so i'll create a folder here called data and we need to add here a user context so user context this class user context will extend from db context so using microsoft entity framework core we need to add the constructor here so public user context that has a db context options like this with our user context options will extend from base options like this so this is our user context and this will have a property here so db set of user don't forget to import the model and this will be the users array that we will work so we added the db context now let's connect with the database let's go to the startup and here in the configure services we'll add the services add db context we need the user context and inside we'll have the options and the options will use mysql like this and we need the connection string to connect with mysql so to connect with mysql we will add the connection string here so connection strings and inside we'll add the default connection string and it will be like this the server will be localhost the port is 3306 the user is root the password is root root and the database was youtube c-sharp host so this is a connection string and let's add this connection string here let's call configuration get connection string default like this so we added the the connection and now we are ready to run migrations to run the migrations around this command dotnet entity framework migrations add create users table we need to build so we probably have an error so net build so my mistake here when i install the entity framework core where is it it should be 3.1.10 so just a smaller version so this was the design and we need also the entity framework core so if we run build right now it should work so it does work and now let's run again the migration create user stable and we will have a folder right now migrations where we have our users table so these are all the columns that it will create just the email is available true i want the email to be unique so how do i make the email unique first we have to remove all the migrations here by running this command so dotnet ef migrations remove so we removed all those migrations and now let's make the correct changes to other to make the email unique so in the user context here we will add protected override on model creating and we have this function that we want to override here what we want to do is add model builder entity we want the user here and what we want to do is call the entity and the entity will have has index the entity email here will pass the email and is unique so with this we will call the user entity and we will say that this email is unique so let's run the migration again and now it will have the email as a unique index so we created it and now if we see the users we'll say here that uh here the index is the email is unique to true so now everything is correct and now let's run the so.net ef migrations update and let's see sorry i made a mistake it should not be migration it should be database and now the build has succeeded and if we refresh the table we'll see the migration history here and the users table with the fields that we wanted so we have the id name email and password and also the email is unique so now we have the user model that is connected with the database and what is left is adding the methods to register the user in our controller but first we have to create the user repository so in the data here i'll create an interface and a class so let's create first the interface i'll call it i user repository and this user repository will have some functions but the first one is user create and will pass a user as a variable here so this interface we will inject it here so we will get the constructor so public house controller inside we'll have the i user repository as a repository and i will initialize this so we'll get the eye user repository as a property inside the controller we will set it here and we can use it directly so this repository if we use it here we'll have the method create that we just added in our interface so this will be available but we need also to implement it so to implement it we need to add another class which is the user repository and this class will implement that interface so let's implement the missing members which is this uh user create here before adding anything here we need to inject the context this user context here so let's add also the constructor here user repository and this user repository will have the user context as an inject variable so and we need to introduce the user context here also so this is not called inject variable sorry my best this is called dependency injection so we have the context here and now let's implement the user that we want to create and this is really simple we have to call the context we have the users so in our context we have the dbset which is users and we want to add another user so this user here and that's it so the context in the end it needs to save the changes since this says user here we have to return the user that was just created this user that we set here doesn't have the id so what i will do right now is set the user that id is equal to this so when we save changes this will return the id of the user that was just created in the end let's return that user so we finished the create method and now how do we distinguish that this i user repository is the type of this user repository because other classes can implement the same interface how do we make sure that this is the type of user repository and to do that we have to do it in the startup so in the controllers here we will add services add scoped and we'll say that i user repository is a type of user repository i made a mistake this should be with this science and with this we can say that the i repository that we inject here is a type of user repository so we can use this function and now we have that function let's create the register method and before adding the method i will change the route to api here so it should start with api and this method is http now post and the end point is register so this route now becomes api slash register and the method is register now let's test this endpoint first let's uh run.net run and also make sure to install postman so to test this endpoint we have to install postman i already did it and let's add the end point here which is http localhost port 8000 slash api slash register and this is not a get request if we send the error and the request will get the method not allowed this is a post request right now and we are getting success so now we send a post request to api slash register and we want to get the request data inside here so to transfer data we have to use dtos so i'll create another folder here dtos dto stands for data transfer objects so inside i'll create another class and i'll call it register dto and this dto will have so what data we will send from the front end so we'll send a name name set get here we'll send an email and a password so these are all the data that we will send and we can use those here so register dto i'll call it dto now with this ddo let's create our user so let's create a variable user is equal to new user and i will manually set the values so the values for this user will be the name so let's import it name which is equal to dto dot name email is equal to dto dot email and the password we have dto.password but we have to hash our password so let's go to nugget nugget.org and get bcrypt here so we need this package here and i will copy it and install it to the cli not the this i'll paste it and i'll install it so now let's hash this password by using bcrypt dot net bcrypt hash password and we'll pass this password here so now when we create the user we will have the password hashed and now let's uh send this user to the repository so we have to call here repository create and will pass the user and the user will be created and we want the user to be in the response so instead of okay here i'll return created the message is the same and the value is the return of this repository create so that's it now let's try to register this user so we'll send the data we'll send a name a email ata.com and the password is also a so this is basically the dto so the exact same data as the user as a registered dto so this will be mapped here and we will create our user let's send the request so i forgot to dot net run let's send the request again and as we can see we get the id the name the email and the password which is hashed so this is also inserted in the database if we check the users everything is correct so we gestured our user now with this user that is registered what is left is to login so let's create another function i action result login this will be also post request to api slash login so let's add also a dto for the login so i will add here a new class login dto and this will have the same as register except we don't have the name here we'll send only the email and the password and in the out controller here we'll send the login dto dto so what do we want to do with this login dto first we want to get the user from the email so i'll add in the i user repository another function which also returns a user which is get by email so we'll send a string here email and that's it so in the user repository now we need to add public user get by email and to get the user by email simply return context users first or default and we will loop the users and we'll get the user with the email which is equal to this email and that's it so with this we'll get the email let's go to the out controller where user is equal to repository get by email and we'll pass dto email here so in case the user is now so we send the wrong email what we want to do i'll wrap it with a curly braces we want to return a bad request and we want to return also a message so new message is equal to invalid credentials also return the user in the end so if the user is null we will return this message so we won't return the user so it should be like this better and uh in case uh the second uh condition now is we don't we find the user with the email but the password is incorrect so another condition here if not so i'll add an exclamation point here and i'll call decrypt again dot net dot b crypt verify we want to check if the password is correct so dto that password is the same as the user that we found password and if that fails also will return the same error so we return the same error because we don't want to know which is the wrong the email or the password so this is a little bit more secure and if everything is correct we return the user so let's try this endpoint right now so first let's restart i'll copy this open a new tab and this will be a post request to api slash login and in the body we'll send an email which is ata.com and the password which is a but i will send the wrong email send a request and we will get invalid credentials also bad request here so the email is wrong in this case if we send the wrong password we'll get the same error but we don't know which of this is wrong in the end if we send the correct data we'll get the user that we want actually we don't want to return the user here now with these validations we pass the validations we have to generate a jwt token so first let's get the package of search here jwt and we need this so system identify model tokens jwt i'll copy the link and i will install it now it's finished now let's generate a jwt token so i'll create first another folder i'll call it helpers and i will call i will create a class called jwt service so we want to create here two functions so the first one is generate so this will be a public string generate and we will pass int id so we'll pass the user id here and we want to generate a jwt token and how do we do it first we have to get the security key so we have to get the secure key here so it's public string not public private string secure key so this is a [Music] key that we want to encode our jwt with this id so what i will do here i will write this is a very secure key so it should be a long string otherwise we'll have an error if we put a short string so i added the secure key and now let's use it so we have to get the bytes which is equal to new symmetric security key encoding u tf8 get bytes of this secure key so maybe bytes is not the right name but uh symmetric security key i will call it and we have this now we have to get the credentials credentials are equal to new signing credentials will pass our symmetric security key and we need the security algorithm which is security algorithm each mac is so this is the security algorithm i cannot pronounce it so with this we created the credentials and now we need the jwd header so i'll call it header is equal to new jwt header and we will pass the credentials so we got the jwt header and now we let's use this id by creating a payload so let's create a payload the payload is a data that we set so these are standard security data so we merge this with the secure key and the payload is the data that we want to encode so this will be equal to new jwt payload and inside we'll pass the issuer so the id is our issuer so we have to pass also other values which we don't need so the first one is the issuer the second one is the audience claims and this should be null also and the last one is the time that this token will expire so i'll add daytime today and i will add day to one so this will leave for one day this token also we are having an issue with the issuer since this should be a string so we created a jwt payload that has the issue this value we don't need these values but we can set the expiration time to tomorrow so now let's combine the header with the payload so we have to create here where security token is equal to new jwt security token and we will pass inside the header and the payload and that's it we created the security token and the last step is to return it as a string so because this is not a string and to return it to the string we have to return here new jwt security token handler write token and we'll pass a token oh sorry this is a security token so this is our generate method dc all these steps are required to create a jwt string so let's use it to our out controller and we want to inject it also here so i'll create here jwt service jwd service let's also add it here so we have the injection for the jwt service and our jwt is equal to jwt service generate and will pass the user id so this should be upper case and for the moment let's return a new jwt so i will return it like this let's see it on the browser how it looks like so let's send the request and i have to restart it so it should be dot net run send a request so i should add the jwt service in the startup here so i'll duplicate this and we need to add here the jwt service so it's a good idea to have also the jwt service interface but i won't complicate it i will keep it simple and let's restart it and this time should work so send a request and as we can see we got a jwt here so this is a token that we want to send it to the front end so it's not enough that we return the gwt as a value here because we have to return it as an http only cookie so what is the last step right now is adding response cookies append we will add the cookie named jwt the value will be our gwd value that we set and we have some options which are new cookie options and i want to set here http only to true so now the jwt will be inside an http only cookie where the front end cannot access it the only purpose of an http only cookie is to get it in the back end and the beckham can modify it or access it the front end just have to get it and send it and instead of the jwt here i'll send the message to success that's it so right now we are generating a gwt and we will set it to the cookies and the frontend doesn't have to access it so the same request i will run a.net run here so we can see we don't have any cookies right now let's send the request we'll get a message success but we also get a jwd cookie which we set as an http only value so the jwt is set so we are not finished yet because for the front end to get this cookie we have to add also another option which is the credentials so to do this we have to get another package here called course so we have this package all copied and i will install it and let's go to the startup and here on top i will use services add course so before i continue what is course so course when we create a single page application the browser will prevent requests from different ports so our port is 8 000 in this up and the front end will run on different ports and if the front end sends the request to the to our back end it will prevent that and to not allow it we have to add cores here and we have to add also another configuration here after the routing so we have to add up use course and this will have some options and we will add the options so what options do we want to add so we will allow any header we will allow any method and this was the important one allow credentials so this is the option that we need in order to send cookies in the front end if we don't add this option the front end won't get those cookies and also we need to add here with origins we want to specify the origins that will access this endpoint and i'll create a new array here and we need this endpoints which is http localhost port 3000 this is for react i'll copy the url let's add another one 8080 this is for view and uh 4200 this is for angular so these are the ports that a lot for all of them but you can pick only one which front end you want so now that we added the course everything else should be correct it won't change anything from the request so this is not something that we will see a difference in postman but the front end will need that and now the login has finished now let's get the authenticated user so let's create the function public i action result user and this is a get request http get to user and now we want to get the user based on the jwd token that we set in the cookies so first let's get the jwt which is equal to request cookies jwd so with this we got the gwt and now we want to decode so here we encoded the gwd now we have we have to decode it so we will add the new method here which is public bull verify and we will pass jwt as a string so string jwt so now let's verify this token first let's create the token handler which is equal to jwt security token handler we need to get the key which is in bytes so key is equal to encoding get bytes of the secret key that we have secure key so now we have the key as bytes now we have the token handler i forgot new here sorry and now we have to validate the token so we will use this token handler validate token will pass gwt and we will pass a new token validation parameters we will add the parameters later but this will output so we want to get out a security token validated token so this is what we want to return and also now let's add the parameters so we need some parameters the first one is the issuer signing key which is equal to new symmetric security key and will pass the key that we generated as bytes here and the other one are options so validate issuer signing key to true and that's it so these are enough to validate our token but we have to add two more which are the validate insure to false we have to manually set the don't validate these things value validate audience to false and that's it so we got everything so we got the validated token here and uh i returned bull here but actually i will change this we will return jwt security token and this will be our validated token and we have to cross it also like this so we will get our validated token now and let's use it to our out controller so let's get the tokens of our token is equal to jwt service verify and we'll pass the that we got from the cookies we got the token now and now let's get the user id so i will do it int user id is equal to token issuer is what we want but the issuer is a string so can i cast it to integer so i have to use int parse the token issuer so we successfully got the user id now what is left is querying the user so let's go to the i user repository and i will duplicate this get by id and i will pass you a ninth for the id of the user let's add it also to the user repository so i'll copy this paste it and this is get by id and this accepts an int as an id so the change here is we will get the user by the id and that's it so let's go to the out controller now and our user is equal to repository get by id will pass the user id and let's return an ok response for the user also something else an error may happen anytime here so what i want to add here i will wrap it with a try catch because the token can be invalid or a lot of problems can happen here so this will have a general exception which we won't use but in the end i will return unauthorized so in case we have an error we will return unauthorized so we won't use the exception here and now let's see it so first let's restart the server and i'll copy this url paste it here and we'll send the guest record get request to the user also something to mention is that the cookie will be preserved if we send the request here now we will have also this cookie that we generated in the other tab so let's send the request and as you can see we get the authenticated user and we got also the cookie so this is the user that we got from the cookie we validated it and we queried it so this is our authenticated user also something else i don't want to return the password if we get the authenticated user because this value should be secure and to fix that in the password here i'll add decorator json ignore so with this when we return the response as a json we want to return the password send request again now and as you can see we get the id the name and the email this will work also for the register so let's create another user right now send and we created the user but we are not returning the password so we logged in we got the authenticated user the last function now is to log out so let's add here public i action result log out and this will be an http post to logout and this will be very simple we will simply remove the cookie that we set so response cookies delete the jwt and that's it so in the end let's return okay new message success so this is our logout function the only purpose is to remove the cookie now so let's restart the server send a post request to logout and uh before sending the request here we get the authenticated user because we got the cookie and now let's send a request to logout we got message success and we remove the cookie the cookie is removed here which means it will be removed here let's send the request and we get unauthorized so we successfully logged out we can log in again and we can get the user again so this is how our authentication works i hope you liked this tutorial and if you did please share and subscribe thank you
Info
Channel: Scalable Scripts
Views: 3,718
Rating: 4.884058 out of 5
Keywords: coding, programming, full stack development, scalable scripts, programming tutorials, developer, coder, software, laravel, react, vue, angular, django, python, nestjs, nextjs, nuxtjs, golang, denojs, nodejs, microservices, docker, kubernetes, rabbitmq, kafka, event driven architecture, event driven design, containers, mircorservices architecture, api, spa, single page application
Id: WNKwdgr34fA
Channel Id: undefined
Length: 56min 38sec (3398 seconds)
Published: Mon Mar 15 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.