Full Stack React & Django [5] - Django Token Authentication

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's going on guys welcome to video 5 in the Django reactor Redux series now we're gonna start to get into authentication because right now we can add leads we can list them we can delete them update them without any login or any authentication whatsoever so obviously that's that's not what we want in a production application so I want to be able to authenticate and we shouldn't we shouldn't be able to get these leads or add them or do anything without authenticating with a token so we're gonna have to go back to the backend to implement this kind of thing so let's go to in our lead manager we want to go to leads ok you want to go to our leads app and then models dot PI and we want to bring in the user model which comes default with Django so we're gonna say from Django dot contribs we want to bring in our import user ok so we're bringing in the user model and then I'm going to add another field to the lead of owner because we want to be able to basically track the leads per owner and we want each owner user to see only their own leads so I'm going to say equals models and then we want this to be a foreign key for the user table or the user model so we're gonna pass in here the user model we also want to add the related name which is going to be leads and then we can decide what we want to do if a user is deleted and we just want we want to delete all of the users leads as well so let's say on delete and we're gonna set that to models dot cascade okay and then I'm also gonna set null to true meaning that it will allow null values the reason for that is because we already have some stuff in the database and there's no owner and I don't want to get an error so we're just gonna allow null to be true for now all right so let's save this now just doing this obviously doesn't do anything we need to create a new migration so I'm going to open up my terminal this is my web pack server this is my django server so i'm gonna just stop the django server and let's see I'm just gonna CD into lead manager and we want to use manage dot PI for this so let's go ahead and do Python manage dot PI and let's do let's say we want to do make migrations alright so what happened here is it created a file called 0 0 0 to lead owner dot PI and we want to run this migration so let's say Python managed dot pi migrate okay so now it applied the migration and now we should have an owner field if we go back to our application well I'll actually have to run our server so let's say python managed pi runs server and reload it should still work and everything should should be the same now I want to make it so that we can't fetch these leads or add them or anything unless we're authenticated so to do that we have to go to our API and what we did before is we just set permissions to allow any we want to change that now for let's see instead of just setting this query set parameter here are this this query set property we're actually going to overwrite the get query set method because we only want to return the leads of the authenticated user so we're going to get rid of that and I'm actually going to go under the permissions here and let's say define get a query set this takes in self as a parameter and then we want to return self dot request dot user dot leads dot also it's going to get only the leads of that user all right now as far as permissions go we're gonna go ahead and change this from permissions dot allow any two permissions dot is authenticated all right and then let's see we also want to add down here another method let's actually move the serializer class up here like that so we have all our methods down here so we also want to do define perform underscore create and this is going to take in self and it's also going to take in the serializer which we have yeah it takes himself serialize err as a parameter and basically what this does is it it it allows us to save the lead owner when we create the lead so let's say serializer dot save and then we want to pass in owner and we want to set the owner to self dot request dot user alright so that should be good for the view set so I'm going to go ahead and just save this and let's reload and now notice that we're not seeing any leads down here and if I open up my terminal and go to the console you can see we get a 403 forbidden error now what I'd like to do is is have the arrows get added to our state so let's actually head into front end and go to actions lead j/s and right here I want to dispatch the get errors action to the reducer so just like we did down here when we add a lead in the catch right here we want to be able to do that now instead of just doing this for every error that we want to send down let's actually create a separate function that deals with this so we can just dispatch that function or that action and I think that a good place to put it would be in the messages the messages action whoops that's a reducer no that's the action so inside here this actions messages j/s let's go ahead and create an action to return errors so we'll say export const return errors and it's going to take in the message and the status okay and then all we want to do is return get sorry we want to return the type of get errors okay so this will dispatch to the to the reducer get errors and then for the payload instead of just creating an errors object and doing all that code I'm just going to simply pass in an object here with the message and the status okay so let's save this and let's go to leads and we'll bring this in so we're already bringing in create message let's also bring in return errors and that way we don't even need to bring in get errors here and let's go down to the add lead and inside of our catch instead of doing this let's just let's see we're get rid of this whole was this end right here so we'll get rid of this whole thing and let's just do a dispatch to return errors and remember it takes in a message and a status so we're gonna take the error dot response dot data that gives us the message from the server and then we'll pass in the error dot response dot status from the server okay so we'll take that dispatch let's see gens right here so I'm gonna just grab this and we'll do the same thing for the get lead okay so get leads instead of just console logging we'll go ahead and paste in that so let's see if that works we'll save and reload and now if we go to our Redux tools we should see it in the state so go here and make this a bit bigger you look in errors and you can see status 403 and message is authentication credentials are not provided all right and if we went to postman and made our get request we get that same message authentication credentials were not provided all right so we're now protecting this and even if we try to add here if we look in our errors we get of the same thing 403 authentication credentials not provided good and it's still going to just log this here now we need a way to authenticate and the way that we're going to do that is we're going to create a registration API so we can register a user and then once we register a user will be we'll create a login API once we do that if we log in we'll get a token okay when we get that token we can send that along with the headers or in the headers to to either add a lead or fetch the leads or anything that required or requires authentication all right so we're gonna do a lot of the testing with that with postman before we implement it into our front react app so I'm just going to minimize the front-end app here and we're going to be using something called Django rest Knox which we already installed I believe let me just double check the apps on our pip file a of Django rest Knox now we have to add that to our settings so let's go to lead manager settings and let's say we want to add this right here so let's say Knox and then we're also gonna add rest underscore framework okay so we want to set this we just want to set an option for authentication classes we're gonna say default underscore authentication underscore classes and we just want to basically let the system know we're using Knox authentication token authentication so we want to set this to Knox dot auth dot token authentication all right so save that and let's make sure we have no errors in our server now in order for this to happen we need to actually run a migration as you can see we have six on applied migrations so let's actually let's stop the server ok the Django server and we're gonna use Python dot manage to migrate so python I mean manage dot pi manage doc PI and we want to migrate okay so this applied whatever we need to the database which is these you know auth tokens expires off token key and so on alright so we can run the server again with our managed by run server now what we need to do is start thinking about creating our serializers for creating a user and logging in now we could do this in the leads app but I don't think that makes very much sense so I want to create a brand new app to do that and I'm gonna call it accounts so let's go ahead and let's run Python manage dot PI start app and we'll call this accounts okay and that will create an accounts folder as you can see right here now I'm just going to run the server again and since we added since we created a new app called accounts we need to go to a lead manager settings dot PI and add that as an app so it's ad counts okay we'll save that and inside accounts now we want to create a serializer file so it's a new file serializers dot pi and it's the same workflow that we did with the leads really it's just more in-depth because we have more to do registering logging in checking your user logging out stuff like that so we're gonna focus on registration first I want to get at least I want to be able to register a user using postman before we move on to anything else so in the serializers file we're gonna bring in from the rest framework we want to import serializers and then from Django dot contribs we want to import the user model okay Django already has a user model and already has all that authentication stuff in place we're just using Knox for tokens so we also want to bring in something called authenticate so we'll say from Django dots contribs dots off we want to import authenticate all right now we're going to create a user serializer so I'm just gonna put some comments in here just so you know what we're gonna do we're going to have that we're gonna have a register serializer and we're gonna have a login serializer all right so the user serializers is going to be pretty simple and it's gonna be very it's actually very similar to the lead serializer that we created so we're gonna say class user serializer and we're gonna pass in serializers dot model serializer we're gonna define class meta just like we did in the leads and define the model which is going to be the user model and the fields which are gonna be ID username and email all right and then for the register let's say class and we'll call this register serializer and let's pass in same thing serializers dot model serializer and we're gonna create a class of meta set the model to user fields oops fields we're gonna set to let's set to the same same ones we have up here except we want to also include the password look quotes around that because when we create a user we obviously we need to enter a password and then we need a couple extra if we need any extra arguments we can add this extra underscore kwargs kwa RGS and we just want to make sure the password is right only so let's say password and we're gonna set that to rights underscore only which is going to be set to true okay and then let's create a method here so on the same level as the class we're gonna say def create okay this is gonna take in it's gonna take in self and then validated underscore data alright we want to be able to validate username password email so we're gonna say user equals and when I say validate I just mean make sure it's the right type of data following following the the structure of a user model which we didn't create that's included with with Django so I'm gonna say user objects and then we want to create user create underscore user and we want to pass in the validated data and then each field so user name and then we'll put a comma here and let's say validated data and then email validated data and password and it should take care of the hashing of the password and stuff for us alright so the last thing we want to do here in this this method is just return the user alright so a create create the user return it and that should be all set so let's save this and now we need to create an API file just like we did with the leads so in accounts let's create a file called API dot PI and in this file we're gonna let's say from rest framework we're gonna import something called generics and we're gonna bring in permissions which we're not going to use just yet but we will be and then we also we need to send a response from this API so we want to bring in from rest framework dot response we want to import response okay and then for tokens we're using Knox so we're gonna say from Knox top models we want to import something called auth token okay and then finally we want to import the serializers that we just created so we want to bring in whoops from I mean import I get mixed up between the like the react the the es6 imports and python imports so let's say import user serializer as well as the register serializer okay so that should be all we need to bring in now let's create say register api we'll also have a login API and I guess a get user API just to get the user so for the registration let's create a class we'll call it register will call it registration API I guess we'll just call it register API and let's pass in generics and then this generics object has something called a generic API view so that's what we're going to use and it's kind of it's kind of an abstraction so we don't have to do you know if they're manually right every piece of functionality it takes care of a lot of stuff for us so we need to include the seria serializer class which is going to be the register serializer that we just created and brought in then we're going to define a method of post okay so this is gonna take in self it's gonna take in the request so when we make a request to register all the data we send the email password that's all going to be in here along with the headers and everything that we send and then we just want to do asterisk args and double asterisk kW args or kwargs which just just basically means like it can take more arguments it's kind of hard to explain it's something that has like that confused me for a long time it's part of Python so in here let's say serializer if a problem typing serializer for some reason and then we're gonna set this to self dot get underscore serializer and then this takes in data which is going to equal the request dot data okay so anything that comes in any data that comes in here is going to get passed into this this serializer and then we want to make sure it's valid so we can call serializer dot is valid and we're just gonna pass an option in of raise underscore exception and set that to true so that we send any send back any errors that are needed and then we need to save the user in the database so we're gonna say user equals serializer dot save and then finally we want to send our response back all right now this response we're gonna say return response which we brought in up above from rest framework and inside here we're gonna have an object I should say a dictionary this is Python and we're gonna send the user and the token okay so for the user we'll set it to the user serializer pass in the user object here and then a context which is gonna be equal to self dot get underscore serialize or context okay and this is actually a method and then we're just going to tack on to the end of this dot data that should give us the you the serialized user and we're gonna send that as a response I'm gonna put a comma here and we also want to send the token okay so just like if you log in once you register euro you'll also get a token so you can log in immediately okay if that's how you want it to work so this we're gonna use auth token from from Knox which we brought in up above here and we just want to do objects objects dot create and then pass in user so what this is gonna do is it's gonna it's gonna create a token that's specific to that user so that when you make a request from your front end whatever whether it's postman or react or view or anything else it's gonna know what you who you are from that token okay and that token goes in the header it goes in the authorization hat part of the header all right so hopefully this makes sense I know it's a little difficult so let's save this and obviously we need a way to interact with this so we need to create an endpoint so inside accounts I'm gonna create another URLs dot PI file and any URLs that have to do with authentication will go in here so let's say from Jango dot url's we're gonna import path and include and then we also want to bring in from our API that we just created we want to import the register API and from NOx I'll say from NOx we want to import views as NOx underscore views all right and then we want to send our URL patterns just like we would in any URLs dot PI file and we're gonna set this first path of API slash auth and we want to set that to include the NOx URLs Knox dot URLs okay and then let's put a comma here and we're gonna create the register path which is going to be that same API slash auth except it's gonna be slash register and then we're gonna set that to our register API in this register API we just have to tack on as underscore view okay because it's a generic API view now let's save this and we have to now include this file in the main URLs file so let's go to lead manager URLs dot PI and we'll put a comma here and bring this down and let's just change this to accounts dot URLs alright and then I'm just gonna reset the server just to make sure everything's okay here and now we're gonna try to register a user with postman okay so I'm going to open a new tab and I'm gonna make a post request to HTTP let's do localhost port 8000 slash API slash auth slash register and we need to send along in the header we need to send along the content type and that's going to be application / Jason and then in the body will choose raw and we'll send along our data ok the user we want to we want to register so username and we'll set that to let's just do I don't know just do John and email say J Doe and password and it'll hash the password automatically that's included with Django so password I'll just do 1 through 6 alright so let's try this out we might get an error looks a click send okay so we're getting a 500 error let's check the console here type object is not iterable alright guys so I paused the video because I couldn't find the answer for the life of me everything is fine what and what it ended up being I think I haven't tested it yet is in the settings file so if we go to settings dot PI where we put this this rest framework to fall authentication classes this is a tuple and with a tuple if you only have one value you need to add a trailing comma okay if you don't do that it's gonna look at it as a string so hopefully that's it let's go ahead and save this okay so now we're gonna we'll just restart the server here for good luck and let's go back to postman and let's try this again so same request to post request to register with this data and let's send and it works awesome so you can see that it gives us back the user and it gives us this token okay and this token is going to identify this user but we're sending the user data back you know if you want to use it somewhere in your application if you want to say welcome John or something like that okay so this response is coming from our API right here okay if you want to send other stuff along you could do that as well but now at least we know that we can register with our back-end so the next thing to do is move on to login okay we want to be able to log in as well which will give us basically the same response so let's go back to serializers and let's go down to our login serializer and we're gonna give this a class name of login serializer pass in serializers dot serializer and notice I didn't do model serializer because we're not actually we're not dealing with creating a model or anything like that we're simply validating that a user is authenticated okay or that a user name and password passes so let's say let's create a variable called user name we're gonna set it to serializers dot char field and password we're gonna set to serializers dot char field and let's say define validate we're gonna pass in self and we're gonna pass in data okay and then we're gonna set user to authenticate okay remember we brought authenticate in up here from Django and then authenticate we're just gonna pass in this double asterisk and then the data alright and then we just want to check to see if the user has is active so we're gonna say if user and user dot is underscore active okay which is a property of user and this stuff is all included with Django by default that's why this this code might not look I guess complete because it's already there it's already included in Jiang we're not we're not straight up saying you know if the password equals this or this it's it's it's it's more abstract than it would be with like let's say node and Express with you know passport or whatever so if this is true then we want to just return the user and then if not we want to we want to raise you want to send back an error so we're going to say raise serializers dot validation error and we're just going to pass in the era of incorrect credentials okay and this stuff is all in the documentation so you might want to check out the Django auth document documentation as well as the rest framework documentation and even the Knox Doc's the Knox tox so let's save that and now that we have our login serializer we need to create our login API so let's go to API dot pi and in here we're gonna go down to here and create a class of login API and this is gonna take in generics and if this is a generic API view just like the register we need to create a serializer class actually know what I'll just copy this whole thing so we'll just paste that in and let's see we have serialize a class is gonna be login serializer which we didn't bring in let's go up here and just bring that in and then let's see we're gonna get serializer get data pass the data in check if it's valid we're not gonna save a user that's that's obviously the register job we're gonna set this to serialize or dot validated underscore data all right and then for the response we're gonna send the same thing that we did with the register the user and the token all right so save this and now we have to add an endpoint for this so we're gonna go to our accounts URLs dot pi and let's bring in our login API and then we're gonna put a comma here we'll just copy this down and we're gonna say login API as view and then the URL is gonna be off slash login okay so let's save that so now I'm gonna go and open a new tab and let's make a post request to HTTP localhost port 8000 slash API slash off slash login and let's set for the headers a content type of application Jason and for the body we want to send the username and password that we're logging in with so it's a username let's do one that's gonna fail first so use your name Brad password okay so if I send this and we get a four hundred response which is a bad request which is correct and then we get an error of incorrect credentials okay so let's change this to the correct credentials which is John and send and we're still getting incorrect credentials API auth login login API as view that's correct hmm okay so this looks fine and let's look at login oh I forgot parenthesis right here think that should be it let's just let's try that so let's go back and let's try something that's wrong again okay incorrect John there we go so now it's working so as you can see when we login it gives us the same response that the registration gives us so in your application you can make it so that when they register they can immediately log in you know or get sent to a route that is protected that needs a token alright so let's see we have our registration our login the next thing that I want to do is just create like a get user API so that we can just simply get the the user with the token so we have to actually add the token it'll be a protected route so let's go to let's go to our API and go down here and create a class of user API and say generics and this is going to be a retrieve API view and we need to set permissions okay so we want this route to be protected meaning it needs to have a valid token you need to be logged in to be able to to access this so let's say permissions and we want to do dot is authenticated and we want to put a trailing comma here and then let's bring in our serializer class which will be the user serializer alright and then we just want to define a method called get underscore object because we want to return the user so we're gonna say get object's self and then we want to return from this self dot request dot user so what this will do is it's gonna look at the token that we send along and it's gonna send back whatever the user is okay whatever whatever user is associated with that token so let's save this and let's add an endpoint for it so we'll go to our accounts URLs dot pi and let's bring in our user API and then I'll just copy this down let's change this to user API as view and it's gonna be Ott's lash user all right so let's save that now we are we logged in here we have a valid token but let's go ahead and open up a new tab and this is actually gonna be a get request so we can leave it and let's go HTTP localhost 8080 eye slash auth slash user so let's just try that so we get authentication credentials were not provided so what we need to do is provide a valid token of a user which we just logged in here and it gave us a token back so we're gonna grab this and we're gonna provide a headers value of authorization and then for the value we just want to put in the word token and then a space and then paste in that token and let's send and it gives us the user okay if I change this token at all like let's just add a 1 on the end and send it it's an invalid token okay and it knows that this is John from this token it's all--it's it can look it up in the database and tell that this is John okay if we register another user actually we'll just do that so let's register another user of let's say Jeff and send ok so now we get a different - a different token we're gonna grab that go to this tab and change the token okay same endpoint we're just changing the token and we'll send and it gives us Jeff okay and we're gonna be protecting all of our routes including the leads you know to add a lead to delete a lead you're gonna have to send this token along to be able to do that okay so the last thing that I want to do here on the server side and in this video is create a logout so for logout there's actually a view that we can bring in to our URLs so right here let's see we're gonna add another path and that path is gonna be API slash auth slash logout alright and then we're gonna take that knocks views that we brought in above and we're gonna say dot logout view you can log out all users but we just want logout view and do dot as underscore view and then we're just gonna give this a name as well so let's put a comma here and just say name equals knocks logout and we'll save that so what this is going to do is it's going to invalidate the token so they'll have to log in again and and get a new token and it's an I think it's important to do it on the back end you might see sometimes people will just clear it out of local storage on the front end but it's not truly logging out because that token is still it's still available what this will do is is destroy that token so if I let's let's actually open another tab and let's say what I want to do here actually we'll just use this tab but we'll change this to off log outs and we'll keep the authorization here let's send oh I'm sorry this should be a post request okay so it doesn't give us anything back but let's try again with the same token to do off slash user and we'll send and now it's invalid okay so when we log though we invalidate that token so the user has to again login get a new token and then use that to access protected routes alright so this is probably the most difficult part of this whole series especially if you're not that familiar with Python just because everything with Django things are so abstract that it can be a little difficult to wrap your head around at least for me I'm just speaking for myself I don't know if if you guys feel that way maybe this is very self-explanatory to you but I find it a little difficult just because it's it's very abstract but yeah so that's going to be it in the next video what I want to do is start to implement authentication on the front-end so we're going to create a login form a registration form and we want to interact with these end points from react and redux so that we can actually you know integrate this into our app and and have full authentication all right so I'll see you in the next video
Info
Channel: Traversy Media
Views: 104,904
Rating: undefined out of 5
Keywords: django token authentication, django, django rest, django knox, token authentication
Id: 0d7cIfiydAc
Channel Id: undefined
Length: 45min 5sec (2705 seconds)
Published: Thu Jan 31 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.