Bearer token authentication in flutter & secure storage package

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody it's Kevin here again and this week we're going to cover a little bit more API integration with our Dart applications so if you remember from last week we covered how to make API calls how to send get requests how to get how to send post requests and how to use a do package and it was pretty straightforward uh so this week we're going to expand on that so if we look here we still have the same basic structure of the application we'll actually reuse the old one I believe in the old one I had the uh login button here in the center not a big deal uh the new functionality is really going to take over all all of that so if I get rid of that and I send a bad login a bad password that's it's going to be the same as before but now if I say all right here's the correct password and I try to log in we have some cards now so hopefully you're not thinking oh boy we're going to do update and deletes in this video because we're we're not this is just the basic structure that uh I threw in here just so that we could kind of demonstrate what's going on but if you remember from the API these are the current items that we have access to so if we send the get users request we have access to some of these items here now it'll be a little tricky it'll appear a little tricky I know I say that all the time but it's it it really will be uh because we have to come up with a solution now for storing the token we have to use a a service to store the data and I I I shouldn't say we have to now a lot a lot of this is completely subjective so let me pull up the project here open this up with Visual Studio code so the deal is that the way that I do certain things here in this class is the way that I do them is is is my way right so that that's how I that's how I've written that's how I've WR written apps my whole life uh the these structures that I use are the structures that I have basically always been us I've always been using so the whole Bearer token authentication that's what I most use um I'm always used to that uh with what else the way that I present the data that's that's what I'm used to uh using services to uh move data back and forth and to use use them as a structure to hold data that's something that I've always done at least in the uh professional at least in professional development environments now that doesn't mean that you you can't do it your own way that's totally acceptable it's just realize that this this is how I'm going to do it this is what I'll provide support for at least uh for the class and I I'm totally aware that there's other ways to do it there's probably better ways to do it there's definitely worse ways to do it but this is the way that I'm going to do it and you know that's that's that so so to get started though why don't we start the application here to see where we are at and we'll kind of go over what we need to do we need to have a starting point at least but while that gets started we we need to think about what we have to do so if we think back to the old app we displayed the token so we had the token available uh but now we have to store the token somehow and we have a couple options right we can use local storage we can use Secure Storage we can use a global variable that can be referenced through throughout the entire application now what I'm going to be doing is I'm going to be using Secure Storage and the reason is because it corresponds with structures in both IOS and Android so if you compile this application if you're writing your own app and you write it for U an i for an iOS platform you can you can use local storage and it'll it'll access I believe the keychain and actually why don't we pull up the exact documentation here so do Secure Storage pulling it up in another page here bear with me please so this is the documentation for Secure Storage uh if we look here basically uh keychain is used for iOS AES encryption is used for for Android the beautiful thing about newer highlevel programming languages such as Dart and Frameworks more than anything such as flutter is that all of these structures all these all all of these low-l structures relatively speaking uh they're they're kind of Hidden Away with essentially what's an API now it's it's not an actual I guess it depends on what you define as an API right this this is just the library essentially that we're calling and uh we're going to reference it we're going to use some of the some of the uh members that are inside of that Library such as we're not actually going to use delete yet but we're going to use read and we're going to use write so it's it it's it's pretty nice because we can we can kind of offload some of that off to this here if we wanted to write our own implementation say we were writing an application for an an application in Objective C uh for iOS or even in Java for Android or cotlin or whatever uh you want to use for Android development there are libraries out there but you could also write your own implementation and that takes time and it takes a lot of time so that's the beauty with with these Frameworks now of course that kind of comes with the caveat where if you don't know exactly what this library is doing or this package it can be problematic because if there's a security issue or maybe something wasn't implemented properly uh that can obviously be problematic uh because at the end of the day if you think about open source anybody can contribute right so that's this now don't take this right away as like oh I'm knocking on open source open source is awesome just realize that if somebody creates a package and this package say was was written by some random guy in college right it's totally fine if the package works and all but if they're if they're not maintaining it if they're not actively maintaining it there's no other available package for what you're looking for and you just go ahead and use that package that can you know raise some red flags in a production environment so just just keep those things in mind you got to do a little bit of research dart's pretty good with having good packages and reliable stuff but just one thing to keep in mind so we are going to be using like I said the Secure Storage package uh and that's going to be used to store the token we can also use it for other items later on in the application like passwords and anything else uh so I'm going to set up the whole framework so that we can add stuff easily rather than just referencing that package each time uh and that's going to be known as the data service at least in this this application that's what I'm going to be calling it and that's what we're going to be referencing it as so that's that part of it the token storage and the token use why am I making such a big deal out of the token the problem is that if you have a token that is easily available and this can vary by what what you do right so if if you use like an ooth type implementation it can be a little bit different it also depends on your Json web token implementation because you can store some stuff in J in Json web tokens so like if I go on to a JWT encoder I go on here see if I can find okay so here's a Json web token for example right here notice how we can store some stuff in there we can store an issue date we can store some data right so this payload here and we can store some other information here so if I start changing this up the token itself is going to change we can also change the header and we can use different algorithms for encryption and different types for the token so the deal the deal here is that uh if somebody has access to this and you have a token that doesn't and store a whole bunch of stuff like for example permissions so if you have an API for example here let's pull up this one right here the one that I wrote we have this API here and say this API has a user access type logic where if you pass in a token and that token has um say like author admin type access and another one has just permissions basically so uh a token with a certain permission can access this route but not these other ones the what can happen is with a pretty simple uh pretty simple imple implementation like the one that I have here the bearer token implementation there is no uh permissions there's no user access uh delegation right so what that means is that if you have say some say say you have some resource right so you're a user your username is uh USR right just for this example your username is USR and you're trying to access your stuff in the server so what you might do is you might send uh your your token right to the server here and you're going to go into this route and we're going to check to see if your token is valid if it is then we're we're going to start moving forward with the logic if it's not we're going to send a 401 and we're going to say hey there's a problem with the authorization what can happen though is if you have a token and if intercept it somehow via like a man in the middle of attack or say you're writing a web application and you're storing the token in plain text or you're not flushing it out after the session's done what can happen is you can use that token and you can pass in something else so like a different username and that resource can be returned so this is common this this this kind of stuff happens out an industry so you got to take care of this token because this token essentially is your key to access to to accessing all this data here that's available in the database for this API so this again this does happen it is widespread so protect yourself against it protect protect your applications against it's kind of like the whole salting and hashing type deal where you you don't want to store your passwords in plain text and there's a whole bunch of reasons behind that but you just don't want to so it's the same deal here you want to you want to secure your tokens but now that that rant is over let's get back to writing our application and actually kind of demoing and going through what functionality we're going to need to add so we have that token we're going to use it we're going to have a data service to uh store that token securely we are going to have another page to display the stuff on screen so so all the users in this case and see if I can think of anything else as of right now that's about that's about it we're going to have some nice cards that we're going to use and those are going to come from here this card Library actually I copy pasted most of this card Library code kind of to show how easy it is to uh take the documentation examples and just form them around your use case so what we're going to do here is let's kind of move forward with the demonstration here just a test password try to log in it's not going to work it's a login failure if we try to send in a good password we get a token back so first off right off the bat we're not going we're not going to want to show this token anymore so let's get rid of that right away let see here get rid of this just return in there not do anything actually I suppose we can we do have to uh actually let me think here send the request all right not going to return cuz if we were return early we're never going to set uh the state and set the loading to F so that we can get rid of that so let's just kind of leave it at that and we'll set a comet here just to let our formatter kind of keep it every keep everything nice and clean so that we can access that later so we have the token at this point so what do we do with the token well we have two options we can we can display the to we can store the token from the UI or we can store it at that uh the API level inside of the client so that's actually what I'm that's what I'm going to do instead but to do that we're we're going to want the data service so what I'm going to do is inside of this repositories um directory I'm going to create a new file I'm going to call it data service whoops and probably would help to give it an extension or file name file type and it's going to be pretty straightforward it's just going to be a class name data server service now we need to we need an we need to add a package in order to actually get anything done here with a data service so in order to do that we're going to stop the application we're going to add the package now let me look back at the documentation to see what the package name is flutter Secure Storage so let's just do flutter Pub add flutter Secure Storage just some snake case [Music] there all right that's been added if we look at our pubp doyo we should see should see okay there it is flutter Secure Storage pretty useful kind of like our npm install or like our uh what is it in C the new get package manager pretty straightforward just do your flutter Pub ad and again in case you missed it last video you can always go to the installing installing portion here installing Tab and just use this command so now that that's added we are going to go back to the data service and we're going to add some stuff here so first we're going to want to reference that library that we're going to be using for Secure Storage so we're going to import we have two options right uh I know I I know I say that a lot but it's because we do so we have two options we can import it directly we can import it directly this way or we can start referencing it so either or right the reference has to show up eventually when I say referencing it I mean trying to uh instantiate flutter Secure Storage so I'll just add it manually this way there we go now inside of this class we are going to want an instance of floa Secure Storage going to call it Secure Storage I'm going to break a little bit of the naming rules here so I'm going to use a capital S here it's going to give us a little it says right there right so it's it isn't it doesn't follow their identifier policy that's fine because the app's still going to work fine totally depends on your organization and what the coding standards are there if there are any it's good to have coding standards though kind of keep stuff clean my standard is this property that I'm going to be referencing I'm just going to keep it uh Capital there so going to set it as constant and I'm going to create the instance perfect now we're going to get a little bit into documentation here writing your own documentation so let's start off with uh function add item so I'm going to create function ad item which returns uh what would be equivalent to a task in this case it's going to be a future so future typeb all this is saying is that there's going to be some sort of asynchronous action that's going to take some time so we can't just return A Primitive directly or any any type directly it has to be has to be wrapped around in this future so I'm going to call this add item it's going to take in a string whoops string key and a string value it's going to be asynchronous whoops we're going to try to do some stuff catch the air print the A and return false so if we look into the documentation uh with flutter Secure Storage we will see that it's asynchronous so the that flutter Secure Storage trying to read from it is uh an asynchronous action so notice here how they do await storage. delete key of course storage is the instance of flutter Secure Storage or the identifier for the instance uh so we need we need to handle that that's that's why it's asynchronous and what we're going to do here you'll you'll start to see as I start writing the logic the first thing I'm going to do as I'm going to check to see if the if the item exists you don't you don't have to do it I'm sure that it handles it automatically but this is just something so that I don't have to offload that onto onto its own logic it might do it under the hood it might not not entirely sure could read the documentation to determine whether or not it actually does it but in this case I'm just going to check to see if if the item exists if the key exists in Secure Storage already and if it does we're not going to add anything and if it doesn't then we're going to add it so if the key is null so notice here if we look at read it returns a nullable string so it decrypts and Returns the value and it it'll return null if the key is not in storage so it's not in storage we want to add it so we're going to say await Secure Storage right the key is the key that we pass in here the value is the value that we pass in again this here uh it might be a little bit controver IAL where I have the in this case the uh the argument is the same it has the same name as the identifier that we want to pass in uh I guess probably the technical ter the technical jargon here would be like the parameter has the same name as the argument but it it'll compile it'll work fine just it's something to keep in mind so once we add that we are going to return true we're going to assume that it looks good because it looks like it's void but we're just going to assume that if it gets this far and if it doesn't break it will return true right there because it must have added and if not so if it's if it is insecure storage we just want to return false because we can't add it excellent now let's hover over at item notice how add item doesn't give you any I'm going to actually look at the time here quick okay perfect notice how add item doesn't give you any details it's something that you've defined so what we can do is we can add a little bit of documentation three uh three forward slashes and we can say we can give it a small description so stores string in local storage or in Secure Storage save that if we have over it notice storage string and Secure Storage if we reference this later on in the application that can be a little bit not a little bit it can be quite useful especially if it's a huge class that you've written that has a whole bunch of functions that do a whole bunch of different stuff so now that we have that created we can reference this so let's go back to my main doart let's see where we are we have once the login is is completed we fire off this logic do a set state so we are going to want some more logic here so the first block of logic we're going to want is the block of logic that'll be executed when we uh when we want to make the API call so right after the login because we can't we can't make that API call without the token and actually I'm kind of getting ahead of myself aren't I because if we think here we are going to need that Bearer token so what I'm going to do here is pulling just get getting everything synchronized here on both screens what I'm going to do here is I'm going to get rid of some of the logging that I have here because this is not actually this one might be kind of necessary so we have access to the off response which is an instance of off response we are going to want to import the data service because we're we're going to be reading and writing to Secure Storage so we're going to import that so now that we have that imported we are going to want an instance of that so we're going to say just a okay so this is going to be notice how I did the capital here over here should I should I continue with that or should I follow convention that I have here I'll just follow convention that I have here cuz it'll be private we don't want any other member accessing data service outside of user client so we're going to name this data service now that we have that instance created that we can access we're going to do a little bit of checking here so first thing we're going to do is we're going to check to see if the token's not null so if the response the response token isn't null we'll go ahead and uh store that in the in our data service so I'm going to say await notice that it's already asynchronous so we can do some asynchronous stuff here a wait add item and the key is going to be token the value is going to be access author response. token so that's going to be stored in local storage insecure storage I'm sorry and we will return the off response we're not necessarily going to use it but we'll will'll return it in case at some point in the application we want to at some point later on in the application life cycle we want to reference it so that's good so far we have stored it in local storage now let's kind of get this block down let's let's uh let's add the API call for fetching users so what we can do here is we can create another another uh sorry function to to get our users here so just going to say future it's going to return a list of type user it'll be a nullable list of user oops and we have to add our reference to user here whoops oh whoops I don't have user defined yet of course so let me pull it up on other screen just so that I can get the parameters all the um sorry not parameters all the um properties defined so under models we will create a new model we'll call this user. Dart this will create a class user a couple properties string username string password string email I'm going to keep going here then the Constructor again in case you haven't noticed that corresponds with all of the properties of user that we return I'm not going to use this I believe it's versioning for we're not going to reference that it's not going to be relevant on the client side so the application here the idea we're not quite yet uh we can always add it in afterwards but at this point we're not going to reference it uh actually you know what I might as well just future proof this because we will need it for updates and deletes later on because that's how we're going to that's how we're going to find it so string ID okay perfect on the Fly changing of the mind I hope it's not too inconvenient for everyone so we can call this get users async because it's just an asynchronous get users call and since it's just a get requests with no qu query string parameters we are not going to pass anything in we don't need anything we need to add the reference to user here and again we we need to do our Tri catch or return null if there's any problems and in here it's going to look quite similar to our po our our post request except instead of sending in data we're going to send in some some request headers because that's how um our authorization is set at least with beer token authentication so what I'll do first is I will try to read the token so variable token we're going to try to fetch it from local storage or I'm sorry I keep saying local storage from Secure Storage did I even add that yet I did not add the get item logic yet so let's add that here what this will return is a string a nullable string because it might exist in local storage or it might not I'll call it try get item it'll take in a key it'll be asynchronous and we'll have some error handling perfect we have our triy get item implementation here add a little bit of documentation here perfect hover over that that looks perfect now that we've handled that we can try to get our item which is our token this is the key so we need to check to see if the uh actually one second I need to look over one item here quick okay it's just a minor detail on the implementation it's not going to be a big deal here uh if you're wondering it I referenced this before rather than referencing the token even though I defined the token above so it's it's inconsequential it's going to be it's going to be the same result but in this case here I'll just reference the token to make it a little bit more readable so if the token's not null we can send our our request and if it is null or return null because the user is not authorized or The Tokens The token's not set so yeah the user is not authorized so since the token's not null and the token does exist we are going to try to send the API request so what we can do here is we can just again just like here in a variable response we'll try to send a get request notice how this corresponds with see here our get users route and that corresponds with get users in here our route prefix we have set up here somewhere there we go so that's not going to be it's not something that we have to worry about at least in this this uh class so we're going to send a get request to get users here's where it gets a little interesting I'm going to add the semicolon there just to keep it clean we need to add our headers we need to start building our headers so the way we can do that is we can use uh property options here so if we hover over here we can see that we have property options that we can pass in so options that'll take in an options object or not an instance of options which I believe is defined by do yep it's from do it's in our do library so options will options we can we can have headers set so headers and if you look at what that is it's a map of type string D string comma Dynamic so string comma object and if you think back to here back to our requests remember Json is the it's the language essentially that we communicate all of our rest calls in including headers so notice the way that this is formatted it'll be formatted just like that so see here our headers create a create a new map here content type might be wondering where where does where is this right what is what is content type uh let me Define it here quick in case you're not familiar with with this this port of representational State transfer into HTTP more than anything honestly hypertext transfer protocol if we look here and we look at the request that we sent via Postman notice how the header defines an authorization token an I'm sorry notice how we have a authorization header item and a key and then we have the value of the bearer token and then this exact format it has to be in this format or else it's not going to work right we don't Define anything else here and it'll probably work without it but in this case we will anyways just to be explicit so our content tape is what we if if you remember back to the rest in the whole API introduction lecture it kind of goes back to that with headers accept what we'll accept is application Json just like this we don't want XML we don't want anything else we will just accept application Json authorization this is the most important part for making the request for sending the request if you run into any issues during the implementation here with uh authorization not working properly keep in mind that uh if you misspell this it's going to be problematic these things are case sensitive well actually I'm not entirely I'm not entirely sure if they're case sensitive but they do have to be spelled correctly so if you don't spell them correctly that's going to be problematic remember how I said that we have to have Bearer defined or we have tab beer this way this exact way the way that it's the way that it's written right here or else it's not going to work right and then in here we're just going to interpolate token see if I'm forgetting anything anything but doesn't look like it next what I'm going to do is we want to parse this response just like we did up here we're going to do the exact same thing down here we're going to say we're going to create a new uh list of users that we are eventually going to return going to name this list users and here's where can get a little tricky uh might stum stumble on this if you're working on your own implementation so if we don't assign anything to list here uh and then you try to assign something to it later on it'll give you a problem it'll give you a little error uh saying essentially that something has to be assigned initially so for that initialization we're just going to say it'll be equal to a new list new empty list of course this is going to compile this will all work great but then this will also lead to a problem when we try to add something to it because it won't be growable so we can set the growable Boolean argument to true all this says is that the list here can grow just as it just like the way it sounds it's growable next we want to check to see if the response is null so if the response now depending on who you talk to uh some people like to say that uh you want to handle you want to handle uh this block essentially rather than handling the negation first handle the inverse and that can lead to that can lead a code that's a little bit more readable uh we can handle it either ways right so we we can handle it via the negation so if if the response isn't null then do some stuff else do some other stuff uh I'm again I'm going to handle it this way I understand and I'm making all of you aware that this can be frowned upon with with development in a production development environment however it it'll compile right so it'll still compile it's just one of those uh code guidelines that some people have so if the response is not null we're going to Loop through the response data we know that we're going to be expecting users so we're going to name it appropriately and why can't I access data okay let me look at this real quick again just like last video um error message ID i z t idiot eror we need to wait this I'm surprised it didn't throw an error before really should have I suppose since it's assigned to a variable response it just sets that variable to the uh the future right the the future instance that the future response of type T so that's why it that's why it didn't throw any errors so if we would have said response type Dynamic response which is I believe what that returns so if we don't do that it's going to be it's going to say hey there's a problem because we can't assign uh the future right this this task essentially to uh the non-ask right so we need to wait it but since we didn't do that we just use variable it worked just fine so keep that in mind this variable this VAR keyword can be useful it can be a blessing and a curse I mean it's it depends on it depends on how you use it right so if you are creating if it's pretty clear that you're creating an instance so I could I could have done this right so I could have done our users is equal to new list. empty uh that might actually be problematic since I don't Define what's going to go inside of this list might might not but if it's like a primitive that you're trying to access you don't have have to Define it explicitly or like if you're just trying to create an instance of users and you say VAR users is equal to new user that'll work just fine and it's pretty obvious that it's being assigned and it's the type as user but the uh the type isn't resolved until runtime so kind move past that and like I know I keep going off on tangents but it's important to be aware of all of these items when you're writing logic so we're going try to add something to here and a user inance of user because again this is a list of users so we're going to add a new user and we will be accessing properties of user right each one of these respon so let's look back at the data that we get back so this entire response payload is the uh it's it's the whole response if we look at response.data it's that map of all of these items and then if we think into this for this for Loop here each item in data is one of these that's how they correspond so just just keep that in mind that's that's what I'm doing here uh we can break through it so I can kind of demonstrate how we we're moving through it how the data is flowing through but just so you're aware that's that's how that works and since should have really covered it back here again when I had it pulled up last but it'll it'll correspond here so username password email off level they need to be they need to be written the exact same way so whatever they're whatever it it'll expect that's how it needs to be set here I am aware that you can create a from Json implementation so if we go into if we go into our class here that we that we're creating in instances of if I look up from Json Dart we can pass in Json and uh it's it's the serialization SL deserialization uh that whole deal basically this this is this is the deserialization into a type so from this Json we'll deserialize it into uh type person in this instance in this case right so that's an option we can do it that way it's probably a little bit cleaner be aware that that is a way that it can be handled I don't want to handle it that way I want to handle it this way and this is the way that I'm going to handle it so this is what you all will see but be aware that that is a way to handle it so user if we look at what user takes in it takes in ID whoops so we also need to pass in the ID which is just underscore ID so what does it take in next it takes in a username so user position username then it takes an email I believe no a password and then an email I believe that's what it is off level Yep looks good okay there we go so now that we have our list of users filled we want to return our list of users so that's perfect right there so we have our get users async function method function whatever written here so now we need to we need to invoke it now we need to call it we need to send this API call and if we remember when we have to send this API call we have to send the API call after uh the login is successful so let's go back to our login function we need a function get users this function won't take anything it'll just be invoked it's essentially a granular granular isation of our blocks of data instead of of our blocks of code instead of having a a bunch of code just a huge block here we can have functions that we can call later on so if we want to get uh get users in a in another area here we can just call the get users function of course so inside of this get users function we want to set State the reason we want to set state is because we want to start loading we want to let the user know that we're loading then we want to send the request get users async won't take anything in because again it's a get request that doesn't take in any query string parameters oops there we go once we get the response that's pretty nice right there how I just tabbed handled that for me we can say response and now we want to have another function to hand handle that so I'll name this function get users on get user success now if you if we remember what this response is it's a list of type user a nullable list of type user so that's what we're going to pass in here we have to add our reference excellent it's all coming together quite nicely so far so we need to set State again if you remember from the last video as you jump between different blocks of code you need to set State as as the state changes so it's fine to set State multiple times I'm sure if you're setting state within a four within a for Loop or anything like that that can probably be super problematic so something to keep in mind look at the time here okay perfect so in here we want to check to see if the users are null and if they're not we want to let's just display our users just display the username for each user and have we invoked it we have not so we need to invoke that function call invoke either or same same same but different see here okay and since we don't need to do anything with our off response we can just call it I guess in this case we could probably just get rid of this code because it's not it's not necessary because the response is not null so let's go ahead and start debugging here oh whoops I think it's loading there it is down there I will I'll be right back when it when it's running okay so here we are let's try to send try to log in here going to S send in a bad password see what it does excellent good password we did some stuff we didn't see what exactly we did let's try that again looks like we did not display our users so we need to determine why this is not working right okay oh we don't do anything with the response of course it's pretty obvious and I stopped it it's beautiful so what we want to do here is we want to call function on get user success and this should be a little bit cleaner now I will be right back when it okay or or not it'll starts right up just fine so let's try to log in right away and see if we have anything here okay that's good whoops perfect so we have two admins and one test let's see if that's correct admin admin test perfect so that all looks good so far we have our data coming into the client side to the front end the front end of the client side so again let's kind of look at what we are doing here so far if we go into our get users async function we can and check here to see what it's doing at each step so we sent our login request right right as right after that happened and actually I will move a couple steps back let's let's start off here so everything happened everything was perfect we sent our login request we got the token back and it wasn't null so we added it to local storage so let's step into there and see what it's doing here is our add item function in local store in our Secure Storage uh class that we wrote and I'm curious as to why it returned false let's try that again okay oh because it already exists in memory that's right so we tried WR the token out to uh the Secure Storage but it already exists so we'll return FSE that's perfect and we try to read it why are we in here this is one part that can be a little it might be due to the set State okay there we go so we are out of that that can be a little bit finicky with the debugger so if that happens just set a break point right after or to the next spot that you want to C of execution so the response we got to the get users actually I'm sorry about that we went too far ahead so we were inside of here right here the login so we stored that token right after we stored the token we go to our un login call completed so let's try that once we get into this function we have a response with some stuff with some good stuff so we know it's a good response so the response is not null then we go into our function get users step into get users and if we look we set the state set loading to true we jumped right past that me set a break point in there okay so now we are in the get users function we set loading to true we sent the API that request to get users async request well not not quite yet we will so I'm going to F12 into this and let's let it send that request continue the request has been sent if we look at the response we have a 200 status code response which means it's okay just as the status message States what else let's look at our data we have three items that came back and this looks beautiful so so far so good now we need a parse all of the data so if we go into this for Loop we will grab the response. dat okay so can do that sometimes during asynchronous during debugging inside of asynchronous functions so let's just kind of just restart the debugging instance here sorry about that it might do it again it might not let's just try it one more time see if it works okay that was our old breakpoint so really quick before this breaks let's step into this look at response.data okay yeah so that's not an option we can't do that essentially what happens at this point is we read response.data we store that into user which again is we we take response. data we take the uh first iteration of it we put we throw that in a variable user which will be one of these once that's done we add to the users list a new instance of user here a new user is probably the better term there and we return the users right away so let's go back start debugging again let's get to this point again so at this point we got our response of users if we look at our locals because what can happen sometimes so yeah in this case for example it might be because of the set state so the execution or the maybe all the way down to down to the level of the pointer might be at a different spot than if we didn't have the set State here so we can't view it directly here might be a bug might not be but we can see it here in our locals take advantage of that so here is our list of our our knowable list of users since the users are not null we will open through them and then we'll display the username we'll print that to the console that's exactly what we see down here so far so good this is all looking pretty clean so what we can do what we can do now is we can create a views directory and we can create a users View and of course just like last time I didn't give it file type so it be Dart file and in this users's view see here it'll be a state full widget so just stf tab call this users view Escape out of that and we need to we need to add our own parameter in here so actually before I do that I'll just I'll just create it I'll name it in users and that's because we will be referencing a different we we'll be referencing users again but I just want to avoid any ambiguity because of that so we want to add our reference here now we need to add we need to add it in the Constructor whoops not required in I'm thinking way back to another programming language there we go now we need to pass in our instance here after that we want to add our our instance of users that we'll be referencing within the actual UI so I'll just say late list and if you remember back to week five I believe that's where I covered this so if you look back to the week five video that's where I covered the interpage navigation and creating new creating new views and Pages widgets I guess is the appropriate term then we have to call this here so far it should compile all looks good let's start building the UI now that we're in here I'll kind of start flying through it because whoops I lost my window there sorry sorry if this is it's it's kind of technical difficulties here okay sorry about that everyone now now so we're at about an hour so I kind of want to start flying through this so we will return container this container is going to have a child of scaffold because it'll be a new page we'll take in an app bar set all our app bar stuff let our Auto formatting do do its magic in the body we will want a single child scroll view the reason is because we we don't if we if we display more than the items that we can show on screen and that's we want to handle that we don't want to have any UI pixel overload Lo your pixel Auto bounds erors so single child scroll View and set the child to a column children of column let's just say just a text widget for now excellent so now we need to navigate to this if we go back to our main. Dart in our function get user success instead of just printing the users what we can do is we can pass them into the we we can push a new route modally we can push a new page modally so oops lowercase pass on the context let's add the reference here to semicolon and a reference takes in in users as you can tell right there and an elble key so we're just not going to pass the key in because it's not necessary at least for pushing the route perfect so in theory here if we hit the login button we should move to the new page and we do here we go view users so that functionality is pretty good so far let's go back to our users view here's where it'll get kind of interesting uh let's go back to the let's go back to this kind of to show how I how I used it all I did is I just copied this card so here is the card that we that we had before we were displaying so or that we saw online in the documentation so we can just work with this so now that you see it here I'll create the uh iterable structure before because I don't want to work around this and refactor it so just get rid of that but just so you know a lot of it's just copy paste like that and then you can modify stuff as as you go so since since we have a column here it can take in children we can also do a neat little trick here which is to map our users then we need to two list here okay let's let me look over that really quick just to save time okay so one thing I don't really like about flutter very much is how sometimes it'll give you all of these obscure is errors like argument type list of type null can't be assigned to parameter list of widget and I mean yeah I guess if you sit down and think about it that is true um but really I mean it's it's just syntax that's all it is so just had to return something so here we go flying through it back and forth let's continue with the implementation though I did make a few changes like I said just to have it suit our use case one of them was adding a little bit of padding around each item so we'll add some padding have it be three pixels all around oops and then we have we have to have a child there we we'll have a card that's the structure that I used that's all I looked up by the way just to I just looked up card essentially you look back flutter card it's all I looked up pulled up the documentation immediately this card will take in a child this child would be a column it's because we want an iterable or not an iterable I'm sorry I'm sorry we want uh several things in there displayed using that uh nice structure that column provides so main exercise now since I didn't write this logic myself I just grabbed it from the docs I'm not entirely I I don't always use all of these properties but be aware that they exist and they were using the documentation so this is one change I made rather than having whatever icon was displayed before I had have a person essentially to kind of show the user that it's it's a user that they're looking at a person some someone that's being represented then we want a title and once we get this title written let's look at what it looks like so far save that log in and there we go that's how that looks so far we have our user icon and we have some data here some information next we want to display the subtitle I can't stress it enough how useful this is by the way the save and automatically having the all of the changes and logic update on screen so if you work with Maui for example since the uh since the UI is handled via zaml it's it's a it's like it's essentially its own version of like it's a markup language it's not its own it's not proprietary anything but it's it's uh what it's what Maui uses it's also what WPF so that's Windows presentation Foundation I believe that's what that uses uh zamarin so the whole Microsoft ecosystem that's what all of that uses that's what all those use uh the thing is that while they do have UI hot reload which is kind of like our hot reload here which I think well just VI the save every time we save we we do a hot reload then here this would be a restart while they do have that for the for the UI they don't have it for the for the logic at least not to the same extent as this so for example here we can go and add a new API call and add a whole bunch of parsing logic and all that and more often than not it's going to work just fine you're just going to have to save and then right after that you can go and make that API call from the UI side and it'll it'll compile it'll do that just in time compilation and it'll work just fine so that's a huge advantage of flutter over that over you know the whole Microsoft ecosystem again you do have to pick and choose though uh you don't get the same level of native interaction as you do with with a Maui and zamarin and what I mean by that is while you do have structures so while they are structures to read to get from the camera so like flutter I know I'm going off on a tangent but it's valuable information so while there are packages like the camera package that we can access and we can use uh it's not it's not accessing the native it's it's kind of hard to explain but I guess it's it's not at the same level of um interaction with native code AS zamon and actually something that's kind of interesting about zamon and I know that we have like our Android area here we can make some changes to that to make to change like the app name and the app icon and all that kind of stuff but with the nice thing with uh zamon and with Maui is that those when when those access those items directly from from the device it's it's direct access so it's it's accessing it via an API whereas this compiles down has an intermediate layer between which I don't know it's it's a horse a piece as as they might say out in the rural areas it's uh it's entirely subjective if you are just working on a create read update delete app kind of like we are here with an API it do really matter but if you really want to get down into the nitty-gritty uh device like accelerometer access camera access all the physical stuff of the device you might be better off choosing FL uh choosing Maui or U or zamon I know that they have their some people love it some people hate it but uh and I mean ideally if you have the time if you have the team you would just use you would just have two teams right so you'd have a team for iOS development and a team for uh Android development so one of them writes in the native language for iOS and then the other one writes in the native language for Android but that's not always possible and if you think about what we're able to do here which is create a mobile application that runs on both Android and iOS with just one codebase just one programmer writing all the logic that's quite incredible so again it's it depends on the use case a lot of the big companies though they're all all all of the not all but a lot of the really important applications uh I don't want to name any cuz I don't want to be wrong but just be aware that a lot of the bigger applications that that people use every single day are probably written in their native language so just something to keep in mind now that that tangent is over let's continue here after this list title we want to display some buttons I'll set the alignment so in here now that we have the second area let's just display a text widget so as we can tell here kind of How It's formatting each card just be mindful of that forming our UI here so instead of displaying a text widget we want to display a text button this text button will take in a child of text widget says update and then the onpressed of course oh okay so just so that we can have this be green let's add a little bit of quote unquote logic it's not going to be actual logic but we'll be fooling the compiler into um into thinking that it is logic so it'll just it'll show up as blue so that we can tap on it see here there we go so now we can tap on that next we want a sized box that's just to separate them width of eight pixels another button sorry if hear my dogs barking in the background there he goes again I'll pause if need be sorry about that so as I was saying we we're going to have another text button here this one's going to say delete and then we're going to have our unpressed let's see here see what I'm missing here perfect and there we go that should be it we could add another size box at the bottom I suppose there we go that kind of wraps up the UI so let's kind of go from start to finish again so bad login login failure good login we display all of our users and we can now do some stuff not actually but we have the option to so it got kind of long hour and 20 minutes so far but I hope this kind of demonstrates so far how we can how how we can use our access tokens later on in the application via the Secure Storage uh there's like I said there's other structures that you can use there's other ways to handle it but this one as you can tell works and with the benefit of course just like any other good system where we could we could access that token with any other call if we wish to add any other API calls so it's coming along pretty nice it's uh taking a little bit of time but it's it's coming through so if uh I hope you all like the video thanks for watching
Info
Channel: Kevin Gutierrez
Views: 986
Rating: undefined out of 5
Keywords:
Id: WvgVqzeIDJU
Channel Id: undefined
Length: 80min 36sec (4836 seconds)
Published: Wed Oct 25 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.