in this video you're going to learn pretty much
everything you need to know about JWT using Spring Boot 3 and Spring Security so about three weeks ago we posted a crash
course on Spring Security 6 and there was a lag with JWT section so we decided to re-record the entire
section and actually make it so extensive this crash course right here is brought to you by Alibou
and is the one that led the spring security so go ahead and subscribe to this Channel show some
love because it's going to be bringing you awesome content like this from time to time security
is a must when designing and building apis and it's really important that you understand Spring Security and JWT so
that you can secure your apis before we crack on literally just take one second and smash the like
button also if you're new to the channel subscribe and if you haven't joined the private Facebook
group as well as Discord go ahead and join because the community is growing going and we're waiting
for you so without further Ado let's kick off I just want to say that you can grab the entire
source code and the description of this video so that if you have any issues or you want to
take what you learned from this course and then apply it within your own API you can do
so feel free to clone the repo and yeah just just use the code as you intend and if you
have questions regarding JWT literally just ask on the community and someone within
the community will be able to help you before we start the implementation process let
me first explain to you how this JWT validation mechanism works the whole story starts when a
customer and a client send an HTTP request to our backend system which is running using spring boot
container run running on an Apache Tomcat embedded server so just a reminder for you the first thing
that gets executed within a spring application is the filter so anytime and each time you create
a filter just notice and remember that it will be the first thing that gets executed within
our application so in this case the first thing that will be executed is our JWT authentication
filter and this is only a once per request filter and has the role to validate and check everything
regarding the token or the JWT token that we have so now let's start the process the first thing
that will happen we will have here an internal check to check if we have the JWT token or not
so if the token is missing as we can see here we will send a 403 response to the client so
and the reason is this missing JWT all right so now we have our GWT token and then after that we
will start the process or the validation process so this validation process will start in this
way so the filter like the internal execution will first make a call using the user details
service to try to fetch the user information from the database and this we will base on
the user email that we will set as a claim or a token subject that we will extract within
this JWT authentication filter so I repeat again this JWT authentication field will check the
JWT token extract the username or the email or we call it the subject when we talk about JWT
tokens and it will use that email to fetch the user details information from our database okay
so this is the first call then once the user is fetched we have the response from our database
and the response can be either way can we existing user or non-existing user okay so once we get the
response to our JWT authentication filter here we will make a few checks which is if the user does
not exist we will also send a 403 to our customer in case everything is fine and we get our user
from the database we will start then a validation process so this validation process because the
this JWT token was generated for a specific user so we want to validate this token based on the
user and here we have this validate JWT process or mechanism which will try to call a JWT service
and this JWT service will take as parameter uh the the user itself and also the token or the
string token or the JWT token call it whatever you want after the execution of this validation
process here we have two case scenario so the first one the token is not valid so it's not so
for example the token is expired or the token is not for that specific user so what we do we will
send also a 403 back to our customer so and the reason will be this and valid JWT token otherwise
what will happen we will call or we will update the security context holder and set this connected
user because when we fetch the user details information from the database we will be able to
set this security context holder so we will tell spring or we will tell the set of the rest of our
filter chain that this user is now authenticated and we will update the authentication manager so
every time we check if this user is authenticated for this request the answer will be yes once the
security context Holder will be updated it will automatically dispatch the the request and it
will be sent to the dispatcher servlet and from the dispatcher servlet it will be sent directly to
the controller we will do all the execution that we need to do for example calling the service
going to the database and so on so forth and then we will send back the response for example it
can be a JWT and it will be a HTTP 200 or whatever any process that will get executed within this
controller so this is how JWT authentication mechanism works now let me show you how to
implement this and how to realize these steps let's first start by creating a new spring
boot project to do so the recommended way and the weight I also recommend is going is going to
start.spring.eu which is the spring initializer and create a new project from that so first of
all make sure you will use Maven this is what I will be using in this video and tutorial then
we want to use the recent version of spring boot which is now 301 okay and also here make sure
you select Java 17 because the minimum required version which is compatible with spring 3 is Java
17. next select the jar packaging and now let's fill this project metadata so for the group
ID I will call it com.alible and the artifact I will call it security okay so I will leave
the rest as it is and now I will move on and add some dependencies so first of all we need
the spring web because we want to expose few endpoints we need also the security and this is
the main object of this video and then we will need GPA or spring data jpa because we need
to manipulate and interact with the database then we need a post degree SQL driver to connect
to post degree SQL you can also use any other SQL database like MySQL or Oracle or whatever finally
we want to use lombok to reduce the boilerplate code so now we have our project ready we can just
go ahead click on generate and start decoding as I mentioned before we will be using post degree
SQL or as a database for this application so let's first start by configuring our data source for
that I will be using ntdj and I will use this database tool so this one is available only with
the ultimate version otherwise if you don't have the ultimate version just make sure you install
post degree SQL and you can use the PG admin or you can use the dbiver tool to connect to any
data source okay so let's start with that click on here and then we have this class icon so
click on this plus icon and then we want a data source and then filter for post degree SQL
click on that and to be able to connect so make sure here if this is the first time you will have
instead of driver post degree SQL you will have a link or you will have a button here to download
the driver so just go ahead and click on it and download the driver next the host is localhost
because it's the local one and the default port for post degree SQL SQL is 5432 then if
you create when you created your post degree SQL did you made or did you choose a username and
password if yes so just go ahead and specify them here so for me for the purpose of this tutorial
I made it Amigos code and for the password it's just password okay and then once you fill all
this information just to check if everything is working fine click on this test connection
and make sure you get this succeeded otherwise just check your configuration all right so now
everything is done I will go ahead and click on OK and the first thing that I will do is
I will create a new database so right click on this data source new and then database so I will call it JWT security and then hit OK so the first time it will not be
automatically shown so just click here on this 2 of 8 the number the numbers May might change
from one laptop to another and here I want this JWT security okay so open it in here and here we
can see that we have zero of three schemas just select the public one because this is the one we
need and this is where we will find all our tables once we create them so now we have our data source
available let's move on to the next step foreign now let's establish a connection between our
application and the database we just created so the first thing to do is go here to this
application properties and rename it and use the representation yaml okay so this is what I prefer
personally and you can keep properties if you want to but to better follow this tutorial it's better
to transform it to yaml so in order to connect to a database we need to provide a bunch of
properties right here so we will start with spring and then data source and one of the of
the things that we need to provide at first is the URL and this one is a URL of the
connection string to our database if you don't know it just go here to this database click
on it right click on the the connection you just created properties and you copy this one
you copy this part right here it's gdbc colon post degree SQL and then the address Port
slash the database so let me close this I will just paste this one and make sure
here you you write the correct database name so for us we call the JWT security now
we need to provide the username and password okay so for my case it's empty make sure you
provide the correct one and here it's password so next property is after providing the
data source information we want now to give some other GPA properties okay so
here it will be jpa and then hibernate and here I want to tell spring what
to do at the at the startup or update application startup and this property is
the ddl auto and here we have a bunch of options so we have create drop create non-update
the end validate so I will be using the first one because every time I want to start the application
I want to create a new database a new schema and when I stop the application I want to destroy it
okay so I always want to start with empty database all right so the next one within JP within jpa
like you see now you need to really pay attention about the indentation right here because this one
the CTL Auto is part of the hibernate and the one I will write right now is part of jpa so it's
spring jpa and then show SQL I want to show SQL when when we perform or when spring data jpa
performs um a query I want to see that gray okay I want also to add some other properties so here I will type properties and one of these
properties and here I have hibernate and within this hibernate I
want also to format the SQL so format SQL and true I want my queries to
be formatted now go back to the same level as properties and provide some information
about the database so here we want to tell jpa which database we are using and for this case
we are using post degree SQL and then we can also provide the database platform that we are using
and this will help spring performing and writing the better queries to to suit our post degree SQL
database so for this one it's org dot hibernate dot dialect dot postgre SQL dialect all right and here we just forgot one property
right here which is the driver class name so this will help a spring to detect or use the
best driver class name and here we are using post degree SQL so and 3dj will automatically
propose it to you otherwise it's the org.post degree sql.driver and this is the one that we
got from the post degree SQL driver dependency all right so that's it about this configuration
let's move on and start implementing our security when we talk about authorization and
authentication we mainly talk about users so let's go ahead and create our user class
so within the Java package and within the main package that we have right here right click and
new class and here we can create a package and a class at the same time so the package I will
call it user and here I will just call the class user so user.user will create a packet user and
inside of it it will create a class user all right so this is our user class let me make this one
full screen and now I want to write a bunch of properties within this class okay so my user has
the the following characteristics or the following Fields so first of all I want to have an integer
ID and then I want to have a string first name and private string last name and also of course we need an email and password
for this user to be able to authenticate and connect to our application so here I will
add email and also private string password so these are the information about our user now I
will add a bunch of loanbook annotations in order to reduce the boilerplate because you know
when we create a class we need Getters and Setters we need Constructors we need also the
design pattern Builder to build to be able to easily build our object and so and so forth so
let's start with that so we will need the date annotation and this annotation will provide us
with is the equivalent of getter Setter as you can see here so it generates Getters for all fields
for useful method methods to string and so on so forth so it's the equivalent to the getter Setter
required as Constructor to string and equals and hash code okay also I want to use the Builder
annotation so this Builder annotation will help me build my object in an easy way using the
design pattern Builder okay and also I will need the no arcs Constructor and of
course when we talk about design pattern Builder we need always the all construct the
or arcs Constructor okay so let's add this one and like this we have our we have our user
class now let's make this user class an entity to make this user class an entity so the first
thing we need to add is this entity annotation and since we are using the Springwood 3.0 here make
sure that the package is jakarta.persistence and it's no longer Java x dot persistence so this also
will help you tell if you are using the correct version of springboot okay so here we need the
entity annotation and because this username this user class is already reserved for post degree SQL
because post degree SQL already has a table called user so we cannot create a second table called
user I will use the table annotation right here because you know the table annotation if I do not
provide if I don't provide any name right here it will take the entity or the class name him as a
default name for the table okay but here I want just to call it underscore user to avoid this
ambiguity between this user class and the one with and the one with post degree SQL so now this
is kind of sufficient to tell that this user class now is an entity but we still need to provide one
small information okay so here we have this error right here we see that this persistence entity
user should have a primary key okay so we need to add and add an ID attribute which we already
have right here but we're still missing this ID annotation so this ID annotation it's coming
from the jakarta.persistence and it's telling that this ID is the unique identifier of this
user class now I want also this ID to be Auto incremented or Auto generated so every time I want
to create user I don't need to provide this ID and every time this ID is null I want it to be Auto
incremented by the system or by Spring data jpa so to do so and to make it in an easy way
I will use The annotation generated value okay so this generated value it will make this
ID or this object Auto generated using whether a sequence a table and so on so forth and we
call this strategy so for this strategy we have we have several options okay we have Auto identity
sequence table and uui ID so the auto is the default value identity means that it would use an
identity number like an auto increment sequence means that we will create a sequence within our
database and use this sequence to increment each time the value of the ID the table this means
that we will create a table and the database and we will call it by default it's called hibernate
sequence and this table will always be requested and queried by a spring data jpa to get the last
value and increment it for the last one the uuid is using this one I think you know it from from
the Java Java utils but if you leave it to Auto if you leave the generation type to O2 hibernate will
try to detect the best suitable option for you for example if we are using post degree SQL it will
pick by default sequence if you are using MySQL for example it will pick table because my SQL
does not work with sequences so it will it will pick table for that so for the moment I will just
keep it empty like this because as I mentioned the default value is auto so it will be automatically
detected okay so now we have our entity let's try to start the application and make sure that
we have our table created within the database here enable The annotation processing for lombok
and now we have our application started let's have a look quickly on the logs and here we
see that create sequence user sequence start with one increment by 50. this is automatically
generated as I mentioned and here we see the SQL that we have create table user with an ID
email and so on so forth okay and here we have Spring Security is auto generating a security
password and this one we will see later on okay so also if you want to check you can open your
database right here click on this one refresh it and within the public schema we see that we have
this user table right here and if we open it we will see the ID or the attributes
attributes that we already provided when Spring Security starts and set up the
application it will use an object called user details and this user details is an interface
that contains a bunch of methods okay and each time you want to work with Spring Security you
need to ensure that you are providing this user details object in order to make a Spring Security
life easy to use okay so to do this for us for our user I recommend this way so every time
you have a user think always to make it or to implement user details interface so like that
your user or your application user is already a spring user if we may say so okay so to do
that just go ahead to the to this user class that we created and Implement an interface called
user details okay and this user details is from the package.org.spring framework security core
user details okay click here and now it will ask us to implement a bench of method so click
on this one Implement method and we see right here that these are the methods that we want
or that we need to Auto generate okay not Auto generate but we need to implement so it's get
authorities username and we have this Boolean methods account expired logged and so and so
forth okay so just go ahead click OK and we will see how to override but before that I want to go
a bit a bit uh more into details about this user details interface so I will open the definition
download the source so we can easily see it so here if I click on this icon right here to
see all the implementation of this interface we have this mutable user mutable user details and
so and so forth and also we have our user class the one that we created and we can see also
that we have this user from Spring framework security core user details and let's have a look
on this one okay so this user detail contains the username password authorities and the bunch of
booleans the account expired locked non-expired and enabled or not and this information or these
uh this attribute spring will use automatically to play with authorization and authentication
and for example if we can rely on this account non-expired but if we want to have some expiring
dates or use the user can expire and also if we want to lock and unlock the user or the same if we
want to work with credentials and so and so forth okay so I will I will give you the the time to
play and check this and here we see that we have a bunch of Constructor and we have these methods
that they need to be overridden right here okay so here we see that this user already implements user
details so for you you have two options whether you implement this user details interface within
your user class or you can create for example a user you call it app user and then extend the user
the one from Spring boot so it will be the same but for me I want always to have control over my
object so I create my own user class and Implement user details so now let's go ahead and implement
this methods okay so here the first one is we need to provide a collection of granted authorities and
already the method is called get authorities so these get authorities will return or should return
a list of roles like let me explain it like that when we talk about roles so here we need to add
a role okay so I will do or I will create a role and this one it will I will create
any num for it and I will call it role and this let's create this class and here you can
choose the option create a num role hit OK and we want to create it within the same package and
within this rule it's so easy I will just user and admin okay so we we want to have only two
roles within our application so now we have this Rule and because it's an enum we need to add
this enumerated annotation and this enumerated annotation is to tell spring that this is an
inam and we want to use it whether the in-am type uh ordinal or string so by the way by by default
it's original means it's a zero one two and so on so forth string it will take the string value
of of the of the inner okay so let's go back to this get authorities so in here because um with
our design we said or we decided that user can have only one role so I will just return a list
dot off and here I want to return a new simple granted Authority okay so the object that I want
to return is called Simple granted Authority and here I want to return the role dot dot name okay
so the role is referencing this role right here next one is this get user name so the username
for us is our username so it's the email okay then we have this account not expired so here
we have this is account non-expired here make sure and be careful it's non-expired false this
is the negation so non-expired should be true otherwise we will not be able to connect
our users so non-expired not locked and non-credentialed on expired and if the user is
enabled false and here I want to make it true here there is one thing that I need to mention
right here so within this method let's go back to this user details interface we see that
we have this get password okay but this get password was not uh was not overridden right here
because we have this string password right here and we have The lombok annotation so we have
already the method called get password but here if I just name this one we see that we will see
that here we will automatically tell that we want to override this method okay so let's override
it just to be to be more visible or like better visible for you I will rename this one to password
and here for this password I will just return my my password okay so I just wanted to mention this
one so in the next time or like when you have a different name for this password field you don't
get surprised when you see this get password or when you have this password exactly like that and
you don't see it so now you know the reason why okay so now we have everything we need
within our user details so we created a new role and we overridden or we defined all
the methods that are required by Spring Security now our user is ready so let's move on and create
a repository for that user class so the repository is the class which is responsible to communicate
with the database so when working with spring data GPA we don't need to create a class all we need to
do is create an interface and let's call it user Repository and this user repository to make it a
repository all we need to do is to extend another interface called jpa repository okay and as you
can see here this jpa repository is from Spring framework data jpa and so on so forth and it's
a generic interface that takes a t so which is the class and an ID which should be the ID of our
user class so let's use this one and pass these types so this the user and we used integer
as an ID so let's pass integral right here okay so now our repository is ready and as you
know the spring data jpa has also a bunch of methods or ready to use methods like save find
all find by ID and so on and so forth okay now I will create one method that we will need later
on and this method will will try to retrieve or find a user by email because email is unique so
we need to find or we need to fetch a user by its email all right so I'm gonna create this
optional user and like optional is a generic type so it's an optional off user and here I
will use the query method provided by Spring and I will use the method find by and here
all you need to do is providing the attribute or the field name that you have within your
class so for our case it's email for example if you use username just find by username and
here all I need to do is to pass string email all right so this is it now we have our repository
ready to use let's move on to the next steps when we when we check again our schema right here and
the architecture that we have right here so we see that the first thing that we will get or
the first thing that will intercept our HTTP request is the JWT authentication filter
so let's go ahead and create this filter so here within our base package
right click right here new and I will create a new package I will
call it config so I want all this to be part of my configuration package and I
will create a JWT authentication filter I will call it like that so this is our
authentication filter class and now in order to make it a filter we have multiple options okay
but here as we can see in this schema right here we have the we want this filter to be active every
time we get a request so every time the user sends a request we want our filter to get fired and do
all the job that we want that we wanted to do okay so this one we need to extend a class called once
per request filter and as the name indicates it's it will be a filter by one every request so let
me download the data source and you can see here once per request filter extends already generic
filter bin and this generic filter being already implements the interface called filter so for us
we had two options whether using or extending this once per request filter or implementing the filter
interface right here so it will be the same but let's use something already provided by spring so
it's better to use the ones per request filter so now let's implement the methods and we see
here that we have a method called do and filter internal and we have three parameters to
request the response and the filter chain let me explain each part of it I will just align these
parameters right here so you can see all of it so these are our parameters so here we what
we have we have this HTTP servlet requests the response and the filter chain so the request
is our request and the response is also our response so we can intercept every request
and make and extract data from for example from the request and provide new data within
the response so for example if I want to add a header to my response we can do it using this
once per request filter okay and the filter chain is the chain of responsibility design
pattern so it will it contains the list of the other filters that we need we need to execute
so when we call this filter chain dot do internal filter or do filter it will call the next filter
within the chain so here I want just remove this uh These Warnings so because this uh these
three parameters they should not be null and to do so I will just add this non-null
annotation the one from springframework.lank and I'm gonna copy paste it and move it and
put it in here okay so like this we no longer have this warning and now the last thing to do
before moving on and start implementing this the last thing to do is we need to tell spring
that we want this class to be managed bin okay or to become a spring pin and to do so we need
to annotate whether with service annotation or component annotation or also repository it
works because three of them are the same annotation the repository and the service
they both extend the component but I will just make it a component right here and also I
will use another long book annotation which is the required RX Constructor and this required
arcs Constructor it will create a Constructor using any final field that we declare right here
so for example if I use if I do private final string my string this annotation it will create a
Constructor using this private final field Okay so now we have our filter ready to use let's
now start implementing it part by part from this diagram right here we see that
the first thing that gets executed or the first thing we do within this JWT
authentication filter is checking if we have the JWT token okay so
let's move on and implement this all right to do so within our method do
internal filter let's try to perform some operations okay so first of all I will create a
string I will call it authentication header all right why because when we make a call we need
to pass the JWT authentication token within the header so it should be within a header called
authorization so what we need to do here is create is try to extract this header okay so this
authentication header is part of our request and from the request we can call a method called
get header and within the header we can all we need to do is to pass the header name so our
header is called authorization like that so this is the header that contains the JWT token or the
bearer token we call it also computer token okay all right so now I will create another variable
let's also make it final string I will call it JWT or JWT token call it whatever you want so here I
want to implement this check that we did before so we we talk about here we talk about this check
JWT token so let's go let's implement this so here the test that I want to do is if the author
authorization header is null so I want to do an early return or if not my authorization header dot
starts with because as I told you the build token should be always or should start always with the
keyword beater Okay and it should be exactly like that and then we have a space so if we don't have
these two conditions all I need to do is call the filter chain dot do filter and I need to pass
the request and the response to the next filter okay and here don't forget to call the return
semicolon so we want we don't want to continue with the execution of the rest of that one okay so
here this is the check that we that we implemented now let's try to extract the token from this
header okay from this authentication header the next step is we created already a JWT
variable now I want to extract this token from my authentication header or from my
authorization header and I want to do a substring starting from the position number seven
and why position number seven because if we count this beer with this space the count is seven okay
so let's move on and check what we need to do next after checking the JWT token what we need to do is
to call this user details service to check if we have the user already within our database or not
okay but to do that we need to call a JWT service here to extract the username all right so let me
show you what we need to do so right here I will just go back and create a final string username
or email call it whatever you want so I'm just gonna call it user email okay to be consistent and
avoid confusions so I will call it user email so after extracting the JWT token what I need to
do is I want to extract also this user email so this user email equals and here I will add a to-do extract the user email
okay but to do so I need to extract it from let me add it here from JWT token so to extract
for this user email from the token I need a class that can manipulate this JWT token okay so
let's try now to implement this class this class I will call it here I will just create my class
here private final I will call it JWT service so I don't have yet this JWT service but
within this JWT service what I want to do here I want to use a method that I will call
it for example JWT dot extract username okay so let me call this JWT service Dot extract
user name or user email okay let's keep it username within the JWT because mainly with
Spring Security we talk about user names and to extract this one I need to pass the JWT as
a parameter okay so um I will create this class now I will ask antherity to create this class
JWT service and I will create it you can keep it together with the config with the config package
or you can move it to a different one so I will keep it within this package and also do not forget
to add this service annotation to make it or to transform it to a managed beam all right so now
I will just create this extract username method so create method extract username in JWT service
and yes this is what I want to do I need a method that will return a string username and
it takes as a parameter string token or string JWT okay so let me call this one token
I think it would be better as a name and yeah that's it so I will just return null for the
moment and let's move on and I will show you how we can how we can implement or how we can
extract this information from our JWT service so now in order to be able to manipulate JWT
tokens generating one extracting information from the token validating the token and so on so
forth we need to include new dependencies within our application so let's go open our pom.xml
file and here within this pom.xml scroll down and go next to the lombok or post degree SQL
dependency and here just add a new dependency and this is the first one called jjwt API
API and it's from a i o just dot Json web token okay and the recent version at this
time is the 0 11 5 so let's use this one we need also to add another dependency
which is also from the same artifact uh from the same group ID but it's a different
artifact so we need a jjwt implementation so it's called jjw WT amp and from the same group
ID also the same version you can extract this version too uh to a property and use it from there
and next we need a final dependency which is the jjwt Jackson okay so also from the same group ID
and the same version too now once we add or once you add these dependencies or any dependency
to your palm.xml or if you make any updates to your pump.xml make sure you click this button
load Maven project but also if you don't see this button just right click inside the bomb.xml
file Maven and then you have the option reload project Okay so until DJ will download all the
dependencies and add them to the to the class path all right so our dependencies are ready to use
now we will go back and implement this JWT service so before we go and Implement all the services
and dive too much into the code let's first try to understand what is a JWT token so a JWT token
stands for a Json web token which is a compact URL save means of representation of representing
claims to be transferred between two parties the claims in JWT are encoded as Json object that is
digitally signed using a Json web signature okay so the JWT consists of three parts so here we have
the header we have the payload and also we have the signature so the header typically consists of
two parts the first one is the type of the token which is JWT and the sign-in algorithm being used
such as for example hmac or sh-250 256 or RSA okay the second part of the token is the payload which
contains the claims claims are statements about an entity T typically the user and additional data
so as we can see here we have the subject we have the name we have this IIT we have we can have
also extra information like authorities or extra claims right here okay so there are three types
of claims registered public and private claims the registered claim claims are a set of predefined
claims which are not mandatory but recommended to provide a set of useful and repeatable claims
some of the registered claims are is are ISS or the issuer we also have the subject the the odd
the X exp like the expiration time and so on so forth this we will see when we will implement the
token Generations okay we have also the public claims which are the claims that are defined
within the Ia and a Json web token registry or public by Nature private claims are custom claims
created to share information between parties that agree using them okay the last one or the third
part of the token is the signature which is used to verify the center of the JWT is who it is
claims to be and to ensure that the message wasn't changed along the way okay so now let's move on to
the code and see how we can generate or how we can extract claims from this JWT token okay so also
within this jwt.ao website you can play with the payload you can add some information here and as
you can see everything you add some every time you add something you see that it changes right
here okay let's move on and go back to our code now before start implementing this extract
username method I want to implement or write some code to extract all the claims and also another
method that allow us to extract one single claim okay so first of all I want to create this method
I will it will return a claims and this claims if you if you see right here when you click on import
class it's the one from io.jsonwebtoken.claims it's the dependency that we just added so this
claims I will call this method extract all claims okay so this extract all claims of course
it will take a string token as parameter and now I will show you how
to extract this so to do it we need to return our jwts and this jwts is also
from so this jwts is also from the io.json web token and we need this jwts.pars Builder and in
order to pass this Builder or the patopars the token and here we need to set the signing key okay
set signing key because as we mentioned before when we try to create to generate or to decode
a token we need to use the signing key so I will here just let cook call this one get sign in key
and I will explain it later on we will implement this method and then we need to build because
it's a builder and once the object is built we can call the method parse claims JW jws okay so
this one this method pass claims jws so we want to parse our token and once the token is parsed
we can call the method get body okay so within the get body we can get all the claims that we have
within this this token right here all right so now before we implement this signing key method
which should return a key as you can see in the definition here so this one let's first understand
what is a signing key okay so in the context of Json web tokens a signing key is a secret that is
used to digitally sign the JWT the signing key is used to create the signature part of the JWT which
is used to verify that the sender of the JWT is who it claims to be and ensure that the message
wasn't changed along the way so we want to ensure that the same person or the same client that is
sending this JWT key is the one that claims who to be okay so the signing key is used in conjunction
with the sign-in algorithm specified in the JWT header to create the signature the specific
sign-in algorithm and key size will depend on the security requirement of your application and
the level of trust you have in the signing party okay so here in order to do that first of all
we need to go ahead and generate a new token or a new signing key or a secret secret key okay
so uh to generate this secret key we can do it online because now we like for security reasons we
need at least or like the minimum assigning key of size 250 six okay so and in order to generate a
key so you don't need to worry about this there are so many tools and online tools to to do this
so here I will just go ahead and create a private static final string I will call it secret key and this secret key equals the value that I will
generate right now okay so now go to the browser and navigate to this address which is all
keysgenerator.com and then slash random slash security encryption key generator a DOT
aspx okay and we have here encryption keys and here we have also the security level so as I
mentioned the minimum required for JWT tokens is 256 bit okay and then click on this checkbox
yes that the eggs make it check it and make it yes so we can get this x x secret key okay so
if you need more security just go ahead change it and do like you can go even up to 4096 bits
okay but for now for the sake of this tutorial I will just make it or leave it to 256 bits okay
now let's go back to our code and paste this code right here or this key right here also we can
you can move it to the application properties and use it from there all right now let's continue
and let's implement this get signing key so here I will use n3j to Auto generate or to create this
method so I will ask him to create this method and this method should return not byte but it
should return a key okay so now to do this first of all I need to create or to make an object or
a variable of type byte I will call it key bytes and this one equals decoders and the DOT base
64 because it's a base we want to decode it on base64 dot decode and we want to decode our secret
key okay so once the secret key is decoded now I need to do just to return keys Dot h m a c
sharp key4 this is one of the algorithms that we mentioned before and all I need to do is
to pass these key bytes right so now we have our get signing key method and we have also
this extract all claims method ready to use now we have extract all claims method ready to
use now we'll go ahead next and Implement another method which will allow me or which can extract
a single claim that we pass okay so I will use generosity for this so I will use a public T it
I wanted to be a generic method and then we call it extract claim and for this claim I need of
course the token the key token or string token and then I want to pass a function the one from
java utils and this function is of type claims and T which is the type that I want to return
okay I will call it claim resolver or claims resolver or claim call it whatever you want
resolver and here it's an it's a simple it's a simple method I will create a final claims
object I will call it claims equals extract all claims from my token okay so first of all I
want to extract all the claims and then I want to do return this claim resolver the function
that I pass as parameter dot apply and as you can see the apply it will take or it will
require a claims T so the claims is the one or the list of all the claims that we have okay so
this is the extract or claims all claims method now extracting any claim from my token will be an
easy peasy test so I will show you how to do that so once I have everything ready extracting all the
claims and also extracting one single claim let me show you how we can extract the username out of
this token okay so extracting a username is easy peasy so it will be extract claim and we need to
pass the token and only we need to pass the claims dot get subject okay so because as I mentioned
before the subject is or should be the email or the username of of my user okay so this should
be the subject of of the token so that's it this is only uh all about extracting the username
let's now move on and try to implement other methods that we will need within this JWT service
class like testing if the token is expired also um extracting the expiration date
generating the token and so on so forth let's now implement the method that will
help us generate a token so the token as you know is a string so I will create a public
string method and I will call it generate token all right so this generate token
will take as parameter a map a map of string and object okay and this map
of string object will will contain the claims or the extra claims that we want that we
want to add okay I will call it claims unlike extra claims I think it's better
to call it extra claims and also I want to pass my user details so here user details
and it's the one from the spring framework I will just call it user or user details all right
so this is the method and here this extra claims is the one if I want for example I don't know to
pass authorities to pass any information that I want to store within my token all right so to
do this it's easy peasy it's just return jwts dot Builder and then I want to set my claims
so these are my claims and those will be the extra claims okay so extra claims and after
passing the claims I need to set my subject so the subject as I mentioned before it
should be my username or user email okay so I will use the object user details dot
get username all right so because for us username or the unique part of the user is
the email but for spring it's always called username that's why we are using username
okay so also we need to set the issued ad means the when this claim was created and
this information will help us to calculate the expiration date or to check if the token
is still valid or not okay so it I will use a new date right here and I will pass just
the system dot current milliseconds okay so this is the the issue the issue date
and I want also to set the expiration date so the expiration date it will be the same a
new date and here like it's up to you to set how long this token should be valid okay so
also system Dot get dot current milliseconds and then for example I want to add let's say 1000 times 60 which is 60 Minutes times 24 so my
token for example will be will be valid for 24 hours plus 1 000 milliseconds okay and then you
can you can decide or you can set any expiration date that suits you okay the final step is to sign
with like which key that we want to use to sign this token and the signing key is the get signing
key method that we already created before and then we need to pass also the signature algorithm
so signature algorithm and then we want to use the eight the hs256 okay so it's this one so let's
select it and then finally call the method compact compact is the one that will generate and return
the token so as you can see this is how we can generate a token out of extra claims and the
user details all right so now this method will um like we don't have a choice but passing claims
and user details but what if I want to pass or I want to use um or I want to generate a token
without having or without extra claims I only I only want to generate a token from the user
details itself so it's easy peasy I will create another one public string I will give it the same name
generate token and the generate token it will take it I will pass only user details as a
parameter and here I will just return generate token out of null or let's say a new hash
map like an empty one and then user dictates okay so now I have this generate token
method that I can use later on okay as a Next Step let's Implement a method that
will validate or can validate a token Okay so I will create a Boolean and I will call
it is token valid all right and this token this method is token valid will take two
parameters as input which is the token itself and the user details why we need the user details
because we want to validate if this token right here belongs to this user details right here okay
so first of all I need a final string username or user image but within this within the context of
this JWT service let's stick to username and this one it would be extract username out of the token
we already have the method for that and then then what we want to do is to return if or whether
the username that we have right here equals the user details Dot get username all right so we
want to make sure that username we have within the token is the same as the username we have as input
okay and I want to make sure is is token expired like I need to check that my token is not
expired okay and I want to pass my token as parameter so this is token expired this
is a method that we need to create so let me go ahead and create this token expired
and let's implement this token Okay so I want for this is token expired I want I will
create a method I will call it extract expiration from the token that we have dot before because we
it's a date so it I want to make sure that it's before today's date okay before new date
now let's create this extract expiration so this extract expiration should return a
date and it has or it passes as a parameter the token itself so it's also easy
so it's extract claim from the token and then it's claims dot dot or Colin colon get
expiration okay so this is how we can extract the expiration date all right so how we have
here if uh the East token expired we have the is token valid we have all the methods that we
need so is still converted this one will use it later on so now let's move on and go back finish
implementing this authentication filter foreign so here we just finished implementing this JWT
validation process or validation service right here and now we want to go back to this validate
JWT process so within our code what we did here we extracted our user name so we have now our
username valid let's go ahead and perform or finish our validation process all right so here
I want to check if my user email is not null so I have user email or I can extract my user
email out of my JWT token and I want to check something else I want to check that the user
is not authenticated yet because if the user is authenticated I don't need to perform again
all the checks and setting or and updating the security context and so on so forth so here I want
to check if the user is already authenticated I don't need to do all this process and so on so
forth all I need to do is pass here and leave it to the dispatcher servlet okay so to do that
or to check if the user is already connected or is already authenticated or not we have
an object called security context holder and from that we can get the context and then
we have a method called get authentication and when the authentication is null means that the
user is not yet authenticated okay so this means that the user is not connected yet all right
so once the user is not connected what we need to do here like when we go back to follow this
process we need to perform and to check or get the user from the database all right so once
we do this validation process we want also or we need to check if we have the user within the
database all right so to do so I will create an object called user details or we you can just
call it user because our user already extends or implements the user details interface I will
call it user details equals and here I will use this dot user details service which we don't
have yet and here we have a method load by user username okay and you and my username
in this case is the user email all right so here the method called load user by username and in this case we don't have this user
detailed service but let's create one here so this user details service is already
an interface within the spring available within the spring framework and it's from
Spring framework security core and so on so forth and I will call it user details service
so this interface if we check it right here so here we have some implementation for it okay
but we want our own implementation because we want to fetch our user from our database
all right so make this one final don't forget this and let's move on and implement
or provide a bean of type user details service at this level we need to create a bean of type
user details service or we need to create a class that implements this interface so and also give it
the service or component annotation so it becomes a managed bean and spring will be able to inject
it but let's do it in a fancy way within this config package I will create a class I will call
it application config so this application config will hold all the application configurations such
as bins and so on so forth all right so to make this class A configuration we need to annotate
it with The annotation called configuration so at the startup spring will pick up this class and
try to implement and inject all the bins that we will declare within this application config all
right we also need the required ice Constructor in case we want to inject something so what we
need to do now is to implement or to create a bin of type user details service and to do so first
of all we need to use The annotation bin this to indicate to Spring that this method represents bin
and a bin always should be public no private means and our bin is of type user details service okay
so let's call it user details Service as easy as that or as simple as that and then we can use
a Lambda expression so we can use or we can say return a new user details service and we implement
the load user by username so we can do like that new user details service like this and
automatically you will see here that we have this load user by username method
the one that we want to use in here this method right here okay but but we can make
it more simple than that and we can use a Lambda expression and the Lambda expression it's it looks
like that so here we all we already see that uh anteriority is proposing to replace this with
a Lambda so we'll just go ahead and click on it so the Lambda is the username so we provide the
username the one we have as an input within this method right here and then we need to provide
the implementation Okay so in this case what we want to do is to fetch the user or to to get
the user from the database and to do that we need to inject our user repository okay so let's
create a private final user Repository let's call it repository or user Repository and here
simply what we need to return is user Repository dot find by email the method that we created when
we just created the user repository and find by email we need to pass the user name okay and since
defined by email returns an optional off user here I want to add an or else throw so in case we
don't have or we don't find the the username or the user within our database we need to return
an exception of type where the entity not found exception or we can also return the exception
username not found exception okay so I will use the username not found exception and I will just
provide here it should be also Lambda and for example as a message we can say user not found
all right so here now we have our user details service so now it's ready to use let's continue
implementing our JWT authentication filter now we can go back to our filter and finish the
implementation all right so here we have our user details or we have our user and the next step is
to validate and check if the token is still valid or not so here I will add the if JWT service dot
is token valid okay and here I need to pass my JWT and the user details that I just got from
the database all right so if the token is valid then what I need to do I need like we have in here
we need if the user is valid we need to update the security context and send the request to our
dispatcher servlet okay all right so once the our token is valid I need to create an object of type
username password authentication token so username password authentication token I will call it auth
token and this object is needed by by Spring and by the security context holder in order to update
our security context okay so equals new username and password authentication token and it takes as
parameter the user details and then for the next parameter for the authorities I want to pass it
as null and then the user details.get authorities so here because we are we don't have credentials
as you remember when we created the user we don't have credentials so that's why I'm
passing these credentials as a null value so once I finish creating or finish instantiating
this user name authentication token I want also to give it some more details so I will use the
auth token dot set details and this details it takes an object so I will pass a new object
of type new web authentication detail source authentication details source and here I want to build the details out
of our requests out of our HTTP request all right now the final step is as we
mentioned here the final step is to update the security context holder so to update the
security context holder it's security context holder dot get context dot set authentication
with our authentication token all right and that's it now like let's recap this one so here
when if we have our user email and the user is not authenticated we get the user details from the
database and then what we need to do we check if the user is valid or not if the user and the token
is valid so we create an object of type username password authentication token we pass user details
credentials and authorities as parameter and then we extend or reinforce this authentication token
with the details of our request and then we update the authentication token and don't forget as
a last step and always do think about after this if think about always calling our filter
chain dot do filter so we need always to pass the hand to the next filters to be executed okay
and here we need the request and the response and that's it about our JWT authentication filter it is ready to use let's move on and
see what we need to implement next this whole process is now implemented
but we still need to do some extra steps the extra step we need to do is to tell spring
which configuration that we want to use in order to make all this works okay so we created the
filter we implemented the user Detail Service validation updating context and so and so forth
but what we are missing is The Binding we need to bind because we created a filter but this filter
is not yet used so we need to use it and in order to do that we need to create a new configuration
class I would call it security configuration okay so I will call this class
security config or configuration and this is going to be our security configuration
class and as always to make a configuration class become a configuration we need to add this
configuration annotation from Spring also because we talk about security right here we
need to enable web security let me make it full screen and again we will need the required arcs
Constructor so these two annotations they need to do they need to be together when we when we
work with springboot 3.0 okay so next whatever what I will need to do because as at the startup
or at the application startup Spring Security will try to look for for being of type security
filter chain and this security filter chain is the bin responsible of configuring all the HTTP
security of our application so I will create a bin public security filter chain I will call it security filter chain and
within this method of this bin I will pass a parameter of type HTTP security I will call
it just HTTP just for a short variable name now let's start configuring our HTTP security
so here as you can see it's type it's of type security filter chain and to do that let's first
return HTTP dot build and here we need to add also the exception to the method signature
because this build might throw an exception all right so now to do the configuration I will
start by HTTP dot I will first disable the csrf um verification and we may we made we might talk
about this in in a different in a different video so here now once we disable this one and
now let's move on or we will implement the configuration the real configuration
So within the security we can choose and decide what are the URLs and the pathways
that we want to secure but of course Within every application we have always a white list
whitelist means that we have some endpoints that they do not require any authentication
or any tokens but which are open for example when we talk about creating an account and logging
so in this case to create an account we don't need a JWT token because at that time we will create
a user account and we will require or will ask for a token after that also the same when we
want to log in we don't need to pass the token as parameter because we don't have one yet so in
this case this is when we talk about whitelisting and here is how we can Implement white listing
so after disabling the csrf I want to authorize HTTP requests and after authorizing after using
or calling this authorized SCP request here we can call a request matcher Dot request matchers
and for this request matches we can pass a list of strings and a list of patterns this will
represent the application or our application patterns we will go back to this later on and
for this list I want to permit all I want all the requests in here all the all this list I
want to permit all okay and then any request all the other requests I want them to
be authenticated so this means I want to whitelist this this list and authorize all the
requests within this list but any other request should be authenticated okay now let's talk about
and let's see how we can configure our session management decision management means what we said
that when we implemented the filter we want a once per request filter means every request should be
authenticated this means that we should not store the authentication State or the session State
should not be stored so the this the session should be stateless and this will help us ensure
that each request should be authenticated okay so now we use the end to add a new
configuration and here let's add Dot session management and here I want to talk about
the session creation policy how we want to create our session so as I mentioned our session we want
it to be stateless session okay so I will use session creation policy dot stateless and like
this spring we'll create a new session for its request and then and here I need to tell spring
which authentication provider that I want to use the authentication provider I will explain it
in just a few seconds okay so I will just add it authentication provider and I will create
an object of type authentication provider and then I will go back and create it later on and
then after the authentication provider I want now to use the JWT filter that we just created okay so
to do that I will use the method add filter before because I want to execute this filter before the
filter called username password authentication filter because as you remember when we implemented
the JWT authentication filter we check everything and then we set the security context we
update the security context holder and after that we will be calling the username password
authentication filter okay so here I will use JWT auth filter I will call it like
that and I want it before the user name password authentication filter.class okay now let's let me create this object so
I will use the oops not local variable but create a field and this one I want it
to be of type JWT authentication filter okay so this is the first
one and I need it to be final so it will be automatically injected by spraying
and the next one is the authentication provider so let's create a field of type authentication
provider and let's make it final too all right so now I have my configuration
ready all I need to do or I need to implement now is this authentication
provider and let's do it right now now we need to provide this authentication
provider bin so let's go to our application config class and let's create a
new bin of type authentication provider okay so for this authentication
provider let me make this full screen so I want to create a bin foreign type Authentication provider oh authentication
provider always from the spring framework package and I will call it authentication provider
and let's start implementing this bin right now so this authentication provider is the data
access object which is responsible to fetch the user details and also encode password and
so and so forth so for this we have for this authentication provider we have many
implementations and one of them is the Dao authentication provider so data access object
authentication provider I will call it auth provider equals new Dao authentication provider
okay So within this authentication provider we need to to specify few Properties or like not
few but just two of them and the first one is the user details service so we need to tell
this authentication provider which user details service to use in order to fetch information
about our user because we might have multiple implementations of the user details one for
example getting the information from the database another one based on another on a different
profile fetching the users from from in-memory database from ldap and so and so forth okay so for
this one we already have our oops we already have our user details service right here so this one is
referencing this method next we need to provide a password on encoder so which password encoder we
are using within our application so if you have a specific one or if you are using specific one
you need also to precise this one because when we want to try or we want to authenticate a user we
need to know which password encoded in order to be able to decode the password using the correct
algorithm okay so auth provider Dot set password encoder and here I will create a method I will
call it password encoder okay and I will create a bin out of it later on so this is the minimum
required information that we need to provide and then all I need to do is returning this auth provider right here now I will just go
ahead and create this password encoder so this password encoder is also should be also
a bin so it will be public and I will give it the bin annotation and for this I just need to return a new
decrypt password encoder and that's it so now I have my authentication provider and
also I created the password encoder bin one more step is needed to finish this application
config class which is the authentication manager and the authentication manager as the name
indicates is the one responsible to manage the authentication so the authentication
manager have or has a bunch of methods and one of them there is a method that allow
us or help us to authenticate user based or using just the username and password and
for that we need also to create a bin or to provide the bin to be able to use it later
on okay so I will create a bin and public authentication manager because this is
the being that I want to to create and I will call it authentication manager and within this mean I want to inject an object
of type authentication configuration okay and I will call it config this authentication
configuration hold already the information about the authentication manager so I will just return
config dot get authentication manager all right so here we are using the default implementation of
springboot and this is more than sufficient for us here don't forget also to add the exception to the
method signature so that's it let's move on and now we're done with all the security
configuration for our application but we still need to provide at least two endpoints
where the user can create an account or also can authenticate and to do so within the
base package I will create a package I will call it auth and within this package I
will create a new controller Authentication controller and this authentication controller will
have two endpoints that will allow me to create or register a new account and authenticate an
existing user so in order to call this or to make this class a controller we need this annotation
rest controller and also I will give it a request mapping and for the request mapping it will be
slash API slash V1 slash auth and also I will need the required arcs Constructor okay now within
this authentication controller I will create two endpoints one for resistor and the other one
for the authenticate so the first one it will be a post mapping and I will give it a register for
the name and here it will be a public response entity and now the type will be authentication
response I will create an object later on for that we will call this method register
and this register will need a request body and this request body I will create an object
called register request which will hold all the requests or the registration information
like first name last name email and password okay so I will leave it empty for now
we will implement it later on I will do the same I will just copy paste
this one and I will create another method but this one we call it authenticate and it
will also return an authentication response but instead of register request we will
need an authentication request okay so it's an authentication request yeah that's it so we have our controller ready
now let's move on and start implementing things let's now create our authentication response so
now just I mean I will use ntvj to create this class authentication response and I will
click create it within the same package so this response is a simple
class that will have only a string token so this is the token that would be
sent back to the to the customer or to the user and to do that we will need this
data annotation we'll need the Builder and of course the all arcs Constructor and
the no arcs constant so that's it so our authentication response is ready let's
move on and create the register request now let's create this register request
class so create a class right here and we will create it within the same package so this register request it will also have
few attributes like private string first name private string last name and also an email and password so we will also need the same annotations as we
used within this authentication response so just go ahead and copy them and put them within this
register request okay so now we have also our object register request ready I will create as
a Next Step the authentication request object finally we need to create this authentication
request within the same package so I will just paste the same annotations and here this
object will hold only two information which is the string email and string password
okay so that's it our object now ready let's move on and start implementing this
author register and authenticate request so for the registration and authentication
implementation I will delegate this to a service so within this auth package I will create a new
class and I will call it authentication Service all right this is the place or the class
where I will Implement these two methods register and authenticate so here I will just give it the service annotation and of
course the required RX Constructor all right so here we have these
two methods I will just move on and here just make a simple call
for for this service methods but first let's inject it okay so I will
need the private final Authentication service I will call it just service right here and within this authentication Service let me
make this full screen now I will just make the return statements for these two methods all
right so here I will return a response entity dot OK and I will call my service Dot resistor
and I will pass this request as parameter okay and I will copy paste this and paste it right here
and instead of register it will be authenticate so here we don't have yet our register and
authenticate method so let's go ahead and create them so create method register and this
one will return the authentication response so this is what we want to return and now we can also create this authenticate
method and the same it should return an Authentication response all right so now
I will start implementing these methods so now let's implement this register
method and this register will allow us to create a user save it to the database
and return the generated token out of it okay so uh for that because we need or we
want to interact with the database and see if the user so the first thing
that we need is to inject our Repository let's call it repository right here and
then what we need to do I want to create a user object out of this register request so I
will create a VAR user equals user dot Builder and here dot build so to build this user out
of this register request so I will have the first name which is request.get
first name same for the last name and same for email so it's email and then the
value will be the request dot get email now for the password as you remember we created
our Bean of type password encoder so for this we need to encode our password before saving it
to the database okay so in order to encode the password we need first of all to inject our
password encoder service so I will do that password encoder password encoder and this I
will use it right here password encoder dot encode and here I have the get password or the
request.getpassword that we will receive within the registration request Okay so here I will
just make a static roll always so I will use a user role and then we call the build method
all right so once we build our user object the next step we need to do is our repository dot
save and we want to save the user that we just created all right and finally to be to return
this authentication response that contains the token I will create a new variable I will
call it JWT token equals now I will need my JWT service to generate that token so I will I
will inject also the private final JWT service and I will use it to create or to generate
the token using this user object right here so JWT service dot generate token the one only
using user details for the moment I don't need to set any extra claims so I will use this
user object to create auto generated token and finally I will return an object of type
authentication response dot Builder dot build and I need to pass DOT token or I need to pass the
token that I just generated okay so this is the register method and now everything is implemented
let's move on and implement this authenticate for the authentication it's it's an easy
peasy so you remember we spoke before about the authentication manager bin and we said that
this authentic and authentication manager bin has a method called authenticate which allow us
to authenticate a user based on the username and password so for that I will inject first of
all my private final authentication manager bin I will call it authentication manager
all right so I will go back here to this authenticate method and to authenticate
the user all they need to do is to call the authentication manager.authenticate and
this authentication manager takes an object of type username password authentication token so
I will pass a new username password authentication token and within this I need to pass the email
so request dot get email and also the password request dot get password and this authentication
manager will do all the job for me and in case the user is not a username or the password are
not correct so an exception would be thrown all right so I'm totally secure when I just
call this method otherwise what I need to do I need to create a user and if the user so
if I first of all if I get to this point right here means the user is authenticated so
means the username and password are correct if both of them are correct so I will just need to
generate a token and send it back okay so I will first of all find try to get the user and find
by email and I will use the request dot get email and here or else I will just throw okay I'll just
throw any exception like it's not so important at this level but for you you might want to throw
the correct exception and you need to catch it handle the exceptions and so on and so forth
all right so now I will just go ahead and copy this code because it would be the same and put it
right here so once I get the user I will generate a token using this user object and then return
this authentication response so now we have this authenticate method and the register method ready
to use let's move on and see what is the next step now we have our authentication controller ready to
use but there is one extra step that we need to do do you remember when we first implemented
the security configuration and we spoke about this white list right here
so what we need to provide now within this request matches that we want to
permit all we need to provide or authorize all the URLs or all the methods that we have
within this authentication controller so go ahead copy the request mapping that you created and for
example here I want to authorize all the methods that I have within this authentication controller
why because based on my design everything that I have in here only uh authentication related
methods so I don't have any business logic methods or endpoints within this authentication
controller so that's why I'm allowing I'm allowing all the methods within this controller so that's
it now let's create a demo controller for that I will create a new controller within a new
package so right click here new class and I will call the package demo and I will call it
demo controller so this demo controller will be also secured so I want this endpoint to be secure
they will copy this this annotations right here paste it here and so this one will be
demo and let's call it demo controller and now I will create just a
get mapping a simple method that public that will return a simple string
okay response entity of type string say hello for example and then
I will just return a response entity.okay and with a body hello from
secured hello from Secret endpoint and that's it now let's go ahead start
our application and test these changes foreign let's start the application and make
sure that all the code that we wrote together is working fine so go ahead click on start
and let's see what we will have in the console so let's make sure that everything is fine
so as you can see here from the logs we no longer have this auto-generated password by Spring
Security and we have here that we are creating the sequence and we have the table user gets created
and the application is running correctly okay so now let's start our Postman and test this endpoint
so I have my Postman started right now so I will use this end point within a get request so the
endpoint is localhost and my port is 8080 slash API V1 demo controller is the same one that I have
right here within my code it's demo controller and now I will click on send we see that we have no
authorization we have nothing in here so I will just go ahead and click on send and normally
like the expected behavior is this end point should be secured okay so when I click on send
we exactly can see that we have a 403 Forbidden means that we are not allowed to access this
endpoint okay next we have our two endpoints the authenticate and the register so let's first
start with this register endpoint or let's before that let's start with the authenticate and
for the authenticate now we know that we have no user within our database we can also
double check that at so if I open let me close the other tabs so here I don't have any user
registered then within my database okay but now if I try to connect to or to authenticate a
non-existing user I also expect to have a 403 as a response and this is what we see right here so
it's 403 Forbidden and the user is not allowed to access this endpoint and this why because we
have here within our schema so we try to check and validate everything even if the endpoint uh
even if the end point is secured so we we get into this authentication filter we validate everything
but once we get to the user details we don't have the user in the database so in that case we will
send back a 403 to our customer okay so now let's create a new user so I will register a new user
so I give it alibu as a first name alibu last name and alibuatme.com and one two three four as
a password so now when I click the send button I should get generator token or a JWT token as a
response so this is what we see right here so I will just copy this token and I want to decode
it and let's see what we have within this token so let's go back to the JWT dot IO website and
paste the generated token in here so we see that we have the algorithm here which is the hs256 the
one we use to generate this token and we have our payload so we set already the subject to the
to the user email and we have the issued at so the creation date and as you can see in here
it was created December 29 and 1414 and this one will expire at in 24 hours okay so uh this
is our generated token let's go back and test the authentication right now so we see that the
register is working but let's ensure that within this same username and password we are also able
to get a token or to generate a token so this is the same email and the password that we have
and if I click on send I should get the token but let's first try with a wrong password so when
I click on send so here we have our 4403 and here it's because of this process so we have the token
and then we start the validation process so we extract the username and password and then we
are calling the user details service to try to fetch the user from the date database and the
user we got it because the user already exists but when we move to the security filter chain
and use when we move the security context holder we will try also to use the authentication
manager to authenticate that user using the password and the user made that were provided
within the request but this password is wrong so that's why we are also throwing throwing a
403 as a response okay so now let's test with a correct password so if I click on send I see
that I have my JWT token I will copy this one and then I will go back to this get method
I will click again and make sure that it's always 403 and how we can authorize this
request right now so within the authorization here within the type click and choose Bureau
token all right so remove or delete if you have something in here and paste the token that
you just copied Okay now click on send and we see that we have the message hello from secured
endpoint and we have this 200 okay which which is compatible with all this process so we have
the filter we validate everything we check the token user details and then we pass everything
to security context holder we update it and then our request is sent to the dispatcher servlet hit
the controller and then we get our response pack so I hope uh this was clear if you have any
questions don't hesitate to drop a comment and especially don't forget to follow me
to learn more and more about spring boot okie dokie congratulations now you know how
to implement JWT using spring boot 3 which is the latest version of spring Boot and Spring
Security as well if you enjoyed this crash course literally just take one second and smash
the like button also if you haven't subscribed to alibu channel go ahead and subscribe it's
got awesome content around springboot Java and angular it was a pleasure this is all
for now and I'll catch you on the next one