Lecture thumbnail 0:00 / 27:35 So after successful login, we have got the token from the server, but the second part of the
implementation is the same token must be submitted as a request header in all the subsequent requests
that can be made to the server. For example, if you try to understand the logical flow of
the application, first a user will try to log in and then he navigates to the cities page
and here he tries to get the list of cities and make post, put and delete requests.
So in all the requests for cities, we have to automatically include this token value
as a part of the request header, that is authorization is the request header key.
In order to do the same, at first open up your city service in the Angular application
and here we are trying to create a request header called authorization
and the default syntax for this authorization header is bearer and then a space compulsory
and then the actual token value. So instead of supplying the dummy value like my token,
we have to actually write the actual value of the particular token that we have got from the server
and we have already stored it in the local storage, right?
So from the local storage, try to get the token value.
The key is token and it must be same as the key that we have used while adding the value
into the local storage. For example, in the registration component, we are adding the
token from the response into local storage of token. Here token is the key, so you must use
the same here. Okay, let’s use the back tick here for string interpolation, then this value
will be substituted with the actual value of the particular token from the local storage
and repeat the same syntax for all the remaining requests. For example, for post city
and then put city, then delete city, etc. So this adds the authorization bearer and then
the token value for all the requests made to the cities. Now first go to login page
and then enter the value. Currently delete this particular existing token value from the
application. Of course, it must be automatically deleted when the user clicks logout. We will do
that in a moment. So entering the correct values and we make a request to the login.
As a part of this, the token gets generated and that will be sent as response from this application
and you can see the token here and this particular token value will be sent as a response
and we have got the same here. Ignore that HTTPS error message and you will not get that error
message when you enable HTTPS protocol in your Angular application. Okay, it is out of context
for our course. It is specific to Angular course. Okay, we are not going to do that.
Anyways, after successful login, we have got the new token and this particular token value
must be sent as a request header. So go to the network tab. After successfully we have navigated
to the cities component. So we are making a request to the API slash v1 slash cities
and we make a get request and if you notice over here in the request headers now you can see a new
value that is authorization and this is the most important part. So we are submitting bearer and
there must be a space otherwise it will not work. So make sure you give space after this bearer
within this string value itself and then the actual token value.
So this is the token value that we have already stored from the local storage.
Does the server application really validate the token? I mean will it reject the request if the
token is not submitted? Really no. We have not written any code to validate the token in the
server side application and we have to do it. So before that let’s write the code for logout.
Go to the app component ts file in the logout button clicker method here before navigating
to the login. Let’s write local storage of otherwise we can say remove item of
token. So that token gets removed from the local storage when the user clicks on logout.
That’s fine. So here the question is how do you validate the token on the server side application?
Assume that we have received the JWT token into the server application and we have to do something
to validate the same. And exactly for that purpose only we already had use authentication middleware.
So this particular middleware is responsible to check the JWT token if submitted. But as of now
it is not configured to validate the JWT token. I mean the middleware is ready but it is not
configured to validate the JWT token. But how to do so? You require to explicitly add the
authentication service to the service container and configure validation of JWT token in the
same service. In order to do so you have to install that NuGet package. The same NuGet package which
we have already installed in the core project. That is authentication.jwtbearer package.
So right click on dependencies of web api project. Manage NuGet packages. Browse. Search for
Microsoft.AspNetCore.Authentication.JwtBearer and select the same version. Install 7.0.4.
It should match with the one which was already installed in the core project.
Okay. Ignore these errors. Those are related to Angular. Now we have to explicitly add the
authentication service. So just above this build method we can say that hey builder.service.
I would like to add authentication. And I know you are offering a lambda expression that contains
options parameter. And through this options parameter we can supply some additional settings.
For example we can access the property called default authentication scheme.
By default it is cookie authentication which works with MVC controllers. We have already
configured the same in MVC controllers earlier. But with web api controllers we have to set the
authentication scheme as jwt authentication scheme. That is jwtbearer defaults.
which come from Microsoft.AspNetCore.Authentication.JwtBearer namespace.
Make sure you import it the same. So we are setting the jwt authentication scheme as a default
authentication scheme as well as default challenge scheme. Whenever a request is received from the
client application, first it will try to validate that particular request by using the default
authentication scheme that is jwtbearer.authentication scheme here. But if this authentication is failed
here, especially for redirecting the user to login page, it will try to validate the user by using
the challenge scheme. But alternatively when the user is not authenticated by using jwt,
you would like to redirect that particular user by using cookie authentication scheme.
In that case you can mention the different value, I mean cookie authentication defaults.authentication
scheme. That means if the user is not authenticated by using jwt then it has to automatically redirect
to cookie authentication scheme. Okay, but this configuration is not enough. We have to explicitly
specify what are the properties that has to be checked in the jwt token, how the token has to
be processed and what things have to be validated within the token. To configure the same, you can
continue an extension method called add jwtbearer and here also we have an options parameter
inside a lambda expression and in this particular lambda expression you can write options related
to jwt. Here it has a property called token validation parameters and create an object for
the same. By the way it is coming from microsoft.identitymodel.tokens namespace.
So you can also import that particular namespace at the top. Import that namespace. Okay, make sure
you imported authentication.cookies and authentication.jwtbearer. Alright, come back to
the same place in the program.cs file. Here within this token validation parameters we have a property
called valid audience. So it is asking, okay we have received the token and it contains the value
of audience as a part of the payload, right? The payload contains the issuer, IAT, JTI and
audience property values. So we have to validate the audience and you have to mention the same for
true and in the same way we have to explicitly specify what are the valid audience. I mean what
is the actual valid value for audience property. In this case we have to get the value from the
configuration, right? So builder.configuration of in the jwt key, see under jwt we have audience.
I would like to get this particular value and specify this as a valid audience property value.
So we are writing the same, audience. This must match with this jwt and audience over here.
Okay, exactly in the same way we have to specify to validate the issuer. Validate issuer
and the actual valid value for issuer property and we are getting this value
also from the same configuration from app settings. So now it knows that okay it has
to check the audience value as well as issuer value and these are the valid values. So within
the token if the audience value doesn’t match with this one and issuer value doesn’t match with this
one then it means the token is invalid and in the same way it has to validate
the lifetime, I mean expiration date. It has to automatically check if that token is already
expired. So if it is expired it is treated as invalid token automatically. Then that action
method will not execute. That is automatically done by the authentication middleware and in
the same way it has to validate the signature. Issuer signing key equal to true. Yes it has to
validate the signature. See the signature is the base 64 string of the hashed data and you will
get the hashed value based on the header and payload here and also the secret value. So you
have to mention the secret key value which was already configured in the configuration file.
Then rest of the process will be automatically taken care. So we have to mention issuer signing
key equal to new symmetric key. I mean symmetric security key and we have to get the key from the
configuration. Under JWT we have key but this value is by default a string type. We have to
convert the same into byte array. So system.text.encoding.utf8, I mean unicode transformation
format 8-bit and convert this string value into bytes. So this is the actual key that was stored
in the configuration. First we will get this and we will convert this particular string value into
byte array and that byte array is supplied to the constructor of this class. So the key is ready for
us but we are not writing actual code for the signature generation. Only the thing is you have
to just inform that it has to validate this signature and supply the key value that’s all.
Okay these are enough configuration properties for configuring the JWT token validation
and also you have to explicitly add authorization. Of course it is optional by default it gets added
but the benefit of adding this explicitly is that if you want you can write options explicitly and
write any properties that you want to customize in these options. Okay currently we don’t have
anything so let it be empty. Okay so so far we have just configured how does the JWT token has
to be validated, what properties have to be checked and with what values those must be compared. That
means we have configured what is the actual value of the audience issuer and the signature key.
That means we have informed the valid value of the audience issuer and the signature key
and also in order to force this authentication process to perform
we have to explicitly apply authorize attribute for all the API controllers.
Something like this for example authorize but instead of applying this authorize attribute
manually and explicitly for every controller instead of doing so you can also apply the
same as a global policy. We already know that. Let’s try. Go to the add controllers in the
program.cs file somewhere within this options lambda expression
create a policy that is authorization policy builder
and just call a method called require authenticated user
and build this policy and add this policy as a global filter. So filters.add
so when you apply this as a global filter it gets applied for all the controllers
but it is including account controller. Oops it must be authorized filter
and it works based on this policy and import the namespace microsoft.aspnetcore.mvc.authorization
this one
okay since we have applied this as a global filter it applies authorized filter for all
the controllers including cities controller and account controller also but our requirement is
we don’t want to apply this for account controller because the account controller
action methods must be accessible even without login or registration
so all these action methods of the account controller should be accessible
without an authenticated user so that is the reason we have already written
hello anonymous attribute it bypasses the requirement of that policy that means the
requests to account controller gets accepted even if that user is not authenticated so apply this
authorized filter for all the controllers globally at the application level and
and give exemption for account controller by using hello anonymous
so the code changes that we have made in the program.cs file validates the token from the
request header and verifies whether the token is valid or not and it verifies the values of
the issuer audience and also signature values okay now run this application and verify
try to log in first
enter the valid values first of all remove this token that is in the application tab
local storage click on this localhost 4200 just remove the token if it is stored already
so click login yes the login action method executes oops we have got 500 response over here
and it indicates internet server error that means there is an error at server side code
click on the response to see error message so it is the problem result and it contains an error
invalid email or password that means the password is incorrect let’s re-enter the same
harsha123 and login yes we made one more request
and now yes this time we have got success response so now the response status code is 200
and we have got this particular response from the server person name token expiration and email
so this token is already stored in the application local storage that’s fine
here the point is when we redirect to cities component again switch back to network tab
we have redirected to cities component and as a part of the cities component
we are making a get request to api slash cities so we make a get request url is api slash v1
slash cities and this request is accepted and we have got the proper response from the server
with city objects it is because as a part of this particular request we are sending the token as a
part of the request header so go to the request headers now you can see the value of authorization
bearer and there must be a space and after that the same token from the local storage
if you don’t submit the token in this authorization request header
then the server rejects that particular request for example let’s say let’s make some changes
in the cities component service go to the cities service in angular code
assume that in the get cities method we are not going to submit a valid token
so we are just submitting some dummy token okay so it is not a valid token right
this particular token value will be validated when you make a request and that gets rejected
because the authentication middleware will verify that jwt token based on the above configuration
and it’s invalid token it cannot be parsed into a valid token to verify these properties
so that is invalid so it simply reject the request or redirect that request let’s see
what exactly happens so again try to log in enter the valid value login yes we are good
okay this time when you make a request to api slash series we have got 500 response
and the response says that invalid operation no authentication scheme was specified
and there was no default challenge scheme found in the program.cs file go to the add authentication
and specify jwt authentication scheme for default challenge scheme also because in our application
we are not configuring cookie authentication so we change it back to the jwt authentication
run this again it may work when you enable cookie authentication and jwt authentication in the same
application at the same time okay we are not doing that let’s re-login again so when you make
a request to api slash cities this time we have got 401 response and that is what we are expecting
unauthorized so 401 indicates unauthorized that means the request authentication is failed
because the token is invalid because in this case in the request header we are sending a request
header that is authorization and we are not sending a valid token it’s a dummy token so
this is verified by this particular jwt authentication and according to the configuration
that you mentioned here that token is invalid so it simply rejects that particular request
so automatically it sends 401 unauthorized response you can check once again log out login
clear the requests enter the valid values and the login is successful but
when you make a request to api slash cities we are getting 401 unauthorized response
that’s fine because the token is invalid but when you try to re-enable that particular token
in the cities service.ts file in the angular code we just undo the changes so again we are
trying to submit a valid token from this and login also delete the existing token
of course it gets deleted when you click log out
so when you log in here first the login attempt is successful so we are getting 200 response
then the angular application redirects to cities component and in the cities component we are
making a request to api slash cities and in the request headers we are submitting authorization
and then a valid token value so this token is verified by asp.net core application
and the token is valid now so then it executes the cities controller get action method
for example if you add a breakpoint here and refresh since the token is valid over there
it executes the action method because the authentication is successful here
so it executes that action method and returns the response
and that response reaches back to the client application
that’s how does it work so we have learned how do you enable login functionality for the user
and how do you generate the token on the server side send the same back to the client application
store the token value in the browser memory and submit that particular token as a part of the
request header in all the subsequent requests and validate that particular token and return
the appropriate response if it is valid so this is how do you enable authentication and authorization
for web api controllers
Play Play Play Play Play Play Play Play Stop Play Play Start Start Start