#38 Spring Security | Validating JWT Token
Summary
TLDRThis video tutorial demonstrates the process of implementing JWT authentication in a Spring Security application. It covers creating and verifying JWT tokens, modifying the security configuration to prioritize JWT over traditional username/password authentication, and adding a custom filter to handle token validation. The presenter guides viewers through coding examples, troubleshooting, and adapting to changes in library versions, ultimately enabling a secure, token-based authentication system.
Takeaways
- 🔒 The video demonstrates the process of creating and using a JWT (JSON Web Token) for authentication in a Spring Security context.
- 📝 It explains that after successful login with username and password, a JWT is generated and sent to the client for subsequent requests.
- 🔄 The client must send the JWT in the Authorization header without the username and password for accessing secured resources.
- 🛠️ The video outlines the need to create a custom JWT filter that precedes the default username and password authentication filter in the security filter chain.
- 👤 The JWT filter is responsible for extracting the token from the Authorization header, validating it, and creating an authentication object if the token is valid.
- 🔑 The process of validating the token involves decoding it, checking for expiration, and ensuring it corresponds to a valid user in the database.
- 🛑 The video emphasizes the importance of checking if the security context is already authenticated to avoid re-authentication of the user.
- 📚 It mentions the creation of methods in the JWT service for extracting the username from the token and validating the token's authenticity and expiration.
- 🔄 The video script includes code snippets and explanations for implementing the JWT filter and service, including handling changes in library versions.
- 📈 The presenter guides the viewer through the entire flow from token generation to validation, emphasizing the steps involved in securing an application with JWT.
- 💻 The video concludes with a successful demonstration of the JWT authentication flow in a Postman request, showing that the system is working as expected.
Q & A
What is the purpose of JWT in the context of the script?
-JWT (JSON Web Tokens) are used for authentication and authorization in the script. They allow the server to generate a token after a successful login, which can then be used to access secured resources without the need to send username and password with every request.
How does the server verify the username and password in the script?
-The server verifies the username and password by checking them against the credentials stored in the database. If they match, the server proceeds to generate a JWT for the user.
What issue is being addressed with the token in the script?
-The issue being addressed is that while the token is being generated correctly, the application is not able to use it to access resources like fetching students' data. The token needs to be validated on the server side to make this work.
What is the role of the 'OncePerRequestFilter' in the script?
-'OncePerRequestFilter' is an abstract class that ensures the filter logic is executed only once per request in the Spring Security filter chain. It is used as a base for creating custom filters like the JWT filter.
How does the script handle the order of filters in the Spring Security configuration?
-The script modifies the filter chain order by adding a custom JWT filter before the UsernamePasswordAuthenticationFilter. This ensures that the JWT filter is checked first for authentication before falling back to username and password authentication.
What is the significance of the 'doFilterInternal' method in the script?
-The 'doFilterInternal' method is an abstract method that must be implemented in any filter extending 'OncePerRequestFilter'. It contains the core logic for processing the incoming HTTP request and is where the JWT validation takes place.
How does the script extract the JWT from the HTTP request header?
-The script extracts the JWT from the 'Authorization' header of the HTTP request. It checks if the header starts with 'Bearer ', and if so, it extracts the substring that represents the actual token.
What is the process for validating the JWT in the script?
-The validation process involves extracting the username from the JWT using a service method, checking if the token is not expired, and ensuring that the username exists in the database. If these conditions are met, the token is considered valid.
How does the script create an authentication object after validating the JWT?
-After validating the JWT, the script creates a 'UsernamePasswordAuthenticationToken' with the username as the principal, null as the credentials, and authorities fetched from the user details.
What changes are required in the 'JWTService' class to support the new version of the JWT library?
-In the new version of the JWT library, changes include using 'verifyWith' instead of 'setSigningKey', and updating method calls to reflect changes in the library's API, such as using 'signedClaims' instead of 'claims' and 'payload' instead of 'body'.
How does the script ensure that the authentication process is secure?
-The script ensures security by validating the JWT for each request, checking for token expiration, and ensuring that the username mentioned in the token exists in the database. It also sets the authentication object in the security context to bypass the username and password authentication filter for subsequent requests.
Outlines
🔐 JWT Token Creation and Usage
This paragraph discusses the creation of a JWT token for authentication purposes. It explains the process of generating a token upon successful login with username and password verification. The token is then used to access resources like fetching student data without the need to resend credentials. The speaker highlights an issue where sending a token to access a resource is not working as expected and outlines the need to validate the token on the server side. The explanation includes the server's default behavior of using username and password authentication and the intention to prioritize JWT token validation over this default method.
🛠️ Implementing JWT Token Validation
The focus of this paragraph is on implementing JWT token validation in a Spring Security configuration. It details the steps to modify the security filter chain to prioritize JWT token validation before the username and password authentication filter. The process involves creating a custom JWT filter by extending the 'OncePerRequestFilter' class and implementing an abstract method to handle the filter logic. The paragraph also addresses the need to import necessary classes and create a JWT filter object in the security configuration, which leads to the creation of a new class for the JWT filter if it's not available by default.
📜 Extracting and Validating JWT Tokens
This section delves into the technicalities of extracting and validating JWT tokens within a custom filter. It describes how to retrieve the token from the authorization header, verify its structure, and decode it to extract the username. The paragraph explains the importance of checking if the token is not already authenticated and how to use a JWT service to validate the token's authenticity and expiration. It also outlines the creation of an authentication object using the extracted username and setting this object in the security context to pass the authentication to subsequent filters.
🔄 Updating JWT Service for Token Handling
The paragraph discusses updates required in the JWT service to handle token extraction and validation. It mentions creating methods for extracting claims from a token and validating the token's validity, including checks for expiration and the presence of the user in the database. The speaker also addresses changes in the library's method signatures due to version updates and provides guidance on adapting the code accordingly. The paragraph concludes with the successful execution of the flow, where a token is generated, used to authenticate a request, and the subsequent resource access is granted without the need for username and password.
🚀 Finalizing JWT Integration and Security
The final paragraph wraps up the process of integrating JWT for secure resource access. It summarizes the entire flow from token generation upon login to its validation in subsequent requests. The speaker emphasizes the importance of correctly setting up the JWT filter in the security configuration and the JWT service for claim extraction and validation. The paragraph concludes with a demonstration of the successful authentication flow using a token and hints at future implementations in an ongoing project, encouraging continuous learning until the next video.
Mindmap
Keywords
💡JWT Token
💡Spring Security
💡Authentication
💡Authorization Header
💡Filter Chain
💡Username and Password Authentication Filter
💡Claims
💡Token Validation
💡Security Context
💡Postman
💡Service Layer
Highlights
Introduction to creating and using JWT tokens for authentication in a web application.
Demonstration of the login process and token generation upon successful authentication.
Explanation of how to send login details and the server's verification process to generate a token.
Using a token for accessing resources without passing username and password each time.
Troubleshooting the process when the token is not working as expected.
Details on configuring Spring Security to permit certain requests without authentication.
The necessity of adding a JWT filter before the user password authentication filter.
Creating a custom filter class by extending OncePerRequestFilter.
Implementing the doFilterInternal method to handle the JWT authentication process.
Retrieving the JWT token from the authorization header in the request.
Decoding the JWT token to extract the username and validate the token's authenticity.
Using Spring Security context to check if the user is already authenticated.
Creating an authentication object if the token is valid and setting it in the security context.
Continuing the filter chain after successful JWT validation.
The importance of updating service methods to support token extraction and validation.
Changes in the JWT library and how to adapt the code for newer versions.
Final demonstration of the complete flow from token generation to validation in requests.
Conclusion and summary of the JWT authentication process in Spring Security.
Transcripts
so till this point we were able to
create the token the JWT token so just
to show you how it was looking so if you
go back here and if you click on login
so we are passing the details if you can
see the body we are sending the login
details which is Navina and and at the
rate 1 to3 when you click on send the
request goes to the server and then on
the server side it verifies the username
password and if the username is password
is correct in that case it generates a
token which you can see here and of
course using this token I want to do
other activities example I've done the
login once right and I got the token and
now let's say from the application if I
want to access any resource example if I
want to fetch students and I don't want
to pass the username password now so in
the earlier scenario we were sending the
username password but now we don't want
to do that we want to send a token which
is a better token and here we should be
able to paste it and we are doing that
but when you click on send this is not
working and we want to make it work so
generating token done but we have to WR
the token and give the access to the
user that's what you have to do in this
video okay u in fact this token is also
valid we have checked that on jw. we got
the details we got the claims and we got
other details so things are working out
it's just that now we have to validate
token and we have to make this work now
how we are going to do that so of course
there are multiple steps involved the
first thing you have to do is when you
send a request to the server by default
see one there's one thing uh I wanted to
point it out if you go to security
config we have mentioned that for this
two requests the register and and for
login you don't have to check for
authentication so basically they are
permitted but for the all the other
request it will be authenticated that
means when you request for the students
it will be authenticated and by default
the authentication we follow is user
password authentication so by default
that filter comes to picture now if you
remember we have talked about filters
right so in Spring Security we have
multiple filters one of the filter is
user password authentication filter this
is a filter which gets activated and
then it checks for username password now
what we are saying is hey you know I
don't don't want this filter to be
activated first before this filter I
mean I want to make this filter which is
UF as your second filter and the first
filter should be your JWT filter now
this will check for the token right now
once you verify token as a first filter
then it will send the request to the uh
UPA filter by saying hey I have verified
and this is a user already logged in so
I'm confirming that so you can just
continue with the other work so this is
what we want to do so that means we have
to add a filter before the user password
authentication filter and the way you
can do that is very simple it's not
actually you know this this video is
also very lengthy so just be with me and
there a lot of things going on and if
you watch it with me and if you write
the code with me it will make much more
sense so the first thing you do is
before you build you know I'm in the
security config and we are working with
security filter chain basically we're
working with Filter chain and before you
say build what you do is you add a
filter before the user authentication
filter right so you will say add filter
before so you can you can add filter
anytime you can add filter uh you can
add filter at particular point you can
add filter after or before so I want to
add before the user authentication
filter so I will do that uh the first
parameter is actual filter so let's say
I want to say this is a JWT filter so
that's the object we have to pass the
second one is the class the filter class
so I will say usern name password
authentication filter now this is what
we have to specify so what I'm doing is
I'm saying that hey you know before you
hit this particular filter use this
filter but what is this filter we have
to work with this so in that case you
will go up here and create the object of
private
JWT filter J filter so this is what so
we have created the object here I mean
we are doing Auto wire and then that
object would be used here okay but the
problem is and it says that uh this jwd
filter is not able to find it so it's
very simple you can just simply say
control space let's import the package
oh it says no suggestion that means in
your library of sping security we don't
have this filter by default and that's
where you get the opportunity to create
a new filter I know I'm using some
positive words here opportunity yeah we
have to get another class to make it
work so let's do it you know anyway we
are doing this only once so I will just
click here and say hey create a class
and when I want to do that maybe in the
same package config logically it should
be in a separate package called filter
package but config works for this
example I will click on okay and we got
this new class now I want this to behave
like a filter okay how do we make make
something behave like a filter what you
do is you extend those properties right
so if I want to be rich I want to get
adopted by some Bia right so here I want
to extend I want to make this a child
class of some parent class which has a
filter capability so one of the filter
we are going to use here is I mean
that's one one of the class we're going
to extend is once per request filter I
know very nice name to give to a filter
or the class this is called once per
request filter see the reason is every
time you send a request you want want a
filter to get activated and in the
filter chain you want this filter to be
executed only once so for every request
you want this filter to be executed only
once and that's why you're saying once
per request filter now it is giving you
some error I was not expecting but let's
see this once per filter is actually an
abstract class which means there might
be some abstract methods which we have
to implement and if you scroll down down
down all the methods are defined but one
method is there yeah there's always one
so one method is there which is called
called do filter internal which is
abstract method that means if you want
this to work we need to we need to we
need to we need to implement it so let's
click on Implement and okay so this is a
filter we have to work with now if you
go back to our sessions on Spring web we
have talked about HTTP subet behind the
scene everything is sub right and it
gives you two objects to work with
request object to work with the data in
the request of the user response object
if you want to add something to the
response and here I just want to work
with a request so let's use request but
what I want to do that's a big question
see it's actually very simple see on the
client side you are sending a request
right for for the students and with that
request you are sending a token as well
now this token when you receive on the
server side you will not get to the
Token as this just the token what you
will receive is can I type here no I
can't type here uh maybe I will type in
body so what I receive from this server
not a good place to type right okay so I
will just go back here and I will write
a comment so from the client side what
you will get is better that's the first
word and then you will get the token I
think token is this yeah so this is what
you get from the client side so it
starts with better and then a space and
then it starts with the actual token
this is what you get from the client
side right now what you have to do is
you have to get this token and you have
to cut that better part you just have to
focus on this part get this token and
viate it so simple right okay not that
simple I mean breaking out is simple
viting is difficult so let's be with me
so how will I get this thing the entire
stuff and actually it's a part of
request so it sends the data this better
and the token in the request object in
the headers so what I can do is I can
get the headers so I will say security I
will say or header so header will have
lot of things I don't want everything so
from the request I just want a header
which talks about authorization this is
the only header I need it will have lot
of headers but I just want authorization
and once you got this Au header this
will have this token but I want only the
last part so I will save this token
somewhere in the token and by default I
will keep it null I want the username as
well because somewhere we have to work
with the username because because you
will generate a token you will verify
the token with the help of username and
now let's get started so first thing I
want to check is do we have any
authorization header so let's check that
so if there is a o header which is not
equal to null in that case you have to
continue so that's the first thing you
want to check you you want to make sure
that this is not null and you have to
also verify do we have a better token so
again I will check Au header so it
starts with it should start with better
so you can even say B but to be on safe
side I will say it should start with
better in case if it is starting with
that I will set the token and I want to
fetch the token now and fetching token
is very easy you will say Au header dot
uh you want you don't want the entire
string right you just want this
particular token here so I want to skip
these letters now what are this letters
so I will start with index of zero so
this is b is0 1 2 3 4 5 and then six the
space is also there right so I want to
start from seven so it should start the
substring from Seven index number seven
and I want to get the username from the
token so I will say username equal to
now how will you get the uh username
from the token because token is encoded
right so you can see this you have to
find usern from this as a human also you
can't do that so we have to do something
for the program to work but I will make
sure that I do that in the service so I
will use Service uh object and we don't
have the service auto autowired here so
I will say autowired private JWT service
service okay so I will use this and in
this I will make sure that I have an
object I have I have a method called
extract username maybe it will have
username so for where exactly it will
extract the to extract the username from
the token and you can see there's a red
here because we don't have this method
in the service yet so what I will do is
I will say okay uh create this method of
uh extract token and at this point I
will just return empty we'll code it
later so this is empty so so that we
will not get any error and you can see
there's no error here now once you got
this two now we have to verify so once
you got the details you got the token
now you got username so I will check if
so the username should not be equal to
null that's the first thing I to check
and I also want to make sure that
there's no it's not already
authenticated so if the object is
already authenticated why you have to
verify all those things so I will say
security context holder dot get
context. get authentication and this
should be null so if it is not null then
I don't want to continue because it's
already auth authenticated so I will
just continue with this so this should
be null if these two are matching see
ultimately what you have to do is we
have to validate token see we into
filter now right so see if this filter
is Success then we'll forward it to the
user pass authentication filter right
now how do you specify that is this is
Success the first thing you have to do
is you have to validate the token if the
token is valid valid in that case you
will create the authentication object
and that's what you have to do here so
to do that I want to verify right so I
will say JWT service dot in this
particular class I want a method which
will validate the token because all the
things we are doing in the JW service
right so let's do that so there should
be a method called validate token and
you have to pass the token now when
you're validating you have to check two
things one in the token the token should
be valid and second the username which
is it is mentioning it should be part of
a database right and to refer to
database I will pass the object of user
details and we have to create this
object somewhere now where should I
create the object I can do that here so
I can say user details we have to import
the package use it details and then I
can actually Auto if you keep it on top
but I think it will create a cyclic
redundancy so what you can do is you can
get the hold on the application context
object so I will say autowire and applic
context context remember when we were
running about spring framework we have
used this application context to get the
bean so here also I will say context.
get bean of type user
details. class but the problem is it
will give you a empty object I don't
want empty object what I want is I want
the object of user details which will
have the user data now if you go back to
my Detail Service in this you have this
method called load user by username and
this will give you the object of us
details that means if I ask for the
object of my user details service dot
class and from this object if I can get
load by username and if I pass the
username here it will file database and
it will get me the username right and
not just username it will give me the
entire user D object okay so that's what
we are doing here but if you can see in
JW service we don't have this method so
I will just create one so the method
name is Ved token and at this point I
will return true okay let's go back to
the filter now if the token is valid it
in that case remember we have the next
filter we have to make it work so the
next filter is next next filter will
work with the username password
authentication filter but I want to pass
a token there so I will create a token
and I will say new username password
authentication token now this token asks
you for three things one is a principal
next is a credentials and third is
authorities so user principles we
already have which is the object of user
details which will have all the details
about the user credentials I don't want
to mention so I will keep it null
authorities I have is so will get it
from user details. getet authorities
okay that is that that is what it was
asking and we are getting is it a
warning variable token is already
defined in the scope where exactly I'm
using token okay so I will use something
else okay toen token we already have it
here right so this should be Au token if
it makes it happy now o token knows
about the user but or token has no idea
about the request object right so this
request object will have lot of data and
we are just creating this object and we
are passing it so this object should
also know about the uh request object so
you will say set details and to specify
that you have to use web authentication
details Source sometime you have to just
remember the class names and stuff it
becomes very complex you just get get
into it and with this object you will
say build details and you will pass the
request object and now once you have
this OD token ready is just you have to
set this in the context so this
particular thing which is authentication
should not be there by default and
that's what we are taking for null now
once it is verified you have to set the
Authentication so you will say secur the
context holder dot now instead of saying
get authentication you will say set
authentication and you will pass the a
token object so by doing this you are
adding the token in the chain and once
it is ready you will simply pass the
request or the filter so now you will
say filter chain. do filter so continue
the filter because this is one filter go
for the next filter once it is done and
by doing this you'll pass to objects
request and response and done so filter
work is done so the JWT filter it will
valid the token it will uh create the
authentication object it will pass it
next so now it will we not we don't have
to pass the username password now if
you're thinking this is done uh not
exactly what is missing now is this if
you go back to your jbu service we do
have two methods which are empty you
need to make sure that this is completed
now of course we can type the entire
code here but then when you want when
you got a token and when you want to
extract the usern name it's not a simple
process we have to decode it we have to
fetch the claims from that we have to
fetch the username for valid token we
have to do M lot of steps you have to
check for the expiration time uh you
have to check if the account is not I
mean lot of things are involved right so
we can do that here but I what I want to
do is I just want to copy paste so that
we can save some time so basically this
is the thing we do so I will explain the
code to you don't worry okay so this is
the code which you have to work with so
if you can see if you go up this is what
we have done before but now we are
saying that you have to extract the
username now to extract the username
it's not just extracting a username
right first you have to get the claims
because username is is a part of the
claim and that's what you can see here
so we we creting a method called extract
claims in which you are passing the
claims and you're passing the token now
in this extract claim basically it will
fetch the claim it will extract all the
claim and that's what we are doing here
extracting the claim with the help of
signing key because you have to also use
the key to do that and we are fetching
it here in the claims and that's what
you are returning it here so from that
you will get the username so you can see
from the claim we getting the subject
and if you go down we are also we also
have a meod called validating but for
validity of course you have to check if
the token is expired or not and that's
what we are doing here so it's checking
if the expiration time is before this
then it will give you false otherwise it
will give you true and uh I mean of
course it will return true if it is
expired then we have to check it should
not be expired and this is how you're
extracting the expiration time so
basically what you're doing is you are
fetching the claims I pasted this code
because it's more redundant code and
you'll be doing it only once that's why
you pasted it important point to observe
there are few changes from the last time
I did this so first of all let me just
import claims that's one and import this
function type and one more change they
have done some changes in the new
version so the code is for the older
version uh for the new version they have
made some changes the first thing they
did is if you go to pass a builder
there's no passer Builder so jws has a
it's a class and it has a method called
passer and then this passer has a method
so if you can see earlier we used to use
set signin key but now we have to use
something called it's verify with so in
of signing key we have to say verify
with uh but it takes the type of secret
key not the key because get key gives
you key so what I can do is I can just
change the type of it and this should
work so I will use secret key here so
that it will not give issue here so
remember this we have to make one change
uh in the get key you have to return
secret key now depend upon which version
you're using so if you're using the uh
version which I'm using then you have to
make this changes so anything before
this works perfectly for the earlier
code but since I'm using 0.12 and
anything after that you have to make
these changes so go back here to the JW
service okay there's also change in the
past claim so I will first of all do
enter here so in of past claim they they
made some good changes so now it is
signed claims because it makes sense
because it is already signed instead of
body they now call it as a payload and
how will you know all these things if
you go to the method documentation you
will see what they have replaced it with
again that code will work it's just that
it's good to go for the new versions a
new code don't go for dicated methods
and that's it that should work and where
you will find this code you will you can
check the description uh you will find
the link for the GitHub repository if
not there let us know we'll put it there
and now after making these changes I
hope this will work and if it it works I
will tell you the entire flow what we
are doing I hope nothing is null nowhere
okay cool so this got restarted and we
got an error it says okay I
think no filter we are using Auto but
this itself is not a component
component that's what it says Okay so
let's make this component just restart
and there's no error let's go back to
postman first of all let's do the login
so I will click on this and okay we got
the token though there's no problem with
the token I will just copy this and now
when you are sending a request for the
students you don't have to pass of
course the body is not import body is
important maybe you're getting the
you're getting it right so we don't I
have to pass the data uh in the
authorization we have to pass the token
we are not passing username password now
click on send it worked you can see it
says okay so what is happening behind
the scene let's go with the flow again
the first thing you're doing is you are
generating a token now who is
responsible to generate token if you go
back to your security config we are
saying that the authentication manager
now this time we have a hold on it and
we are creating something called login
form so if you see user controller we
got something a login and inside this
login we are doing verify and in verify
we are using this filter to achieve that
so once we got this we are generating a
token so once it is verified the user
ified we are generating a token right
now in this token generation what we are
doing is we are doing all those step
building a token with the help of claims
we are signing it where it's here we are
signing it we have subject issue date
expiration after doing all those things
what you get is the token right now next
time when you send a request you are
sending a token now since we are sending
a next new request and in that request
you are not passing username password in
that case you have to mention hey you
know don't go for username password go
with the jwd filter now what we doing in
filter is in the filter basically we are
saying that uh first of all get the
token from the user or the request check
if the token is not empty or token
starts with the better if it is there
get the username get the token get the
data from the database based on what
username is you are passing and verify
if the it is matching or not if it is
matching of course you have to write a
token if it is matching you have to
create a new authentication object and
you have to set that in the context once
it is done you through because in for
the next filter you have specified that
I do have the authentication but there's
one problem in the validate token we
have to actually validate token and to
do that you have to extract the username
to extract the usern we have to extract
the claims and to extract the claims lot
of steps are involved right so yeah
that's what we have done in the entire
flow and by doing this uh all this thing
have been done now you know what is
sping security now you know how to
generate a token how do you verify the
token now you can make your application
secure so I hope uh this all these
things make sense uh we'll try to
implement this in our project which we
are building and maybe it will take some
time see you in the next video till that
point keep learning bye-bye
Ver Más Videos Relacionados
Learn JWT in 10 Minutes with Express, Node, and Cookie Parser
Adding JWT Authentication & Authorization in ASP.NET Core
NestJs REST API with MongoDB #4 - Authentication, Login/Sign Up, assign JWT and more
#32 Spring Security | Custom Configuration
#36 Spring Security Project Setup for JWT
Spring Security explained with no code
5.0 / 5 (0 votes)