Quickly Authenticate Users with FastAPI and Token Authentication

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video I'll be showing you how to create an authenticated API in Python using fast API and token authentication don't worry if you don't know fast API I will teach that to you in this video and in part two of this series I'll show you how we host the API on a linode server and run it so that anyone can access it will anyone that is authorized now before we get into the video let me mention that my name is Tim I'm a developer advocate for lenode and I run the YouTube channel Tech with Tim which has hundreds of other programming tutorials with that said let's get into the video alright so before I dive in let me just share with you a bit more information about exactly what we're going to be doing and building here so I'm going to start by showing you how to set up fast API how to run the Server create some basic endpoints but then after that I'm going to dive right into authentication and authorization now the way we're going to do this is we're going to have a username and password for every single user and as soon as you sign in with that username or password you're going to be issued a token now this token is a JWT token otherwise known as an authorization token and this is going to contain kind of encoded data that represents you so our tokens are going to have an expiry date or an expiry time maybe they last 15 minutes 30 minutes Etc and essentially what the user will have to do or the client will have to do is every time they want a hidden endpoint that requires authentication they're going to have to submit this token now if their token is expired then they can just resend their credentials and they can get a new token and the reason we have an expiry date on the tokens is so that if someone were to steal the token they'd only be able to use it for a certain period of time before they would need to re-authenticate themselves and sign in again with their username and password there's various other ways to go about doing this but this is going to show you kind of how you do that flow in Python it's actually fairly straightforward you don't need to know too much about cryptography or hashing that's kind of all done automatically for you and with that said let's go ahead and dive in and we'll show you how we actually get that going so the first thing we need to do here is install quite a few python packages so I've opened in a visual studio code I'm inside of a folder I'm going to go to my terminal here now I'm going to be using python version 3.9 please use Python version 3.8 or above just because of the typings that I'm going to be using in this video they'll kind of differ if you're working in a lower version of python all right so let's start installing our packages the first package we're going to want is fast API so let's use pip and install that by the way if you're on Mac or Linux you're probably going to want to use pip 3 here rather than pip and if that doesn't work you can try python hyphen M pip install or Python 3 hyphen M pip install and ideally one of those commands will work for you to install these packages okay next we're going to say pip install and this is going to be UV corn and then standard now this is essentially how we're going to run our web server we're going to use this uvicorn I don't know exactly how to describe it it's pretty much just a web server it's going to take our fast API code and just kind of display that and host that for us as a web server next we are going to install something called Python and then multi-part this is for decoding Json data this is going to be used internally by fast API okay so let's get that installed next we're going to use something called Python and then this is going to be Dash Jose and then here we're going to put cryptography okay this is going to be used to do some password hashing as well as kind of some stuff related to our JWT tokens which are authentication or authorization tokens whatever you want to call them sorry I've just cleared the screen here so we have a bit more room the next Library we're going to install our package is going to be pip install and then this is going to be pass lib and then B Crypt okay now this is what we're going to use if I spell this correctly to do our password hashing so let's install that and there you go that is installed that is all we need just to quickly go through this because there's quite a few we installed fast API we installed uvcorn and then this was the standard version we installed Python and then multi-part we installed python Dash Jose and then here we had cryptography and then we installed pass lib and we installed this with bcrypt okay I think that is all that we had again the fast API unicorn standard python multi-part python Jose and then pass lib decrypt okay there you go now we have everything installed and we are ready to start working with fast API so I'm going to create a new python file here I'm going to call this main.pi feel free to call it whatever you want but main.pi is probably a good name I'll just zoom in here so you guys can read this a little bit better okay so let's set up a basic fast API API to do this we're going to say from fast API import and I'm going to import a few things I'm not going to use all of them right now first is the pens next is fast API make sure you have the capitalization correct then https or sorry just HTTP exception like that and then status we're just going to use this to get some status codes okay next while we're here we're going to say from Fast API dot security Imports and then we're going to import the O auth and then this is to password and then Bearer this is something we're going to use related to our tokens then we're going to import the o auth to password and then this is going to be the request form okay I think that's good for now we'll import the rest of the stuff that we need later okay so now next line that we're going to need here is app is equal to fast API okay we're going to create an instance of fast API and now that we have that we can actually start creating some endpoints uh and it's pretty straightforward and fast to do this so let's create a basic uh kind of get endpoint so to write our endpoint we're going to say at and then app which is the name of this variable here we're going to say the type which is get and then for the root I'm going to do slash and then test and then slash just because this is a test endpoint okay next what I'm gonna do is say Define and then actually this needs to be an async function sorry so async Define I'm just going to call this test you can call this whatever you want and then inside of here I'm simply going to return hello and then World okay very very basic endpoint but I just want to show you how we run the server uh view the documentation for this endpoint Etc okay so now that we have all of this running or we have all this code what we're going to do is go to the folder where our code is in this case it's an API and I'm going to run the following command which is uvicorn then this is going to be main colon app dash dash reload now notice main is the name of our python file and app is the name of our variable here so if you've changed either of those then you want to change this and when you do dash dash reload this just means it's automatically going to reload when you change anything in the file so let's run this notice that it started running and it tells us what port and the URL that it's running on so I'm going to open this with control and then click when I do this it says not found because I don't have an empty root okay that's fine but our web server is indeed running and you can see the kind of responses coming here now what I can do is go to slash docs and when I go to slash docs it's going to bring me to the documentation for this API so you can see here that we have test and what I can do is use this page to try out my different routes which is what I'll do in this video uh just make things kind of nice and easy and fast for us so in this case we have no parameters it doesn't Define the response or anything like that it just says a string is coming in application Json so what I'm going to do is Click try it out execute and notice that we get our response here which is hello world now if this endpoint were to have different arguments like a query parameter we need to pass something in the body then of course it would prompt us to do that here but for now you can see it's just giving us documentation for this endpoint now it's worth noting that there is another form of documentation here if you go to redoc this is going to bring you to a different documentation page I don't know exactly why they have this I think it's just two different pages um kind of both outlining the documentation this one is not as interactive as the other page so you know do with it as you will but that is what you can do you can go to redoc or you can go to docs we're just going to be using docs for the rest of this video alright so now what I'll do is just quickly show you how you would accept query parameters path parameters and request or I guess body arguments body data whatever you want to call that so if you want to accept a path parameter what you can do is go to the path or to the root here and inside of curly braces you can place where you would want this to be so I can do something like item underscore ID then I can go here to the function and I can say item underscore ID now that's automatically going to link to this path here so item id will be equal to whatever you pass here now if we want we can actually specify what the type of this parameter is going to be by doing something like colon and then string this is a type annotation in Python and this is going to be used to help us document our API so you want to provide types for whatever you can what do you call it fast API will try to infer some of the different types but in this case it's not going to be sure if this is an integer or a string or whatever in our case we can just specify it as a string and now we know that we're accepting a string now what I can do is say hello and then item underscore ID just to prove to you that this is actually correct and we're getting the item ID and now if I go back to my documentation so I guess actually can I open up the roots okay I'm just going to do it myself one two seven and then slash docs and now we have item id okay so let's pass an item id we can do something like 100 and then execute and notice that we get hello and then 100 and notice this is a string because the type is string okay there you go that is how you do a path parameter now if you want to do a query parameter what you can do is put a comma here and you can just Define a variable that's not defined in the path so in this case I could just do something like query then if I wanted this to be optional I could do maybe it's equal to one and then of course I could specify the type in this case I would say something like int okay now I don't have to make it optional I can also just say query and then specify this is going to be an INT okay now that I do that if I go back to my documentation it should tell me here that I'm accepting a required query parameter it does say that of type integer and then I could use that okay now let's just make it optional so let's say query ends is equal to one go back here and notice it is no longer required because we made it an optional parameter okay straightforward that's how you do query parameters and path parameters all right so now that we've seen how to use our path and query parameters the next thing I'll quickly show you is how to accept requests or kind of Json data now the way we can do this is create another endpoint I'm going to say app.post for this we can just do something like slash create and then here I'm going to say async Define let's call this create and what I need to do let's just return something kind of in the meantime is I need to create a pedantic model which is going to specify the type of data that I'm looking to accept so I'm going to go here and say from pedantic import then this is going to be base model now I'm going to go here and say class data and this is going to inherit from base model then I'm going to do something like name and I'm going to specify the type as string now that I've created this model essentially what this is doing is defining the type of data that we're trying to accept in our kind of Json data request body whatever you want to call it and pedantic will automatically perform validation on this data for us and make sure for example that the name is a valid string if it's not then it will return kind of a useful error message telling you that this was the incorrect type you can get much more advanced with this I'm not going to show that in this video you can do all kinds of kind of advanced validation however for now just understand you need to Define it in a class which inherits from base model so I'm going to go to create here and now I'm simply going to say data and then the type of this is going to be data now what I can do is simply return data and then data like that and now that I've done this uh fast API automatically knows that this is going to be accepted in the request body as Json data because we're using this pedantic base model if we just put a regular argument here a regular variable here I don't know something like X right and we made this an inch then it's going to be a query parameter but since this is a pedantic model it knows that this needs to be accepted as Json data okay so let's go back to our documentation let's refresh here and now notice we have our post request and let's go to try it out and it tells us this is kind of a sample of what we're looking for in the body so we have name String so let's just go name uh let's just go with Tim for now and then execute this and when we go and look at our response this is our response we have data and then it has what we submitted which was name Tim okay there you go that is kind of you know accepting data into your functions now that we know how to do this let's start looking at authentication and authorization all right so since we're going to do authentication now let's get rid of all of this this was just kind of to explain to you how fast API works on a simple level and now we're going to import a bunch more stuff so let's go here and say from date time import date time and time Delta we're then going to say from Jose import and then this is going to be JWT error and then JWT this is related to our tokens we're then going to say from passlib dot context import and then this is going to be a crypto context and I think that that's all that we need for right now now what we're doing with this line specifically is we are if we spell this correctly importing something that's going to allow us to Hash our password so that's why we have this kind of crypto context I know it sounds a bit weird but that's used for our password hash okay since we're going to do password hashing and uh kind of encoding JWT tokens and whatnot we need a few things here first thing we're going to need is our secret key I'm going to show you how to generate this in one second but for now put that variable next we're gonna need the algorithm that we're using for our encryption uh or our hashing which in this case is going to be hs256 okay and then we need another variable which is going to be your access token and then this is going to be expire and then minutes and in this case I'll make it equal to 30 minutes you can change this to be whatever you want now just while I see this it's telling me that I have an error here with crypto context that's because this needs to be Crypt context okay so let's change that and now when we save everything is okay all right so now what we want to do is generate a secret key again the secret key is going to be used as a part of our kind of encryption and hashing algorithm sorry so what I'm going to do is split my terminal to create a new one and I'm going to run the following command this is open SSL Rand and then Dash hex and 32. now this is going to create a 32-bit um kind of secret key for us that is using hexadecimals and it is random don't worry too much about exactly how this works just run the command should work for you and you're going to get this key now obviously I don't want to share this with people I'm going to copy it and paste it here and that's what I'm going to use for my secret key okay so that's all we need again that's open SSL Rand Dash hex and then 32. okay now that we have that we're going to create kind of a fake database obviously this would normally be a real database in our case we don't want to set up the database so I'm just going to call this fake underscore DB and this is going to be an object or a python dictionary and what we're going to do is have usernames in my case I'll have Tim associated with user objects so I'm going to say username and then this is going to be Tim and then I'm going to have full underscore name this will be Tim rosica then I'm gonna have email let's just go Tim gmail.com that's not my real email obviously okay let's add that next we are going to have our hash underscore password okay I'll explain what this is in a second for now we're going to leave this blank and then I'm going to say disabled is and in this case we'll make this false this is just in case uh you've kind of signed in but your access token is not valid or it's expired all right so that is our fake database now that we have our fake database we need a few models to represent different data that we're going to have kind of as we create the next endpoints so we're going to say class token this is going to inherit from our base model and we're going to say access underscore token this is going to be a string and then the token underscore type this is also going to be a string okay next we're going to have our token data now this is the data that's going to be encoded by our token again you'll see what this is in a second for now we're going to say username and then this is going to be string or none and it's going to be equal to none okay next we're going to have class user we're going to say base model again and then we're going to define the attributes that we want so in this case username string where they're going to have email this could be string or none this will be equal to none and then we're going to say full underscore name this is going to be string or none equal to none and then disabled and this is going to be Boolean or none and this for now will be equal to none again you're going to see where we use all of these in a few minutes but for now let's just Define all of the models so we get those out of the way next we're going to have user in DB this is going to say sorry not user user like that and then it's going to be hash underscore password and then string like so all right so now that we have that let's just grab our app I'm going to move this down below all of this and I am going to set up a few variables first variable is going to be our password context now this is going to be equal to Crypt and then context like that then we're going to say schemes is equal to and then be Crypt this is just the specific cryptography algorithm that we're using next we're going to say deprecated and this is going to be equal to the string which is auto just so that we kind of use the default deprecation settings all right next we're going to say oauth and then underscore 2 underscore scheme is equal to and this is going to be the o auth to password Bearer that we imported earlier and what we need to pass here is our token URL which is going to be equal to token okay now this is going to Define essentially where we go to retrieve our access token okay so now that we have that set up we're going to write a few utility functions that we're going to use to authenticate users as well as to Hash their passwords now hashing a password essentially means that we are going to perform encryption on the password such that we're not storing anything in plain text so that means if someone submits their password as say hello we're going to run this through an encryption algorithm or a hashing algorithm it's going to spit out what looks like a bunch of gibberish but this is essentially going to be the encrypted version of this password what we'll then do in the future is when someone submits another password trying to authenticate as this user rather than checking if this password matches what's in the database we are going to Hash the password they submitted and if that hash equals the hash that we've stored then we know that they have the correct password this allows us to authenticate that someone's password is correct without ever knowing or storing that password okay so to do this we need a few functions first we're going to write the verify underscore or password function this is going to take the plain password okay so plain text password and then the hashed password which will be stored in our database and we're going to return the PWD context Dot verify and then we're going to verify the plane password with the hashed and then password like that now while I'm at it I realized I spelled deprecating correctly so let me just fix that keyword here and now we're not getting an error in our terminal okay so that's verify password next we need to actually generate a password hash so we're going to say get underscore password underscore hash we're going to take in our password and then we're going to return the PWD underscore context dot hash and then we're going to Hash our password okay next we're going to write a function that grabs a user for us from our database so we're going to say get underscore user we're going to say DB username we can specify this is going to be a string then we can say if the username is in the database then the user underscore data is equal to database at username and then we can return the user in DB and then what we're going to do is go asterisks asterisks and then user underscore data now what this is going to do is essentially initialize our model so it's going to initialize this user in DB model which inherits from user which inherits from base model by passing all of the keyword arguments from this dictionary so if we go look here we have username full name email hash password disabled when you use asterisk asterisks on a dictionary if we could type this correctly it essentially takes all of these values out and passes them as key value pairs or kind of named parameters so it's going to say username equal to Tim full name equal to Tim receica it's going to do that uh to user and DB so we'll have you know username is equal to Tim that's kind of how it passes the data so it does that to initialize this model for us because the model accepts these kind of named parameters it doesn't accept uh what do you call it Json data or in our case I guess a python dictionary okay so that's fine for now uh next we're going to write an authenticate user function so authenticate underscore user this is going to take in our database a username which we can say is a string and then a password which again will specify as a string we're going to say our user is equal to get underscore user we're going to get the user in the database that has the username equal to whatever we're trying to authenticate okay so let's go name like that and now what we need to do is essentially make sure this username exists and that the password is correct so I'm going to say if not user then return false just meaning no you are not authenticated I'm going to say if not and then it's going to be verify underscore password we're going to pass the password and we are going to get the password from right here and then user dot hash underscore password like that remember what verify password is going to do is verify the plain text password matches with the hashed password it's going to do that by hashing this password essentially okay so if that's not the case then we're going to return false otherwise we can return the actual user object okay hopefully that makes sense but that's how we authenticate that a user is indeed valid by using their username and password next we need a way to create our access token so I'm going to say Define create underscore access token this is really the JWT token we're going to say data dictionary this is the data that we want to encode and then I'm going to say expires underscore Delta this just means the difference between the current time and when we want this to expire and the type of this is going to be time Delta which we imported from right here or none and we'll just make this equal to none for right now so you don't have to pass one but if you do then we're going to use that okay now we're going to say to encode equals data dot copy so we're going to copy this dictionary so that if we make any changes to it it won't affect the original one then we're going to say if expires underscore Delta then the expired date is equal to date time dot UTC now which gives us the current UTC timestamp plus the time Delta so this is going to be the sorry expires underscore Delta okay otherwise we're going to say expire is equal to date time dot UTC now plus and then we're going to put our own kind of Default Time Delta of 15 minutes so we're going to say minutes is equal to 50. okay now that we have that we're going to say two underscore encode dot update really this just means we're adding a key to it we're going to add the key exp which stands for expiry this is going to be equal to expire and then we're going to say encoded underscore JWT is equal to JWT dot encode and we're going to encode the to encode data and we're going to do this using our secret underscore key and the algorithm we're going to use is equal to the algorithm that we specified up here okay so that's why we needed those values so we're using JWT again we're encoding this data right now uh they're going to be it's going to be whatever data is passed in here plus our expiry date and then we use our secret key and our algorithm now that we have that we can simply return the encoded JWT and that is our access token all right now we are going to write a few functions related to actually getting our user from an access token and then for actually creating an access token based on login data all right so bear with me here this is going to be a little bit complicated uh but I'll try my best to explain how everything works so we're going to create a function here this is going to be an async daf we're going to call this get and then current underscore user now here we're going to say token string is equal to depends and we're going to depend on the oauth 2 underscore scheme so what this does here is essentially calls this oauth 2 scheme function which is going to parse out the token for us and give us access to it in this parameter now you're going to see that we use this quite a bit as we go through the rest of this tutorial we're going to depend on other functions we may actually even depend on this function to kind of compute a value for us before we start actually running anything inside of a specific endpoint I know it seems a little bit weird but that's what this is doing it's essentially parsing out the token data for us and notice that this has the token URL of token meaning it's going to go to that token URL if it needs to generate a new token okay uh you'll you'll see what I mean a sec for now get current user all right now we're going to say credential underscore like this exception is equal to http exception and we're going to say status underscore code is equal to status that we imported above dot HTTP underscore 401 if we could type this correctly underscore on and then authorized like that okay that's our status code detail for this is going to be could not validate credentials if you haven't been able to tell by now we're going to raise this error if we can't authenticate the user and then for the headers we're going to say that this is www dot or not dot dash authenticate let's spell authenticate correctly okay and then it's going to be colon and then Bearer telling you that we could not authenticate the bearer token okay that's our credential exception next we're going to go here and have a try and then accept block we're going to accept the JWT error that we imported above and then we're going to raise the credential underscore exception if we get that exception okay now we're going to say payload is equal to JWT dot decode we're going to decode the token that's provided to us by this dependency and we're going to decode this using our secret underscore key and the algorithms that we're going to use to decode this is going to be equal to algorithm if we spell that correctly okay now make sure you put this inside of a list kind of weird how this one works but it takes multiple algorithms all right next we're going to say the username which is a string is equal to payload.get and then we're going to get sub now this is the key that we are going to encode inside of our JWT token I know it seems a bit weird because we haven't actually fully created the token yet but you'll see that this is the key that we're using that is going to store our username and we're going to check if we have a username or not so we're going to say if username is none now if this is the case we're going to raise our credential underscore exception and then we're going to say that our token underscore data is equal to token data and then the username is going to be equal to the username okay so we're using this token data model that we created here so that we can store our username all right so let's continue here now that we've done this we have our try and accept block let me just kind of clean this up a bit we're gonna go down beneath the accept so if this was all successful if we did not raise an exception here then we're going to go and set user is equal to get underscore user we're going to use our database which I believe I've just called DB and then we're going to say username is equal to and then it's going to be the token underscore data dot username okay so we're just grabbing it from here now that we've done that we're going to say if user is none then again we're going to raise our credential underscore exception otherwise we will simply return this user now get user if we have a look at this here is returning user in DB which gives us access to all of the properties that we need now I'm getting an error here saying oauth 2 scheme is not defined let's go here okay let me just remove that underscore to fix that naming and now it looks like everything is all right all right so next function that we're going to write here is async Define get underscore current underscore active underscore user this is because it's possible the user may not actually be active we could say disable a user and make them not able to log in if that's the case then we don't want to actually allow them to log in we want to raise an exception so what I'm going to do is say that the current underscore user and this is going to be of type user in DB is equal to depends and we're going to depend on the get current user function which we just wrote here okay then we're going to go here we're going to say if current underscore user uh is disabled so dot disabled then what we're going to do is raise an http exception the status underscore code is going to be equal to 400 and then the detail is in active user and I think that's all we need otherwise we're going to return the current underscore user and let's spell current correctly okay so what are we doing here well this is just telling us if a user is disabled or not if they are disabled then we're going to raise this otherwise we'll just return the user that we got so the way this works is that we are relying on the get current user function this function is relying on the oauth to scheme and that means that we're going to parse out the token we're going to decode the token we're going to get the user that was encoded in this token we're going to make sure that they exist if they do we're going to get the token data so the username associated with that then we're going to make sure that this user is inside of our database if they are we'll return the user otherwise we're raising a credential exception then we go here and we're just making sure this user is enabled we could remove this function and just use this one but I just wanted to show you how we would use a disabled property because oftentimes you want to be able to enable and disable different users from logging in okay now that we have that we're going to write our token root so remember here if we go to this oauth 2 scheme we have our token URL so we need to now write a URL that is slash token because that's what we put there so we're going to say app.post slash token and the response underscore model is going to be equal to token now this is specifying what we're returning from this root in this case we're going to be returning a JWT token okay now I'm going to say async Define login for Access underscore token okay we're going to say from underscore data and then this is going to be o auth2 password request form okay and it's going to be equal to depends I know this seems a little bit weird but essentially what we're doing here and this is not from data sorry this needs to say form data is we're specifying that the data that we're going to accept here to generate a JWT token is going to be a username and password and that's what's specified inside of this oauth 2 password request form now we're just making sure that we are relying on this we're depending on this form which is going to parse out that data for us and then once we have that we can use it inside of here again I know it seems a little bit weird uh essentially it's just giving us username and password that's what we're doing okay so we're going to say user is equal to authenticate underscore user and we're going to use our database which is DB and then we're going to have our form underscore data dot username and our form underscore data Dot and then password okay now that we have that we're going to say if not user then we're going to raise an exception so raise http exception we're going to have our status underscore code be equal to status dot http underscore 401 underscore on authorize okay let's spell this correctly and then we're going to have detail equal to incorrect username or password all right and then we're going to have headers and let's just copy the header for my other exception which is right here okay so let's paste that in all right so obviously this is the exception we're raising when you pass us an invalid username our password and we know that that's the case because if we don't get a user from authenticate user then well we got an invalid username and password all right continuing here next we're going to have our access underscore token underscore expires and this is going to be equal to time Delta and then minutes is equal to the access underscore token underscore expires and then underscore minutes okay and then using this time Delta we're going to create our access token so we're going to say access token is equal to create underscore axis underscore token and then our data that we want to encode is going to be Subs remember I told you this is the key this is going to represent our user we're going to say user dot username and then we're going to say expires underscore Delta is equal to and then this is going to be the access underscore token underscore expires like that okay now that we have our access token we're going to say return and we're going to return make sure you do exactly this access token colon access token and then the token underscore type is going to be bear okay now notice that that is in compliance with this token okay so we said response model this is what we're returning we're returning a token so when we do that it's automatically going to be converted kind of into this token object or this Json data and the reason for that is because we're using this base model again let's have a look token where we have our access token and then our token type so essentially this root is what's going to be called when we are signing in with our username and password and then it's going to return to us our token which we can then use for whatever the duration of the token is now that we have that let's create a few routes that we can actually call and that are kind of like authenticated routes right that rely on the fact that we are signed in so we're going to say at app.get Let's Go slash users slash me slash the response underscore model here is going to be user and then we're going to say async Define read underscore users me okay and then we're going to say current underscore user user is equal to depends and we're going to depend on get underscore current if we type this correctly underscore active underscore user okay I think that's all we need and then we're just going to return whatever the current underscore user is okay now let's copy this and let's create another one this time I'm going to say users slash me slash items we don't need a response model here and then for this again we can have our current user that's fine but let's change the function name this is going to be read underscore own underscore items and then we're going to return let's return right I'm kind of just mocking what you would return if you were returning you know user specific data I'll say item underscore ID uh this could be maybe say one and then we'll return uh the owner of this data which is the current user okay and we'll close our object or our dictionary here all right now since both of these roots rely on this get current active user what's going to happen is we're going to go to get current active user we're going to rely on get current user current user is relying on the oauth2 scheme which is relying on our token which means that if we don't have a token then an exception is going to be raised that's going to tell us we're unauthorized that we cannot call these roots so we first need to do is need to access our token by logging in again once we get the token then we are able to send our request now what would happen in a real web flow or in a real I guess website is your front end or your client would first request the token it would then save the token and then it would use the token until it expires then it would request another token so the token is kind of safe to store on the front end for a you know small duration of time and that's why we have this expiry date so that if the token were ever to be leaked it's only vulnerable for you know a few minutes right or however long we set the token kind of expiry time before now that we've done this let's have a look at our documentation and let's actually try this out so I'm going to refresh now and notice we have slash token login for Access token and then we have this and read own items now one thing to notice here is that we now have this authorize button kind of in the corner now what authorize is going to do if I click on it is it's going to allow me to authorize with a username or password it's then going to store my token on this front end and then automatically send that with my request that I don't manually have to do it now the issue here is that we haven't created a registration page so any username or password I type in is not going to work because I don't have a valid username or password so I'm quickly going to show you how you can kind of fake generate a password just for the example of this video so I'm just going to hop out of this for one second first of all I realized that I called my database fake DB not DB and I was using DB everywhere so I'm just going to change this to be DB so that now everything ideally should work and we're just going to use one of these functions here uh so in our case it's going to be get password hash uh just to kind of print out what the password hash would be of a password that we're then going to stick in our database so I'm going to actually stop our server for one second okay so I'm doing that with Ctrl C now I have get password hash I'm going to go down here and I'm going to say PWD is equal to get underscore password underscore hash then I'll just put Tim one two three four that's what I want my password to be and we're gonna print PWD now I'm just going to run my file so python main.pi uh no module name fast API okay let me try running it with this and there we go now we get our hash all right so let me copy this hash here and now I'm going to take this and I'm going to put it as my password my hashed password in my database now I'll be able to sign in when I use the password tim1234 so I know this is kind of uh I guess like a janky way of doing it however we haven't created a registration route and it will take a few minutes to do that so I figured I'll just show you how to do this for now and then you guys could create a register route where you you know get a username you get a password you add that into your database Etc anyways let's rerun our app with uvicorn main colon app dash dash reload now let's go back here and let's refresh now remember the password is Tim one two three four so I'm going to go to authorize now for the password let me type in Tim one two three four I'm going to authorize and I got an issue it says access token expires minutes is not defined let's see why that's the case I'm just going to copy this variable here go to where I've put this and see maybe I just had a typo or something okay it's because I have expire minutes not expires minutes hopefully this is going to work now let's reauthorize and notice that we're all good we have now authorized and it tells us we can log out if we want logging out is just going to clear our token which would then require us to uh we call it re-logging okay so now that I'm signed in I should be able to use these roots and so I have for example read users me what I can do is try it out execute and then notice that I get my response and it tells me the user I am signed in as okay now one thing to note here I can clear this is that we have this little lock telling me that this is an authorization route or that this requires authorization so just worth noting that okay let's go back here let's now go and try this one out okay try it out execute and again we get all of our data and it tells us who the owner is as well as the item id we just made that up of course you could actually create a database and you know store some user-specific data now so last thing I'll mention here is that this authorized button is essentially just using this post root the slash token root so if you were on your own front end and you needed to request a token then you would use slash token and what you would do is you would pass the username and password in your request body and that's all you need to pass and then it would return to you whatever data you want now you can go even further and have a grant type you can have a scope you have client ID client secret I'm not going to get into that here but this is more flexible than what I've demonstrated in this video okay so with that said I think that that is going to wrap up this video that is all I needed to show you related to creating an authorized API or an authentication based API in Python using fast API I apologize if this was a little bit confusing or it went a bit over your head unfortunately this is not simple stuff there is some complicated code that we need to write but ideally this got you on the right track and helped you kind of get started in this process now if you want to go further with this you could actually Host this for example you could use the node you could host a real API you could connect this to a front end create some more routes like a registration route connect this to a database there's a lot more you could do if you wanted to continue on with this project with that said I'll wrap it up here I hope you enjoyed I look forward to seeing you in another YouTube video [Music] thank you [Music]
Info
Channel: Akamai Developer
Views: 56,516
Rating: undefined out of 5
Keywords: linode, linux, cloud computing, alternative cloud, linux server, open source, sysadmin, linode server setup, linode tutorial, fast api, python, fastapi, fastapi python, linode api, authenticated api, authentication api python, authenticated api calls, tech with tim, akamai developer, fastapi tutorial, fastapi python tutorial, fastapi authentication, fastapi create project, api, fastapi crash course, api for beginners, python flask rest api authentication, python projects
Id: 5GxQ1rLTwaU
Channel Id: undefined
Length: 46min 5sec (2765 seconds)
Published: Wed Feb 08 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.