Securing WebApI in Dotnet Core /. net5 with Identity (and JWT)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys thanks for watching my data videos channel uh if you like what you see subscribe down below with that alarm bell today i'm going to talk about web api and how easy it is to secure a web api we're going to talk about authentication and then authorization we'll use json web tokens to authenticate and then we'll use the identity to authorize and let's jump right into it create a new asp.net core web application and then choose asp.net core web application once again and click next here give it a name i'm just going to leave it as web application 2. that's fine and here we're going to choose asp.net core web api leave https configured now as far as authentication goes it does have individual user accounts here but as you can see it's meant for um azure connections so we're just leave it as no authentication we're going to add it ourselves okay let's go ahead and click create and make sure you leave that open api support go ahead and navigate to your startup.cs file and go to your configure services method right here at the top you're going to add a key which is encoding.ascii.getbytes and here you're going to put in a big unique string now long term i don't recommend keeping this in your startup method because you're going to have a copy of this also in your controller where you have your secret method where you're trying to get the encrypted data out so you could put that in a config file somewhere in properties somewhere wherever it is that you like to keep your secrets but for now we're just going to put it here for the purposes of this demonstration now for your encoding just ctrl dot using system.txt press enter so now we're going to add a service so services dot add authentication and you're gonna do x and then do your lambda and often times we do your lab you gotta control z to undo because visual studio tries to put in other things after you put your equal sign but that's okay just ctrl z and keep going your equal sign feel like you're lambda we're going to do some curly brackets because we want to do two things with assign two things to that x the first one just remember default type in default the first choice that pops up is default authentication scheme and challenge we're going to do both of those and then this next one you'll have to type in json web token bearer defaults so jwt bearer defaults and then control dot on that and using microsoft asp.net core authentication jwt bearer dot and there's your authentication scheme all right grab you a semicolon there and now x dot here's your challenge scheme and give it the same value let it know it's json web token defaults authentication scheme again we've set up this authentication service our configure services let it know we're going to use the json web token bearer defaults but we haven't really done enough configuration with it so i'm going to put something here that you've probably seen in some other examples of bearer tokens across the internet that maybe were not specific to web api we'll get to the specific parts here in a moment this is kind of some code that you've seen across the internet but it's important i'll point out a couple pieces here right here we're going to put a to do because once we add authentication authorization to this authentication uh we'll be filling that in there with some claims but just for authentication part it's important to note here that we are requesting a symmetric key so i'm gonna hit ctrl dot on that to use the microsoft identity tokens model there and it's important to note also that we are saving that token so we'll come back to this this was important let's keep going let's scroll down to your pipeline down here which the configure method and before we authorize we want to authenticate so once you add app.use authentication all right let's add a controller so go to your controllers right click add controller and you're going to go up to api api empty and hit add and give it some kind of interesting name i'm just going to use the default of values and we're going to want to give it an attribute of authorize ctrl dot on that using microsoft asp.net core.authorization sounds good and then here we're going to want a few methods we're going to want a registered method for once we use authorization but we're going to want a get token or login method that will get that json web token we're going to want maybe a authenticated data access and a non-authenticated so let's build those now so first let's do a just a i don't know my get fruits method and i get authenticated for it so we could tell the difference so this one's going to be a public action result get fruits uh in there we're gonna take in a username or no this is the unauthentic kid so it doesn't need to take in anything it should be a get so http get sounds good i always say it was called get fruits and in here you can just return um we could have uh we could have a string list so we have list type string my list equals to new list and you could put like apples bananas in here i'll bore you with that so let's return our http verb here or our action verb for okay if you haven't seen that it's really handy and we'll put in an object my list and then let's create the same thing for our authenticated version now one thing on your unauthenticated is you do need another attribute you need allow anonymous we're also going to need allow anonymous on our get token method because when someone goes to login they at least need to be able to attempt to log in before you tell them they're not allowed to access that method right you don't have to already have your json web token in your request because you haven't got it yet so there's going to be a few anonymous methods in here uh one will just be our testing method get fruits the get fruits authenticator obviously will not have that and let's just call this organic you know organic always costs more so that should be our authenticated all right so let's close these up here and actually i'll hit f5 just to show you before we get too far into this but it looks like where we're at so the new web api template uses the swagger interface which is super nice you'll see why very quickly so the one it came with was weather forecast you can click try it out it shows you all this cool stuff execute it even has this curl which if you don't know what a curl is you could drop that into a windows command prompt and it will return the same thing that this website's returning i won't waste any more of your time with that one though so here's our unethic unauthenticated one so if i try that out and execute you'll see that it returned apples and bananas now uh if i do the authenticated one and i try it out execute it returned unauthorized which is exactly what we wanted and because i did okay it's still success there if i did on something else i could have returned a different response all right let's go ahead and create our token now so going back here we're going to minimize these and now we're going to do a post so http post uh get token it's kind of like our login method right so it's going to be public and this one's going to be async you'll see why soon action results oops and now here we do want a parameter because they got to pass in their username and password right and i like to put this uh you'll see in other examples too from body means it's going to be in the body of the request and we're going to do this in fiddler too later so you'll totally see that and now we're going to have a class that contains the user and password so let's just create one let's call it my special my or my login model type my login model and let's create that class so actually i'm going to stop running this and go up here to application add class call it my login model type and uh the identity course what we're going to use for authorization soon uses email instead of username so i'm just going to use email just to save us that step later so prop tab tab string tab email now we can copy and paste that line for password save that and close it it's already referenced here which is nice so now let's compare what we got against this and see if it's what we need so um do an if statement if my login model dot email is equal to and this is just a placeholder folks once we have authorization i'm going to replace this hard-coded string with something from the database but for now let's put uh jones at msn.com if that's your email wow that's lucky but uh unlikely so i made that up and my login model.password is equal to my password one two three uh then we'll go ahead and uh return the token otherwise we'll return that same verbiage actually let's return unauthorized that would be more appropriate right and another block of the code here where i'm just going to paste something in that you've probably seen elsewhere on the web and oop i just remembered gotta zoom in here for those mobile users so i apologize there we go um so this here is a block of code like i said you've probably seen it before um and what you've got is you're creating a token handler a key token descriptor you're basically building the json web token and you get to assign it any claims that you want because once they try to log back in using that token those claims will be in the http context and you're going to decide whether or not those claims should allow that user to access the methods based on roles so let's just go ahead and control dot on each of these here and i'll go through them in a little bit more detail some control dot using system dot text control dot using microsoft identity model dot tokens control dot using security dot system dot claims security claims uh control dot here actually this is gonna be uh my login model i did it previously and i called it chris logan model because my name is chris all right so as you can see so we're getting uh json web security token handler um this is the same key that you had out there in your startup.cs so you're not going to want to hard code this you're going to put it somewhere in a file obviously getting the token descriptor listing out your claims and then here's how long you want the token uh to expire for it because when you're going to be running this on your iis obviously that app pool is not going to reset every day you're going to have it probably run as long as you can so you might want to have it to where they don't have to log in every time as long as they remember it in their browser maybe you could put seven days there and then the signing credentials with the symmetric key and then we're writing out the token and returning it here all right shift alt enter to bring it back into view here and i'm just gonna zoom out a little bit just long enough to see what this error is here so it's saying oh it's just letting us know that it's an async or not returning a task all right so let's just change this to task type action result get token excellent all right so we're going to add a lot more to this method here in a little while all right we did forget one thing on this method to get token and that is allow anonymous got to be able to get in there to log in so i'm gonna hit f5 i'll show you what we've got so far before we add any more so our git for it's authenticated you first have to get the token so if i click post here try it out and execute it's going to pop into our application hit f10 and it's going to take from the body email and password as string which isn't going to match jones or password123 it's going to return unauthorized unauthorized as we expected right so let's go ahead and copy those in as our user and password jones for the email and you gotta love this swagger interface here that's allowing us to do this hit execute it's gonna get inside our block here it's gonna create claims create a json web token and return that boom there you go there's your token so we're going to take this information and we're going to use this token now to use to get inside this roots authenticated method now i don't think it's possible to do it with the swagger interface for this one so we're going to use an external tool called fiddler which is free but just to show if i was trying to get in it directly we get unauthorized we don't even we wouldn't even hit the break point so just popping back in here um the method that we're trying to get to i'll put a break point here and now let's switch over to fiddler alright so once you're inside fiddler click the composer tab and change it to http 1.2 make sure http verb is set to get because that's what we have for our method and in here in the body of the request you're going to do authorization colon space bearer bearer token and then paste your token there get the url from the browser now so i'm going to go back to my browser and scroll up we can collapse these as an accordion let's go to the get fruits authenticated and if you hit try it out hit execute it's gonna give you the url i'm sure you can figure it out it's just api the controller name the method name but i'm gonna copy the whole thing and go back to fiddler and paste it up here and now we're going to hit execute and boom we got inside the method i'm going to hit f5 and if you look over here on the left you might be able to find it look for localhost double-click it there's the more things you see on the left just in case you got more applications open making web requests so just ignore all my other junk as you can see the top is the request the bottom is the response and it gave us this json string here organic apples organic bananas so uh back in visual studio we've got two projects there but that was exactly what we returned all right so what we've accomplished so far is the json web token has been created and we've used the json web token to get back into a method that requires authentication you can see there's no allow anonymous here so what we're going to add now is identity to this mix so that we're not just hard coding the user and password we're going to need a register method and then we're going to need to be able to query that database using entity framework all right let's start okay so there's two commands we're going to run in the package manager console here and i'll just comment them up top so you can see it the first is to install package microsoft dot asp core diagnostics energy framework core these are just ones i found useful then we're going to install the entity framework tools you want to be able to see the errors you know as they come out in your interface too anyways so now that we've installed those we're going to do a little bit of scaffolding so uh go up to your application right click add and now here we're going to do new scaffolded item and you're going to choose identity and hit add there are other ways i guess to do this you could probably create a new mvc project and copy things over one at a time if you did the individual user accounts there but for me i found this was super easy and this actually we're going to add a lot of things we don't need so for those watching that have done this and found you know i was able to uncheck a lot of these things and still work you might want to let it let others know it might be helpful but for me i just come in here super quick i just click that and i hit both these pluses add the data context class for sql server hit plus to add a user class it's gonna create that for us and hit add and this might take a few minutes all right i fast forwarded to finish installing that but we have two more commands that we're gonna run so i'm going to put them up here for you to look at in case you pause your video or something so add migration so we're going to create a migration in sql server and i have running here local a local instance of sql server called sql express you might want to download that if you haven't already and my tool for accessing it is ssms sql server management studio so first let's run had migration create identity schema since this is entity framework and we're creating a migration because we did the code before the database is code first migration and press enter there and that's creating the classes to do the migration and now to actually execute the migration or create the database we're going to do update dash database and i'll put that here now open your sql server management studio right click on databases and click refresh i already did it some mines here it's web application 2 and if you go down to tables you should see all the identity tables should show up for you and the one that most important for getting started is this users table okay let's go back to our project all right let's look at a couple things that this migration did or that this identity scaffolding did uh before we make changes okay so the first thing that's important to take a look at is if you go into the the startup here and you scroll to the top you're not going to see you're not going to see that db context that you might have seen in mvc in the past instead it stuck it inside areas identity identity hosting startup so it's a second startup file so in here you're going to see those two classes that we hit the plus on to create when we did our identity scaffolding which is the web application to user web application to context yours is whatever you called it right you could actually move these to the startup.cs but it doesn't matter what does matter is that you don't have a duplicate because you're going to see some strange errors it might take a while to figure out where they're coming from if you have if you're adding db context um and you're adding or you're adding default identity or adding identity or db context if you're adding it in both this startup and startup.cs you're going to see weird errors can take a lot of troubleshoot so don't do it just leave it right side it's fine there or copy it over here but if you copy it over here make sure to remove it from identity hosting startup okay so now that's out of the way go ahead and get uh your user file into your clipboard just the name of the class and it's over here in data by the way and it inherits from identity user this is where you can put some custom user information because i'm sure you're going to want to at some point put more than just what identity comes with but put that into your clipboard come back to startup.cs and we're going to make that full screen so scroll down to where we put our to do under our json web token bearer on token validated because right here is where we're going to identify what claims are related to that token and we're going to determine if this person is able to access those secure methods based on the token that they've provided so right here we're going to access the context so i'll put in the comments that thing we put into the clipboard oops and we're going to access the context so context dot http context dot and we want this is going to be our user tool set so let's just call it our user machine so let's look for the requested services required services get required service and here right in here we're gonna we're gonna want that uh identity user service and that's actually called user manager you might recognize that if you've done identity for mvcn.net framework but anyways control dot on that and you're going to use using microsoft asp.net core.identity and then ins uh that is going to be of the type of this user class that you created earlier when you did your scaffolding and visual studio likes to add these spaces so just cut those out like that and do another control dot here using your application name dot identity data and we're missing some brackets here parentheses here control dot oh wait we're good all right so now you've got your user machine so to identify the user we could we could use the user machine uh and then you've got your choices to get user well we want to get it by something that's been supplied so choose get user async and here we're going to actually reference the context.httpcontext.user which is going to give us our claims information now i believe there's quite a bit you could do in here but i'm just going to be checking if we found a user with this one that we've looked at or not so if it's null then we're going to go ahead and fail it with unauthorized time to go back to our controller and add a little bit of code that's specific to our authorization so if you go over to your controllers and your values controller i think at this point we're going to need a constructor so what i like to do is just clean things up this is to kind of minimize down to the method headers make sure i don't already have something like that which i don't and there's two things that we need to add which is a user manager and a sign-in manager and i have uh what i pasted is application one because i did this earlier and then your database context which we created earlier so let's go ahead and take a look at where we get that from so going back up to areas identity and then if you go into your see web application context this is going to be the your database class this is your context so grab your application context file name from here and you're going to put that here and ctrl dot using your application name dot data and then as far as the user manager that comes with identity so using microsoft asp.net core.identity and then as far as your user class that's going to be over here in the same folder you can get the name from there and paste that here and ctrl dot again using identity.data all right so we're going to inject the user manager from an assigning manager which are helpful classes from identity into this into this class and we're going to access our database that we've set up so let's create a constructor so public values controller and right in here we're going to have these three things so sometimes it's easier just to paste everything but i'm going to do it like this make it bigger for you guys and lined up so next we got the user manager and i just take the underscores off and then we've got the sign in manager take that underscore off of there and you can close that out it's giving me an error because we haven't finished putting it together i don't think it's that space and now let's assign these things so the context equal to db context user manager user manager sign in manager sign in manager and now we have successfully used in dependency injection to get access to identities powerful methods that we'll use for authenticating and signing it so let's start with the method that we already have which is the get token method so here we're going to use the ideology that we're going to get the user that already exists with this email address since emails are unique in this identity database then we're going to see if that user in the database has the same password as the one that was passed in so first let's get the user if it exists by using our context so bar user equal to db context dot users uh and then there's you could do dot where or something like that i'm just going to do dot first or default where and we'll do this lambda here and once again you have to control c that because visual studio takes it away where the email is equal to what's in your login model from the body of the request dot email now if the user is not null and we've at least found a user whether they've supplied the right password or not we'll use that powerful sign-in manager that i was talking about earlier so um let's try sign in result is equal to sign in manager dot check password sign in async and because async we're going to be awaiting this remember i told you earlier i tell you why we're making an async method it's because the sign-in manager and the user manager use async methods so check password and sign in async and it wants the user which we just found hopefully and the password which is in the login model and then it wants to know whether to lock out on failure for this example video we'll just put false but you can put whatever you'd like there okay so now you can take a look at that sign in result so if sign in result dot succeeded then we want to proceed right otherwise we want to let them know that they weren't authorized to proceed so we could do turn okay failed try again and the reason we're just using okay so it still returns the status 200 because if i returned unauthorized i kind of feel like we're saying you weren't authorized to get to this method whereas in reality i think if they got this far it's kind of like there was authentication issues so um we're saying okay but you know you failed to sign in anyways let's keep going so if the username and password was correct now we're in here and i think at this point we can put all this logic in there so i'm going to remove that and we'll put that right in here and then you can remove the stuff that you had here before because that's already covered and now there's an error here which is saying not all code paths return value so let's the easiest way to kind of figure that out i think is to collapse these if statements but let's take a quick peek so return okay here we return failed here but that's all within that if statement if there was no user found to begin with then i think we want to return fail out here as well some sort of failed you're welcome to use whatever verb you want for your application it's time to build the register method because we can't really get too far if there's no accounts in the system so i'm going to collapse these methods here so we can get a good picture of what's here and let's add the register method so again it's an anonymous method everything's anonymous except for our get fruits authenticated it looks like but it's an anonymous method so they can register and it's going to be async as well because just like the get token method that use the sign in manager which has asynchronous methods in it this one uses the user manager and we want to use those asynchronous methods to register to create a new user so let's begin so let's do a public async task just like before we might as well just use an action result and here we're going to call it register and just like here i'm going to use from body which means i'm telling them to put the username and password in the body of the request and there's no reason why we need a new model so at least from what i can think of so we can just put that there and of course you guys obviously add whatever you want to that model it doesn't have to be just user password if there's more information required for your application registration you can collect it right away there if you don't have a global try catch in your application you're definitely going to want to wrap the register and get token methods into try catch so that you can log the errors that are happening but i'm going to skip that for this demo it's just something a good reminder to always have global track edge anyways so uh let's exit the full screen i want to get the name of my user class because we're going to need to create a user class in order to use that with the user manager not just the login model so we can create it from the information login model though so let's call it uh web application to user lower w sounds good to me uh create a new instance of that and then let's assign it there's a whole bunch more values in here because it matches the database right um but we're just going to assign the values from the login model so let's start with email because that's the unique field the key myloginmodel.email and now you don't want to pass in the password here you'll see why in a minute oh i mean i'll it's the password is hashed and you don't provide it at this step so but what you can do is you can get that username field populated uh and personally i just use the email for the username you're primarily just gonna use the email but there is a username field in the database so now there's one other one here that depending on how you set up your application you may want to set if you want oops if you want to write code to have them you know receive an email and send back a code and set up that kind of authentication before they use your api then you don't want to do this but if your whole registration process is them just signing up then and you don't want them to have to confirm an email address then turn this off here and it's going to make things easier for you okay now we can use that user manager to authenticate so user manager dot dot create async and this is going to be an async call again so the result equals a weight and you're going to pass it in the user which we just created here and here's the password and it's going to hash it out for you excellent now we'll take a look at that result and if it was successful then we need to let them know so i just send back an okay register success there's not much to that otherwise identity likes to put the errors into an array so we probably want to return each one of the errors um so they could see them all depends on how you want to do it especially if this is kind of in a debugging kind of step i don't want to waste too much your time on this so i'm just going to paste something in here and explain it super fast so if you build a string builder you can loop through all the errors that might be in the result and add them to a string and actually you don't need this line at all add them to a string and put it out there for developer to see or maybe you want to send an email log it i don't know but that's what i did here and then i did a response once again at 200 and i just said that you failed to register and here's why all right once you hit f5 and take a look at what we've done so far okay so let's hit register try it out and we're going to enter in an email address so i'll enter in a test email here i'm sure it doesn't exist anymore it's an old school one i had back in the day and then let's give it a password of uh let's see abc my pass one two three uh because because we're using identity it's got some defaults in here so it already knows you have to have capital letters you have to have numbers so if i didn't do this right now it's already going to return an error um so i'm going to go ahead and x execute and register success let's take a look at that in the database so select the top thousand users and oh there it is and it's got a password that's been hashed for us wonderful okay so now let's go back and let's try to log in and get a token with that so try that out see if we did that correctly put in your user and password execute okay we're in our token method and we did find a user and we're going to try to sign in sign in failed let's see why in the output user cannot sign in without a confirmed account well i think we said earlier that you know you can definitely require them to have to validate their logins with email and we did turn it off in one place there there is one other place that you have to turn off you go to identity hosting startup over here where it adds a default identity by default it adds this options that require confirmed accounts so if you change that to false that'll take care of that error so let's run it again and we've already registered so now we'll go ahead and get the token so let's put that back in here and hit execute back in here this time f10 f10 f10 all right here we are again sign in manager and this time it succeeded so we'll go ahead and assign our claims and create a token for a day and here's the token here so we're going to get that token and now let's go ahead and do our fruits authenticated so i'll come back to fiddler like we did earlier go to composer and i'll paste in the token because i stopped and started it we can't use the token that we had before but the rest of it should be okay i'll hit execute and boom we got back in here now one thing to note if we were to expand onto this video is we might want to add here some additional attributes for roles like you know if your administrator uh what what type of user are you are you allowed to use this method and that just all you have to do to do that is to add the claims where we were looking at claims earlier um you know i claim that i'm an administrator etc but this gets you authenticated and it allows you to register and use the identity user and password uh and you can get the rest of that uh role stuff from tutorials that are specific to um identity because it's it's not any different at that point from mvc to web api and so but anyways so we got in here hit f5 and there it is there organic apples organic bananas i'd clicked on the wrong one all right well if you're still with me it's been a long video thank you so much for bearing with the bearer token to the end and hopefully you learned something from this we covered two different things the json web tokens and using identity for authorization so we did authentication and we did authorization for a web api and we did a little bit of scaffolding so that's it for today thank you so much take care
Info
Channel: Data Vids
Views: 13,348
Rating: undefined out of 5
Keywords: secure webapi, authenticated webapi, securing web api, dotnetcore identity, dotnetcore jwt, dotnetcore webapi, dotnet5, .netcore, dotnetcore, .net5, how to secure a web api, how to secure webapi, webapi with jwt and identity, entity framework identity, identity webapi, EFcore identity, bearer, bearer token, json web token, json web tokens with identity, csharp, csharp webservices, c#
Id: Lh82WlOvyQk
Channel Id: undefined
Length: 44min 10sec (2650 seconds)
Published: Sun Jan 10 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.