Spring Security Tutorial - [NEW] [2023]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video you are going to learn about the latest version of Spring Security a few years ago I've recorded the most popular course on Spring Security on YouTube and since then there's been a lot of changes and improvements on Spring Security so one of them is the web security adapter which has been deprecated and I've been getting a lot of questions on how to implement security using the new approach and this is what you're going to learn we're going to start off with an introduction of Spring Security and you're going to learn about basic auth or basic authentication and then towards the end you are going to learn about JWT this video will be led by alibu so alibu has an awesome YouTube channel where it provides really Advanced content on Spring Java and angular so definitely go ahead and show some love and subscribe to his channel if you need to amigo code go ahead and also subscribe and take one second literally one second and smash the like button so we can keep on providing you guys with content like this if you're not part of the community both Discord as well as Facebook group go ahead and join we are waiting for you so without further Ado let's go ahead and learn about Spring Security thank you Nelson for this introduction before we dive into the code let's first answer one question why we need to secure an application the answer for this one comes also with another situation or a question imagine you have an application with sensitive data like customers and the transactions or and their transactions okay would you allow anyone which is or who is not authorized to access this information anytime he wants the answer of course is no what we need to do in this case we need to implement a security layer to secure all the accesses to our application to implement the security within an application there are multiple ways so the first one we can have a security using a form login we can use a basic authentication we can use also an oauth 2.0 implementation we can also use web SSO or what we call the single sign-on we can also use API Management systems or like API API Keys based authentication and so on so forth in this video we will see how to secure an application using basic off authentication and jwtware token authentication but before we dive into the code show me some love go ahead and subscribe to my channel to receive videos every week thank you so much and let's go into the code before we continue I just want to let you know that we are working on a massive course on Spring Security that will teach you pretty much everything you need to know about security so you learn about basic authentication form-based authentication jwts in detail as well as oauth 2 key cloak password resets otps and basically the whole shebank now obviously the course is not out yet so what I'm going to do is to subscribe to the mailing list so that when we release the course you'll be the very first one to be notified and also let me know what you want to see from the Spring Security course enough of me let's go ahead and start this course let's go ahead and create a new Springwood project the easiest way or the simplest way to do it is just to go to the spring initializer website by typing star.spring.io and then you will have this interface to create a new spring boot project so first we want to create a maven project using Java language and the spring boot version should be right now it's the 2.7.4 the 2.7.5 is a snapshot so we we are going to use a 2.7.4 now let's update or create our project metadata so for the group it's it's going to be com dot Workshop the and artifact I'm gonna put my name it's bualy the description it will be demo project for Springwood security and the package name it's going to be auto-generated so the packaging we will use a jar packaging and then we will use the Java 17 because this is gonna make you ready to migrate to the version 3.0.0 of spring boot with the one coming so soon so now let's add some dependencies we will create a rest API and we will use Spring Security so first of all all we need to do now is to add the spring web also we will need lombok for uh for The annotation library to reduce our boiler plate code and that's it so now let's go ahead generate the project and open it using our IDE and for this course I will be using entity J open your ntdj and navigate to well-downloaded and extracted your project so for my case it's here and then select the palm.xml file and click on open to open the project you will be interrupted to whether if you want to open it as a project or not and yes do open as a project now our project is ready and what we will do next is we will create our API like let's create a small and a simple API so we will not use any database will not lose anything except that we will create a simple API so to do this let's go ahead and create a Java class let's call it greetings controller for example and then to tell that it's a controller it should be a rest controller and we need to add our request mapping and here always think about using slash API give it a version and then the correct namings for apis so on for this case let's go ahead and create a public response entity of string for example and here say hello for example and now we'll just return a response sorry ah let's return a response entity dot okay and the body let's say it's hello from our API so this one is going to be a get mapping and we don't need to provide anything because it's just a simple get mapping let's create a different one or another one it's going to be also a get mapping and here and this one let's call it say goodbye for example just it's just an an easy and a simple API the main goal of this course is about Spring Security it's not about creating an API so here it's going to be a public response entity of string also and here it's going to be say good goodbye and now we will just return response entity dot okay and here goodbye and see you later for example let's just fix this small typo and this one too and our API now is ready now let's go ahead and test our API I will run the application I will just tell him to enable processing for lombok now we will start our application and try to reach or try to test one of these of these endpoints so now if we go to our browser and try to access this endpoint slash API V1 greetings we should see this message popping up and here this is our URL which is localhost 8080 because our API is starting on the 8080 port number and it's slash API V1 greetings so here we see that we have hello from our API now for example if we try to access this endpoint we should see a good Buy and see you later now we have the message goodbye and see you later first let's just move this controller class to its correct package I will create a package called controllers and then if I click to fix this one it will propose me to move this package to to move this class to the package controllers the one I just created go ahead and click OK and now it will be moved here let's close this and now what we will do is first we need to install the security dependency for our project let's go ahead to our palm.xml and here under or after the dependency the spring boot starter web let's add a new dependency so the artifact ID is spring Dash boot Dash starter Dash security and this is the starter for Spring Security hit OK and then make sure that the group ID is always org.spring framework.boot and then you have to reload your project to have the dependency available for you so go ahead and click on this small icon load Maven changes or or you can do is just right click here and then you have Maven and then you can just click reload reload project or you have it also here in the maven in the maven tab you just right click on the project and you do reload project and it will update or reload all the dependencies of our project so now we have our dependency installed let's go ahead and just rerun the application without doing or without adding any code so I will just close this run the application and let's check the logs what we will have in the logs so the application is starting and here we can see together that using generated security password so spring automatically generated this password for us and hit just a caution or a warning that this generated password is only is for development only and it must not be used in production and here we see that we have some other logs about default security filter chain and here we can see also that we have a default user configuration user details service auto configuration so what happened here is by default spring is providing a default configuration for security and here if I go back to the browser and try to refresh this we will be redirected to this to this form login page or to this login page and here we have the message please sign in this is an auto field by me I can just remove it so by default it's it looks like this so now let me go ahead and explain what happened exactly and why spring is proposing this interface to do the login but before before that let's just go ahead and try to to login so the default username is user and the password we will just paste the password that we that was generated for us so I will click on sign in and now we see that we can access our endpoint now I will just ask him to log out and to log out is just the localhost the port number and then log out and here we see the message are you sure you want to log out and I will say okay now I'm always or I'm again I'm again redirected to the sign in page let's go back to our code and let me explain to you what happened exactly when the application started the first things Spring Security was looking for is an object or is a bean of type security filter chain so let's try to open this class and see what are the default implementation for this so as you can see this security filter chain is the one from Spring framework security.web and this is an interface so now let's click on this icon here and navigate to the spring bin declaration and as we can see here we see that we have a bin of this type security filter chain and the name is default security filter chain and it has a parameter an HTTP security and what we are doing here is http.authorizer requests and any request should be authenticated this is why first of all we we were not able to directly access our endpoint because here with this line spring is automatically securing all the endpoints and why we had the form login because as you can see here in line 65 we have http.form login means for to secure this endpoint or to secure this API use a form login and here we have also an HTTP basic it's just in case the form login is not working so the HTTP basic will take place so this is what mainly happened when we first started our application so next what we will see how can we implement this HTTP basic become login we just saw how it works so spring will rate can tap the user let's first start by briefly explaining how basic authentication works here we have on the left hand side we have our client which can be a browser it can be a web application a mobile application or it can be also another rest API that wants to communicate with our backend or with our API backend so the client first time he will send an HTTP request without any authorization so the back end he will check the authorization so and nothing was provided as for example as a username and password and the backend will respond with a 4-1 unauthorized the next time or the second time the client will send an HTTP request with a basic 64 username and password in this format so the back end he will check that we have a username and password he will do all the processing to check if those username and password are existing or they are part of our backend or authentication system if the answer is yes so a 200 response okay will be sent back to the client or we will send back the corresponding response so for example retrieving a list of clients or list of students and so on and this is what we mean by a 200 okay so this is briefly how the basic authentication works let's implement the Spring Security now and let's choose or let's try the basic authentication so before doing anything let's first go ahead and create our Spring Security config class so here in our base package I will just go ahead and create a Java class and the package that I will call config dot I will I will create a class name I will call it security config so this is a security configuration class and what will tell spring that this is a security configuration class is this annotation enable web security so spring will know that this is a configuration class and it contains security configuration so as I mentioned before the first the first thing that spring will look for is a bin of type security filter chain as we saw together here he will look for something like this so let's just go ahead and copy paste this one so this is gonna be our security filter chain let's make it public and let's remove this order as as you can see also from the default default implementation of the security filter chain this one I will just rename it to security filter chain and the order the security properties.basic authorization order this is the this one has the lowest order so when we remove this and create our own security disk will give our bin a higher security and it will be used instead of the default security filter chain bin which is provided by spring so let me make this one a bit bigger and here what we want to do here we have this configuration and here we have HTTP authorized requests and here we want any request to be authenticated let me just make it more readable for you let me break the lines format the code and here we can do also and here we can say form login or HTTP basic which is our case and we can remove these two lines so this one I guess it's more readable for you let's just re-explain this so what we did here is we provided a new security filter chain beam because we have here the bin annotation so spring will will create this pin and because it has the default order of beans so spring will pick this bin instead of the default security filter chain which is automatically provided by Spring so now if we start our application and refresh our web page or we try to access our API we will have an HTTP basic instead of a form login because just as a reminder let me go back here we see here that we have this form login and we have this please sign in and so on so forth now let's see together what will happen when we do or when we use this HTTP basic so of course we don't have the full implementation of the security meaning uh how spring should fetch the the user and so on so forth so let's always use this auto-generated password and now I will just try to access our API V1 greetings endpoint for example so when I try to access this we have this prompt let me see if I can zoom in now I cannot make this one bigger but yeah so we have this sign in form or this pop-up to sign in and here we are requested to provide the username and the password so for example if I provide anything here and I do sign in this will not work and the pop-up or the uh the input will will show again to ask me to put the correct user and the user the correct username and password so let me provide here user as we as we did before and auto generated password this one as a password and click on sign in and here we see that we have the message we have the response from our API and this is what we exactly did so the first time we provided empty or wrong authorization and we got a four one and the second time we provided the correct information and the correct or the correct credentials and we got our correct response from the back end so this is how we can configure or how we can use the basic uh the basic Authentication so this is using the browser let's now go ahead and check and I will show you how we can use the same thing with Postman for example go ahead and open your Postman application and to create or to to send a request to the backend all we need to do is to click on this plus icon to create a new request and here we have the request type whether it's whether it's a get post boot patch and so on so forth so for our case it's a get request and we can also use the same URL we can just copy paste it from here and the first time let's go ahead and just send it and as we can see here we have this 401 unauthorized it's sanitation that it's similar also to 403 Forbidden why because here we did not provide any authorization or any credentials to the back end now to do this using Postman click here and on the authorization tab we make this a bit bigger and in the type or the authorization type here we have a basic authentication so we click on this one and here we need to provide the username let me also close this one so here we need to provide the username and the auto generated password we have from here so let me just copy this one again and I'm gonna paste it and now I will send this again so here we see also that we have hello from our API and this is how we can send or how we can provide basic authentication using Postman explained and implemented the HTTP basic authentication but the HTTP basic authentication is really recommended due to its inherent security vulnerabilities so there is a better way to secure our backend API so let's go have a look on it so what we will see next is how to secure our backend or our API using a GWT token and before going ahead and Implement in the GWT authentication or the GWT how it works with our backend so here we still have always our client as I mentioned before it can be where mobile application another AP and so forth to and this this client wants to cons backend API so the first thing we'll do he will send a get request or a request generally speaking to to our API slash V1 and this one will be first intercepted by a filter because the first it's executed in a spring boot applicants are filters and here we will have our GWT authentication filter and what this GWT authentication filter will do is first he will check if a GWT exists if WT in our header sent by the client next once we check that we have the once we check that we have the header what we will do we will just go ahead and ask for the user information means okay I got a request and I have the token and next what I want to do is I want to check if the user is allowed to access my API so first the GWT application filter he will just go ahead and ask our details service which is also a bin or class that has a role or has the functionality of fetching the user information and fetching the user information in the user Detail Service we will try to fetch the user information from weather and in-memory user or a database or an ldap and so and so forth like where you are storing the the your users or application users information that you need to mention that to the user details service so the user data service will send or will try to fetch the user information from the storage system and if the user is found we will have back or the the storage system will send back the user details and this user details will be sent back to our authentication filter then the authentication filter what we do is comparing and wanting the glut data with the current user because we have gwd token for each user so any user that wants to authenticate or to register into our backend or our API will have his own token and the token contains some information and some information is for example the user ID or like a unique identifier for the user so we can use in we can use this information to compare or to check if this user can access our API or not so here after comparing and validating the GWT data or the GWT token data with the current user if everything is fine and if it's the same user that sends that send the request what we will do next is we need to update our security context holder and then call the filter chain so updating the security context Holder will go to this guy here security context holder and do is to set the user as authenticated so when we pass to the next filters we spring will know that the user is authenticated and it and has the valid credentials then the security context holder of the filter chain will just forward the request to our dispatcher servlet and the dispatcher servlet will forward the request to the corresponding or to the correct controller and as we can see here the dispatch let will send the say hello to the hello world controller and then the hello world controller will just exit the method and return the message hello world which will be sent back to client so this is how the GWT authentication works and this is what we will Implement next foreign let's now Implement all the necessary classes that we have in our sequence diagram here into our application so before just moving and starting application I'm and before starting the implementation there is one dependency that we need to add which will help us generate and validate this GWT authentication or the GWT token so let's open our palm.xml and scroll down here and let's add a new dependency and the dependency is called ggwt and this one is from the package io.gson web token and the version is the 0 9 1 like at this time it's the most recent version then click go ahead and click on reload the project so I depend we will do create a wallet WT author filter or as the name you want so I will call it just GWT auth filter so here in order to tell spring or to transform this JWT auth filter class to a filter we need to extend a filter class and this one is a once per request filter and this once per request filter means that each request that comes to our backend would be intercepted by this filter first now let's go ahead and implement the methods here we have our do internal filter method so this one or this is the method that we need to implement in order to tell spring what we need to do when we intercept or when we execute this one so here before going ahead and implementing before going ahead and implementing this do filter internal what we need to do first is we need to tell spring that this is a component or a pin so let's add here the component annotation so this class will be managed by Spring first of all let's create some variables let's create a final string let's call it auth header and I will come back to the implementation of each one we need also the user email also as a string and we also need a final string the GWT you can call it as you want so here in the authentication header what we need to do is to get the authorization from the header and this authorization is within our request the C here which is of type HTTP servlet request so why this because when we want to pass another rate of authorization we need to pass it with the header of the body but generally speaking it's with the header so what we can do we can do request.get header and here we have we have something or we have a constant called authorization and it comes work.spring framework.http headers androidization so I quickly import and import we did and see the implementation content we will it contains the keyword yeah this is what we get from a better Edition so first of all we have or we want to get the authorization header from the request then here I will do some tests before so here if my authorization header is null or my authorization header does not start with the keyword beater so auth header dot if not auth header starts with this the keyword beer so this means that I don't have whether I don't have the authorization header or it's not the authorization header that I'm looking for so all I need to do is filter chain dot do filter and I need to pass the request and the response to this do filter method and here all I need to do is return because I don't want to execute the rest of my method so here what we do let me re-explain it again in an easy way here we are just checking if we don't have a header and also if my header is not a beer that means that my header or the authorization header does not contain a beer token so I don't need to do anything just need to execute the rest now if we have the authorization header and if my header starts with a beer token or with the keyword beer what I need to do first of all I need to do WT token I need to extract the token from my authorization header so I will do authorization header dot substring starting from the position 7 why because the token or the authorization like this space and my token let's maybe change this one would I make it like this like this or the authorization header looks like this and if you count from beer to this one it's seven characters so that's why IG JWT token I need to start from the position 7 which is this one so let me go ahead and delete this line next what I need to do I need to extract the user email and the user email is gonna be equal something here and I will add the to-do here to be implemented I will explain this later okay so then or let's suppose that we have already extracted our user email from the token because this is something that we will Implement later on what I need to do here here so we need first of all what we checked that if the JWT exists if yes so what we did or what we need to do is we want to get the user information from the user details service so here we need to inject or we need to use user details service in here so first of all I will use a lombok annotation which called required RX Constructor and this one it will create a Constructor with all the final parameters that I have here so for example if I do this private final user details serve org.spring framework.security.core and here I'm gonna call it user details service this one will be automatically injected by spring because this required Alex Constructor will create a Constructor with this parameter and automatically spring will inject it so let's go ahead now if our user mail or you the user image or the user ID call it whatever you want if I if my user image is not null and here that we are going to use the security context holder one will set the user as authenticated for bring all the rest of the process I need to check that user is not authenticated because if the user is authenticated I don't need to do all the checks means I checked before within this filter so now let's go ahead and check this call our security con holder dot get cost to text and we have a get or function and I need to check or to need to make sure that this often objects that the user is not authenticated so here I will create and this user detail so let's find it for you yeah it's the first one so this user detail is an object or is an interface that represents user of Spring Security user because it has basic methods that Spring Security will use to implement his security so for example we have the authorities password username and we have a bunch of Boolean method like it's not expired not locked and if the user is enabled or not this is the type of user that we need to use in our application and for example if you have a database based you database storage to sort of store your users just think about implementing this user details interface within your user entity or your user object because this makes your life much much easier so let's continue here we will create our object user details and here we will use our user details service dot load by username user by username and we will pass this one so this loader by username what it would do will try to fetch the user from our storage and this one as I mentioned here it's part of our user details service let me just reduce this one so it's part of our of our user detailed service which is already from Spring as you can see the package of this interface is org spring framework.security.com dot user details so let's go ahead and finalize this now here I will just create a final Boolean and we will come back to implement it here later on and to be implemented like the other one and this Boolean is I will call it is token valid the token is valid or not and here what we need to do is to add a new if or a new test if is token valid and here what we need to do here if the token like comparing and validating the duty with the current user and this is what we will Implement later as we mentioned in the to do what we do next is updating the security context hole so let's go ahead and do it so to update security context holder we need to create an object of type user name authentication username password authentication token I will just call it auth token because the name is a bit too long equals new username of authentication token and for this one when when I create this I pass amateurs in the user details and a null for the credentials because for now we don't have credentials and we need the authorities which comes from the user details dot get authorities let me make this one more visible for you so this is what this auth token or what is this username password authentication token gets or takes as parameters what we need to do next is we need to set some more details to this object so here our off token I will just call a method called set details and it takes an object and the object that we need to pass is of type new web authentication details source and this one it has a build method build details of or building the details from our request so now we also extend it as to our authentication token and what all we need to do now is calling the security context holder dot get context dot set authentication and now is the authentication token we just created So within this line or this block of code we are may we are updating the security folder and also here make sure that you are after or out of this if condition and the thing that we need to do always whether we made it to uh to this or not is calling the filter chain dot do filter like we always need to call the filter chain to execute the rest of the filters so this is the part or how to implement this filter application filter so in the next part what we will do we will just implement this to to do's at this phase we need to finalize implementing these to-do's means we need to create the method that can extract the user email from the token and also we need the method that can validate if a token is valid or not so I did this in the background for you guys so if we go here I created a class which I called it JWT utils and this class contains a bunch of methods and by the way this class you can find it easily online and this will use the jjwt dependency to manipulate the JWT so this class contains a bunch of methods as I mentioned and we have here two methods called generate token one takes user details as parameter and the other one takes user details and a map of claims and the claims are the extra information that we want to set to our token so here and each of these generate token methods they will call a create token method here and this one it takes as we mentioned it takes the claims and the user details and all we would all all these methods will do is calling this Builder from the jwts class it will set the claims that we passed as parameter here set the subject which is in our case it's always we want to set it as the username from the user details and as I mentioned this is the one from Spring Security and also as a as a reminder for you if you are using your own user class or entity think about implementing this user details interface because it will make your life so much easier because spring uses this one okay so here also we can we are setting or we can set claims for the authorities we want to set the authorities and here are the information about the creation date of the token and the expiration date so the token which would be generated will expire in 24 hours and then here we Define the signature algorithm which is HS 256 and using a JWT signing key and in this case it's just a string with with the value secret but for your production application think about injecting this value and having a more complex signing key so also the other method that we will use or will need is is token valid and this is token valid we'll take the token itself and the user details all the object or the user object to validate it and here what we will do we will extract the username we will see later on the implementation of this method and what we will do is as we have here we will compare and validate the JWT token data with the current user so here if our user equals the user that's coming from our user details object and we need to make sure that the token is not expired so both of these conditions will tell if the token is is valid or not now let's go ahead and explain this one so this extract username will call a method called extract claims and this method will get all the claims we have within our token so it's just this line that will get the body of uh of the token we have or the JWT token we have and then we will just get or try to extract the required token that we want and for our case the username is always the subject because when we created the token here the we told spring or we told this one that the subject that we want to do is our username so next what we will do we need to finalize or to implement this to-do's so the first thing we need to do is injecting our JWT utils service or component here so here we have private final to have it automatically in our Constructor using this annotation and we called it JWT utils now let's go ahead and implement this line so here instead of making it static value so let's go ahead and do JWT utils dot extract username from our JWT token so now we can remove this to do because it's already done for this one I will go ahead and replace this with JWT utils dot is tokenvalid and here I need to pass our JWT token and also our user details object so like this everything and we implemented all the to-do's and our authentication filter Now is working fine so that's it and let's go ahead and implement the rest of the services at this phase we need to tell spring to use this filter because the filter exists it's already implemented but spring doesn't know about it so we have to tell spring to use this filter in order to filter all the requests and say that all the requests or the incoming requests to to our application they need to pass through this filter let's go back to our security configuration and here let's we said that all the requests should be authenticated and here we can do also add and here add filter before so here we want to add a filter before another filter and in this case what we need to do we want to use our JWT auth filter before calling the username and password authentication filter and here I want to use it before username password authentication filter dot class so what we are missing right here is we need to create this variable let's go ahead and create it well it's not a local variable let me just move it up here and it's not a filter here I will say private final JWT auth filter and this is our filter and here we need also to use the required RX Constructor from lombok so this way I can remove this end here so this way we still appear we're still using the HTTP basic we will we will just remove it or we can just remove it right now so uh here we told spring hey go ahead and use this filter before authenticating the user because what we do here in this filter just quick reminder we are checking the JWT and if if everything is working fine and if everything is fine what we do is we set or we update the context of the security context holder so we want to to execute this one before this one and that's it now spring knows about our filter and he will or it will use it foreign we need to go ahead and Implement our user details service because this one is used in so many places or will be also used in so many places with spring and as we can see here in the JWT authentication filter here we are calling this method from the user details service to fetch the user details data so what we need to do is we need to provide an implementation for the service so there are two ways or more than way to provide this service so the first one is we just go ahead and create a class that implements this user details service interface and all we need to do is just implement this load by username or we can create also a bin that will return a user details service so let's go go ahead and create a bin because creating a class is so much easy so first of all we need the bin annotation and we want to create a public user details service object that we call it user details service and in here we need to return user Detail Service object so I will just go ahead and do return new user details service so this is an interface and when we do return new it will automatically override or ask us to overwrite all the methods so in this method here load user by username the one that we will use in the JWT authentication filter it has a parameter called user name and here I will just rename it to email so this should make more sense for you and in this method we will not connect to a database to fetch the users but we will try to use a static list or an in-memory users to for our application so here I will just go ahead and create a private final static uh list of user details so this user details as we mentioned here this is the interface and I will just call it application underscore users and here I will just use arrays.ans list and in this arrays as list we can or we should provide an object of type user details mean we need to pass a class that implements this user details and the good thing that spring already has a class user so if I do new user we can see here this user is coming from the spring framework security core user credential user details package and this one if I do new and here we have two Constructors available one that takes string string and the collection so this one is the username password and the authorities and the collection of granted authorities and the other one it takes a username password and all the booleans like is token expired is not token but is account expired blocked and so on so forth and also the authorities but we need the first one so I will just go ahead and type the email for this one so I will just give you my email in case you want to contact left me so this is my email address there is a typo so let me fix this and here I will choose password as a password and here I will use a Singleton list collections dot singlet on list of a new simple granted authorities and here I will just give myself the role admin so I'm the admin of this application and I will create another user first I will just give it the role user here for example let's say that in our application we have an admin and the user role and here the username let's say user dot mail gmail.com so this is all those are the users of our applications and if we want to add a new one all we need to do is to extend this list and add a new user object so now let's go back here and implement or finish implementing this method of the user detailed service so simply what we will do is we will return this application user I will just do a stream and here I will just filter I will just search for the user dot get username should be equals to the username or the email that we passed as parameter and here once we find the username we can do find first for example or find any because I'm here I'm pretty sure that I don't have a duplication of emails for my users so the image would be unique whether in the database or in this list and here or else I'm gonna throw an exception if the user does not exist so I will just throw the username not found exception and here I will just no user was found just as an exception message so like this this is the implementation of this user Detail Service and as you can see here this one is highlighted because we can replace it with a Lambda and if I replace it with a Lambda it will look like this but if any of you or if you are new to Spring Security this might be confusing so I'm just gonna leave it like this so you can understand or you can see that this is a new user details service implementation so that's it for the user Detail Service now we can move on and implement the rest as we can see here we implemented all the necessary or all the required classes that we have in how in our sequence diagram here but something is still missing first we need to tell spring to use this user details service instead of his own implementation and how can we do this so here we have uh in this configuration or like in this security filter chain here we can tell spring to use our authentication provider so here we can all we will do is total spring to use our authentication provider and in this one I will just create a bin of type Authentication provider so I will just go ahead and create the method for that and this one is going to be a bean so it should be public and here I will just add The annotation mean so this authentication provider as you can see here is of type authentication provider and this authentication provider we have it this is also an interface and we have different implementation provided by spring so what we can do I will create a final Dao authentication provider object or class and this class is implementing this authentication provider interface so I will just call it authentication provider equals new authentication equals new Dao authentication provider and for this using this provider so first I'm just gonna return it and then we will see what we will do with that so for this authentication provider we have a bunch of set methods so we can set the password encoder the user details service and so on so forth and the one we want to use here or like the one we want to provide we want to tell spring hey use this user detailed service like use our implementation and our implementation is this one so this is the method that we want spring to use instead and also it's mandatory also to tell which password encoder we are using for our application and here I will create a bin and in our case in our example here we are not we are not encrypting the password here so we can do it we can do the encryption or we can just leave it as plain text so it's up to you guys so I'm gonna tell you how to use both of them so in case so first of all before going let's make this one public and tell that this is a pin so if you don't want to use a a password encoder and this is I do not recommend at all but for example if you are in a Dev environment or you you want to do things in your local machine and you don't care about encrypting the password there is a class called No operation password encoder dot get instance sorry yeah this one dot get instant so this one is a password encoder and it's a class that does nothing just nothing uh okay so here as you can see here this one is deprecated and if you download the source it will tell you that you should not use this one for your production environment so this is the first the first second one if we want to uh use to really encrypt our password there is a class called be Crypt password encoder and we can just return an instance of that and here we need also to encrypt these passwords if we want to use the encryption so let's go ahead and encrypt this so let's inject here a password encoder or we can just use our password encoder um or okay I have a better idea we are in we are in the learning phase so let's not encrypt the passwords let's just keep it not encrypted let's just keep it as a plain text so now here we told spraying let's go back to our main subject here we told spring how or which authentication provider to use because in this authentication provider we are providing or we are telling spring to use a specific user detailed service and also a password encoder there is something super important that we need to add into our configuration which is the session creation policy means how we want to handle the session creation within our security or our authentication system so what we need to do here is we need to tell spring the way we want to handle the session creation so we need first to add here a session management object and then we will tell it a session creation policy and here we have different types of session creation policy so here the option that we will use is stateless means that we we don't want to save this session state so if the user is authenticated and the request is completely done then the session state is not saved and always it's going to be saved if required means if required and never it will never be saved so what we want here it we need it we need our session creation policy to be stateless and here I need to add the keyword and so I can click keep so I can keep continue on adding more configuration so this is super important for you guys to to add otherwise if you authenticate you authenticate your user the first time the session will have always the authenticated state and this is the behavior that we don't want to add our job is almost done what we need to implement right now is an authentication controller so we need to create an endpoint that can authenticate a user and generate a token to be able later on to access these greetings controller that we created at the beginning of our tutorial so I will go ahead and create a new controller I will just call it authentication controller I have a small typo here let me fix it and now that's it so I will just go ahead and copy paste these annotations just to make it as quickly as possible and here it's going to be auth for example now I will just create first of all I will just create an authentication or authenticate method so here it's going to be public response entity of string because all I need to do here like I'm just one not to make it as simple as possible all I need to do is return the generated token so here I will call the method authenticate and here I need to create an object because it's going to be the request body of my my request or my end point and I'm gonna create an object I'm gonna call it authentication request and this one I'm gonna just call it request and this one will be the holder or the class holder that will hold my information so I will create a package I'm gonna call it dto and in this case all I need to do is I need the getter annotation I need also the setter annotation and I need the no arcs Constructor in here so simply I will have two objects or two strings the first one is the image of the user email and the second one is a string password so this is my authentication request object let's go back to the controller now and all we need to do is we try or we will try to authenticate our our user so what we will do like when we want to authenticate the first thing we need to do here let's first add the required RX Constructor annotation and here we when we want to authenticate a user all we need to do we need to delegate this authentication process to Spring we don't need to do anything and to do this I will just inject an authentication manager bin an object of type authentication manager I would just call it authentication manager and here all I need to do is this authentication manager dot authenticate and this authenticate method will take an object or parameter of type authentication and this type authentication I can use the I can use the username password authentication token and here all I need to pass is the request.get email and the request dot get password so here anytime I try to authenticate my user I will delegate this whole process to Spring and this one or spring will do the process and he will call the user details service and so on so forth to authenticate the user so here there is nothing else that I need to do except that I don't have a bin of this of type authentication manager so I need to create one or I need to provide one I need to provide a bin of this type so let's go back to our configuration and our security config and let's add a bean of type authentication manager so it should be public because it's a bin so public Authentication manager I'm just gonna gonna call it authentication manager and for this one I will pass the authentication configuration as parameter I will ask spring to inject this config class because simply my authentication manager is within the config within this config object so here I need to add the throws exception because this authentication manager may not might not be present so I need to add the throws exception to My Method signature so now I have my authentication manager so everything is fine now once the user is authenticated so for example this means if I pass a username and password for example these two ones means that my user is authenticated so what I need to do now I need to get this user and and then all I need to do is to generate a token so I need as spring does so I need to inject the user details service I'm just gonna call it user details service and this one should be final two so here I'm gonna create the object user details I can make it final here because I don't need to change it uh okay so I'm just gonna call it user or user details as you like equals user details service dot load user by username and here all I need to do is to pass the email from the request dot get email and here if the user exists all I need to do here is a small text a test sorry if the user is not null what I need to do I need to inject here my JWT utils class of course this one should be final and because this JWT utils class is the one responsible of generating the token uh okay so now all I need to do is call this return JWT utils.generate token and they need to pass the user details otherwise let's say for example return some error has occurred just an example uh okay so uh yeah this one it should be wrapped that both of them they should be wrapped into a response entity dot okay and this and here it will be something like that response entity dot not accepted but let's say internal server error or let's say about the request it's not it's not the best but we we can tell it's a bad request or here let's say status 400 as a bad request dot body and this is gonna be my the body of of my response so now I need to add the post mapping because it's gonna it should be a post mapping and this slash authenticator will just add authenticate as an endpoint name so it's going to be slash API V1 slash auth slash authenticate to authenticate the user so now we can move on we can move on and authenticate test our application and authenticate one of our users and try to access these greetings controller at this phase I want to do some cleanup for our application code so what I want to clean is this so here we have this load user by username and we have this one and in order to fetch any user information we always need to rely on this user detailed service so I want to break this one by creating a specific class or a specific implementation just to load or to fetch the users like for example imagine that we will Implement user repository that would fetch the users from the database so I will just go ahead and do this I will create a class I'm gonna make it as simple as possible I'm gonna call it user Dao and I will just create a Dell package so it doubts stands for data access object and in this user dial I will just go ahead and fetch well I will just move this one first I'm gonna move it here then I will just create a method in here that will contain this code so I'm just cut this one move it to this method so this method it's going to be public User it's it will return user or user details for example and find user by email for example this one is email and here I'm gonna ask for string parameter email and this one it will be like this so we will just return this one and here we have this find user by email and because this one is a repository or like it stands for a repository functionality so I'm just give it the repository annotation so here we need to go back and update our security config and at this place I will also inject my user Dao I'm just gonna call it user down I will make it final and here instead all I need to do is user dial dot find user by email which is this email and this is gonna make our code more readable and also for example in case you want to implement something using database or fetch the users using the database you can use something like this uh now let's go back to our JWT authentication filter and over here instead of using the utility service let's use here our user dial I will just rename this one to user Dao and here instead of float user by email it's gonna find you it's going to be find user by email and we will do the same thing here so instead also of using the user Detail Service we can user use our user dial service or repository and here I will just rename the variable and here it will be find user by image so like this we are also able to break a bit the dependencies between all all these pins so this is this is what I wanted to improve a bit in our code and as you can see here our code is much much more readable I can optimize the Imports and so on so forth so here we are just using our relying on this user Tau and that's it for this Improvement our application and authentication system is now fully implemented let's go ahead and test it so first of all let's start our application personally I always prefer starting in debug mode so I will start in debug mode just in case something is not working so I'm I would be able to to debug my application so my application started I'm just clean I'm just gonna clean the console and then I will use my Postman to test the application so as we did here let's go back and make a small reminder so to be able to authenticate we need to use this endpoint slash API P1 auth and then slash authenticate to reach the authenticate method so let's go back here and let's do it localhost so this is one okay I already have uh have the URL and as we saw here our request is let me just organize this so our request as we saw here is of type post and we need to pass an authentication request which should contain an email and password as values or parameters so I will just go ahead and select body and then row type and then Json so here I will create an object email which would be in our case for example for the admin User it's going to be Dot social at gmail.com and then I will provide the password and the password is just password now if I click on send I should get the token as we implemented it so let's click Send okay so here it says that can't send the request let's check what what's wrong ah sorry this is the wrong Port it should be 8080 sorry for that let's send the request again and what we see here is we have a 403 Forbidden forbidden means that we are not allowed or we are not uh authenticated to access the authenticate endpoint but logically this end point should be open so let's go ahead and update this and let's tell spring to authorize this requests so here first of all we I forgot something when I did the first configuration first of all we need to disable the csrf and this is a topic that I can cover in in a different video so here we have the authorized requests and what we also can do and here we can add an end matchers means that for this specific patterns what I want to do is I want to permit all means for example anything that comes from us because here in the authentication we have API B1 blah blah blah and then auth and then we have the authenticate and for example in this authentication controller we can also Implement a register functionality so I can cover this just using this pattern so now I'm telling spring hey go ahead and every time you encounter this pattern just permit it or these patterns because we can have a list here and just permit all make them available without any authentication so let's go ahead restart our application and test the changes the application started and let's hit the send button again so oh oops here we see a 500 internal server error so it's no longer 403 means maybe the process passed but we have something not okay in our application so let's quickly check this so here the exception is class not found exception and this one is coming from java X XML bind data type converter and for this one means that we have a dependency missing you might not encounter this one when especially when you when you use the spring boot starter data GPA dependency within your project because it's already provided there but if not if you encounter this exception all you need to do go to your pom.xml file and then add a new dependency and this dependency is the Jax B API this one it's this one this artifact ID jaxby API and the group ID is a Java xxml dot bind and you don't need to provide the version because it will be automatically provided by the spring parent project let's restart our application and now we should see our token if everything is going to work fine once we send or once we hit the send button from Postman we should see the token in the body of the response so let's go ahead and try it well nice this is our token okay I'm gonna just copy this one and I will go to the JWT dot IO website and this website is going to allow us to decode this token so I'm gonna just paste that one and let's see what information we have we have the header which is the the signature algorithm we used which is the hs256 and we have also the payload so the subject that we defined is the user email or the username and the expiration date the expiration date we said that I wanted to be expired in 24 hours so this is the time and the date where when my token was generated and here the issue date is it was generated right now and here if I add 24 hours it's gonna be just the next day and here we have the authorities that we added also if you want to add more claims you will find them here in this payload so now we have our token let's try here to to access this greeting again and we see that we still have a 403 that we are not authorized to access these greetings endpoint so let's go back to our Postman and I will just here for the authorization before just even typing the URL I will just go ahead here and tell spring that I want to use a beer token sorry not spring but Postman sorry for that so let's tell Postman that we want to use a beer token and click here this is an old one I just need to remove it and I will paste the newly generated token now let's go here to our browser and grab this URL and put it in here so now if I send this I get the answer from my back and hello from our API because my back end will intercept this request and check the token and validate everything so like this we are secure and my backend Now using is uses a token to secure all the communication and for example if I just remove the authorization header and do send so we also get a 403. yep so let's let's try the goodbye end point just to be sure that everything's still working fine all right just say goodbye and yeah goodbye and see you later so that's it this is how we can Implement security or this is how we can secure our backend application using where the basic authentication and JWT authentication thanks a lot guys for watching this video and and see you next time all right thanks for making it this far if you haven't subscribed do so and also if you haven't smashed the like button please just take one second it's free and smash the like button because that way we can keep on providing you guys content like this and as I said go ahead and subscribe to the mailing list for when the Spring Security course is released you'll be the very first one to be notified also if you haven't subscribed to alibu channel go ahead and subscribe to his channel go ahead show some love and if you're not part of the Amigos code Community both Discord as well as Facebook go ahead and join because it's absolutely free this all for now comment smash the like button if you haven't done so and I'll catch you on the next one
Info
Channel: Amigoscode
Views: 70,081
Rating: undefined out of 5
Keywords: spring security, spring security tutorial, spring security in spring boot, spring security jwt, spring security oauth2, spring security microservices, web security adapter, amigoscode spring boot, amigoscode java, amigoscode
Id: b9O9NI-RJ3o
Channel Id: undefined
Length: 91min 4sec (5464 seconds)
Published: Tue Dec 06 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.