ASP.NET Core JWT Authentication Tutorial (.NET 7 Minimal Apis C#)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome everybody in this video we're going to cover everything about JWT tokens and asp.net core we're gonna go over the tokens themselves we're gonna go over at the authentication setup we're gonna go over the tools that you use to work with JWT tokens if you don't know anything about JWT tokens or JWT bear authentication with asp.net core this will be a perfect video for you we're going to be talking also about keys I know that can be a bit of a pain point for some or it can cause some confusion and if you just want a good refresher on the topic this is a video for you my name is Anton welcome to the Rock coding YouTube channel let's go ahead and get started today's setup we have three projects we have a server which is going to be dealing out the JWT tokens and it can also act as a consumer of JWT tokens it can actually authenticate based on its own JWT tokens we then have some kind of external API which will try to assume the tokens from this server a big note here is we're not going to be implementing auth and we're not going to be implementing open ID connect we're going to facilitate the movement and management of tokens manually and this is purely for understanding how they work we then have a third project which is called Keygen and this is going to be for generating keys so first of all we are going to generate an RSA key which is an asymmetric key if you don't know the difference between an asymmetric and a symmetric key a symmetric key is a cryptographic key which you basically lock a package and you unlock a package so you encrypt and decrypt and asymmetric key is a key pair you have public and private key these can be used for encryption and signing the signing process is what we're interested in for this tutorial because that's how you generate the signature or your JWT tokens now that is all done you will see in a minute but here are the two or application programming interfaces apis for working with keys or generating an RSA key we will create a key pair we will extract the private key which is also going to contain a public key and we're just gonna save it to a file I will open this application in a terminal and just run it once this is done I should get a key and I'm gonna go ahead and drag it over to the server okay the act that I'm representing here is you can have a local Logic for generating Keys you can have external Logic for generating keys and usually you will have some kind of cloud service that manages Keys rolls them over and we're gonna go through a key rollover as well here is the thing that you would use to create tokens let's go ahead and surface this now on our server we're going to take this code go to program CS over here and at the very top I'm not going to go through any fancy the service creation anything like that you can do that if you want but we're gonna get an RSA key and then instead of writing all bytes we will read all bytes and instead of exporting we are going to import an RSA private key the first parameter are our bytes and the second parameter is how much bytes we've read which we don't care about and the private key doesn't exist here and the method is void that doesn't return anything the thing that we're importing so if we read the tooltip Imports the public private key pair from blah blah blah blah replacing the keys for this object right so it gets loaded into this RSA key cool so we've successfully generated a key in one place and imported it in this place now if you want JWT authentication in your application you need to add a package called Microsoft asp.net core authentication JWT bear this back package is present on both of my applications over here because both of them are going to be authenticating using JWT bare and the way that it works is on the Builder when you go to services and add Authentication on here you would usually add cookie Etc but now we add JWT bear for now I will leave this open and I'm not gonna add any middleware however I will set my default authentication schema to be JWT and I will also Supply the options over here but I won't do anything with them right in order to actually authenticate with the JWT token you actually need one in the first place let's create an endpoint for JWT this is where we will produce a JWT token let's place a delegate over here and accidentally close my menu the tools for working with JWT tokens is actually a dependency inside this microsoftasp.net core authentication JWT Bearer package okay if we open it up and we find it here and we take a look at Frameworks and dependencies the Microsoft identity model package is the main dependency this is the package published by Microsoft which contains all of the tools for working with JWT tokens so if you need to work with JWT tokens but you don't need the middleware this is what you go after okay let's close this off and we'll close the server CS project first of all what we need to surface is a Json web token Handler this is the thing that is going to create your tokens and validate them on the Handler we can create a token and if I go ahead and remove it and go to create tokens you can see there's tons and tons of overloads over here but the one that we're really interested in is the security token descriptor and the return type is a string let's surface this here we will say that this is a token and say new security token descriptor if we take a look inside so opening security token descriptor we can specify an audience compression algorithm most of this stuff doesn't matter you can't specify it if you want to but for us it doesn't matter what we're after is setting things like subject so what kind of identity are we trying to hide away and then the signing credentials so this is going to be used to generate a signature okay okay coming back over here let's create our subject that we want to put inside the token this is going to be a new claims identity with a new set of claims we will give it a claim of sub which is going to be a user ID and here I'm going to go to good new good and to string this I will also add a claim called name and I'm going to place Anton in here awesome finally at the end here we will return the token and once we obtain this token we should be able to send it back to the server and then the JWT bare middleware should be able to pick up that token and validate it before we can do any of the validation and stuff like that we need to go through a signing process so let's say that signing credentials are going to be new signing credentials and we have to supply here a security key and an algorithm okay we haven't RSA key and we have to take it from the standard Library cryptography namespace into this identity model package okay so we're basically transferring from one world into the other so VAR this is going to be a key so again let's just hover over signing credentials so security key this will be a new RSA security key where inside we can place the actual RSA key and now we will take this key but it is the first parameter and then we can use security algorithms and grab the RSA shot 256 algorithm okay why this specific algorithm I don't know if you try to use one that is not supported it's gonna throw an exception and it's going to tell you which algorithm you should use okay if you use this one no exception and it looks secure okay additionally I'm gonna add an issuer over here uh whoever you know is going to be issuing this token so it's gonna be on https a local host and a 5000. place a comma over here and there we go this should give us a JWT token opening up the terminal I'm gonna go to this tab over here where I have the server and by the way I'm going to restart my app every single time when I'm gonna change this key because the key is going to change right let's make sure that the application has started correctly and it did coming over to the website over here we have hello world and if I just go to JWT I should get my JWT token now we have this token we can grab it over here and there are many many resources which talk about what a JW token is it contains of three parts a header which describes what algorithm has been used to create this token and what type of token it is so it's a JWT token it's a pardon for the scrolling I'm trying to scroll up in this box but it doesn't have its own scrolling wheel anyway and then there is the payload which you can see contains the issuer my name and my user identifier which is the sub and then there is the signature so this is what we use the key for to generate the way that this is generated is the header and the payload are taken encrypted together using the private key and this signature is then spat out in this video We're not gonna have a manual process of actually creating this signature just know that this signature is created through using this tool over here okay coming back to the website here we have our token let's copy it and let's try to use it on one of our endpoints I'm okay with using it on this hello world endpoint over here and same as other authentication handlers if you have not watched my previous videos about authentication at least watch that at least you're gonna know what an authentication Handler is out of which part it consists and where in the Middle where it loads we're gonna add our use authentication middleware because we're ready add authentication is set to JWT by default and this is the Handler let's open it up and this is going to be probably the hard part for most of you you've seen that we've not specified any options and here we have JWT bear post configure options this is going to be some default configuration that is going to be applied on your options we're gonna open it here and we're gonna forget about it for now JWT Bearer extensions the main thing that we're interested about is the JWT bear Handler if we take a look at handle authenticate async and come back to server program CS for the uninitiated use authentication Handler is where the handle authenticator sync function is going to be triggered to try to load your claims principle out of the token the function itself starting from line 54 going down to 203 so you know I had a 150 lines of code who's got time to read that us okay us let's go ahead and do it it's not that hard we don't need to go inside every single method message receive context over here captures the context the whole information about the current request and says we've received this message go ahead and send it to the events events we can actually intercept these if we already set the result so through the events we can resolve the loading of the claims principle and basically Short Circuit Market this whole service otherwise also we can set a token on this message received context if the token is not set go ahead and try to load it from the bearer header if we fail to load the token bail authentication we're about online 93 so one third of the way there some kind of configuration if it's not set and the configuration manager is present let's go ahead and get the configuration this bit right here is pretty important if you're familiar with open80 connect and the discovery endpoint which says what is where on your authentication Service this is the thing that goes on the configuration manager and attempts to get some kind of configuration what is that configuration these are going to be endpoints where to refresh your tokens where to get new tokens Etc more importantly that information is going to contain a public key the key that we generated the private public keeper it's going to obtain a public key and if we go inside this function so configuration manager you can see there is a little bit of caching here so it will go to your authentication server come back with a bunch of configuration information and a public key which it then caches for some time and it then uses the public key to validate the token every time a request is made to your API to validate the token it doesn't pass the token along to the authentication Service every single time otherwise your authentication Service would become the bottleneck if we travel a little bit further down to get configuration async and in here this is basically using the document Retriever and HTTP client on the address the discovery endpoint address if you don't know what that is don't worry too much we're basically calling the authentication Service to get a Json web key and this is a set there can be multiple ones but mainly we're getting a Json web key the Json web key is important because it is the public key which is going to be used for validating your token if there is anything you take away from here okay if you're confused completely the thing that happens at this step is we get a public key from the authentication Service okay and that is only if we have our configuration not set and if it's not set we set it from the configuration manager this is where I could detour into the post configure options if you yourself you haven't set your configuration manager however you did set your open ID connect configuration that is going to create a static configuration manager what the static configuration manager does and is used for is if you have keys present on you on the application on the authentication server you don't need to go anywhere to get any Keys you already got them and this is what this is for okay so this service is just something that already contains all the keys all the information needed or dealing with the incoming token otherwise we go ahead and Forge the metadata address this is where the call for the public key is going to be made and all the other information on the well-known endpoint of the open ID configuration we then set more information like the back channel it's just an HTTP client and then finally we create the configuration manager and this is where you've seen us walk down the function call chain to basically see where that batch request for the public key and other configuration from that endpoint is happening this is where the setup of all of that happens in the background if you're not setting anything so let's go ahead and close JWT Bearer post configure options so main takeaway here is we get a public key which we can use to validate the token the next couple of steps we are assembling an object the validation parameters for validating out of this configuration that we've just fetched we extract the signing Keys which are the things that are going to validate the signature which also in turn validates the token the next for each Loop is going to go through all the validators and the main thing here is that it's going to be validating the tokens I have a breakpoint over here we're going to be stepping through the debugger so you know when this happens and if your Json web token is invalid so this for each Loop this whole for each Loop we can basically discard it as try to validate the token if we successfully validate the token we don't enter the catch Clause we go down over here if we have the option to save the tokens we save the token as the access token we also fire some events that we've successfully validated things and finally in the end we can either Short Circuit the returning of the result and if you watched my authentication landscape video and you seen me talk about discarding the tokens or saving tokens to the database this is an asynchronous event tokens validated go ahead and save them to the database and then proceed with your authentication just make sure you got cash and stuff like that otherwise you know you're going to be attempting to save them multiple times so this is on line 166 for two thirds of the way there last bit over here if we do have validation failures go ahead and fail authentication also just a fail authentication over here and catch any errors and rethrow the exception or fail authentication and that's the whole function how do we condense it token coming in and let's go ahead load the token let's get the public key to validate the token validate the token if it's valid it give you the claims principle if it's not valid or something bad happens no claims principled not authenticate okay that's all the jw2 bear Handler does because the logic over here is extracting the JWT token from the header I'm actually gonna short circuit it over here and extract it from the query let's come back to program over here I'm gonna go on to options events and I will set a new JWT bear event and I'm gonna subscribe to oh the JWT bear message received okay so on message received this is gonna give me a context the type over here I already know what type it is right if we take a look over here message received context this is going to be the same thing okay message received context on this context over here we will have the request and I want to say if request query contains key let's say t for the token I want to go ahead and extract that token so from that key let's place it over here T and place that token right here so I'm just gonna Short Circuit the extraction of the token here so it's not going to be empty and it's not going to go through this process we're going to go straight to public key fetching and validating of the token coming back over here this is also a task so let's just return as complete task and there we go semicolon on the end here on the default endpoint that I have over here a let's replace context user and find first we are going to look for the subclaim so if we have the subclaim good we have managed to pass authentication if the subclaim is not there we're gonna fail application is still running good let's come back over here and I will grab the whole token I will duplicate this tab I will get rid of JWT I'm gonna put a t query parameter and set it to the Token here we have null so we're not authenticated cool why well we haven't specified anywhere to get the keys and we haven't given any there is no key this middleware doesn't know anything about keys or this key that we have created over here okay so we will actually need to give it the key if I again I go into add JWT bear we're gonna go into post configuration as I've mentioned the configuration object is the one that you configure for your server because you already have the keys you can just set them there is nowhere for you to go to get them coming back over here let's find o configuration new open ID configuration right and let's look for what signing Keys how do I know I'm looking for signing Keys add JWT bear JWT better Handler and over here it is attaching the signing keys from the configuration in order to validate the JWT token let's come back to program CS signing Keys what kind of signing keys do we have or not this one remember is using the underlying Library we actually want to give it this key let's place it over here and this is the public and private keeper it can do both creation of the signature and verification of the signature we have that oh let's give this a refresh and we're still not this is not because of the signing keys this is because of something else if we come back to JWT bear extensions what we're configuring is indeed JWT bear options if we open them up and there should be a section around validation so token validation parameters there is a default instance here token validation parameters and it asks us to validate the issuer and the audience we set the issuer we don't validate the audience let's go ahead and over write these validation settings so token validation parameters new token validation parameters validate audience false and then validate issuer false as well if you're wondering am I destroying security this way what if somebody else dealt out the token what if the token is for the incorrect component lesson body the key that we have here the super encryption tank thing this is the main keys to the door okay everything else is just application Level validation all right it's not so much security as it's just the token is being used the way that you designed it it's not like somebody stole your keys and is now generating these tokens that are being used maliciously so we got that let's come back over here refresh and it is still nope are we still failing authentication well let's find out I'm going to attach a debugger to the server over we're gonna go to JWT bear extensions JWT Bearer Handler we're gonna close the rest because there are too many tabs open I will scroll down to where we're doing the validation so right over here on server program CS let's come down here place a breakpoint just on the statement over here come back to the browser refresh and here we hit the validation logic if we go further we pass the validation logic and we don't go into the exception so the token is valid if I play on we are in our endpoint and we're going to take a look at the context at the user and then add the identity that we have here and the claims look at the claim type it is an abysmal behavior from Microsoft to take the claims that I've originally defined and mapped them to their own right ridiculous this is like the whole coursing Internet Explorer down your throat thing right it's a bad mentality I don't know why they do it horrible Behavior how do you go about this on your configuration over here find map inbound claims and we will set it to false explicitly coming back to the browser we get a pretty good exception over here because we're actually getting the good claim uh as I've said before claim has way too many stuff on it so it doesn't serialize to Json what we want to do is extract the value from it and if it is let's just say that it's empty right so if we don't have it let's just say empty here we have it let's give it a refresh and there we have it there is the user ID so let's just double check that is the same user ID as here right we have generated the jwc token and we have successfully authenticated with our server now I want to do the same but I want to authenticate with this external component how do we do that well I said we're not going to be using auth and as we've seen with the configuration manager the thing that is going to the well-known endpoint and retrieving the public key we would need open ID connect for that but we don't have it what do you do you need to generate this public key and get it over to this external component so then it can actually do this validation let's come back to the server we're gonna go all the way down and we are going to generate ajw K Json web key okay we're no longer gonna have any tokens We're not gonna have a Handler over here we're looking for a Json web key we can create it from a Json payload although that is not what we're looking for we're looking for a class that's called Json web key converter on here we can convert from Ace RSA key so we would be supplying an RSA security key over here we have the RSA a security key right here okay let's pass the key and on the end we should be able to get a Json web key let's return this what we have here is essentially a crucial mistake we are putting the private and public key into this Json web key so if we would give this over to an API or over to an application that doesn't belong to me it can now start creating tokens so this is pretty bad let's pass jwk private over here so this is the net point for this we just want to see what this looks like right otherwise let's go to the RSA key over here and let's export RSA public key this is going to give us the information for the public key we're going to go all the way back up here I'm gonna create a new public key so this RSA key is going to be a public key public key is going to be import from here so import word public key and it's going to be import from the RSA key right over here remove the semicolon and enter the RSA security key we are putting in the public key so we got the private key we're extracting the public key from it we're putting it into this identity model world and then we're creating a Json web key from it let's remove the private on here coming over to the browser let's go to the jwk endpoint and this is what this looks like if we then duplicate this and go to private it's going to be significantly bigger it includes more information because it's two keys not one key you don't want to start sending this over you want to be sending this over so I'm taking the value of this coming back to the application going to the external component and I'm not building out the infrastructure for fetching this Etc I will again reuse as a configuration manager where the signing keys so this is just going to have keys embedded otherwise if I want a support key rollover and dynamically resolve keys I already know that I need to go to O configuration manager and implement this okay but I'm not gonna do that because it's quite a lot of work just as long as we understand that that is what we would have to do let's create our jwk string and there we go less writer such a good piece of Kit so then we grab the same configuration that we have here drag it over to the external component let's import all of this again I'm gonna still have the same logic for extracting the token from the query but now the RSA security key that we have over here I'm actually going to use the JWT or sorry Json web key create function and pass the key string or what did I call it Jake WK string and here and that should create me a Json web key which is an implementation of the security key abstract class again I'm not mapping the inbound claims I'm going to go to server program I'm gonna grab this extraction of the claim actually place it over here and also not forget to add middleware so use authentication just to reiterate by placing the jwk string over here the Json web key we circumvent we remove the process for going to our authentication server and obtaining that public key coming back to the browser where we're doing this access over here I'm going to duplicate this and I'm gonna go to Port 5001 which is what this application is running on so let's change this to one I refresh this a couple of times and I still get the same result now what if we would use the same logic for generating a web token but using the public key let's place this over here we will import Json web token Handler we don't need this key over here because we can create a Json web key place this over here and all is good I'll come back I will go to this endpoint over here I'll duplicate it I will go to 5001 and JWT and here I'm going to get an exception which basically means listen dude you gotta public key this is not how you do any of this right you cannot generate a signature with this you're not allowed to create a JWT token okay okay I'll do this properly so you know if you're handing out public Keys they're not going to be able to generate a JWT tokens however they will be able to verify that those are valid tokens now for the key rollover over I'm gonna take this key and I'm gonna delete it I'm gonna go to key gen again I will run it so I'm generating a new signing key I'll place this over here I will restart the server with that restarted I'm gonna go to the JWT endpoint and because the external API hasn't reobtained a new jwk the validation of this JWT should fail let's load up a new JWT here we have it we should have a new identifier so there it is 9C the rest of the payload is the same we're gonna go to Port 5000 let's place this over here we're gonna be able to get the new guid if we go to 5001 which is the external component and we go over here the good is empty because the validation of the JWT token is failing let's attach a debugger so we can see it so on the external component coming back over here refreshing here we are at the validation step if I go forward an exception is thrown and then we start logging validation once we approach our hello world endpoint there is no user to get the claim from okay so we get an empty claim and that is all we have for today from JWT creation through the middleware how it's being handled in the Middle where how the token can be used for authentication with the individual server how it can then be consumed by external components without adding all of this auth and open ID logic explanations about the security keys and all of the internals hopefully you've enjoyed it thank you very much for watching if you have any questions go ahead and leave them in the comment section don't forget to leave a like subscribe click the notification Bell please come support me on my patreon get the source code very big thank you to all my patrons that are already supporting me your help is very much appreciated enjoy your day and goodbye
Info
Channel: Raw Coding
Views: 19,249
Rating: undefined out of 5
Keywords: .net, jwt, authentication, asp.net core jwt, AddJwtBearer, tutorial, explanation, guide, jwk, rsa, symmetric, asymmetric, key, minimal api, asp.net core
Id: 8FvN5bhVYxY
Channel Id: undefined
Length: 32min 53sec (1973 seconds)
Published: Tue Oct 25 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.