Spring Boot 3 + Spring Security 6 - JWT Authentication and Authorisation [NEW] [2023]
Aug 15, 2023
Spring Boot 3 + Spring Security 6 - JWT Authentication and Authorisation [NEW] [2023]
In this video, you’ll learn how to implement JWT authentication and authorization in a Spring Boot 3.0 application using Spring Security 6 and a Postgres database to store user credentials. You’ll see how easy it is to secure your application and protect your endpoints using JSON Web Tokens. We’ll start by setting up a Postgres database and creating a user table to store our credentials. Then, we’ll configure Spring Security to use JWT and define some security rules for our application. Finally, we’ll test our setup by building a simple API and using Postman to send authenticated requests. Whether you’re a beginner or an experienced developer, this tutorial will give you the tools you need to secure your Spring Boot application with JWT authentication and authorization. 👉🏿 Subscribe to @BoualiAli channel - / @boualiali Code - https://github.com/ali-bouali/spring- … #springboot3 #springsecurity #jwt Don’t Forget to =========================================== 💯 Subscribe to Amigoscode - http://bit.ly/2HpF5V8 💯 Courses Available for free here - https://amigoscode.com/courses 💯 Join Private Facebook Group and Discord - https://amigoscode.com/p/join-community ⭐ Table Of Contents ⭐ =========================================== 🙊 Here are the goods for all my videos video 🙊 ► Recommended Books =========================================== - Clean Code - https://amzn.to/2UGDPlX - HTTP: The Definitive Guide - https://amzn.to/2JDVi8s - Clean Architecture - https://amzn.to/2xOBNXW ► Computer and Monitor =========================================== - New Apple MacBook Pro - https://amzn.to/3464Mmn - Dell 27 INCH Ultrasharp U2719D Monitor - https://amzn.to/2xM3nW1 - Double Arm Stand Desk Mount - https://amzn.to/3aYKKfs - USB C Hub Multiport Adapter - https://amzn.to/2Jz7NlL ► Camera Gear ============================================= - Sony ILCE7M3B Full Frame Mirrorless Camera - https://amzn.to/346QIJn - Sigma 16 mm F1.4 DC DN - https://amzn.to/2wbic3Q - Sigma 33B965 30 mm F1.4 DC DC - https://amzn.to/39G37Fd ► IDE \u0026 Tools I use for coding 💻 🎒 =========================================== - ITerm - VsCode - GoLand - IntelliJ Ultimate - Sublime P.S =========================================== 💯 Don’t forget to subscribe | http://bit.ly/2HpF5V8 💯 Join Private Facebook Group and Discord - https://amigoscode.com/p/join-community 💯 Follow me on Instagram | http://bit.ly/2TSkA9w ❤️ Thanks for watching
Content
0 -> in this video you're going to learn pretty much
everything you need to know about JWT using Spring Boot 3 and Spring Security
10.44 -> so about three weeks ago we posted a crash
course on Spring Security 6 and there was a lag with
18 -> JWT section so we decided to re-record the entire
section and actually make it so extensive this
25.08 -> crash course right here is brought to you by Alibou
and is the one that led the spring security so
30.6 -> go ahead and subscribe to this Channel show some
love because it's going to be bringing you awesome
35.34 -> content like this from time to time security
is a must when designing and building apis and
42.24 -> it's really important that you understand Spring Security and JWT so
that you can secure your apis before we crack on
48.36 -> literally just take one second and smash the like
button also if you're new to the channel subscribe
54.12 -> and if you haven't joined the private Facebook
group as well as Discord go ahead and join because
58.86 -> the community is growing going and we're waiting
for you so without further Ado let's kick off
72.84 -> I just want to say that you can grab the entire
source code and the description of this video so
77.82 -> that if you have any issues or you want to
take what you learned from this course and
82.14 -> then apply it within your own API you can do
so feel free to clone the repo and yeah just
89.1 -> just use the code as you intend and if you
have questions regarding JWT literally just
95.04 -> ask on the community and someone within
the community will be able to help you
106.8 -> before we start the implementation process let
me first explain to you how this JWT validation
113.88 -> mechanism works the whole story starts when a
customer and a client send an HTTP request to our
122.76 -> backend system which is running using spring boot
container run running on an Apache Tomcat embedded
130.68 -> server so just a reminder for you the first thing
that gets executed within a spring application is
140.64 -> the filter so anytime and each time you create
a filter just notice and remember that it will
148.26 -> be the first thing that gets executed within
our application so in this case the first thing
155.58 -> that will be executed is our JWT authentication
filter and this is only a once per request filter
162.78 -> and has the role to validate and check everything
regarding the token or the JWT token that we have
171.42 -> so now let's start the process the first thing
that will happen we will have here an internal
178.86 -> check to check if we have the JWT token or not
so if the token is missing as we can see here
187.26 -> we will send a 403 response to the client so
and the reason is this missing JWT all right so
195.24 -> now we have our GWT token and then after that we
will start the process or the validation process
203.64 -> so this validation process will start in this
way so the filter like the internal execution
210.06 -> will first make a call using the user details
service to try to fetch the user information
217.56 -> from the database and this we will base on
the user email that we will set as a claim
225.24 -> or a token subject that we will extract within
this JWT authentication filter so I repeat again
233.52 -> this JWT authentication field will check the
JWT token extract the username or the email or
241.02 -> we call it the subject when we talk about JWT
tokens and it will use that email to fetch the
248.22 -> user details information from our database okay
so this is the first call then once the user
258.24 -> is fetched we have the response from our database
and the response can be either way can we existing
266.1 -> user or non-existing user okay so once we get the
response to our JWT authentication filter here we
274.32 -> will make a few checks which is if the user does
not exist we will also send a 403 to our customer
283.68 -> in case everything is fine and we get our user
from the database we will start then a validation
291.48 -> process so this validation process because the
this JWT token was generated for a specific user
299.28 -> so we want to validate this token based on the
user and here we have this validate JWT process
308.58 -> or mechanism which will try to call a JWT service
and this JWT service will take as parameter
318.84 -> uh the the user itself and also the token or the
string token or the JWT token call it whatever
325.98 -> you want after the execution of this validation
process here we have two case scenario so the
334.08 -> first one the token is not valid so it's not so
for example the token is expired or the token is
341.16 -> not for that specific user so what we do we will
send also a 403 back to our customer so and the
348.9 -> reason will be this and valid JWT token otherwise
what will happen we will call or we will update
357.48 -> the security context holder and set this connected
user because when we fetch the user details
365.64 -> information from the database we will be able to
set this security context holder so we will tell
373.32 -> spring or we will tell the set of the rest of our
filter chain that this user is now authenticated
380.64 -> and we will update the authentication manager so
every time we check if this user is authenticated
386.82 -> for this request the answer will be yes once the
security context Holder will be updated it will
395.22 -> automatically dispatch the the request and it
will be sent to the dispatcher servlet and from
402.18 -> the dispatcher servlet it will be sent directly to
the controller we will do all the execution that
408.12 -> we need to do for example calling the service
going to the database and so on so forth and
413.34 -> then we will send back the response for example it
can be a JWT and it will be a HTTP 200 or whatever
422.52 -> any process that will get executed within this
controller so this is how JWT authentication
431.58 -> mechanism works now let me show you how to
implement this and how to realize these steps
447.24 -> let's first start by creating a new spring
boot project to do so the recommended way and
453.42 -> the weight I also recommend is going is going to
start.spring.eu which is the spring initializer
460.32 -> and create a new project from that so first of
all make sure you will use Maven this is what
466.68 -> I will be using in this video and tutorial then
we want to use the recent version of spring boot
475.74 -> which is now 301 okay and also here make sure
you select Java 17 because the minimum required
484.62 -> version which is compatible with spring 3 is Java
17. next select the jar packaging and now let's
493.62 -> fill this project metadata so for the group
ID I will call it com.alible and the artifact
500.88 -> I will call it security okay so I will leave
the rest as it is and now I will move on and
507.6 -> add some dependencies so first of all we need
the spring web because we want to expose few
514.62 -> endpoints we need also the security and this is
the main object of this video and then we will
524.7 -> need GPA or spring data jpa because we need
to manipulate and interact with the database
532.86 -> then we need a post degree SQL driver to connect
to post degree SQL you can also use any other SQL
541.92 -> database like MySQL or Oracle or whatever finally
we want to use lombok to reduce the boilerplate
551.76 -> code so now we have our project ready we can just
go ahead click on generate and start decoding
568.08 -> as I mentioned before we will be using post degree
SQL or as a database for this application so let's
575.82 -> first start by configuring our data source for
that I will be using ntdj and I will use this
583.86 -> database tool so this one is available only with
the ultimate version otherwise if you don't have
591.12 -> the ultimate version just make sure you install
post degree SQL and you can use the PG admin or
597.12 -> you can use the dbiver tool to connect to any
data source okay so let's start with that click
605.64 -> on here and then we have this class icon so
click on this plus icon and then we want a
613.26 -> data source and then filter for post degree SQL
click on that and to be able to connect so make
621.96 -> sure here if this is the first time you will have
instead of driver post degree SQL you will have a
628.02 -> link or you will have a button here to download
the driver so just go ahead and click on it and
633.54 -> download the driver next the host is localhost
because it's the local one and the default
641.1 -> port for post degree SQL SQL is 5432 then if
you create when you created your post degree
651.3 -> SQL did you made or did you choose a username and
password if yes so just go ahead and specify them
659.4 -> here so for me for the purpose of this tutorial
I made it Amigos code and for the password it's
667.14 -> just password okay and then once you fill all
this information just to check if everything
673.8 -> is working fine click on this test connection
and make sure you get this succeeded otherwise
681 -> just check your configuration all right so now
everything is done I will go ahead and click on OK
690.72 -> and the first thing that I will do is
I will create a new database so right
697.44 -> click on this data source new and then database
703.5 -> so I will call it JWT security
709.68 -> and then hit OK so the first time it will not be
automatically shown so just click here on this
717.66 -> 2 of 8 the number the numbers May might change
from one laptop to another and here I want this
724.92 -> JWT security okay so open it in here and here we
can see that we have zero of three schemas just
734.28 -> select the public one because this is the one we
need and this is where we will find all our tables
740.4 -> once we create them so now we have our data source
available let's move on to the next step foreign
756.42 -> now let's establish a connection between our
application and the database we just created
762.96 -> so the first thing to do is go here to this
application properties and rename it and use the
770.94 -> representation yaml okay so this is what I prefer
personally and you can keep properties if you want
776.82 -> to but to better follow this tutorial it's better
to transform it to yaml so in order to connect
784.44 -> to a database we need to provide a bunch of
properties right here so we will start with spring
791.88 -> and then data source and one of the of
the things that we need to provide at
799.62 -> first is the URL and this one is a URL of the
connection string to our database if you don't
807.36 -> know it just go here to this database click
on it right click on the the connection you
814.62 -> just created properties and you copy this one
you copy this part right here it's gdbc colon
822.12 -> post degree SQL and then the address Port
slash the database so let me close this
831.3 -> I will just paste this one and make sure
here you you write the correct database
836.82 -> name so for us we call the JWT security now
we need to provide the username and password
843.96 -> okay so for my case it's empty make sure you
provide the correct one and here it's password
854.64 -> so next property is after providing the
data source information we want now to
861.3 -> give some other GPA properties okay so
here it will be jpa and then hibernate
869.28 -> and here I want to tell spring what
to do at the at the startup or update
875.16 -> application startup and this property is
the ddl auto and here we have a bunch of
882.78 -> options so we have create drop create non-update
the end validate so I will be using the first one
889.62 -> because every time I want to start the application
I want to create a new database a new schema and
897 -> when I stop the application I want to destroy it
okay so I always want to start with empty database
905.4 -> all right so the next one within JP within jpa
like you see now you need to really pay attention
914.04 -> about the indentation right here because this one
the CTL Auto is part of the hibernate and the one
921 -> I will write right now is part of jpa so it's
spring jpa and then show SQL I want to show SQL
931.32 -> when when we perform or when spring data jpa
performs um a query I want to see that gray okay
939.9 -> I want also to add some other properties so here I
944.52 -> will type properties and one of these
properties and here I have hibernate
953.22 -> and within this hibernate I
want also to format the SQL
958.62 -> so format SQL and true I want my queries to
be formatted now go back to the same level
965.94 -> as properties and provide some information
about the database so here we want to tell
971.88 -> jpa which database we are using and for this case
we are using post degree SQL and then we can also
979.56 -> provide the database platform that we are using
and this will help spring performing and writing
987.06 -> the better queries to to suit our post degree SQL
database so for this one it's org dot hibernate
996.96 -> dot dialect dot postgre SQL dialect
1005.48 -> all right and here we just forgot one property
right here which is the driver class name so
1012.08 -> this will help a spring to detect or use the
best driver class name and here we are using
1019.4 -> post degree SQL so and 3dj will automatically
propose it to you otherwise it's the org.post
1025.04 -> degree sql.driver and this is the one that we
got from the post degree SQL driver dependency
1033.02 -> all right so that's it about this configuration
let's move on and start implementing our security
1046.94 -> when we talk about authorization and
authentication we mainly talk about
1052.52 -> users so let's go ahead and create our user class
so within the Java package and within the main
1060.56 -> package that we have right here right click and
new class and here we can create a package and
1068.84 -> a class at the same time so the package I will
call it user and here I will just call the class
1074.72 -> user so user.user will create a packet user and
inside of it it will create a class user all right
1082.22 -> so this is our user class let me make this one
full screen and now I want to write a bunch of
1089.48 -> properties within this class okay so my user has
the the following characteristics or the following
1097.22 -> Fields so first of all I want to have an integer
ID and then I want to have a string first name
1109.94 -> and private string last name
1114.14 -> and also of course we need an email and password
for this user to be able to authenticate and
1120.86 -> connect to our application so here I will
add email and also private string password
1131.3 -> so these are the information about our user now I
will add a bunch of loanbook annotations in order
1141.32 -> to reduce the boilerplate because you know
when we create a class we need Getters and
1146.66 -> Setters we need Constructors we need also the
design pattern Builder to build to be able to
1153.2 -> easily build our object and so and so forth so
let's start with that so we will need the date
1160.28 -> annotation and this annotation will provide us
with is the equivalent of getter Setter as you can
1168.62 -> see here so it generates Getters for all fields
for useful method methods to string and so on so
1174.74 -> forth so it's the equivalent to the getter Setter
required as Constructor to string and equals and
1180.86 -> hash code okay also I want to use the Builder
annotation so this Builder annotation will help me
1190.64 -> build my object in an easy way using the
design pattern Builder okay and also I
1197.42 -> will need the no arcs Constructor and of
course when we talk about design pattern
1201.74 -> Builder we need always the all construct the
or arcs Constructor okay so let's add this
1208.82 -> one and like this we have our we have our user
class now let's make this user class an entity
1226.76 -> to make this user class an entity so the first
thing we need to add is this entity annotation and
1236.12 -> since we are using the Springwood 3.0 here make
sure that the package is jakarta.persistence and
1243.86 -> it's no longer Java x dot persistence so this also
will help you tell if you are using the correct
1250.58 -> version of springboot okay so here we need the
entity annotation and because this username this
1258.62 -> user class is already reserved for post degree SQL
because post degree SQL already has a table called
1266.18 -> user so we cannot create a second table called
user I will use the table annotation right here
1273.5 -> because you know the table annotation if I do not
provide if I don't provide any name right here it
1282.5 -> will take the entity or the class name him as a
default name for the table okay but here I want
1288.74 -> just to call it underscore user to avoid this
ambiguity between this user class and the one
1295.34 -> with and the one with post degree SQL so now this
is kind of sufficient to tell that this user class
1304.76 -> now is an entity but we still need to provide one
small information okay so here we have this error
1314.12 -> right here we see that this persistence entity
user should have a primary key okay so we need
1319.82 -> to add and add an ID attribute which we already
have right here but we're still missing this ID
1326.72 -> annotation so this ID annotation it's coming
from the jakarta.persistence and it's telling
1334.34 -> that this ID is the unique identifier of this
user class now I want also this ID to be Auto
1344.24 -> incremented or Auto generated so every time I want
to create user I don't need to provide this ID and
1351.02 -> every time this ID is null I want it to be Auto
incremented by the system or by Spring data jpa
1359.48 -> so to do so and to make it in an easy way
I will use The annotation generated value
1365.36 -> okay so this generated value it will make this
ID or this object Auto generated using whether
1374.96 -> a sequence a table and so on so forth and we
call this strategy so for this strategy we have
1384.02 -> we have several options okay we have Auto identity
sequence table and uui ID so the auto is the
1392.96 -> default value identity means that it would use an
identity number like an auto increment sequence
1400.4 -> means that we will create a sequence within our
database and use this sequence to increment each
1408.14 -> time the value of the ID the table this means
that we will create a table and the database and
1415.46 -> we will call it by default it's called hibernate
sequence and this table will always be requested
1422.24 -> and queried by a spring data jpa to get the last
value and increment it for the last one the uuid
1429.74 -> is using this one I think you know it from from
the Java Java utils but if you leave it to Auto if
1440.18 -> you leave the generation type to O2 hibernate will
try to detect the best suitable option for you for
1448.4 -> example if we are using post degree SQL it will
pick by default sequence if you are using MySQL
1455.66 -> for example it will pick table because my SQL
does not work with sequences so it will it will
1461.78 -> pick table for that so for the moment I will just
keep it empty like this because as I mentioned the
1468.08 -> default value is auto so it will be automatically
detected okay so now we have our entity let's try
1476.24 -> to start the application and make sure that
we have our table created within the database
1485.78 -> here enable The annotation processing for lombok
and now we have our application started let's
1495.98 -> have a look quickly on the logs and here we
see that create sequence user sequence start
1502.04 -> with one increment by 50. this is automatically
generated as I mentioned and here we see the
1507.8 -> SQL that we have create table user with an ID
email and so on so forth okay and here we have
1515.36 -> Spring Security is auto generating a security
password and this one we will see later on okay
1521.72 -> so also if you want to check you can open your
database right here click on this one refresh it
1528.62 -> and within the public schema we see that we have
this user table right here and if we open it
1536 -> we will see the ID or the attributes
attributes that we already provided
1553.58 -> when Spring Security starts and set up the
application it will use an object called user
1562.16 -> details and this user details is an interface
that contains a bunch of methods okay and each
1570.26 -> time you want to work with Spring Security you
need to ensure that you are providing this user
1576.32 -> details object in order to make a Spring Security
life easy to use okay so to do this for us for
1585.02 -> our user I recommend this way so every time
you have a user think always to make it or to
1592.58 -> implement user details interface so like that
your user or your application user is already
1599.18 -> a spring user if we may say so okay so to do
that just go ahead to the to this user class
1607.1 -> that we created and Implement an interface called
user details okay and this user details is from
1614.78 -> the package.org.spring framework security core
user details okay click here and now it will
1622.16 -> ask us to implement a bench of method so click
on this one Implement method and we see right
1629.42 -> here that these are the methods that we want
or that we need to Auto generate okay not Auto
1637.22 -> generate but we need to implement so it's get
authorities username and we have this Boolean
1644.12 -> methods account expired logged and so and so
forth okay so just go ahead click OK and we will
1652.82 -> see how to override but before that I want to go
a bit a bit uh more into details about this user
1660.8 -> details interface so I will open the definition
download the source so we can easily see it
1668.3 -> so here if I click on this icon right here to
see all the implementation of this interface we
1675.38 -> have this mutable user mutable user details and
so and so forth and also we have our user class
1681.8 -> the one that we created and we can see also
that we have this user from Spring framework
1688.22 -> security core user details and let's have a look
on this one okay so this user detail contains the
1695.72 -> username password authorities and the bunch of
booleans the account expired locked non-expired
1702.8 -> and enabled or not and this information or these
uh this attribute spring will use automatically
1713.9 -> to play with authorization and authentication
and for example if we can rely on this account
1722.06 -> non-expired but if we want to have some expiring
dates or use the user can expire and also if we
1730.94 -> want to lock and unlock the user or the same if we
want to work with credentials and so and so forth
1737.42 -> okay so I will I will give you the the time to
play and check this and here we see that we have
1742.76 -> a bunch of Constructor and we have these methods
that they need to be overridden right here okay so
1750.8 -> here we see that this user already implements user
details so for you you have two options whether
1758.66 -> you implement this user details interface within
your user class or you can create for example a
1766.28 -> user you call it app user and then extend the user
the one from Spring boot so it will be the same
1772.58 -> but for me I want always to have control over my
object so I create my own user class and Implement
1780.5 -> user details so now let's go ahead and implement
this methods okay so here the first one is we need
1790.22 -> to provide a collection of granted authorities and
already the method is called get authorities so
1798.02 -> these get authorities will return or should return
a list of roles like let me explain it like that
1805.82 -> when we talk about roles so here we need to add
a role okay so I will do or I will create a role
1816.98 -> and this one it will I will create
any num for it and I will call it role
1822.32 -> and this let's create this class and here you can
choose the option create a num role hit OK and we
1831.26 -> want to create it within the same package and
within this rule it's so easy I will just user
1838.16 -> and admin okay so we we want to have only two
roles within our application so now we have
1844.7 -> this Rule and because it's an enum we need to add
this enumerated annotation and this enumerated
1852.14 -> annotation is to tell spring that this is an
inam and we want to use it whether the in-am type
1860.36 -> uh ordinal or string so by the way by by default
it's original means it's a zero one two and so
1869.36 -> on so forth string it will take the string value
of of the of the inner okay so let's go back to
1876.98 -> this get authorities so in here because um with
our design we said or we decided that user can
1884.72 -> have only one role so I will just return a list
dot off and here I want to return a new simple
1896.6 -> granted Authority okay so the object that I want
to return is called Simple granted Authority and
1904.34 -> here I want to return the role dot dot name okay
so the role is referencing this role right here
1911.42 -> next one is this get user name so the username
for us is our username so it's the email okay
1922.22 -> then we have this account not expired so here
we have this is account non-expired here make
1931.7 -> sure and be careful it's non-expired false this
is the negation so non-expired should be true
1938.9 -> otherwise we will not be able to connect
our users so non-expired not locked and
1945.68 -> non-credentialed on expired and if the user is
enabled false and here I want to make it true
1952.82 -> here there is one thing that I need to mention
right here so within this method let's go back
1960.02 -> to this user details interface we see that
we have this get password okay but this get
1966.68 -> password was not uh was not overridden right here
because we have this string password right here
1975.62 -> and we have The lombok annotation so we have
already the method called get password but here
1982.82 -> if I just name this one we see that we will see
that here we will automatically tell that we want
1989.72 -> to override this method okay so let's override
it just to be to be more visible or like better
1997.1 -> visible for you I will rename this one to password
and here for this password I will just return my
2003.52 -> my password okay so I just wanted to mention this
one so in the next time or like when you have a
2011.02 -> different name for this password field you don't
get surprised when you see this get password or
2016.36 -> when you have this password exactly like that and
you don't see it so now you know the reason why
2021.94 -> okay so now we have everything we need
within our user details so we created
2027.04 -> a new role and we overridden or we defined all
the methods that are required by Spring Security
2044.8 -> now our user is ready so let's move on and create
a repository for that user class so the repository
2052.9 -> is the class which is responsible to communicate
with the database so when working with spring data
2060.28 -> GPA we don't need to create a class all we need to
do is create an interface and let's call it user
2066.22 -> Repository and this user repository to make it a
repository all we need to do is to extend another
2076.84 -> interface called jpa repository okay and as you
can see here this jpa repository is from Spring
2084.1 -> framework data jpa and so on so forth and it's
a generic interface that takes a t so which is
2091.24 -> the class and an ID which should be the ID of our
user class so let's use this one and pass these
2099.64 -> types so this the user and we used integer
as an ID so let's pass integral right here
2107.74 -> okay so now our repository is ready and as you
know the spring data jpa has also a bunch of
2115 -> methods or ready to use methods like save find
all find by ID and so on and so forth okay now
2122.08 -> I will create one method that we will need later
on and this method will will try to retrieve or
2131.02 -> find a user by email because email is unique so
we need to find or we need to fetch a user by
2138.58 -> its email all right so I'm gonna create this
optional user and like optional is a generic
2146.38 -> type so it's an optional off user and here I
will use the query method provided by Spring
2151.96 -> and I will use the method find by and here
all you need to do is providing the attribute
2158.38 -> or the field name that you have within your
class so for our case it's email for example
2163.3 -> if you use username just find by username and
here all I need to do is to pass string email
2170.8 -> all right so this is it now we have our repository
ready to use let's move on to the next steps
2189.34 -> when we
2194.08 -> when we check again our schema right here and
the architecture that we have right here so we
2200.56 -> see that the first thing that we will get or
the first thing that will intercept our HTTP
2206.44 -> request is the JWT authentication filter
so let's go ahead and create this filter
2217.18 -> so here within our base package
right click right here new
2223.12 -> and I will create a new package I will
call it config so I want all this to be
2229.6 -> part of my configuration package and I
will create a JWT authentication filter
2237.28 -> I will call it like that so this is our
authentication filter class and now in order
2244.84 -> to make it a filter we have multiple options okay
but here as we can see in this schema right here
2253.36 -> we have the we want this filter to be active every
time we get a request so every time the user sends
2261.46 -> a request we want our filter to get fired and do
all the job that we want that we wanted to do okay
2268.84 -> so this one we need to extend a class called once
per request filter and as the name indicates it's
2279.46 -> it will be a filter by one every request so let
me download the data source and you can see here
2288.46 -> once per request filter extends already generic
filter bin and this generic filter being already
2294.64 -> implements the interface called filter so for us
we had two options whether using or extending this
2302.62 -> once per request filter or implementing the filter
interface right here so it will be the same but
2309.34 -> let's use something already provided by spring so
it's better to use the ones per request filter so
2317.32 -> now let's implement the methods and we see
here that we have a method called do and
2324.76 -> filter internal and we have three parameters to
request the response and the filter chain let me
2331.24 -> explain each part of it I will just align these
parameters right here so you can see all of it
2341.62 -> so these are our parameters so here we what
we have we have this HTTP servlet requests the
2351.34 -> response and the filter chain so the request
is our request and the response is also our
2356.68 -> response so we can intercept every request
and make and extract data from for example
2363.46 -> from the request and provide new data within
the response so for example if I want to add a
2369.94 -> header to my response we can do it using this
once per request filter okay and the filter
2376 -> chain is the chain of responsibility design
pattern so it will it contains the list of
2383.5 -> the other filters that we need we need to execute
so when we call this filter chain dot do internal
2390.04 -> filter or do filter it will call the next filter
within the chain so here I want just remove this
2400.6 -> uh These Warnings so because this uh these
three parameters they should not be null
2406.66 -> and to do so I will just add this non-null
annotation the one from springframework.lank
2415.48 -> and I'm gonna copy paste it and move it and
put it in here okay so like this we no longer
2423.04 -> have this warning and now the last thing to do
before moving on and start implementing this
2429.1 -> the last thing to do is we need to tell spring
that we want this class to be managed bin okay
2435.34 -> or to become a spring pin and to do so we need
to annotate whether with service annotation or
2441.34 -> component annotation or also repository it
works because three of them are the same
2446.44 -> annotation the repository and the service
they both extend the component but I will
2453.16 -> just make it a component right here and also I
will use another long book annotation which is
2461.38 -> the required RX Constructor and this required
arcs Constructor it will create a Constructor
2468.28 -> using any final field that we declare right here
so for example if I use if I do private final
2476.32 -> string my string this annotation it will create a
Constructor using this private final field Okay so
2487.36 -> now we have our filter ready to use let's
now start implementing it part by part
2505.3 -> from this diagram right here we see that
the first thing that gets executed or the
2511.36 -> first thing we do within this JWT
authentication filter is checking
2516.22 -> if we have the JWT token okay so
let's move on and implement this
2524.62 -> all right to do so within our method do
internal filter let's try to perform some
2532.96 -> operations okay so first of all I will create a
string I will call it authentication header all
2539.98 -> right why because when we make a call we need
to pass the JWT authentication token within
2548.8 -> the header so it should be within a header called
authorization so what we need to do here is create
2555.82 -> is try to extract this header okay so this
authentication header is part of our request
2564.46 -> and from the request we can call a method called
get header and within the header we can all we
2571.48 -> need to do is to pass the header name so our
header is called authorization like that so this
2579.82 -> is the header that contains the JWT token or the
bearer token we call it also computer token okay
2587.32 -> all right so now I will create another variable
let's also make it final string I will call it JWT
2596.86 -> or JWT token call it whatever you want so here I
want to implement this check that we did before so
2605.56 -> we we talk about here we talk about this check
JWT token so let's go let's implement this so
2613.24 -> here the test that I want to do is if the author
authorization header is null so I want to do an
2622.06 -> early return or if not my authorization header dot
starts with because as I told you the build token
2632.68 -> should be always or should start always with the
keyword beater Okay and it should be exactly like
2640.3 -> that and then we have a space so if we don't have
these two conditions all I need to do is call the
2647.44 -> filter chain dot do filter and I need to pass
the request and the response to the next filter
2655.06 -> okay and here don't forget to call the return
semicolon so we want we don't want to continue
2663.52 -> with the execution of the rest of that one okay so
here this is the check that we that we implemented
2673.42 -> now let's try to extract the token from this
header okay from this authentication header
2681.76 -> the next step is we created already a JWT
variable now I want to extract this token
2690.76 -> from my authentication header or from my
authorization header and I want to do a
2696.7 -> substring starting from the position number seven
and why position number seven because if we count
2703.36 -> this beer with this space the count is seven okay
so let's move on and check what we need to do next
2720.28 -> after checking the JWT token what we need to do is
to call this user details service to check if we
2729.34 -> have the user already within our database or not
okay but to do that we need to call a JWT service
2738.04 -> here to extract the username all right so let me
show you what we need to do so right here I will
2747.1 -> just go back and create a final string username
or email call it whatever you want so I'm just
2754.96 -> gonna call it user email okay to be consistent and
avoid confusions so I will call it user email so
2763 -> after extracting the JWT token what I need to
do is I want to extract also this user email
2772.66 -> so this user email equals
2777.4 -> and here I will add a to-do extract the user email
okay but to do so I need to extract it from let
2788.32 -> me add it here from JWT token so to extract
for this user email from the token I need a
2795.52 -> class that can manipulate this JWT token okay so
let's try now to implement this class this class
2806.5 -> I will call it here I will just create my class
here private final I will call it JWT service
2815.98 -> so I don't have yet this JWT service but
within this JWT service what I want to do
2823.42 -> here I want to use a method that I will call
it for example JWT dot extract username okay
2830.68 -> so let me call this JWT service Dot extract
user name or user email okay let's keep it
2841.78 -> username within the JWT because mainly with
Spring Security we talk about user names and
2847.84 -> to extract this one I need to pass the JWT as
a parameter okay so um I will create this class
2858.34 -> now I will ask antherity to create this class
JWT service and I will create it you can keep it
2865 -> together with the config with the config package
or you can move it to a different one so I will
2871.06 -> keep it within this package and also do not forget
to add this service annotation to make it or to
2877.9 -> transform it to a managed beam all right so now
I will just create this extract username method
2888.16 -> so create method extract username in JWT service
and yes this is what I want to do I need a method
2896.26 -> that will return a string username and
it takes as a parameter string token or
2903.76 -> string JWT okay so let me call this one token
I think it would be better as a name and yeah
2910.66 -> that's it so I will just return null for the
moment and let's move on and I will show you
2917.62 -> how we can how we can implement or how we can
extract this information from our JWT service
2931.96 -> so now in order to be able to manipulate JWT
tokens generating one extracting information
2939.46 -> from the token validating the token and so on so
forth we need to include new dependencies within
2946.12 -> our application so let's go open our pom.xml
file and here within this pom.xml scroll down
2955.12 -> and go next to the lombok or post degree SQL
dependency and here just add a new dependency
2963.76 -> and this is the first one called jjwt API
API and it's from a i o just dot Json web
2973.18 -> token okay and the recent version at this
time is the 0 11 5 so let's use this one
2979.66 -> we need also to add another dependency
which is also from the same artifact uh
2986.74 -> from the same group ID but it's a different
artifact so we need a jjwt implementation
2993.94 -> so it's called jjw WT amp and from the same group
ID also the same version you can extract this
3001.32 -> version too uh to a property and use it from there
and next we need a final dependency which is the
3010.14 -> jjwt Jackson okay so also from the same group ID
and the same version too now once we add or once
3020.88 -> you add these dependencies or any dependency
to your palm.xml or if you make any updates to
3026.16 -> your pump.xml make sure you click this button
load Maven project but also if you don't see
3032.64 -> this button just right click inside the bomb.xml
file Maven and then you have the option reload
3039.48 -> project Okay so until DJ will download all the
dependencies and add them to the to the class path
3046.26 -> all right so our dependencies are ready to use
now we will go back and implement this JWT service
3063.18 -> so before we go and Implement all the services
and dive too much into the code let's first try
3070.08 -> to understand what is a JWT token so a JWT token
stands for a Json web token which is a compact
3078.96 -> URL save means of representation of representing
claims to be transferred between two parties the
3087.24 -> claims in JWT are encoded as Json object that is
digitally signed using a Json web signature okay
3095.82 -> so the JWT consists of three parts so here we have
the header we have the payload and also we have
3105.18 -> the signature so the header typically consists of
two parts the first one is the type of the token
3113.04 -> which is JWT and the sign-in algorithm being used
such as for example hmac or sh-250 256 or RSA okay
3125.52 -> the second part of the token is the payload which
contains the claims claims are statements about an
3133.2 -> entity T typically the user and additional data
so as we can see here we have the subject we
3139.92 -> have the name we have this IIT we have we can have
also extra information like authorities or extra
3147.12 -> claims right here okay so there are three types
of claims registered public and private claims the
3156.3 -> registered claim claims are a set of predefined
claims which are not mandatory but recommended
3163.32 -> to provide a set of useful and repeatable claims
some of the registered claims are is are ISS or
3172.32 -> the issuer we also have the subject the the odd
the X exp like the expiration time and so on so
3180.18 -> forth this we will see when we will implement the
token Generations okay we have also the public
3187.32 -> claims which are the claims that are defined
within the Ia and a Json web token registry or
3195.66 -> public by Nature private claims are custom claims
created to share information between parties that
3204.66 -> agree using them okay the last one or the third
part of the token is the signature which is
3212.82 -> used to verify the center of the JWT is who it is
claims to be and to ensure that the message wasn't
3221.58 -> changed along the way okay so now let's move on to
the code and see how we can generate or how we can
3229.68 -> extract claims from this JWT token okay so also
within this jwt.ao website you can play with the
3239.1 -> payload you can add some information here and as
you can see everything you add some every time
3243.78 -> you add something you see that it changes right
here okay let's move on and go back to our code
3256.62 -> now before start implementing this extract
username method I want to implement or write some
3264.96 -> code to extract all the claims and also another
method that allow us to extract one single claim
3272.46 -> okay so first of all I want to create this method
I will it will return a claims and this claims if
3281.64 -> you if you see right here when you click on import
class it's the one from io.jsonwebtoken.claims
3287.76 -> it's the dependency that we just added so this
claims I will call this method extract all claims
3295.2 -> okay so this extract all claims of course
it will take a string token as parameter
3302.1 -> and now I will show you how
to extract this so to do it
3307.8 -> we need to return our jwts and this jwts is also
from so this jwts is also from the io.json web
3320.94 -> token and we need this jwts.pars Builder and in
order to pass this Builder or the patopars the
3330.24 -> token and here we need to set the signing key okay
set signing key because as we mentioned before
3338.16 -> when we try to create to generate or to decode
a token we need to use the signing key so I will
3347.16 -> here just let cook call this one get sign in key
and I will explain it later on we will implement
3355.56 -> this method and then we need to build because
it's a builder and once the object is built we
3362.16 -> can call the method parse claims JW jws okay so
this one this method pass claims jws so we want
3372.84 -> to parse our token and once the token is parsed
we can call the method get body okay so within the
3381.12 -> get body we can get all the claims that we have
within this this token right here all right so now
3397.08 -> before we implement this signing key method
which should return a key as you can see in the
3404.46 -> definition here so this one let's first understand
what is a signing key okay so in the context of
3413.58 -> Json web tokens a signing key is a secret that is
used to digitally sign the JWT the signing key is
3423 -> used to create the signature part of the JWT which
is used to verify that the sender of the JWT is
3431.76 -> who it claims to be and ensure that the message
wasn't changed along the way so we want to ensure
3439.44 -> that the same person or the same client that is
sending this JWT key is the one that claims who to
3447.78 -> be okay so the signing key is used in conjunction
with the sign-in algorithm specified in the JWT
3456.36 -> header to create the signature the specific
sign-in algorithm and key size will depend on
3463.5 -> the security requirement of your application and
the level of trust you have in the signing party
3469.98 -> okay so here in order to do that first of all
we need to go ahead and generate a new token or
3478.74 -> a new signing key or a secret secret key okay
so uh to generate this secret key we can do it
3486.72 -> online because now we like for security reasons we
need at least or like the minimum assigning key of
3494.76 -> size 250 six okay so and in order to generate a
key so you don't need to worry about this there
3503.94 -> are so many tools and online tools to to do this
so here I will just go ahead and create a private
3513.72 -> static final string I will call it secret key
3521.4 -> and this secret key equals the value that I will
generate right now okay so now go to the browser
3528.36 -> and navigate to this address which is all
keysgenerator.com and then slash random
3535.14 -> slash security encryption key generator a DOT
aspx okay and we have here encryption keys and
3544.74 -> here we have also the security level so as I
mentioned the minimum required for JWT tokens
3551.34 -> is 256 bit okay and then click on this checkbox
yes that the eggs make it check it and make it
3561.54 -> yes so we can get this x x secret key okay so
if you need more security just go ahead change
3570.96 -> it and do like you can go even up to 4096 bits
okay but for now for the sake of this tutorial
3580.44 -> I will just make it or leave it to 256 bits okay
now let's go back to our code and paste this code
3590.04 -> right here or this key right here also we can
you can move it to the application properties
3596.4 -> and use it from there all right now let's continue
and let's implement this get signing key so here I
3605.04 -> will use n3j to Auto generate or to create this
method so I will ask him to create this method
3611.52 -> and this method should return not byte but it
should return a key okay so now to do this first
3620.1 -> of all I need to create or to make an object or
a variable of type byte I will call it key bytes
3629.52 -> and this one equals decoders and the DOT base
64 because it's a base we want to decode it on
3640.62 -> base64 dot decode and we want to decode our secret
key okay so once the secret key is decoded now
3652.02 -> I need to do just to return keys Dot h m a c
sharp key4 this is one of the algorithms that
3662.82 -> we mentioned before and all I need to do is
to pass these key bytes right so now we have
3670.32 -> our get signing key method and we have also
this extract all claims method ready to use
3686.88 -> now we have extract all claims method ready to
use now we'll go ahead next and Implement another
3694.68 -> method which will allow me or which can extract
a single claim that we pass okay so I will use
3703.56 -> generosity for this so I will use a public T it
I wanted to be a generic method and then we call
3710.7 -> it extract claim and for this claim I need of
course the token the key token or string token
3718.92 -> and then I want to pass a function the one from
java utils and this function is of type claims
3727.62 -> and T which is the type that I want to return
okay I will call it claim resolver or claims
3735.48 -> resolver or claim call it whatever you want
resolver and here it's an it's a simple it's
3742.86 -> a simple method I will create a final claims
object I will call it claims equals extract
3749.88 -> all claims from my token okay so first of all I
want to extract all the claims and then I want to
3758.58 -> do return this claim resolver the function
that I pass as parameter dot apply and as
3767.4 -> you can see the apply it will take or it will
require a claims T so the claims is the one or
3774.54 -> the list of all the claims that we have okay so
this is the extract or claims all claims method
3781.98 -> now extracting any claim from my token will be an
easy peasy test so I will show you how to do that
3799.38 -> so once I have everything ready extracting all the
claims and also extracting one single claim let me
3805.98 -> show you how we can extract the username out of
this token okay so extracting a username is easy
3813.9 -> peasy so it will be extract claim and we need to
pass the token and only we need to pass the claims
3823.98 -> dot get subject okay so because as I mentioned
before the subject is or should be the email or
3832.32 -> the username of of my user okay so this should
be the subject of of the token so that's it this
3839.76 -> is only uh all about extracting the username
let's now move on and try to implement other
3845.94 -> methods that we will need within this JWT service
class like testing if the token is expired also
3855.12 -> um extracting the expiration date
generating the token and so on so forth
3866.76 -> let's now implement the method that will
help us generate a token so the token as
3872.58 -> you know is a string so I will create a public
string method and I will call it generate token
3882.84 -> all right so this generate token
will take as parameter a map
3891.54 -> a map of string and object okay and this map
of string object will will contain the claims
3899.28 -> or the extra claims that we want that we
want to add okay I will call it claims
3904.62 -> unlike extra claims I think it's better
to call it extra claims and also I want
3911.7 -> to pass my user details so here user details
and it's the one from the spring framework
3920.64 -> I will just call it user or user details all right
so this is the method and here this extra claims
3928.98 -> is the one if I want for example I don't know to
pass authorities to pass any information that I
3934.98 -> want to store within my token all right so to
do this it's easy peasy it's just return jwts
3944.4 -> dot Builder and then I want to set my claims
so these are my claims and those will be the
3957.72 -> extra claims okay so extra claims and after
passing the claims I need to set my subject
3968.04 -> so the subject as I mentioned before it
should be my username or user email okay
3974.28 -> so I will use the object user details dot
get username all right so because for us
3982.14 -> username or the unique part of the user is
the email but for spring it's always called
3988.14 -> username that's why we are using username
okay so also we need to set the issued ad
3994.86 -> means the when this claim was created and
this information will help us to calculate
4002.3 -> the expiration date or to check if the token
is still valid or not okay so it I will use a
4009.56 -> new date right here and I will pass just
the system dot current milliseconds okay
4019.52 -> so this is the the issue the issue date
and I want also to set the expiration date
4027.86 -> so the expiration date it will be the same a
new date and here like it's up to you to set
4033.92 -> how long this token should be valid okay so
also system Dot get dot current milliseconds
4047.6 -> and then for example I want to add let's say 1000
4054.38 -> times 60 which is 60 Minutes times 24 so my
token for example will be will be valid for
4065.18 -> 24 hours plus 1 000 milliseconds okay and then you
can you can decide or you can set any expiration
4072.8 -> date that suits you okay the final step is to sign
with like which key that we want to use to sign
4081.74 -> this token and the signing key is the get signing
key method that we already created before and then
4090.62 -> we need to pass also the signature algorithm
so signature algorithm and then we want to use
4098.72 -> the eight the hs256 okay so it's this one so let's
select it and then finally call the method compact
4109.22 -> compact is the one that will generate and return
the token so as you can see this is how we can
4115.82 -> generate a token out of extra claims and the
user details all right so now this method will
4125.24 -> um like we don't have a choice but passing claims
and user details but what if I want to pass or I
4133.16 -> want to use um or I want to generate a token
without having or without extra claims I only
4138.86 -> I only want to generate a token from the user
details itself so it's easy peasy I will create
4146.96 -> another one
4150.56 -> public string I will give it the same name
generate token and the generate token it
4158.96 -> will take it I will pass only user details as a
parameter and here I will just return generate
4169.22 -> token out of null or let's say a new hash
map like an empty one and then user dictates
4181.88 -> okay so now I have this generate token
method that I can use later on okay
4196.58 -> as a Next Step let's Implement a method that
will validate or can validate a token Okay so
4207.02 -> I will create a Boolean and I will call
it is token valid all right and this
4215.3 -> token this method is token valid will take two
parameters as input which is the token itself
4224 -> and the user details why we need the user details
because we want to validate if this token right
4232.7 -> here belongs to this user details right here okay
so first of all I need a final string username or
4241.76 -> user image but within this within the context of
this JWT service let's stick to username and this
4248.84 -> one it would be extract username out of the token
we already have the method for that and then then
4256.04 -> what we want to do is to return if or whether
the username that we have right here equals
4265.4 -> the user details Dot get username all right so we
want to make sure that username we have within the
4273.68 -> token is the same as the username we have as input
okay and I want to make sure is is token expired
4284.6 -> like I need to check that my token is not
expired okay and I want to pass my token
4291.2 -> as parameter so this is token expired this
is a method that we need to create so let me
4297.62 -> go ahead and create this token expired
and let's implement this token Okay so
4307.04 -> I want for this is token expired I want I will
create a method I will call it extract expiration
4317.72 -> from the token that we have dot before because we
it's a date so it I want to make sure that it's
4325.94 -> before today's date okay before new date
now let's create this extract expiration
4336.38 -> so this extract expiration should return a
date and it has or it passes as a parameter
4342.56 -> the token itself so it's also easy
so it's extract claim from the token
4350 -> and then it's claims dot dot or Colin colon get
expiration okay so this is how we can extract
4360.2 -> the expiration date all right so how we have
here if uh the East token expired we have the
4367.52 -> is token valid we have all the methods that we
need so is still converted this one will use it
4374.48 -> later on so now let's move on and go back finish
implementing this authentication filter foreign
4390.26 -> so here we just finished implementing this JWT
validation process or validation service right
4398.3 -> here and now we want to go back to this validate
JWT process so within our code what we did here
4406.58 -> we extracted our user name so we have now our
username valid let's go ahead and perform or
4414.56 -> finish our validation process all right so here
I want to check if my user email is not null
4423.74 -> so I have user email or I can extract my user
email out of my JWT token and I want to check
4433.16 -> something else I want to check that the user
is not authenticated yet because if the user
4439.28 -> is authenticated I don't need to perform again
all the checks and setting or and updating the
4446.36 -> security context and so on so forth so here I want
to check if the user is already authenticated I
4452.3 -> don't need to do all this process and so on so
forth all I need to do is pass here and leave
4459.74 -> it to the dispatcher servlet okay so to do that
or to check if the user is already connected or
4465.74 -> is already authenticated or not we have
an object called security context holder
4474.2 -> and from that we can get the context and then
we have a method called get authentication and
4482.78 -> when the authentication is null means that the
user is not yet authenticated okay so this means
4490.88 -> that the user is not connected yet all right
so once the user is not connected what we need
4498.5 -> to do here like when we go back to follow this
process we need to perform and to check or get
4506.18 -> the user from the database all right so once
we do this validation process we want also or
4512.42 -> we need to check if we have the user within the
database all right so to do so I will create an
4519.98 -> object called user details or we you can just
call it user because our user already extends
4527 -> or implements the user details interface I will
call it user details equals and here I will use
4536.24 -> this dot user details service which we don't
have yet and here we have a method load by user
4547.76 -> username okay and you and my username
in this case is the user email all right
4556.16 -> so here the method called load user by username
4561.14 -> and in this case we don't have this user
detailed service but let's create one here
4573.44 -> so this user details service is already
an interface within the spring available
4580.46 -> within the spring framework and it's from
Spring framework security core and so on so
4585.26 -> forth and I will call it user details service
so this interface if we check it right here
4594.56 -> so here we have some implementation for it okay
but we want our own implementation because we
4603.56 -> want to fetch our user from our database
all right so make this one final don't
4609.32 -> forget this and let's move on and implement
or provide a bean of type user details service
4624.08 -> at this level we need to create a bean of type
user details service or we need to create a class
4632.48 -> that implements this interface so and also give it
the service or component annotation so it becomes
4640.88 -> a managed bean and spring will be able to inject
it but let's do it in a fancy way within this
4648.08 -> config package I will create a class I will call
it application config so this application config
4656.9 -> will hold all the application configurations such
as bins and so on so forth all right so to make
4664.34 -> this class A configuration we need to annotate
it with The annotation called configuration so
4670.34 -> at the startup spring will pick up this class and
try to implement and inject all the bins that we
4677.3 -> will declare within this application config all
right we also need the required ice Constructor
4683.24 -> in case we want to inject something so what we
need to do now is to implement or to create a bin
4691.04 -> of type user details service and to do so first
of all we need to use The annotation bin this to
4698.18 -> indicate to Spring that this method represents bin
and a bin always should be public no private means
4707.3 -> and our bin is of type user details service okay
so let's call it user details Service as easy as
4717.38 -> that or as simple as that and then we can use
a Lambda expression so we can use or we can say
4725.24 -> return a new user details service and we implement
the load user by username so we can do like that
4735.92 -> new user details service like this and
automatically you will see here that we
4744.74 -> have this load user by username method
the one that we want to use in here
4754.94 -> this method right here okay but but we can make
it more simple than that and we can use a Lambda
4764.42 -> expression and the Lambda expression it's it looks
like that so here we all we already see that uh
4771.02 -> anteriority is proposing to replace this with
a Lambda so we'll just go ahead and click on it
4777.26 -> so the Lambda is the username so we provide the
username the one we have as an input within this
4784.1 -> method right here and then we need to provide
the implementation Okay so in this case what
4793.1 -> we want to do is to fetch the user or to to get
the user from the database and to do that we need
4801.02 -> to inject our user repository okay so let's
create a private final user Repository let's
4810.08 -> call it repository or user Repository and here
simply what we need to return is user Repository
4821.84 -> dot find by email the method that we created when
we just created the user repository and find by
4830.3 -> email we need to pass the user name okay and since
defined by email returns an optional off user here
4839 -> I want to add an or else throw so in case we
don't have or we don't find the the username
4847.34 -> or the user within our database we need to return
an exception of type where the entity not found
4853.64 -> exception or we can also return the exception
username not found exception okay so I will use
4860.3 -> the username not found exception and I will just
provide here it should be also Lambda and for
4871.7 -> example as a message we can say user not found
all right so here now we have our user details
4879.68 -> service so now it's ready to use let's continue
implementing our JWT authentication filter
4896.36 -> now we can go back to our filter and finish the
implementation all right so here we have our user
4903.44 -> details or we have our user and the next step is
to validate and check if the token is still valid
4909.92 -> or not so here I will add the if JWT service dot
is token valid okay and here I need to pass my
4920.66 -> JWT and the user details that I just got from
the database all right so if the token is valid
4931.16 -> then what I need to do I need like we have in here
we need if the user is valid we need to update
4938.84 -> the security context and send the request to our
dispatcher servlet okay all right so once the our
4947.54 -> token is valid I need to create an object of type
username password authentication token so username
4956.24 -> password authentication token I will call it auth
token and this object is needed by by Spring and
4967.76 -> by the security context holder in order to update
our security context okay so equals new username
4976.04 -> and password authentication token and it takes as
parameter the user details and then for the next
4986 -> parameter for the authorities I want to pass it
as null and then the user details.get authorities
4996.86 -> so here because we are we don't have credentials
as you remember when we created the user we
5003.7 -> don't have credentials so that's why I'm
passing these credentials as a null value
5009.88 -> so once I finish creating or finish instantiating
this user name authentication token I want also
5018.04 -> to give it some more details so I will use the
auth token dot set details and this details it
5026.14 -> takes an object so I will pass a new object
of type new web authentication detail source
5037.6 -> authentication details source
5041.56 -> and here I want to build the details out
of our requests out of our HTTP request
5050.92 -> all right now the final step is as we
mentioned here the final step is to update
5057.7 -> the security context holder so to update the
security context holder it's security context
5066.1 -> holder dot get context dot set authentication
with our authentication token all right and
5076.66 -> that's it now like let's recap this one so here
when if we have our user email and the user is
5084.7 -> not authenticated we get the user details from the
database and then what we need to do we check if
5091.72 -> the user is valid or not if the user and the token
is valid so we create an object of type username
5100.06 -> password authentication token we pass user details
credentials and authorities as parameter and then
5107.5 -> we extend or reinforce this authentication token
with the details of our request and then we update
5115.48 -> the authentication token and don't forget as
a last step and always do think about after
5121.84 -> this if think about always calling our filter
chain dot do filter so we need always to pass
5131.32 -> the hand to the next filters to be executed okay
and here we need the request and the response
5139.9 -> and that's it about our JWT authentication filter
5144.16 -> it is ready to use let's move on and
see what we need to implement next
5157.72 -> this whole process is now implemented
but we still need to do some extra steps
5165.4 -> the extra step we need to do is to tell spring
which configuration that we want to use in order
5172.18 -> to make all this works okay so we created the
filter we implemented the user Detail Service
5179.32 -> validation updating context and so and so forth
but what we are missing is The Binding we need to
5186.94 -> bind because we created a filter but this filter
is not yet used so we need to use it and in order
5193.72 -> to do that we need to create a new configuration
class I would call it security configuration
5201.82 -> okay so I will call this class
security config or configuration
5208.12 -> and this is going to be our security configuration
class and as always to make a configuration class
5216.88 -> become a configuration we need to add this
configuration annotation from Spring also
5224.32 -> because we talk about security right here we
need to enable web security let me make it full
5231.52 -> screen and again we will need the required arcs
Constructor so these two annotations they need
5239.62 -> to do they need to be together when we when we
work with springboot 3.0 okay so next whatever
5247.96 -> what I will need to do because as at the startup
or at the application startup Spring Security will
5256.06 -> try to look for for being of type security
filter chain and this security filter chain
5262.66 -> is the bin responsible of configuring all the HTTP
security of our application so I will create a bin
5273.64 -> public security filter chain
5287.5 -> I will call it security filter chain and
within this method of this bin I will pass
5293.92 -> a parameter of type HTTP security I will call
it just HTTP just for a short variable name
5302.86 -> now let's start configuring our HTTP security
so here as you can see it's type it's of type
5311.14 -> security filter chain and to do that let's first
return HTTP dot build and here we need to add
5319.9 -> also the exception to the method signature
because this build might throw an exception
5325.84 -> all right so now to do the configuration I will
start by HTTP dot I will first disable the csrf
5334.84 -> um verification and we may we made we might talk
about this in in a different in a different video
5344.2 -> so here now once we disable this one and
now let's move on or we will implement
5351.16 -> the configuration the real configuration
So within the security we can choose and
5357.58 -> decide what are the URLs and the pathways
that we want to secure but of course Within
5364.54 -> every application we have always a white list
whitelist means that we have some endpoints
5371.08 -> that they do not require any authentication
or any tokens but which are open for example
5379.36 -> when we talk about creating an account and logging
so in this case to create an account we don't need
5386.68 -> a JWT token because at that time we will create
a user account and we will require or will ask
5392.98 -> for a token after that also the same when we
want to log in we don't need to pass the token
5399.16 -> as parameter because we don't have one yet so in
this case this is when we talk about whitelisting
5406.72 -> and here is how we can Implement white listing
so after disabling the csrf I want to authorize
5414.76 -> HTTP requests and after authorizing after using
or calling this authorized SCP request here we
5423.52 -> can call a request matcher Dot request matchers
and for this request matches we can pass a list
5432.7 -> of strings and a list of patterns this will
represent the application or our application
5439.24 -> patterns we will go back to this later on and
for this list I want to permit all I want all
5445.48 -> the requests in here all the all this list I
want to permit all okay and then any request
5454.18 -> all the other requests I want them to
be authenticated so this means I want
5461.92 -> to whitelist this this list and authorize all the
requests within this list but any other request
5470.02 -> should be authenticated okay now let's talk about
and let's see how we can configure our session
5478.78 -> management decision management means what we said
that when we implemented the filter we want a once
5486.94 -> per request filter means every request should be
authenticated this means that we should not store
5494.08 -> the authentication State or the session State
should not be stored so the this the session
5500.92 -> should be stateless and this will help us ensure
that each request should be authenticated okay
5508.66 -> so now we use the end to add a new
configuration and here let's add Dot
5519.1 -> session management and here I want to talk about
the session creation policy how we want to create
5527.68 -> our session so as I mentioned our session we want
it to be stateless session okay so I will use
5534.4 -> session creation policy dot stateless and like
this spring we'll create a new session for its
5542.32 -> request and then and here I need to tell spring
which authentication provider that I want to
5553.06 -> use the authentication provider I will explain it
in just a few seconds okay so I will just add it
5562.06 -> authentication provider and I will create
an object of type authentication provider
5571 -> and then I will go back and create it later on and
then after the authentication provider I want now
5578.74 -> to use the JWT filter that we just created okay so
to do that I will use the method add filter before
5587.68 -> because I want to execute this filter before the
filter called username password authentication
5595.6 -> filter because as you remember when we implemented
the JWT authentication filter we check everything
5606.64 -> and then we set the security context we
update the security context holder and after
5612.34 -> that we will be calling the username password
authentication filter okay so here I will use
5619.78 -> JWT auth filter I will call it like
that and I want it before the user name
5627.7 -> password authentication filter.class okay
5634.78 -> now let's let me create this object so
I will use the oops not local variable
5645.1 -> but create a field and this one I want it
to be of type JWT authentication filter
5652.48 -> okay so this is the first
one and I need it to be final
5658.96 -> so it will be automatically injected by spraying
and the next one is the authentication provider
5670.18 -> so let's create a field of type authentication
provider and let's make it final too
5677.98 -> all right so now I have my configuration
ready all I need to do or I need to
5683.5 -> implement now is this authentication
provider and let's do it right now
5698.68 -> now we need to provide this authentication
provider bin so let's go to our application
5706.06 -> config class and let's create a
new bin of type authentication
5711.64 -> provider okay so for this authentication
provider let me make this full screen
5720.58 -> so I want to create a bin foreign
5725.2 -> type Authentication provider oh authentication
provider always from the spring framework package
5738.1 -> and I will call it authentication provider
and let's start implementing this bin right
5746.44 -> now so this authentication provider is the data
access object which is responsible to fetch the
5754.72 -> user details and also encode password and
so and so forth so for this we have for
5760.78 -> this authentication provider we have many
implementations and one of them is the Dao
5768.4 -> authentication provider so data access object
authentication provider I will call it auth
5775 -> provider equals new Dao authentication provider
okay So within this authentication provider we
5785.92 -> need to to specify few Properties or like not
few but just two of them and the first one
5794.56 -> is the user details service so we need to tell
this authentication provider which user details
5802.9 -> service to use in order to fetch information
about our user because we might have multiple
5809.68 -> implementations of the user details one for
example getting the information from the database
5815.08 -> another one based on another on a different
profile fetching the users from from in-memory
5821.38 -> database from ldap and so and so forth okay so for
this one we already have our oops we already have
5830.2 -> our user details service right here so this one is
referencing this method next we need to provide a
5839.86 -> password on encoder so which password encoder we
are using within our application so if you have
5847.96 -> a specific one or if you are using specific one
you need also to precise this one because when we
5853.6 -> want to try or we want to authenticate a user we
need to know which password encoded in order to
5859.54 -> be able to decode the password using the correct
algorithm okay so auth provider Dot set password
5869.38 -> encoder and here I will create a method I will
call it password encoder okay and I will create
5875.86 -> a bin out of it later on so this is the minimum
required information that we need to provide
5886 -> and then all I need to do is returning this auth
5888.94 -> provider right here now I will just go
ahead and create this password encoder
5899.44 -> so this password encoder is also should be also
a bin so it will be public and I will give it
5906.7 -> the bin annotation
5912.22 -> and for this I just need to return a new
decrypt password encoder and that's it so
5921.16 -> now I have my authentication provider and
also I created the password encoder bin
5935.68 -> one more step is needed to finish this application
config class which is the authentication manager
5944.92 -> and the authentication manager as the name
indicates is the one responsible to manage
5951.88 -> the authentication so the authentication
manager have or has a bunch of methods and
5958.6 -> one of them there is a method that allow
us or help us to authenticate user based
5964.84 -> or using just the username and password and
for that we need also to create a bin or to
5970.78 -> provide the bin to be able to use it later
on okay so I will create a bin and public
5979.72 -> authentication manager because this is
the being that I want to to create and
5985.9 -> I will call it authentication manager and within
5989.14 -> this mean I want to inject an object
of type authentication configuration
5995.8 -> okay and I will call it config this authentication
configuration hold already the information about
6004.56 -> the authentication manager so I will just return
config dot get authentication manager all right
6014.04 -> so here we are using the default implementation of
springboot and this is more than sufficient for us
6020.76 -> here don't forget also to add the exception to the
method signature so that's it let's move on and
6036.66 -> now we're done with all the security
configuration for our application but we
6041.64 -> still need to provide at least two endpoints
where the user can create an account or also
6048.24 -> can authenticate and to do so within the
base package I will create a package I
6055.08 -> will call it auth and within this package I
will create a new controller Authentication
6062.1 -> controller and this authentication controller will
have two endpoints that will allow me to create
6070.56 -> or register a new account and authenticate an
existing user so in order to call this or to make
6077.64 -> this class a controller we need this annotation
rest controller and also I will give it a request
6085.92 -> mapping and for the request mapping it will be
slash API slash V1 slash auth and also I will need
6097.2 -> the required arcs Constructor okay now within
this authentication controller I will create
6106.02 -> two endpoints one for resistor and the other one
for the authenticate so the first one it will be
6112.26 -> a post mapping and I will give it a register for
the name and here it will be a public response
6124.8 -> entity and now the type will be authentication
response I will create an object later on
6132.96 -> for that we will call this method register
and this register will need a request body
6142.02 -> and this request body I will create an object
called register request which will hold
6150.18 -> all the requests or the registration information
like first name last name email and password okay
6158.4 -> so I will leave it empty for now
we will implement it later on
6164.4 -> I will do the same I will just copy paste
this one and I will create another method
6171.3 -> but this one we call it authenticate and it
will also return an authentication response
6178.5 -> but instead of register request we will
need an authentication request okay
6187.08 -> so it's an authentication request
6190.2 -> yeah that's it so we have our controller ready
now let's move on and start implementing things
6203.88 -> let's now create our authentication response so
now just I mean I will use ntvj to create this
6214.56 -> class authentication response and I will
click create it within the same package
6221.28 -> so this response is a simple
class that will have only a string
6227.34 -> token so this is the token that would be
sent back to the to the customer or to the
6234.48 -> user and to do that we will need this
data annotation we'll need the Builder
6241.74 -> and of course the all arcs Constructor and
the no arcs constant so that's it so our
6250.56 -> authentication response is ready let's
move on and create the register request
6264.06 -> now let's create this register request
class so create a class right here and
6270.78 -> we will create it within the same package
6274.14 -> so this register request it will also have
few attributes like private string first name
6287.34 -> private string
6292.26 -> last name and also an email and password
6303.24 -> so we will also need the same annotations as we
used within this authentication response so just
6310.68 -> go ahead and copy them and put them within this
register request okay so now we have also our
6319.86 -> object register request ready I will create as
a Next Step the authentication request object
6333.54 -> finally we need to create this authentication
request within the same package so I will just
6340.68 -> paste the same annotations and here this
object will hold only two information which
6347.04 -> is the string email and string password
okay so that's it our object now ready
6355.56 -> let's move on and start implementing this
author register and authenticate request
6372.6 -> so for the registration and authentication
implementation I will delegate this to a service
6378.84 -> so within this auth package I will create a new
class and I will call it authentication Service
6388.86 -> all right this is the place or the class
where I will Implement these two methods
6394.02 -> register and authenticate so here I will just give
6397.98 -> it the service annotation and of
course the required RX Constructor
6404.94 -> all right so here we have these
two methods I will just move on
6410.94 -> and here just make a simple call
for for this service methods but
6419.46 -> first let's inject it okay so I will
need the private final Authentication
6426.96 -> service I will call it just service right here
6431.46 -> and within this authentication Service let me
make this full screen now I will just make the
6439.38 -> return statements for these two methods all
right so here I will return a response entity
6449.82 -> dot OK and I will call my service Dot resistor
and I will pass this request as parameter okay
6458.94 -> and I will copy paste this and paste it right here
and instead of register it will be authenticate
6468.72 -> so here we don't have yet our register and
authenticate method so let's go ahead and
6474.18 -> create them so create method register and this
one will return the authentication response
6485.4 -> so this is what we want to return
6490.5 -> and now we can also create this authenticate
method and the same it should return an
6497.34 -> Authentication response all right so now
I will start implementing these methods
6515.64 -> so now let's implement this register
method and this register will allow
6522.36 -> us to create a user save it to the database
and return the generated token out of it okay
6530.46 -> so uh for that because we need or we
want to interact with the database
6536.34 -> and see if the user so the first thing
that we need is to inject our Repository
6544.68 -> let's call it repository right here and
then what we need to do I want to create
6551.94 -> a user object out of this register request so I
will create a VAR user equals user dot Builder
6564.66 -> and here dot build so to build this user out
of this register request so I will have the
6572.28 -> first name which is request.get
first name same for the last name
6582.12 -> and same for email so it's email and then the
value will be the request dot get email now
6591.06 -> for the password as you remember we created
our Bean of type password encoder so for this
6599.34 -> we need to encode our password before saving it
to the database okay so in order to encode the
6606.96 -> password we need first of all to inject our
password encoder service so I will do that
6616.74 -> password encoder password encoder and this I
will use it right here password encoder dot
6625.26 -> encode and here I have the get password or the
request.getpassword that we will receive within
6632.58 -> the registration request Okay so here I will
just make a static roll always so I will use
6642.78 -> a user role and then we call the build method
all right so once we build our user object the
6652.08 -> next step we need to do is our repository dot
save and we want to save the user that we just
6658.86 -> created all right and finally to be to return
this authentication response that contains the
6667.62 -> token I will create a new variable I will
call it JWT token equals now I will need my
6676.68 -> JWT service to generate that token so I will I
will inject also the private final JWT service
6688.32 -> and I will use it to create or to generate
the token using this user object right here
6696.72 -> so JWT service dot generate token the one only
using user details for the moment I don't need
6705.72 -> to set any extra claims so I will use this
user object to create auto generated token
6714.42 -> and finally I will return an object of type
authentication response dot Builder dot build
6723.48 -> and I need to pass DOT token or I need to pass the
token that I just generated okay so this is the
6733.02 -> register method and now everything is implemented
let's move on and implement this authenticate
6747.66 -> for the authentication it's it's an easy
peasy so you remember we spoke before about
6755.1 -> the authentication manager bin and we said that
this authentic and authentication manager bin
6760.5 -> has a method called authenticate which allow us
to authenticate a user based on the username and
6767.7 -> password so for that I will inject first of
all my private final authentication manager
6777.06 -> bin I will call it authentication manager
all right so I will go back here to this
6783.36 -> authenticate method and to authenticate
the user all they need to do is to call
6788.46 -> the authentication manager.authenticate and
this authentication manager takes an object
6795.12 -> of type username password authentication token so
I will pass a new username password authentication
6802.98 -> token and within this I need to pass the email
so request dot get email and also the password
6814.5 -> request dot get password and this authentication
manager will do all the job for me and in case
6822.66 -> the user is not a username or the password are
not correct so an exception would be thrown
6828.9 -> all right so I'm totally secure when I just
call this method otherwise what I need to do
6837.42 -> I need to create a user and if the user so
if I first of all if I get to this point
6843.9 -> right here means the user is authenticated so
means the username and password are correct
6849.72 -> if both of them are correct so I will just need to
generate a token and send it back okay so I will
6858.18 -> first of all find try to get the user and find
by email and I will use the request dot get email
6866.4 -> and here or else I will just throw okay I'll just
throw any exception like it's not so important at
6874.8 -> this level but for you you might want to throw
the correct exception and you need to catch it
6881.28 -> handle the exceptions and so on and so forth
all right so now I will just go ahead and copy
6887.76 -> this code because it would be the same and put it
right here so once I get the user I will generate
6896.7 -> a token using this user object and then return
this authentication response so now we have this
6904.68 -> authenticate method and the register method ready
to use let's move on and see what is the next step
6920.52 -> now we have our authentication controller ready to
use but there is one extra step that we need to do
6929.52 -> do you remember when we first implemented
the security configuration and we spoke
6936.06 -> about this white list right here
so what we need to provide now
6941.16 -> within this request matches that we want to
permit all we need to provide or authorize
6947.76 -> all the URLs or all the methods that we have
within this authentication controller so go ahead
6954 -> copy the request mapping that you created and for
example here I want to authorize all the methods
6962.16 -> that I have within this authentication controller
why because based on my design everything that I
6970.5 -> have in here only uh authentication related
methods so I don't have any business logic
6977.82 -> methods or endpoints within this authentication
controller so that's why I'm allowing I'm allowing
6984.72 -> all the methods within this controller so that's
it now let's create a demo controller for that
6999.9 -> I will create a new controller within a new
package so right click here new class and I
7007.34 -> will call the package demo and I will call it
demo controller so this demo controller will be
7016.16 -> also secured so I want this endpoint to be secure
they will copy this this annotations right here
7024.62 -> paste it here and so this one will be
demo and let's call it demo controller
7035.18 -> and now I will create just a
get mapping a simple method that
7042.92 -> public that will return a simple string
okay response entity of type string
7053.84 -> say hello for example and then
I will just return a response
7058.28 -> entity.okay and with a body hello from
secured hello from Secret endpoint
7067.82 -> and that's it now let's go ahead start
our application and test these changes
7082.58 -> foreign let's start the application and make
sure that all the code that we wrote together
7089.18 -> is working fine so go ahead click on start
and let's see what we will have in the console
7097.4 -> so let's make sure that everything is fine
so as you can see here from the logs we no
7103.7 -> longer have this auto-generated password by Spring
Security and we have here that we are creating the
7110.12 -> sequence and we have the table user gets created
and the application is running correctly okay so
7117.08 -> now let's start our Postman and test this endpoint
so I have my Postman started right now so I will
7127.52 -> use this end point within a get request so the
endpoint is localhost and my port is 8080 slash
7135.92 -> API V1 demo controller is the same one that I have
right here within my code it's demo controller and
7144.86 -> now I will click on send we see that we have no
authorization we have nothing in here so I will
7152.96 -> just go ahead and click on send and normally
like the expected behavior is this end point
7159.2 -> should be secured okay so when I click on send
we exactly can see that we have a 403 Forbidden
7166.94 -> means that we are not allowed to access this
endpoint okay next we have our two endpoints
7175.88 -> the authenticate and the register so let's first
start with this register endpoint or let's before
7182.48 -> that let's start with the authenticate and
for the authenticate now we know that we
7187.46 -> have no user within our database we can also
double check that at so if I open let me close
7196.04 -> the other tabs so here I don't have any user
registered then within my database okay but
7203.12 -> now if I try to connect to or to authenticate a
non-existing user I also expect to have a 403 as
7211.52 -> a response and this is what we see right here so
it's 403 Forbidden and the user is not allowed
7218.72 -> to access this endpoint and this why because we
have here within our schema so we try to check
7227.12 -> and validate everything even if the endpoint uh
even if the end point is secured so we we get into
7236.06 -> this authentication filter we validate everything
but once we get to the user details we don't have
7242.48 -> the user in the database so in that case we will
send back a 403 to our customer okay so now let's
7251.9 -> create a new user so I will register a new user
so I give it alibu as a first name alibu last
7258.2 -> name and alibuatme.com and one two three four as
a password so now when I click the send button I
7267.38 -> should get generator token or a JWT token as a
response so this is what we see right here so
7277.1 -> I will just copy this token and I want to decode
it and let's see what we have within this token
7285.56 -> so let's go back to the JWT dot IO website and
paste the generated token in here so we see that
7294.62 -> we have the algorithm here which is the hs256 the
one we use to generate this token and we have our
7302.54 -> payload so we set already the subject to the
to the user email and we have the issued at
7309.8 -> so the creation date and as you can see in here
it was created December 29 and 1414 and this
7317.96 -> one will expire at in 24 hours okay so uh this
is our generated token let's go back and test
7326.48 -> the authentication right now so we see that the
register is working but let's ensure that within
7333.08 -> this same username and password we are also able
to get a token or to generate a token so this is
7339.92 -> the same email and the password that we have
and if I click on send I should get the token
7345.2 -> but let's first try with a wrong password so when
I click on send so here we have our 4403 and here
7354.86 -> it's because of this process so we have the token
and then we start the validation process so we
7362.24 -> extract the username and password and then we
are calling the user details service to try to
7368.24 -> fetch the user from the date database and the
user we got it because the user already exists
7374.72 -> but when we move to the security filter chain
and use when we move the security context holder
7382.28 -> we will try also to use the authentication
manager to authenticate that user using the
7388.88 -> password and the user made that were provided
within the request but this password is wrong
7395.48 -> so that's why we are also throwing throwing a
403 as a response okay so now let's test with
7402.98 -> a correct password so if I click on send I see
that I have my JWT token I will copy this one
7412.52 -> and then I will go back to this get method
I will click again and make sure that it's
7419.12 -> always 403 and how we can authorize this
request right now so within the authorization
7428.12 -> here within the type click and choose Bureau
token all right so remove or delete if you
7435.08 -> have something in here and paste the token that
you just copied Okay now click on send and we
7442.52 -> see that we have the message hello from secured
endpoint and we have this 200 okay which which
7450.2 -> is compatible with all this process so we have
the filter we validate everything we check the
7456.62 -> token user details and then we pass everything
to security context holder we update it and then
7463.34 -> our request is sent to the dispatcher servlet hit
the controller and then we get our response pack
7470.78 -> so I hope uh this was clear if you have any
questions don't hesitate to drop a comment
7477.68 -> and especially don't forget to follow me
to learn more and more about spring boot
7494 -> okie dokie congratulations now you know how
to implement JWT using spring boot 3 which is
7504.14 -> the latest version of spring Boot and Spring
Security as well if you enjoyed this crash
7509.54 -> course literally just take one second and smash
the like button also if you haven't subscribed
7514.82 -> to alibu channel go ahead and subscribe it's
got awesome content around springboot Java
7519.98 -> and angular it was a pleasure this is all
for now and I'll catch you on the next one
Source: https://www.youtube.com/watch?v=KxqlJblhzfI