JWT Refresh Token with Asp.net Web API 8 and C#

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone welcome to my channel my name  is Foad Alavi and because you asked me a lot of   questions about how to implement refresh token for  JWT authentication I'm going to show you how to do   that then stay tuned I have a project here it is  using JWT for its authentication and authorization   let's see the structure of the project and  after that we can have a deep dive into how   to implement refresh token injecting a connection  string here telling the asp.net engine that I am   using asp.net identity for storing the password  and username related informations using identity   user and identity role uh I set everything to  false because I'm going to use one 123 as the   password Here we said that we are going to use JWT  beer default a scheme for creating authentication   and authorization and we are just reading a key  one static key from the app setting. Json file   and validate the token you can see here that  I have the key here we have issuer audience   here but here I'm not validating them let me go  to the controllers I have two controllers one   out controller in the out controller I have two  methods one for registering a user and another one   for logging in and they are using the out service  that I have for the out service we have the login   method it is accepting the user if I check the  user user has just sorry let me check it it has   just username and password it is receiving this  information from the client and then send it to   the out controller. lugin in the lugin first we  check if a user with this username exist in our   asp.net Identity or not if the user doesn't exist  or if the password is not correct we just return   the response what is the response model that we  have here the response model has two properties   is logged in and JWT token by default is logged  in is equal false then when we return it here   without changing it it means that it is not logged  in but otherwise we are going to change it to true   and generate adjon web token and place it in JWT  token let's see how I'm doing that we are just   setting some claims username as a name and admin  as their role we are just getting the key from   the application. Json creating the security  key creating the signing credential and then   create this security token and out of that we  can write one Json VB token I have five videos   about authentication and authorization and one  dedicated video about how to use Json web token if   you are not familiar with Json web token and how  authentication and authorization Works in asp.net   core please review them the concept that I taught  you there is applicable for net Core 5 6 7 and 8   because there are some Concepts there is no change  there's almost no change in these Concepts and you   can apply them on all Frameworks uh now that we  have a logged in user let me go back to the out   controller based on the login result if the login  is successful we are returning okay login result   otherwise I'm returning unauthorized by default  it is better to return okay if it is authenticated   unauthorized if it is not uh if it is not uh  authenticated correctly and return internal server   error or bad request if something goes wrong I'm  not checking it here but for the real projects do   not forget to check these things now that we know  how this project works it is better to talk about   what is a refresh token in the previous videos  I explain that refresh token is something that   stores some credentials and some information on a  token and this token is encrypted encrypted means   that we can decrypt it if I generate one JWT I  can go to jw. paste it there and you will see   the values there but what if another user or a  hacker find this token and start using it for   making our site more secure we are not going  to let this token be alive for more than 60   Minutes for more than an hour honestly speaking  in the project that I'm working in some of them   the expiration time for the tokens are less than  half an hour but should we ask users end users to   log into the server every half an hour or every  an hour I guess it is not a good user experience   then how can we make it a bit more secure imagine  that we have a mechanism that we are issuing one   token for the user and the token will be expired  every 15 minutes but we let the users to create   another token without sending the username and  password to us this mechanism is called refresh   token this refresh token should be called by the  client side or the consumer of the service which   means that if you want to refresh the token the  client side application or the other API which   is calling your authentication API should realize  that that they are not authenticated anymore by   getting the first unauthorized response and  send a request for the endpoint that we have   for generating the refresh for generating the new  token based on the refresh token for being more   secure we want to have an expiration date for the  refresh token as well because if you generate a   token and let developers to use a refresh token  for the rest of their lives what will happen it   is not secure anymore because eventually someone  may have access to that token and refresh token   okay enough with this uh introductions and let's  see how can we do that first of all the thing that   we need is to create a refresh token and send it  back to the user when the user is going to log in   we are returning login result to the users let's  go to the login result our login result inside the models and just add one string which is refresh  token we are going to return not only token but   also refresh token to the users and now it is  time to generate this refresh token let's go to   the lugin method uh in the response I have JWT  token let's create the refresh token I want to   have a refresh token inside the response user uh  inside the login response and generate a refresh   token and place it here let's create a method  for this one this is my method and I just need   to generate one uh refresh token the refresh  token is just some meaning list numbers that   we generate them randomly and send them to  the client here uh I created a random number   which is an array of byte 64 bytes I'm using  the random number generator that create and   create this number generator and getting  the bytes out of that and create one Str   string based on the 64 by array uh now we have  refresh token here and sending it back to the   user Let's test it and see what happened for  testing that uh I'm going to run uh net watch   but before doing that because I don't have the  database for this project yet I need to create   it I placed one read me file here about how to  generate the migration and update the database   you need to have Entity framework installed  inst on your application and on your machine   uh let's do it I'm going to create let's  use the rme file that I have here first of   all I'm going to create the it should show the  preview when I'm clicking on it I'm pretty sure preview no preview nice yeah miracles of  Microsoft let me just copy these things   which is doet framework Entity framework migration  and add migration with name initial it is going   to build my application and after that create it  for me and after that after having the migration   I have the migration files here right now I just  need to update my database based on the connection   string that I have it is going to create a  database for me and push all the migration   information that I have to the server if I go to  SQL server and refresh my database I will see that   now I have my ASP server identity based database  which is nice we don't have any user then first   we need to register a user I created a tunder  client request uh set or what you call call it   the collection set of the requests you can use  Postman you can use um Swagger but I prefer to   use Thunder client in one of my videos that  I put the link here uh in the up right side   or up left side I'm not sure I'm going to place  it that how can you generate this request using   this thunder clients and Postman then you login  you can just create a variable read it from the   server place it inside the variable and after  that just use it okay let's see before running   the application let me go back to the out  service that I have and let me check this   token will be expired in a minute 60 seconds and  inside the program. Cs I'm going to remove this   one I haven't explained it uh it remained here  from the preparation that I had for this video   I'm going to explain it don't worry and let's  run the application using net watchet watch   is a command which is building the application  running the application and if I change anything   it is going to rebuild the application behind  the scene and I can use it without any delay this is the request I created to register a user  it is going to send a request to this address how   do I know that what is the port for checking the  port you can always go to properties inside the   properties we have a launch setting application  and in launch setting application the profile   the first one which is not IIs which is not is  Express you need to check it and the application   URL here it says it is going to run it on Local  Host and on Port 92 tunder client again send it   it says successfully done if I go back to my  database go to the users and just select it I   will see that I have an admin there is no password  here which is good for us because the password is   secure and it is going to be it's not encrypted  it it is going to create a hash out of that which   means that even if we want as developers to uh  somehow reverse engineering that and get the real   password out of the hash that we have here it is  not possible because hash is a one-way algorithm   when you hash something you cannot reverse it  encryption is two-way algorithm which means when   you encrypt something you can decrypt it we will  explain it a bit later in another video that I'm   going to create about how JWT works and how to  use public key and private key for JWT uh fine   again back to the tunder client if I can find  it if I login the body is username admin and   password is 123 if I send a wrong username and  password it is returning unauthorized but if I   send the correct one it will generate a token and  refresh token for me what I need to do right now   I'm sending a refresh token to the consumers of  my service which means that when the token itself   is expired this refresh token will help them to  automatically generate another token but I said   it is a good idea to have an ex expire date for  this refresh token which is maybe one day maybe   a week a month 6 months but it is better than  not having it and let them to use this refresh   token Forever This is the first thing that I  need to implement and the second thing I need   to save this refresh token for each user inside  the database to be sure that this refresh token   is valid and it is something that I generated  for them and send it to the client let's start   with the second one first by adding this  information to the database let me close   everything and go to the context this is identity  DB context I don't have any DB set which is weird if I see the implementation I can see that   we have some DB sets here by  default if I can find them roles user roles claims and so many other things  like uh identity users this Base Class it has some   tables it has some dys sets but what if I want to  store some more information to some tables as an   example here in this table if I want to store  the refresh token here to check it every time   and see if the refresh token that user is sending  to me is the correct one or not for doing that I   have to create a model and let's call it extended  user identity and in this extended sorry extended   identity user and in this extended identity  user I'm going to inherit from the identity   user which is the default implementation for the  user in asp.net identity we need to have two more   properties refresh token and an expiration for  the refresh token and we are going to save them   inside the database fine but how to do that for  doing that I need to go back to the out demo DB   context and add them here the reason that I'm  not typing here and pasting everything here is   that I prepared it uh behind the scene and in  advance and just for the sake of saving time   I'm not going to type them and just past P them  here and don't worry I'm going to put this code   on my GitHub repository that you can find the  address inside the description now we need to   tell the identity that instead of we need to  tell to the Microsoft identity that instead   of using identity user you have to use extended  identity user let's go to the program. Cs in the   program. Cs when we injected at identity we said  use identity user but now we want to tell them use   extended identity user and don't forget to go  to the alt service inside the alt service when   you created user manager from the type identity  user now you need to tell them it is not from the   identity user just change everything to Extended  identity user now we can just create another   migration and after that update the database or I  can remove move the migration that I have go just here delete the database using this command  netf database drop if I run it it takes time   but it is going to drop the database for me and  I can create a really fresh clean database from   the beginning okay it throws an error it said  that it couldn't build the application let me   build it and see what's wrong with it okay there  is nothing wrong with my application because I   have it on watch it doesn't let another build  to get complete I just press contrl C to break   this uh build break this run and watch and let's  run it again here I can run it again easily using   drop it is going to start building build drop the  application yes I really want you to drop it drop   pick the server and create another migration see  the folder here yeah migration is here and now   I want to update the database database is getting  updated perfect and now let's run net watch again   go to database run it the table is clean go to  Thunder client and send this request go go to   table again let me see okay why I cannot see the  fields here I guess it is because I need to press   start because when I right clicked on this table  and said select the first th000 rows it generated   the number of the columns for me now I can see  I should be able to see the refresh token come   on I should be able to see it yeah this refresh  token and refresh token expiry I was looking for   it at the end of this the list of the columns  but it was here good for me let's go back and   see how it works I need to make another change  as well let's go to the visual studio and to the   out service let me put it here all unexpected  things happen when you are recording a video   uh fine this refresh token is generated and  now we need to save it inside the database   I got this identity user from the database and  check the password now I just need to add this   refresh token value to the refresh token field  that I have and said that for 12 hours from now   this refresh token will be expired and and then  update the user let's save it and see if it is   done yes now if I click on login it is going to  login generate a refresh token which starts with   for o and ends with EQ equal equal let's go to  the database and check it I have a refresh token   which starts with 40 and ends with EQ equal  equal and after 12 hours which is the 4th of   February 2024 at 1:00 in the afternoon uh why it  is 1:00 in the morning sorry because it was 12   hours not 24 hours 1:00 in the morning it will  be expired very nice let's start with creating   the model that user should send us with token and  refresh token uh let's call it the refresh token   model I'm really bad with names you can see that  and it should have JWT token and a refresh token   now I can go to the controllers and inside the  controllers just create this controller here this   controller it accepts the refresh token the name  is refresh token and you can call it by sending a   request to refresh token endpoint it is using  a refresh token service in out service let me   generate it yes I have it here and go to the out  service in out service I should implement it as well I need to have a method called refresh token  uh it has an error because it says that you need   to return something something okay fine what  do I need first I need to go to the database   find this user and get the refresh token value  and the expired date for the refresh token for   going to database and finding this user we need  to have access to the username of this user how   can I have the username of this user okay let  me show you a thing let me go to jw. here I can   paste my token I can find the token here in  Thunder client and paste it there I have my   username as name inside the payload of the token  and I can show it here show it to you here as well   when we generated the token string this one is  refresh token when we generated the token string   we pass the username and place them in inside a  claim which is called name how to get the claim   out of a token for getting a claim out of a token  we need to retrieve the principle user principle   if you don't know what is user principle go to  the first video that I have for authentication   and authorization using asp.net 5 that I put  the link here or there on the right or left   I'm not sure then let's generate a method for  get token principal inside this method I just   need to get the security key that I have inside  the application. Json which is just a random gu   ID create a validation token this validation  token parameter should be exactly the one that   we create that we pass here and that we are  checking here this validation parameters here yeah and then we should just return JWT security token Handler and validate  token we do have a token yeah let's call it token   and it is going to uh based on the validation it  is going to return the result and result should   be claim principal if I can find it it can be  null as well let's make it nullable we have the   principal here let's see what do we have inside  this principle uh principle do identities let's   go to identity because I don't have more than  one identity I have just one identity and here   I have a name that I know that I placed usern  name inside the name now that I have the name I   can just send a request to the identity server and  get the user um before that let me just generate   the response that we are going to return and do  some checks and get the user information from the   server we are checking if the principal is null  or identity is null or name is null just return   the response which in this response as you can  recall the is logged in is equal to false and   and then it is going to retrieve the identity  user using user manager. find user by name async   let's don't think about the conditions that we  are going to generate this token for now and   just generate the token how should I generate  the token really easy exactly the way that we   generate the token and refresh token for the  login I'm going to copy it from here and paste   it there easy peasy the user we have it then the  login should be true JWT token we are going to   generate a JWT refresh token we are going to  generate a new refresh token we are going to   update the refresh token inside the database and  update the expiry date for this a specific token   and refresh token and update the user okay great  now we have a refresh token mechanism but how   about the conditions that I said the condition  that I usually check for issuing a new token   and refresh token is something like that first  I will check if the user is still exist inside   the database or not imagine that 4 hours ago I  generated a refresh token and a token and user   got deleted or got disabled in that time then if  a request comes from that user it is not valid the   refresh token that I have inside the database  if it is not equal the refresh token if it is   not the same refresh token that I'm receiving  okay then it is not valid anymore this is not   valid this is not valid and if the refresh  token expiry date is later than the current   date I'm going to return the response and for  now response is logged in is still false uh it   shouldn't be UTC because I just used now but in  most of the projects I use UTC now because if   your application is going to get executed in  more than one region more than one time zone   region it might get confusing if you generate  refresh tokens in different uh time zones then   create an standard and the standard should be the  UTC one fine now we have everything let's go back   to the controller inside the controller it says  that we we still have some issues let me see what   issues do we have uh it is a task this task should  return let me see what we are returning here lugin response fine and now if I save everything and  go here netw watch because we added a file we   need to say yes rebuild it it is going to rebuild  everything for me and now I can go to my uh tunder   client again and generate a new request and save  it here in my collection for refresh token let me   do it new request the new request name is refresh  token or something like that it should be post   method it should be post method correct and what  should it send let me check the body there is no   shame in not knowing what should you send there  uh let's use Swagger in Swagger it says that you   have to send JWT token and refresh token thanks  Swagger but how can I get this JWT token and   refresh token if I go to login I will see that  I am passing the Json JWT token to a variable   called JWT token fine go back to the refresh token  and replace it with this one the color changed to   Blue and I need to create another one it should be  set variable environment json. refresh token and   the variable name is refresh token fine let's  save it go to the refresh token and paste it here if I just run it again hopefully I will see that it is loading everything for  me if I click on this button for showing the   code and click on shell from the codes  it is showing me that what it is going   to send to the server it is going to add  this JWT token and refresh token and the   values are things like that the refresh token  start with j4 ends with wa let me check it   go to login j4 wa and the token should work  because it was working previously as well uh let's close everything go to login again send  a new login request inside the refresh token   oh [ __ ] I forgot to save it let me create it I  just paused the recording and generate it again   and press crl s to save it because I don't want  to do it anymore it says unauthorized let me see   what is happening send another login and see the  refresh token and this one is correct and it is   returning an unauthorized error let me check  the code and see what is that I will pause it   and explain it to you later hm let me think the  first time that I run it it says successful and   after that said unauthorized let me log in again  we are creating Json web token and refresh token   and storing them inside the database now if I just  send it it says okay and it is going to generate   the JWT token and refresh token for me the next  time that I try to send it it says unauthorized   which is correct why because it is trying to  use this JWT variable and this refresh web token   variable which we set when we are logging into the  server then here I need to go to test again copy   it from here and go here and paste it and it is  from environment again it is Json web token now   that the variable names are correct let's see the  name here here which is JWT and here it is refresh   token let's save it and now if I lug in again and  go to refresh token and send it again and send it   again and send it again it will work for us for  testing it I created another controller here uh   where is the controller that I have let me find  my controllers oh I place this identity user in   a wrong place let me move it here yes and it  just fixes visual studies wise enough to fix   this name space as well great I have a test  controller and I have an authorized uh test   controller sorry test endpoint and authorize test  endpoint inside the test controller for this one   the first one you don't need to authenticate but  for the second one you need to be authenticated   we can test them and see what will happen uh  now it is getting a bit funny uh let's log in again let's go to the authorized test and  unauthorized test okay both of them are   returning status 200 it is it is because  the token is still valid but what if I   change the token validation period come on  token validation period to 20 seconds or 10 seconds let me change it to 20 seconds now that  that we know how to generate JWT token how to   generate refresh token how to use it how to call  it everything it is time to show you one a small   Corner case that JWT is going to surprise you  the first time that I saw it you know I spent   a lot of time maybe a day just investigating  online how should it uh be fixed and how is   it even possible for showing that to you I need  to change something I have this test controller   and for the authorized end point instead of just  returning okay I'm returning this one I'm checking   authorized header getting the HTTP context  request and authoriz authorization header if   I don't have it I will say that no not yet it is  not valid in this case because we have authorized   attribute here let's get rid of the this if  I don't want this port as well I will explain   it again I'm showing authenticated new line and  then here the token that we have I'm extracting   it from the authorization header remove the beer  replace it with nothing and after beer we have   the token using JWT security token and passing  the token which is a string we can decrypt it   and by decrypting that I mean everything that I  had and I placed inside the JWT can be retrieved   here let's check it JWT do I can have access to  issuer subject everything one of the properties   that we have is valid two valid two means that  what is the expir date for this token you might   ask a question that for we have the claims here  here why for generating refresh web token you   just uh bother yourself to create the identity  principle honestly I don't know maybe for learning   purposes or maybe I trust that more I'm not sure  it is just an old practice that I do in the Json   web toen uh this JWT I'm just going to print out  the expired date based on that and then the local   time and let's change it to now not UTC great  and let's check it if I go here it is running   if I come here and log in before that again let  me show you that after 20 seconds this Json web   token should not be valid anymore let me lug in  go to authorize test send okay great the time the   expire date is 1:30 and the time is 2:22 oh I need  to change it back to the UTC because I live in am   uh not in Amsterdam but I live in the Netherland  and we have one R difference between here and UTC   uh because JWT worked B based on Linux time and  Linux time is based on UTC then I need to leave   it as UTC but it is not my point here my point is  of course it is 1255 refresh it is 1335 it is more   than 20 seconds how is it possible that it is a  still valid the answer is and I found it in JWT   documentation some years ago when I faced this  issue for the first time that they decided to   ignore not really ignore but extend the lifetime  of the token by 5 minutes which means that if you   say that this token should be valid for an hour it  will be valid for an hour and 5 minutes if you say   that it should be valid for 10 seconds it will be  valid for 5 minutes and 10 seconds which is funny   but for testing that how can we get rid of this  um how can we get rid of this uh 5 minutes let   me go to the program. Cs can you remember that we  had something here clock SCH and thasan zero and   I said let's remove it for now and at the end of  this uh video you will see that how to use it when   we set it to zero we say that that five minutes  that you said in your documentation forget it I'm   wise enough I can make decision for myself you  don't have to make decision on my behalf and let   me see if it is wrong again because I changed  something inside program. CS I need to run it again and now it throws an error because the  application was not up and running yet but now   it says unauthorized good let's try it again  log in I'm logged in I can have access to this   one until 44 seconds now it is 26 seconds 34 36  38 come on 40 42 43 and now it is unauthorized   just by changing that let's test our refresh  token by sending the refresh token go back   to the authorized test and now it works again  okay great it was all about how to implement   refresh token for your web application but be  careful because you implement that one on your   web application but the consumer the client  side of this service this authenticate server   is responsible to get the unauthorized response  from the server and realize that okay I have a   token and refresh token now it is time to send  a request to the refresh token end point using   the token and refresh token and request for  another one there are some ways that you can   do it from the server but uh yeah it is out  of the scope of this video maybe we can talk   about it later if you say that you need it  do not forget to subscribe to my channel and   like this video keep watching to my channel  because I'm going to post another video next   week about JWT how it works behind the scene  and another one about how to have public key   and private key and not share this secret with  all with all the clients if we have more than   one server which is using the JWT and just  send the public key with them and secure the   private key in the server then do not miss  it keep practicing and enjoy your life as a developer
Info
Channel: Foad Alavi
Views: 5,018
Rating: undefined out of 5
Keywords: C#, .NET CORE, Web API, ASP .NET, Test, XUNIT, SQL, SQl Server, tutorial, For Beginners, TDD, JWT, Refresh token, step by step
Id: DzBwfoKnmhk
Channel Id: undefined
Length: 43min 31sec (2611 seconds)
Published: Sat Feb 03 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.