Upgrading to .NET Core: Adding JWT Authentication to Our API - A TimCo Retail Manager video

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome to another special edition of a tIMCO retail manager course we built the timco retail manager application to simulate what a real-world application would look like so we can use it as a testbed one of the big areas of focus was on upgrading to dotnet core and we're currently in the middle of upgrading that this prot these projects a dotnet core now in this video we're gonna finish our upgrade of the API by adding authentication back in as well as adding back in swagger but first for those of you who are patreon members the $5 per month level or higher don't forget to hit a patreon to get today's source code then we'll also give you a chance to check out a special bonus offer for patreon members during this upgrade process mailing list members you should have gotten a special offer all right as week and if you aren't me unless member sign up by using the link in the description another special offer to going out later this week finally I'm launching a series as a course on IM tim quarry calm now it's going to exclusive for a while to just those of you who are hearing this message it will not be published visibly on the site until later now you can purchase the entire course including all the videos in this series the source code from every video fully downloadable content and more the course will cover everything through the upgrade to dotnet core if you've been a patreon never paying for a source code each week you'll be getting a great deal in this course and if not you'll have to pay a bit more which is only fair but you'll get everything all at once check out the link in the description for more details okay so let's dive into where we're at with the code now when we stopped we were having err I'm gonna run this again just to show off the air or what's going on it seems to work alright it seems to boot up and it seems to run we hit the login form but when we try a law again we get not found which is interesting and then he looked at the Castrol to find out well why isn't it found and we see that we're getting a 400 message that's our 404 I'm sorry 404 meaning the end point / token is not being found so you can have a slash token now I did a little bit of playing around afterwards just to see what I was like I kind of poke I this and get to work and I found out something interesting now first of all if we were to run this again I should have kept it going but if you run this again and bring up the API okay there we go and I were to go slash products its product me its products me see real quick so you have the API we have controllers and its product singular we have just to get but notice it's authorized for role cashier so slash product should give me a list of products only if I'm authorized and that's actually slash API slash products so API slash product now I get this instead I don't get an authorization error instead I said it says hey it can't find the connection string okay so this configuration manager isn't working the way we intended to and we can't get a connection string so I'm gonna stop it right here and we're gonna do something that normally well this is a good testing step okay but this is not a final solution I'm gonna return the actual connection string so let's go to DPF let's go to app config oops not DPF it's the API so the old API and the old API is web config there we go we have TR M data so this right here is the connection string that will normally be looking for no you pass a name but really we're always asking for that one connection string so I'm gonna fake it by passing back the connection string and to put a similar other because these this character right there so this is not something you want check in a source code but it's great for testing okay so I'm gonna run this again this time passing back a connection string so I'm bypassing the problem I have with getting the connections and now let's come up here and go to slash API slash product and it gives me back a list I can see it or not that's actually the products isn't that interesting so I've got an authorized attribute on there that says you have to authorize oh and by the way you also have to be a a cashier and neither of those is getting it we're out listening to either of those so we've got a bigger problem here than just we don't have slash token we're not actually doing authentication at all okay there's there's nothing in here for authentication that's doing this the right way and that's actually a clue that makes things a little better we're gonna figure out how to add token authentication into this Web API okay so first I want to take care of this problem though because this we don't want to check that in a source code I don't want to keep it there so I gotta figure out a way to get a connection string into or a configuration into the into here so I can do a connection string now we've already upgraded the the class library using but it's evidently not good enough because we don't we didn't catch this okay so I'm going to do is I'm going to create a constructor for this data access I'm going to say I'm going to ask for I configuration do a control dot here I've got to install the package Microsoft I extensions duck configuration distractions okay and I ask for config and I'll do a control dot to create the field for that and now instead this returns to me here what I can do is say return and they'll say config dots get connection string which is actually an overload to see though or I'm sorry a extension method because normally it's just config dot get value and then you pass in the path of the connection string but this is a extension method that makes things a little easier so either pass in just the name of the connection string alright and now as long as our API has the connection string attribute we should be good to go so let's add that connection string so our old connection string which we just deleted is called TR m data and there is the connection string copy that now in my TR m API I'm going to go to my app settings dot JSON at the end of this I'm going to put comma and I'm going to put t RM data and then in quotes outputs my connection string so there we go there's the other connection string it should be that now as long as we pass in an I configuration that we get the value we're looking for from TR m data but we're not quite done here because we're going to break some things let's look at data access or we have inventory data and we're doing new sequel data access and we're passing in no constructor that's a problem so in here I'm going to say ctor and that ask for an eye configuration do a control dot config control dot and I'm going to create my private field which that allows me to pass that in to my sequel data access you see before in our API we were not doing the Pennsy injection so everything was just mooing things up now we have dependency injection but we need to actually rewire things so we're not doing this equals new we'll get rid of this later but the very beginning we're going to at least pass and we need and pass it on to this class okay so let's do the same thing for the others that are going to need this so product data constructor and then pass this in do a control dot to add the user to event another control dot to create initialize a field and then finally we're going to do our underscore config and pass that in wherever we ask for sequel 3 giving us sales data so we'll paste this into our control dot add the using statement do our control dot to create the field and then wherever we pass in new product data we're going to pass in our config see that's actually calling a different class it's calling the product data we can just pass in later we'll get this product ative from our dependency injection so every have that new statement we're going to clean that up but we're trying to do is one step at a time instead of every step at a time ok and finally user data it does ask for sequel data access so ctor and then we'll paste this in we'll do a control dot to add the using another control dot for the field and then do our config I believe that's all of them so if we were to do a build now I think if we let's do a build first on our library and that builds okay so library has been built but we're not done yet okay and the reason why is we called these these values up here somewhere in our controllers probably so let's look at our inventory controller and sure enough we're doing the equals new inventory data now again that should come from dependency injection but for now I'm going to do is just do my constructor and ask for the same thing we're going to install install the package and then we're going to do the well I thought is gonna install it there we go took a minute then we're going to initialize a field and then we'll pass in that config so we're basically to a manual dependency injection for right now until we wire up dependency injection it wouldn't be a lot more to wire out the dependency injection but I do want to separate that out so let's do our control dot and our control dot again and then our config our sales control the same way so we say config config and finally our user controller let's see if we actually need it anywhere in here I don't think we do let's do a build solution oh we have some more errors ah in the inventory well that's interesting aha so we have it in the old API so we're going to do is the TR M Data Manager I am going to temporarily unload the project and now I'm going to build the solution again and we have one more in user ID so as is in the user controller so therefore let's we already have a constructor so we just need to add an argument to it so there we go control dot and control dot and now we can say config I think that might have been the only one let's build our solution again we have five warnings or five errors I'm sorry inventory data where is that do not modify you know what I think I'm off at the wrong controllers let's reload this controllers yep I'm off of the wrong you probably only but about that okay so unloaded product let's go back to inventory control oral histories all over again at least now you have you're used to it right so control dot control dot and then config and config the good news is that we can roll back the changes on this trm Data Manager we don't have to keep those changes that where I messed up they may also be wondering where does the I configuration come from they keep passing the buck up the chain which is what depends in version is but at some point somebody's got to provide this I configuration and yes somebody does but in our case is going to P our depends the injection system which is already built into Web API so we don't have to do anything to get it it's already there we can extend it or change it with things like Auto fact if we would like to but the either box works for probably about 80 to 90 percent of the scenarios you'll use it with so unless you have a little more complex application you probably are fine with the default out of box solution for dotnet core now that still doesn't answer the question of yes but whereas I configuration come from if you go and look lives and startup we don't have any where we're saying add the I configuration to the services which is where you find this is in here somewhere well that's because it's built into dotnet core to ask for configuration so you can modify if you want but they're already an i configuration there that's able to look at all the various configuration places and properly override which one is the most important so it looks at environmental variables it looks at your app settings dot JSON it looks at your app settings dot development dot JSON and so on so you can even add in later key vault and other areas and I do encourage kevo because while this is great for testing you would not want to put an actual connection string here for production now the way we used to do with dotnet framework is we would override this value or or wipe it out and put a new value in when we do the build process for production and that can be fine because you control access to your server and so even though it's in clear-text the only people who have access to it are the people to already have access to the connection string anyway so therefore it's safe however you can put it in Asscher and say override the connection string with this one and that's encrypted or you can put into a Shorkie vault and using even a local machine you can use a shark evil magic Kiva is super expert cheap not expensive it's very very cheap to use and they really do encourage you with that low low price point to use it whenever possible to secure your your passwords and your connection strings other sensitive data all right let's see if this part works which this is just testing did we get the connection string right that's all we're testing here we're not testing whether or not authentication is turned back on we know it's not so if I do slash API slash product I get my my products again not ideal because we're not asking for authentication here we're not authenticated you we're not saying are you a cashier but at the very least the API is working ok so now we're passing the connection string through properly we're not we're not doing weird with how we save it work chena system we're getting the connection string from our app app saying that JSON which again can be overridden for production so now we've got that working let's just add just those changes so actually going to exclude these changes so let's let's add everything from the API let's add nothing from the TR I'm data manager for everything from the library ok so that you can use get to properly stage or not stage parts of your work so add proper connection string lookup I won't put a message I'll just stage this I won't even push it and I come back over here I'm going to reload this project and then I'm going to right click and sync will off a screen here let me see if I can get it up a little higher I'm going to go to source control let's say undo and it says you brought to undo pending changes these six items yes why yes and so I did was I just fixed all the things that I broke and did I was changing the wrong API well they're now all fixed because they should all be let's close all documents and open up the controllers they should be back to where they were before I started messing with things and they are which also means that this will no longer work because I'm asking for the that config now if you wanted to keep long-term compatibility we have the new API you're working on but you want the old API to still work what you could do temporarily is you could create a dual constructor so you can come down in here to your inventory data and create another constructor here like so and then what you do is you would just have a check whenever you look for that config to see if it's null okay and if it is null then don't use it maybe use a test you or something else or use that old way of looking things up now I'm not gonna do that so I'm gonna undo that but that is an option to you okay now let's unload the trm Data Manager because let's let's scroll up here if you can see it's going off a screen sorry about that I'm gonna unload the project it's still attached but it's no longer being built with the project so it's it's still there if they were I'll reload it but it's not going to be built and it's not gonna be error checked so now it configures out the way let's deal with our our authentication so to start with this we need to add a couple of libraries and here's why we don't have our old API we use token-based authentication where we login we get a token back I mean use that token as a way to say yes I'm authorized we don't have that in the new system by default it's one of those things where it's available to you and you can plug it in but you could also go a third party and get their version of it so identity server 4 or others like that we could plug in here we're gonna roll our own we're gonna be as simple as possible with this just to get something working I do wish they would have kept in the default or allowed for a much easier way of doing the default but they didn't they wanted to have that that flexibility to choose whatever you want so we're gonna create our own using some of the libraries they provide for us in nougat so the first one is Microsoft asp net core dot authentication dot JWT bearer okay so there's the new get package we're gonna add we'll install that we'll accept that cleared out we're add one more which is system died entity model dot token JWT tokens sorry plural so system dot identity model tokens JWT for JSON web tokens that's we're gonna be installing and using okay so now we have those two things installed the next thing we need to do is come to our controllers and add a new controller if you an MVC controller and I called this controller token remember the slash token we had before we're at this is what that slash token is going to be we're creating it okay so let's start off I'm actually going to to wipe out the index for minute rest start over entirely so start from scratch or I start off with two things well let's first sort of constructor the asks for two things the first thing is going to ask for is the application DB context all right let's read do are using for that and then we're going to do or essay context and control dot to add the private field for that and they're also going to ask for the user manager of identity user all right so it's a couple of using statements here I just want it looks like an recalled us user manager and control dot to create that field as well okay that's just a constructor to get a couple of things from dependency injection they're gonna need for the rest of this let's turn off was with establishing a route for slash token and this is give me a post RSA public a sync task of I action result create where I pass in username password and grant type net last when we don't technically need but because the original system used grant type we're going to make sure we're compatible that original system by asking for it we're just not going to actually use it because we don't need it okay so if we're into a check here oh wait actually know what before I do is create we got create couple methods to call in here let's create a method down here you gotta do a check to see is this a valid username password so private async task of type bool is valid user username and password string username string password okay so we are we've passed it using a password now we're going to do is we have validate it surest save our user equals a wait user manager dot find by email async username never the username is also the email address so I'll look up the username they give us and say did he find this next we're gonna do it or return a wait user manager dot check password a sink or you pass in that user and then the password as well and that's going to tell us is that password valid okay and if it is it's true if it's not it's false now we've done this we can do a check up here to see if a weight is valid you use password username password so if it's valid then we can do something okay and if it's not where I returned back return bad request okay and that's just it so you passing it using a password if it's valid or if it's not valid we're going to pass back of a bad request what happens if it is valid well that's we're going to generate our token so private async task of type dynamic generate token okay we're gonna pass in the username so the first thing we'll do here is say user equals a wait user manager died find by email async username which you already know it will work and we'll find the right user because you've already verified that their password matches our username so that will work and then I get the roles remember that user does not return anything but the user information but we're going to turn all the roles for this user so roles equals from it's gonna look familiar you are in context dots user roles where I join this are in context roles not roll claim rolls on you are dot roll ID equals our ID so again we're grabbing the user roles and the roles were matching them up based upon the role ID matching and then we're going to say where this is a new clause where and as you are that user ID equals use I D so I take the user II got and just say only get that user IDs rolls select new you are dot user ID you are dot roll ID and are dot name that will give me a list of all the roles for a given user ID gonna have this will be repeated if you have user ID the same user ID the same user ID all the way down but we will have it and then we'll have the roll ID that there that the rolls ID is and also the rolls name so I believe right now my user ID has cashier and admin so it will say my user ID the first roll ID and cashier my user ID the second roll ID and admin is a name so that's we're gonna have in that link statement then when I start creating claims because JWT or the JSON web tokens they use a claim system and sort of create a claims equals new list of claim control dot here to add our usage limit and then let's do curly braces and set up some initial claims so a new claim claims type claim types there we go dot name equals user name so I first say one of the claims rent passed back is our user name and it's not equal that's actually comma so a claim is essentially a key value pair and so there are certain claim types that are default or that are standard one of them is the user's name okay and it's all comes from a standard schema if you mouse over you can see there's the schema that it comes from for identity it's a name well that's gonna be our user name and so we're passing that back now what's gonna happen it's gonna take all these claims Korea token out of it which is then signed now it's not encrypted okay it's signed the difference is you can decrypt the token and see what your user name is see what your user ID is since we're gonna pass that back as well and you'll also be able to see things like what roles you're a part of as well as when this token expires these are all visible to the end-user if they know how to open up a token and that's okay we're not going to pass down to the client our our secret which is what we use to sign these and a secret what does is it is it allows us to create a signature for our token that will only be valid if nothing in the token has changed okay and that's the that's the security part so you can open up you can look at it but if you were to change something that makes the signature invalid which means that you can't pass back the changed claim and have it work okay so we are safe but they're not encrypted there's a difference okay and yes security is tricky alright next new claim claim types dot name identifier this is the ID of the user so user dot ID let's put a semicolon at the end here so we can stop getting yelled at we have two more and these are little interesting new claim and this is JWT registered claim names so control dot here to add a using statement I believe is this top one right here ah wrong yep I spell it wrong that's awesome so I did a controlled dot here and it said yeah I'll get a normal eye that but you know what maybe you're expecting something a little bit different maybe you were trying to type that instead and yes yes I was dot now you have a few of these who a lot of these abbreviations some of them are kind of self-explanatory give a name family name that kind of stuff but then we're going to choose is n B F what you're saying what is NB f that's not before and that says that this token is not valid before a certain date and time well in our case we want to be valid right away therefore let's say new date time offset date time dot now date time dot now make sure your casing right and then we're gonna say to unix timestamp or times seconds to string okay that's a lot to type what that's saying is that we're going to take our date time now and essentially convert it to the unix time seconds so as returns neuro seconds to have a lab since 1970 on January 1st okay so and this initialize a new instance of the offset so there's an offset on this but we're going to UNIX times seconds and that's where I start from or say not before okay so not before essentially right now next we're gonna say new in fact you're gonna do I'm gonna copy and paste this because this is gonna be close but not the same instead of NBF we're gonna have exp which it stands for expiration so when is it expire I know that the help tips aren't exactly helpful exp equals exp awesome don't don't what that means but cool I had to look him up so now for and this link spires and so it's the same layout here except for gonna say ad days one that means it's going to expire tomorrow at the same time you may say way that's way too long no problem go ahead and change that ad hours ad minutes whatever you want to do to get this to work the way you want for your system is fine one day is fine for this system for us and this point I'm not gonna get into refresh tokens and making this short and adding refresh tokens will wait on that for another day we're just trying to get to work like it used to okay so now I have these standard claims in the user name user ID when it is valid from what 94 and then when it expires if I need to add some more claims to it its I gotta add my rolls well how I know what my rolls are well I just googled those essentially I asked for those from the database now I can just do a for each and say whoops var roll in rolls I can say claims dot add new claim claim types dot roll and roll dot name that's all I need now no matter who you are now hammer no matter how many rolls you have it's gonna find that out it's gonna add that to your claims all right now we have our claims and our roll we're almost done we need now create our token so let's say new JWT security token and then inside here we're going to say let's let's do on a different line because this is gonna be a little lengthy probably we're going to say new JWT header and then inside here let's put another line why did that eat up my for some reason it ate up my closer so inside here we're gonna have a new signing credentials which it's this right here I'm going to try and take off the that and do a control dot a day using statement makes it a little smaller so new signing credentials and I'm going to keep wrapping I'm gonna see if I can get this to work without wrapping it which do I have my yeah see it's hard to keep track of all these opening and closing so new signing credentials inside here I have new symmetric security key and then in here I have encoding which control dot dot utf-8 dot get bytes and then we need to give it a secret key my secret key is secret so don't do not tell like so is a good secret key no no it's not but don't worry we're going to make it better in to submit and so I do need a new line here that's just it's just too much so now that closes out this but now we need to say , and security algorithms dodge H max shot 256 and then we need to say a new line new JWT payload claims and I think now I don't need these so that's a lot of new new new new new so let's talk through Weds doing so what we're we're seeing here to create a new JavaScript web or JSON web token we can start a header and assigning credentials we're using a the algorithm for the signing credentials not for encrypting it but for signing it we're using the H Mac sha-256 security algorithm the key that we're using to sign it again not encrypted to sign it is we're using this encoder right here which is essentially it takes it takes the these the string and encodes it into UTF okay and gets the bytes of that and that's the key that it uses to sign this token now this key is very important this is a secret key if this key were to get out then what would happen is somebody else could using the H Mac sha-256 Inc algorithm it could encode a new claim and say well you gave us to me and we look at the signature of it and say yep that looks valid so this key is important so we're not going to put it into our source code we're not going to leave it here we're not going to make it my secret key is secret so don't tell we're going to make it into a pray a longer string that is random letters and numbers we're gonna store this in eventually as your key vault or something similarly encrypted and protected for now just for testing purposes we're gonna leave it right here then we will improve it by putting it into our app settings dot JSON and then later when we go to deploy this application we will improve it further by taking it out of app settings dot JSON at Build time and replacing it with that as your key vault value or something similar okay so the header has the the signature of that's that's encoded with our secret key and the payload is our claims which these are our claims so for every user look at their username their user ID when it's valid from when it's valid to and then what roles they're a part of ok so that is our our token creation now we still need to return something now I chose dynamic here for a reason I want to match up what we were sending originally which was two pieces of data so var output musn't var a lot here and the reason why I'm using types that are dynamic or they're from a link query where it's anonymous and or it's just from something where the output type is is longer so that's okay so say var output equals new on our dynamic object so access underscore token equals new JWT security token handler oops handler dot right token and pass in our token so actually I write the took it's gonna create the string from our token next I'm asking a past back username which we already have and the reason why is that's what our original contract passed and back to our from our authentication system finally I'll return output so I returned from all of this generate token is we generate a token and they passed that back as access token and we pass back the username which is the the email address of the user now that's technically inside the token you could pull that out on the other side but I'm trying to avoid rewriting things so we write pass back these two values now that we have this generate token up here we can say return new object result a wait generate token passing in our user name and what this will do is it will generate our token once is dungeoneering the token return that dynamic value back it's going to send that object back to our caller as our action result okay so notice we need to talk about controllers for web MVC you're talking about returning pages but in this case we're not returning a page we're just returning an object instead so instead of action results it's object result which does implement my action result so therefore the object result is just an object which is essentially just this object right here so there's our slash token on the authentication side now let's talk about the receiving side of those tokens so let's go over to the start up and by the way if this felt overwhelming to you I totally understand that security is tough it's difficult it's confusing and do it this way where we are the ones in charge of building it is a lot of work and a lot of digging through documentation to figure out the way of doing it and making sure that you're not leaving a security vulnerability somewhere I would prefer at some point we will I'd prefer to redo this to allow to offload the work to somebody else whether it be something federated like me an azure active directory or whether it's something like a Google authentication or Facebook or somebody else to allow somebody else into the authentication for us and we just say hey are they authorized and if so for what and we take a big step back from controlling all this stuff so yes this is complex this should work and I'd love to have you review this if you have any code review questions or thoughts on this process maybe you you see a bug somewhere it's always good to not be one person alone doing this because then you can miss something so if you see something where you say you know what I think there's a bug here and I think here's how you'd fix it I'll definitely love to hear that put in the comments down below and we'll talk it through okay I'm not gonna claim to be the world's foremost expert on authentication systems they are complicated and it takes more than just having done it a few times or haven't yet done a hundred times even to know what you're doing here they always change okay so now let's talk through our start up I'm gonna add a couple of using statements here that believe I'm going to need using Microsoft open I'm not sure if I need this yet let's find out if I even have it installed I don't think I have installed so let's wait on that one I do need using Microsoft identity model dot tokens so we'll need that in just a minute so now let's come down here to our services we're at add authentication so services dot add authentication era say options our arrow function and then in here we're going to set up a couple of options the options dot d fault authentication scheme equals JWT bearer and then options dot default challenge scheme is JWT bearer and then instead of a semicolon here oops forgot my comma oops not comma semicolon so after this instead of a semicolon adds something else I'm going to say dot add JWT bearer so this is where I configure our JDT bear or JSON web tokens bearer answer/essay JWT bearer notice the similarity here between these two that's where we're configuring it and say JWT bearer options arrow function and then inside here about the end we'll put a semicolon by the way inside here is where i configure our different options we're going to keep this pretty light whereas a validate issuer issue signing key if I spill it wrong control dot doesn't have there it's there we'll get there in a minute equals true then I'm gonna say issuer signing key is going to be new and actually grab that from over here it's the same thing as what we did right here okay so it's the same key this is the other side of things and I think I see my issue here we cut us out from it I missed a level and I am typing off of notes because there is no way I remember remembering all this so don't think that I'm somehow Superman remembering everything I'm not so I miss align my notes so JWT bear options dot token validation parameters equals new there we go and then inside here is where we're going to have I have too many curly braces now there we go so let's unpin this from it there's our our key which we can control dot to add we need to for that for the using statement and we need to put a semicolon at the end of this now we can add some other options here so validate issuer where I set that to false we're not going to worry about some of these issues so validate audience we're also going to set that to false we don't worry about the audience you can add these in if you'd like validate lifetime is true so or make sure that it's not invalid now the last thing is we are gonna check for clock skew and what clock skew allows to do is make sure there's a tolerance for your time checks so equals times fan dot from minutes and rest say let's do five minutes that's plenty of clock skew we could probably do less than that and be fine but there is our our bearer Jay duty bearer so that's the configuration for asking for or from sorry for taking these tokens and making sure that your valid okay so to recap the token controller is where you get your token from in here and start up this is where we use your token and make sure that you are authenticated and your token has not expired okay let's try us now let's start up and see if we have any errors we probably do and by the way errors not a bad thing okay so let's start by going over to the web not sure why this keeps opening too large say slash API slash product and says this page isn't working and if we look over here at why we JDT bearer was challenged we got a 401 which is authorization failed so we can't get to the products anymore which is a good thing okay now we can go over to our login form we can login and it says sequence sequence contain no elements ok what's this all about when we took our name identifier which is user ID and that's as you can see from our locals window here the user ID looks like a valid user ID and let's actually capture that so I've copied this could I I kind of cheated and I know the problem is where we did the user data and we're getting the user by ID so if we do an f12 here we're doing a lookup and say do an SP user look up in at erm data database for this user to get the rest of the user information remember we did that where we have that information in the user table here's a question for you do we have let's close this down do we have a user in the user table for this new user why no we don't I actually already have it loaded up here we have Tim Cory but notice that the ID starts with a 603 I pasting this new ID in the ID column notice it starts with F 35 and you can see that so it's a different person even though the first name last name email address and even the password are all the same because I'm a different person I have a different account even though I have the same login credentials that's what you have a user ID so I'm gonna fill it out Tim Cory Tim at I am Tim Cory calm and create date will leave blank so it creates it automatically for us now that I have that information let's stir it up again now eventually we want this we created automatically when you sign up you also get a user account okay but check this out I now have the ability to get to my cart like a user management fatal exception not found let's find out what's not found okay so we're going to do is I close that down my price should enough let's go put a breakpoint and find out what it's not finding so we're go down to our WPF our UI our view model and that's the user display view model where we have in here somewhere we have a constructor right there and that calls the on view loaded await users so let's put a breakpoint there and now I'll login where I'll users so it gets to this point and we step through here right there this is my kestrels so awesome so I'm stepping through the front end but I can listen to what's happening on the back end by just watching this console output so where is might not have shown this I get to see it in real time and see what's happening so I had two hundred which means success when I made the products controller dot get call cool but then they come down here it's successfully validated my token and then I get a 404 what's the 404 on localhost 501 slash API slash user slash admin slash get all users I'm not quite sure why that is give me an error okay so why is it not finding so it is 404 means I can't find this why is it not finding API slash user slash admin slash get all users so user admin get all users let's stop this and go over to our no stop there we go and go to our user controller go down here user API slash user slash admin slash get all users it's there so why isn't it finding it correctly now if you've already spied the problem because again I've kind of cheated in know ahead of time what's this problem is gonna be cool man you're way farther ahead than I was because it took me a while to figure this one out because that route right there seems to be pretty clear that's what we're calling there is no parameters so what's the problem well let's do this instead of figuring this out what I'm going to do is make my life a little easier figuring it out by adding back in swagger remember we had swagger in the original API we want that back and that will show me what all the different routes are and it's going to show me why it's not available so let's go to our solution explorer and add some dependencies and there's quite a few with swagger for the for the front end so or for the API at core so swashbuckle let's just do swashbuckle here we're gonna need swashbuckle dot asp net core let's install that we're going to need swashbuckle core if it's not already installed somebody's get double installed which doesn't double install it's just going to say yes it's installed we're going to need swashbuckle dot aspx core dot swagger and then we need swagger gen swagger UI and we're not gonna use it right now but eventually we'll need swagger annotations so it's install that as well now some of you may be twitching right now because I has installed a bunch of new packages and you say all that's just horrible there's just so many dependencies is just awful I get that but on the other side of this what's happened is we've gotten away from monolithic dependencies so we also complain the fact that this nougat package is 30 megabytes to download that's awful it's just so huge there's so much stuff in it and so the authors said yeah you're right you don't use all that stuff therefore we'll break it apart into pieces and then you say all there's just so many of them well yeah there aren't really broken the pieces and you have you wind five those pieces it may be that our download size I'm I'm just making a stuff off so don't quote me on numbers but if it's 30 megabytes for the monolithic package it may be that we install 15 megabytes which objectively is good we've saved half that space but it looks bad because there's multiple packages so don't get caught up in how many packages there are because it actually is a good thing in most cases with that being said I've also not a fan of just throwing in tons and tons of dependencies because as we'll see as we go on it can make life more difficult when it comes to upgrading the more dependence that you have the more restricted you are and when you can move and how far you can move for example calibre and micro is not yet dotnet core 3 ready and that may freak you out don't worry there's a solution for it but it comes with using a a preview build which we're doing preview builds here as well for swashbuckle either preview build which is a version 5 that's what happens when you do cutting-edge and the more you rely on packages the more you're gonna have to do that ok so it's gonna slow down your development process it's gonna slow down your adoption of new technologies so there is a balance here so don't don't hear me and say that don't hear me saying don't take dependencies and don't hear me say take tons of dependencies there is a balance between the two ok sorry a little bit of soapbox there but we've had that conversation before one you know one two people at a time I want to get that out that Rossetti is a common thought ok so now that we have that we need to add our swagger in here let's get our swagger on so services dot add swagger gen set up arrow function inside here set up dot swagger doc and then inside here we're going to set up some documentation so let's do a version one and then new open API info which lets back up that's where the using statement comes into play that I had commented out here it's for swagger open API info and inside here we're going to have title where I say tIMCO retail manager API and the version is going to be v1 and let's go ahead and change the vo2 via small lower case and then let's get rid of the extra spacing here and put our semicolon here and a semicolon there so we're just doing a really basic initialization of this swagger doc we can come back later and really beef out swagger and put the authentication back in with the tokens and all the rest but for now we're not gonna worry about that as much down below let's go after our authorizations ordering is important in this section right here we're going to say app dot use swagger and then app dot use swagger UI and then we'll say let's do X and the rest say X dot swagger endpoint they're a defiant endpoint for swagger which is swagger / v 1 / swagger JSON that's what JSON file is gonna live for swagger these remember swagger is a dad's heart a JSON file which we then just put a UI on top of and we'll call this Tim Co API v1 alright so now that in theory configures our swagger those two settings let's run again and see if in fact our swagger is up and running we'll bring this up bring it down slash swagger nope let's give this error that says fetch error it's kind of cool against you could hide or show it but it says undefined slash swagger slash of e1 slash swagger JSON so did I get the path wrong the answer is no pass not wrong again this is where Kestrel is gonna save you Kestrel is awesome this is why you use Kestrel instead of of is so it can be trickier you sometimes but that's pretty obvious right there the big red fail now because it has so much information it scrolled off a screen you don't see it let me scroll up you can see the big red fail and it says an unhandled exception has occurred while executing the request okay so you got on a hill exception ambiguous HTTP method for action trm API controller's Dodds inventory control or get action requires an explicit HT team F method binding for swagger to point out so as a saying is we need to have some type of explicit binding for our inventory controller let's go look at our inventory controller for I get it does not say HTTP GET so now instead of having and there's a post down here as well so in our old API it just read this based upon the naming convention but it's saying for swagger 2.0 you need to be explicit in this let me guess this isn't the only one that has a problem prize controller get sale controller post get user controller we already have a get here we already have a get here we have a post here a post there so it looks like all of these are marked our token controller is a different type of controller but they are marked post and the rest are private so they huh the one is marked post let's try again and see if we've gotten them all okay so wait for the API to start up we'll do slash swagger and there we go swagger is now up and running okay so we have our inventory there's how you call it and again we have formatted this at all this is just read a box but notice down here in the user section does anything look squirrely our API for get all users is slash API slash user slash API slash user slash admin / get all users that don't sound right why is that and it's the same for all the rest of them except for the very first one so let's go over to our user controller and look at the top where it says the route is API slash controller so that's API slash user and then down here it says the route is API slash user slash admin / kill users be this route the way we're doing it is additive so it added the top route and then it added this to the end of it so therefore take out the API slash user everywhere including the slash okay now that should do what we expected to be that should have the right end points for what we're used to so you four go back to Swagger let's go login which I used to work still does users well we have a break point here let's it continue check this out we have admin cashier for Tim we have managers a Roley could add let's add the roll let's log out let's log back in go to user management tim has all three roles no roles to add so I can remove the manager and now imagine no longer part of Tim's account so it's working the way it used to work so that's just awesome we now have our authentication in place it's properly identifying if we're allowed to do something or not so if we remove cashier if we were a logout and login forbidden we can't be a cashier go user management and say oh that's right I need to add cashier back to Tim now if we log out and log back in Tim can be a cashier so it's all working the way we expect it to it's it's denying us if we should be denied it's allowing us if we have the right role or if or authenticate if that's all asked for so everything is back in place in theory we may have missed a thing or two about think so and we have done a couple of small upgrades we have a little better understanding of how the tokens work and we can add to them and we now have the newest version of swagger in our UI we can even add on top of that and make it even better okay so that's the rest of the upgrade process for our API so it's adding authentication back in so now let's take all the changes we made and say added token let's add JWT authentication and we're gonna commit and push those changes since we actually already had lets us commit and they'll go a sync and notice we have those two commits because we have two different things that we worked on today really more than that but for our small team to is fine we'll push those up and now we have committed all of our changes and we're ready to move on in the next video where we tackle what we gonna do with this desktop UI we're gonna move that over a dotnet core 3 and how is that gonna work with Caliburn micro ok until then thanks for watching as always I am Tim quarry
Info
Channel: IAmTimCorey
Views: 74,068
Rating: undefined out of 5
Keywords: .net, C#, Visual Studio, code, programming, tutorial, course, training, how to, tim corey, C# course, C# training, C# tutorial, C# app start to finish, timco, timco retail manager, wpf, asp.net, .net core, asp.net mvc, autofac, c# solid, c# solid principles, dependency injection, tdd, unit testing, moq, swagger, asp.net core api, jwt, JSON web tokens, .net core 3.0, .net core 3.1
Id: 9QU_y7-VsC8
Channel Id: undefined
Length: 74min 16sec (4456 seconds)
Published: Thu Nov 07 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.