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