In the last video, we'd got to the point where we had
secured our controller using the [Authorized] attribute. And we had got to the position where a user can
Register, and then Login. And when they logged in, they'd be returned one of these JWTs - JSON Web
Token - that they could then use to actually access the website. But we hadn't actually done
that last bit of it, so let's pick up from there. So you will need to look at the previous video,
I think, if you haven't seen it so far. This was really intended to follow up. But just to show you
very quickly, so we had our BookReviewsController, where we had that [Authorized] attribute, that
means we're not allowed in there until we log in. And we're going to do a bit more work
to make that work properly. And then also our AuthenticationController where we had the
Register and the Login. But of course, that's not [Authorized], because you need general members of
the public to be able to do that. And so if we run that up, then we have a BookReviewsController.
But if I try to access that, I'm not allowed to. Rather strangely, we get a 404 - we should
really be getting the 401 there, but we'll fix that in the rest of this video. But I also have
the Register. I've already registered, so let's just log in. So if I log in, you may recall that
I logged in with a username of ‘Jasper Kent’ and my password was the very insecure ‘Pa$$w0rd’. And
if I execute that, then what we get back is this response where we've got the JWT token, that's the
real thing we need. And then just for information, we're also telling you when this expires, so
you know when you need to renew it or anything like that. So now let's get that working. So we
can actually go back in with that token and get access to the code. And so what we're going to
do is we're going to go to the Program and do some more configuration during the whole startup
process. And so what we need to do is, firstly, we need to configure the authentication. So down
the bottom here - doesn't really matter where as long as it's before that ‘builder.Build()’ - we're
going to say ‘builder.Services.AddAuthentication’ and then in the ‘options’ we're going to set up a
number of things, all of which are basically going to use this JWT authentication. So we're going
to say ‘options.DefaultAuthenticationScheme’ and that's going to be ‘JwtBearerDefaults’ - get hold
of that, and that comes from a different package, so we'll just install that automatically
- and then that's going to simply be ‘.AuthenticationScheme’. And then we're going to
have two others, very similar. So we're going to have the ‘DefaultChallengeScheme’. And we're going
to have simply the ‘DefaultScheme’. Easy enough to set all of those three to being the JWT. That's
telling the system that we're using JSON Web Tokens. As I said, in the previous video, there's
lots of other ways you can do authentication, but that's what we've got here. And then what
we're going to do is configure that specifically, so we're going to say ‘AddJwtBearer’ and again,
have a set of options on there. And in this lot, I'm going to firstly say ‘options.SaveToken =
true’ - that simply means that once the token has been sent in, it's going to store it in
memory so it’ll be accessible from elsewhere in the application after the basic validation
has been done. And then I'm going to say ‘options.TokenValidationParameters = new
TokenValidationParameters’ - get rid of that long namespace there. And then what I'm going to pass
in there, we're going to have the ‘ValidIssuer’ and I'm going to take that from the config
file. So remember, in our config file we had used when we were creating the token, we had
the ValidAudience, the ValidIssuer and the Secret. So we're going to make use of those
now when we are verifying that the token is correct. So we're going to say ‘ValidIssuer’
and then ‘builder.Configuration’ and then ‘JWT:ValidIssuer’ and then I'll
repeat that for the audience, so that's going to be ‘ValidAudience’. And then I
need to set up the Secret. So that's going to be a thing called ‘IssuerSigningKey’. But let's just
make this a little bit different. Let's, up here, I'm going to say ‘var secret =’ and so here
we'll just say ‘builder.Configuration’ and then ‘JWT:Secret’. Remember, there's a risk that
could be null, so we're also going to throw the exception there. So in fact, we can just
take that off the AuthenticationController, because remember, here we're doing the same sort
of thing. So we'll just put that on the end there. And then in here, we're going to on that
issuing key, we're going to say ‘=’ and then we've got this ‘new SymmetricSecurityKey’.
And, again, same sort of thing as we had before. So ‘Encoding’ - get hold of a namespace - and
then ‘UTF8’ and then ‘GetBytes’ from that secret. And then the last thing we need to do, having
configured the authentication, we need to use it. And so down the bottom here, we put it just before
the ‘UseAuthorization()’. So when we're doing the configuration up here before the ‘builder.Build()’
the order doesn't matter too much. But here it is important. And if you get those the wrong
way around, you'll get some very strange behaviour. Authentication comes first. Remember
authentication, as we said in the last video, is the user demonstrating they are who
they say they are. Authorization is then us deciding what this particular user is
allowed to do. So if we now run that up, we're now in a situation where if we send that
JWT back with our request to get the Book Reviews, then we will be allowed access. But the problem
is, we haven't at the moment got a means to provide that token in Swagger when we're sending
the data over. So you can see we're still getting the 401. That's sorted now. That was a 404 before,
but that's the correct 401 for we're not allowed access. But how do we send that token back? Well,
we'll see how we can do that in Swagger in a moment. But let's first use Postman. So if I just
bring up Postman - so this is a standard tool that lots of people use for accessing web services, and
testing web services. And what we can do there is, if we go back to Swagger and actually just
steal the URL that we had for getting hold of those Book Reviews, and pop it in here,
on a get request, send that, as you'd expect, we get back that 401 Unauthorized. But what
we have to do is pass the JWT as an item in the header. So if we go to headers here, and
I'm going to add an Authorization header. And then what I need to do is back on the
Swagger, let's log in so we can get hold of our JWT. I could have logged in in Postman, but I just
find it much easier to use Swagger. So we do that and then that gives us our JWT. So we'll copy
that and then back in Postman, we'll type ‘Bearer’ space, and then the token that we have that. So
that's the bearer token that we've got. And so if we now send that, then you can see we're getting
the information coming back. So that token that we passed in was being examined by the code that
we put in here, checked, decrypted to check that nothing had been tampered with. And then we can
see that it allows us in even though we had that [Authorize] on the controller. So that's basically
what we're going to do. But I personally prefer to use Swagger rather than Postman. And so let's
add that last feature in there. So let's go back here. And now let's configure Swagger to make
use of this. So if we go up here, here is our ‘AddSwaggerGen’. We've seen in previous videos
lots of ways that you can configure Swagger, so we could combine that configuration with
what I'm going to do here. But what I'm going to do is make it so we can enter that in
Swagger. And so what we need is to put in some options here. So let's say ‘options =>’ and then
we'll put those in there. And we're going to say ‘options.AddSecurityDefinition’. And we're going
to call this ‘Bearer’ - call it what you like, really, but that will match up with what
we're talking about. And then we say ‘new OpenApiSecurityScheme’. Again, let's use the using
for that one. And then that again, we can provide some parameters. So we're going to say where it's
going to go. So ‘In = ParameterLocation.Header’. So it's going to be a header. ‘Description’ -
so this is purely what is going to be displayed to the user when they're using Swagger. So we'll
say ‘Please enter Bearer’ and then the ‘[jwt]’. So that's what we put in just a moment ago,
when we saw it in Postman. Again, that word ‘Bearer’ on the front is vitally important.
Then we're going to give it a ‘Name’. Again, call it what you like, but we're calling
it ‘Authorization’ just for display really. And then finally, we will add a ‘Type’. And
that one is ‘SecuritySchemeType.ApiKey’. So that's set up a definition. We then need to
make use of that definition, so we now say ‘var scheme = new OpenApiSecurityScheme’ once again.
But in this case, the only way we configure this one is to reference the one that we've just
put in. So here, we're just going to say, ‘Reference = new OpenApiReference’. And then
what we're typing is this other scheme. So we say ‘Type = ReferenceType.SecurityScheme’. And
then this is where the name comes in. So we say ‘Id = “Bearer”’. We're using the word ‘Bearer’
a lot, but that ‘Bearer’ there corresponds with that ‘Bearer’ up there. And then there's one last
thing I've got to do having put those together, we've now got to actually register them. So
the last thing I'm going to do here is say ‘options.AddSecurityRequirement’. And then we say
‘new OpenApiSecurityRequirement’. And that one is a dictionary for which we're going to have a
key of ‘scheme’ that we just created on the line above, and then a value of just an empty list of
strings. So we can say ‘Array.Empty<string>()’ in there. So that just hooks all of that up.
Again, lots of variations we can have on this. But now, when we run this up, you can see that
it's added at the top of the page this ‘Authorize’ button. And when I click that, you can see it's
got the information like the ‘Please enter Bearer [jwt]’ and it allows us to put a value in there.
So let's log in again. I could have used the existing one, but I don't remember where I put
it. So let's just re-login to get a new JWT. So ‘Jasper Kent’, ‘Pa$$w0rd’. Execute that. Copy that
token. And then go into the Authorize and again, just like we had in the Postman, we've got to
put in the word ‘Bearer’ then paste in the token, authorize that. And all that's done so far
is that means that the Swagger page is now remembering that token, and will send it off
in the header every time you do a request, just like we had sending it from Postman. So now
finally, if we go down to the Book Reviews, and click ‘Try it out’ and ‘Execute’. This time,
we're getting the data coming back because it's passed in that header. And we can then make use
of it. And so if we scroll up there, you can see there, we can see the authorization header that
it's sending off with all of that. So that's that stage complete. So as well as what we did in the
first video, which was getting the server to issue the JWT, we've now got the ability to then send
the JWT back as part of the authorization header, and therefore get access to any restricted area
of the web service. Plus, we've added the ability to Swagger to make that relatively easy for
us to do that. One other thing we need to do, which you may have seen there, is we also need to
log out. So if we just scroll up to the Authorize button and click on that, you can see it's
just got that ‘Log out’. And if I click that, all it does is basically forget about that JWT. So
now if I do that, it's simply not going to send it and so if I try and execute again, we get the 401.
So logging out doesn't involve sending any message to the server saying we're logging out, it simply
means we forget the token and stop sending it. What we next need to do is actually start writing
some genuine clients rather than just Swagger, which is purely a development tool. And so with
those, we can start looking at this as a real application. And I'm going to do that in a couple
of ways. The first way I'm going to do it is with an Angular front end, and then in later videos,
we'll look at some other front ends. So I hope that was helpful. If you enjoyed it, do click
like, do subscribe and I'll see you next time.