JWT Bearer Authentication in ASP.NET 6 | CLEAN ARCHITECTURE & DDD From Scratch Tutorial | Part 9

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everyone i'm kai here in today's video we're going to add authentication to our application we're going to learn it from a technical point of view so we'll look at each one of the methods that we're going to call and understand what it really does behind the scenes and how the magic that we get from the framework actually works okay so what we have at the moment is we set up our project to generate jw tokens when the user logs in and here's an example to it of a token that we know how to return so we are the issuer and the audience and we have an expiration and some other details that we populated and we're using the hmac sha 256 algorithm to sign the token and our actual secret that we're using to sign the token is this string over here which is exactly 16 bytes what we need for our algorithm and so like we said if we're looking at the flow then to generate the token then we call the login endpoint and we pass an email and a password and in the response we get a token that now we can use to authenticate against our system now what we're going to be adding today is we're going to add the dinner's endpoint which for now will simply return an empty list of dinners because we didn't talk about how this is modeled yet i wanted to cover some domain driven design principles beforehand and here we'll specify the token and all the authenticated users will be able to get a response now what you'll usually have is two separate systems one system that's your identity provider for example aad that that they'll generate the token and then the backend system will have to do some back and forth to get the public key of the private key that was used to sign the token to validate the signature but in our case since we're also the identity provider and also the system so we can simply use asymmetrically and that's what we're doing in our implementation but it's more about understanding the concept and how things are wired together behind the scenes okay so let's look at the code and get started okay so i have our application opened in visual studio code and i want us to first add the dinners controller which we'll only want to call as authenticated users so for that in the api project let's create a new controller let's call it dinner's controller right so public class dinners controller this one here from the api controller which is simply our base controller right in here it's from the controller base it has the api control attribute let's give it the route which is simply controller and let's put here the single endpoint that we talked about so public action result list dinners and like we said for now we'll simply return an empty list so array.empty and let's say string string like so great let's add your http get okay so of course for now anyone can call this endpoint we want to add authentication but for that i want us to put a breakpoint over here look what we have at the moment and then see what we want to tamper with so i'm putting a breakpoint over here and let's run the service the api project in the requests folder let's create a new folder it's called dinners and over here let's create our list dinner's request which will be somewhat like one of these but it'll be http get and dinners great now let's attach the debugger so over dinner the debugger is attached let's make the request and we hit the breakpoint and i want us to look at the http context and look at the user property which internally has the identity property and you can see over here we have is authenticated false and you can see that there could actually be more than one identity but what we care about at the moment is that the is authenticated is false and also that we don't have any claims okay now the process of authentication if we look at it simplistically from a technical point of view it's populating this thing over here with the correct details that are that are corresponds to the user based on the token that is supplied that he made the request with so that's what we want to do now and the way this works is it's following so i'm going to stop the application and i want us to look at the program cs okay so over here we have our request pipeline and we're going to add a new middleware called use authentication this will add the authentication middleware that what it'll do is look at the arriving request look at the authorization header and then it'll invoke the correct authentication handler which will take the token say if the user is authenticated and also extract various details etc so let's start writing some code and let's understand it as we go so over here let's add the use authentication middleware now this internally uses different objects that we haven't added to the dependency injection iot container so let's go ahead and add it now so in the infrastructure project we have over here our existing token related configurations right where we're generating the token let's add also the authentication logic so to make this a bit more organized let's create a new method let's call it add off one h and let's move the authlogic over there so we have these two lines over here let's just call them so let's say over here services dot add off and pass it the configuration like so now over here let's actually configure a few things first of all let's add the dependencies that authentication middleware needs and also let's define what do we actually want to validate in the token so the way this looks is as following services dot authentication this will as the dependencies that we talked about we also want to specify here what the default authentication scheme is in our case it's jwt bearer so let's say default scheme is jw2 bear bearer defaults and this isn't recognized let's find where this belongs to so reverse package search and this is the correct package so let's add it so dotnet add to the infrastructure project the package microsoft dot sp net core authentication if you can complete yes jwt bearer great now that we have that let's add the using statement and let's say here authentication scheme which if we look at this this is simply the string bearer and what this authentication method does is other than adding the dependencies it also returns the authentication builder right let's see that i'm not getting the name wrong yes authentication builder which internally has a map between the authentication scheme and the corresponding authentication handler and what we want to do is to add a jwt bearer handler as the authentication handler for the jwt bearer for the bearer authentication scheme okay so let's go ahead and do that so add jwt bearer and over here we can pass whatever we want to actually validate so in our case let's say options options dot token validation parameters and let's walk through yes this seems right let's just include what we need to include okay so what we're doing over here let's close the terminal so there's a bit more room what we're doing over here is as following so like we said there is the actual um authentication handler which validates the token makes sure the token is legit and populates the identity of the user and what we're saying over here is basically we're passing the parameters that we want to validate so in our case we want to validate the issue in the audience and we're passing what we define as valid issuer and audience also we want to make sure that the expiration date is in the future and also we pass it the signing key so the handler it actually calls a different component which does the validation but that the other component knows how to actually validate the signature of the token and that's it okay so this obviously doesn't exist so it's not recognized now the configuration that we have over here when creating the token is the same one that we're using over here all right so if you remember we have over here in the app settings the jwt m settings section right which has over here the definition of what we're using now because we're going to reuse it so let's extract it to a local variable let's say jwc settings equals new jwt settings yes let's bind the values so configuration yes only we want to give it the section name great now instead of adding this like so so if you remember this uses the options pattern to register the jwt settings right eye options with the type of jwt settings so instead what we're going to do because we already have the object over here we can say add singleton and over here we can say um options this one yes dot create and pass it the jwt settings and now these three lines is similar to the configure method it's the same thing just a more verbose way to say it and now we have the jwt settings which we can reuse below right so let's see what we're missing over here did i get this wrong okay now let's use it over here as well so the issuer is us and the audience also comes from this object let's add here yes system text and over here the key itself is under jwt settings settings uh it's capital that's why let's change this to a non-capital j and let's say secret perfect that's it let's simply return from here the services as so yes and this should be it for now so let's run the service again and make the listeners request again i want we still have the breakpoint in the controller i want us to now look at the http context and see what we have now so the service is running i'm connecting the debugger and let's make the request we hit the breakpoint in the dinners controller and again we're looking at the http context at the user and then at the identity and as we can see that is authenticated is still false now the question is why is it still false and the answer is because we're still not passing a token with the request so let's go ahead and do that so let's first of all continue and let's make a register request let's take the token that we get over here and put it over here in the authorization header let's say authorization and it's a bearer and let's paste the token now let's make the request again we hit the breakpoint and now if we look at the http context under user under identity and now we can see a few things first of all is authenticated is true and in the claims we can see that we successfully decoded the token validated it and then the claims were populated under the claims property so you might be asking yourself how did the previous request work without us passing a valid token and the answer is that what we set up is only the authentication the process of deciding if a user can access a specific endpoint based on some policy is the authorization process so let's go ahead and add authorization so let's see the phone first let's stop the service and go to the program cs let's make this a bit smaller okay so when we call add presentation this internally calls the add controllers which cause the authorization for us so we don't need to explicitly add the dependencies for the authorization middleware that's because it was already added for us but what we do need to do is the following is say over here f dot use authorization this will actually add the authorization middleware okay so i want to visualize this so again we have our request pipeline and somewhere in the middle we hit our authentication middleware the authentication middleware finds the correct a authentication handler that knows how to handle the bare authentication scheme in our case it's the jwt bear handler right so it calls this handler and it gets um the whether or not the user is authenticated the claims and so on that's where the actual validation of the token happens now that we have these values we call it the next piece of middleware which is the authorization middleware the authorization middleware will decide if the user can actually access the endpoint okay now for that what we want to do is we want to go back to our controller and we want to add the authorize attribute and now when we have two of these what will happen is that the authorization middleware by default it has a default policy when we simply call ipresentation add controllers and authorization this by default adds a policy that requires the user to be authenticated so we don't have to do anything other than add the authorized attribute which will use the default policy that requires the user to be authenticated so now that we have this we can run the project again make a request with an invalid token so let's corrupt it i change the e to an a and now that we make the request then we get four one um unauthorized and that's because of the authorized attribute and the authorization middleware now if we pass a legit token so i'm making a request taking the token from the register request pasting it over here making the request again and we can see that now we get the response so we have been authenticated successfully okay back in our dims controller another thing that would make sense to do is to move the authorized attribute to the api controller right to our base controller so it's applied to all of our controllers by default so for that let's take the attribute and move it over here now we can get rid of this using statement and it's applied over here but it'll also be applied in our authentication controller which also inherits from the api controller and now users won't be able to register or log in because they'll have to be authenticated to do so so for that if we still want to allow unauthenticated users to access the endpoints then we can say for this entire controller um then we allow anonymous and as you would expect in the authorization middleware there's a logic that says is there the allow anonymous attribute if yes then all good you can continue to the end point okay so just to recap what we have is the use authentication and use authorization middlewares we have the use authentication which will try to resolve what the identity of the user is and the user which will check if the user can actually access the endpoint the default authent authorization policy it requires the user to be authenticated and what it actually does is it checks the property that we looked at in the http context and to wire things up then in the dependency injection of the infrastructure layer then we simply added this where over here we passed details that the jwt bearer authentication handler will use to actually validate the token and that's it that's it for this video i really hope you have a better understanding of the topics that we talked about in the future videos we finally have a lot of the initial project infrastructure out of the way and we can start talking about domain driven design principles and terminology and understand how we actually want to model our system what the behaviors are what different contexts are in our system so if that sounds intriguing make sure to subscribe and i'll see you in the next one
Info
Channel: Amichai Mantinband
Views: 34,514
Rating: undefined out of 5
Keywords:
Id: 7ILCRfPmQxQ
Channel Id: undefined
Length: 18min 1sec (1081 seconds)
Published: Tue Aug 23 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.