Spring Boot + Spring Security + JWT from scratch - Java Brains

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this tutorial we'll be creating a brand-new spring boot and spring security project and we will implement GWT based authentication and authorization will create an endpoint that accepts user ID and password and can authenticate and it returns a JWT and then the fire and some code check incoming requests for charity in the authorization header and authorized requests that have valid GWT let's check it out [Music] as always I'm gonna start creating a new spring boot project by going to start out spring day oh my packages I ordered Java greens and I'm going to call this project spring security JWT now onto the dependencies I'm gonna need the web dependency and the security dependency these are the only two that I'm gonna add for now and we will add a couple more dependencies later once we have downloaded this project and open it in IntelliJ so here's my project open in IntelliJ the first thing I'm going to do is create an endpoint and I'm going to call this hello resource and this is going to be controller and there's gonna have a single method which is a hello / hello endpoint which returns a string hello world this is nothing special here obviously the only reason I'm doing this is because I have an API that I can put behind an authentication wall so that only someone who was authenticated can access this API now since spring Security's added to the class path that's kind of the default behavior for spring security there's gonna create a user out of the box and this /hello is going to be behind that authentication wall and only that authenticated user can access this API but we don't want to do that we want to have some flexibility in this and we also want to seed a user so I'm going to use the user service method of overriding the default user behavior I'm going to create a user data service which returns a static user and I'm gonna see that in do the spring security framework so that it leverages that user data service so I'm going to create this security class now call the security configure extends web security configured added Apter and now I can use the configure method to set values to the authentication manager builder all right I'm gonna do the auth dot use the detail service I'm gonna send it my user details service I don't have this here of course so I'm gonna have to create it I'm going to create a field called my user detail service and I'm going to create a class called my user detail service as well all right so I'm going to create this class and I'm going to auto wire at this if this is not clear I highly recommend you check out this tutorial which explains how to override to use a detailed service right so we create a new service called user details service and I'm going to put this in the services package now this is going to implement you user detail service and this is going to contain a method which Spring Framework is gonna call in order to load a user by user name right so it's gonna pass in this user name over here and it expects your method to load the user based on wherever you got your user saved it could be inside a database it could be somewhere else what I'm going to do is return a hard-coded user with a certain user name this is fine for the purposes of this tutorial but this should ideally be whatever is storing your user information in real world into return new user I'm going to use the spring securities class called the user these user details dot user I don't even bother to create a new user class you might want to do that if you have certain specific values that you want to track for your user all right so the default constructor for a user takes in the user name here which is I'm going to call it - the password I'm gonna call it foo and then let's see a collection of authorities and are dealing with authorities right now so I'm just going to put an empty list here URL list so now what's gonna happen is this I'm going to mark this is a service of course so this becomes a spring service and then my security configure is going to result in spring security calling this method and whatever is the authentication manager builder it's gonna pass in I'm gonna say hey I've got to use a detail service which is this guy use this and now spring security is going to call my service and it's gonna pass in the user name and then say hey give me a user with that username and I'm gonna return a user with foo and foo and I'm just gonna compare whatever password I've entered the password over here which is foo if it matches well and it says authentication successful so I'm going to enter the password foo and the user fool when I'm trying to login then it should ideally work fine now the security configure means an annotation which is enable web security this lets spring security know that it has to do something with this guy all right so now I have a REST API I have we used a detail service which returns one user and I have configured spring security to rely on the user information provided in the use the detailed service there is one last thing for me to do which is to add a password encoder I'm going to choose the North password encoder because I have specified the password as foo in my user details service right so I want the spring security framework to treat the incoming password as as and not do any hashing all right that's the reason I have the normal password encoder it's a requirement in order to get your application up and running but with this yeah kind of done with a basic user credential based authentication so far we haven't done nothing to do with GWT all right this is just a simple user hard-coded and then having spring sec leverage that user right so I'm gonna execute this by going to the main method and running it and now I open a browser and I enter this URL localhost 8080 slash hallo which is the endpoint that I've entered when I access it spring security doesn't let me in obvious reasons it expects me to use one of the user IDs and passwords that is in the system and right now we know that there is just one user in the system is readies foo password is foo and that I hit enter I am able to see the message helloworld which is from this controller now that we have a spring security project working without JWT now we need to add JWT into the picture the first thing I'm gonna do is add a couple of dependencies into the palm dot XML so I'm going to open the palm read XML and add two dependency specifically the first dependency is called JJ WT this is a library that lets me create JW T's and also validate existing JW T's kind of a Java library equivalent for whatever we've been playing with in the UI J Dilla T dot IO in the previous tutorial you can create Jade abilities and you can also Paris existing Jade of duties and verify it that's the s-- library the second library I'm going to add is a Jack's B API library this is specifically required because of certain Jack's B dependencies and also specifically because I'm using Java 9 plus any Java 9 plus version will not have the Jax P dependencies provided in the JDK that got removed as a result of modularity that was introduced in Java 9 so if you're using a Java 9 or newer you will need to add this as a dependency so that Java X XML bind Jack's PAP eyes are available in the class path so these are the two dependencies I'm gonna add and next I'm going to move on to creating a util class alright so I'm going to create a class called GWT yuto I want to create a class which can abstract out all the GWT related stuff I want this to be the YouTube class which allows me to create you did abilities given user details object and I also wanted to be able to pull up information from an existing jet ability like look up user name from a jet ability look up an expiration date from a g8 ability and all that kind of stuff I'm going to copy paste the code here because there's a lot of code to be written I don't want to bore you by typing this whole thing but what I'm gonna do is paste this code and walk you through the methods one by one alright here's the completed GWT util class let's look at the important methods here the most important method here is the generate token method which takes any user details object this is the user details object that our user details services gonna give us and what I want this method to do is to create a JWT based off of this user details which means taking Lee username from the user details obviously and making it into the JWT so what this is gonna do is it's gonna call the create token which is a private method over here and then it's gonna pass in a map of claims which is currently empty but you can pass in any other specific claims that you want to include in the chat ability anything that you wanna include in the payload and then you create a Jade ability for the username that you need right this is the create token what the create token is gonna do is it's gonna call the Jade ability API that we include it in the pom direction we'll just now it uses simple the pattern and it is setting the claims that we've passed in right now it's an empty object but again like I said this can change it sets a subject the subject is the person who is being authenticated who has successfully authenticated in this case I'm using the username over here right and getting the username passing that in and setting that as the subject and now I can set a bunch of dates I can set an issue that date which is the current date and then I'm also going to set the expiration date which is the current date plus I think this is 10 hours here so this is milliseconds thousand plus 60 times 60 times 60 which is gonna give hours and then 10 hours this can be anything depending on your implementation alright so I'm getting the claims which is empty setting the subject with user name setting issue that which is the current date expiration which is ten hours from now and now finally I'm gonna be signing the stoker I'm going to use the sign myth method to sign the token I'm using this algorithm signature algorithm HS two five six and then I'm passing in the secret key here the secret key I have defined it as a string secret this will obviously need to be something a little more complicated than you're implementing a real application then I'm going to do a dot compact which is the end of this whole builds a pattern here right so this is a builder pattern used by the JWT API that we have chosen for this project there are a bunch more you don't have to use this specific API and the specific Jade ability dependency this is just the one that I happen to choose alright so this is gonna do a create token so anytime you can pass in user details do the sooner a token method and what you're gonna get back is a Jade ability for that user so you can imagine when somebody authenticates you will need to create a jade ability out of the user details of a successful authentication and this is what will help you okay now the generate token calls the create token which basically takes in the claims and takes in your user name and then creates a token out of it the next important method here is the extract claim method which takes in a token and then it uses a claims resolver in order to figure out what the claims are right we have a bunch of data that you have passed and then this is a way for you to get that out okay I'm not gonna go into the details of this guy but basically there are a couple of methods that are using this so there's an extract username method which takes in the token and then returns the user name from that token there is an extract expiration which takes in a token and then it returns the expiration date so basically what it's doing is it's using this extracting method to pull information from an existing token okay now there is a token expired method which returns whether the token is expired or not which is basically taking the expert from the token and then seeing if it's before the current date right simple enough finally there is a valid a token method which gets the username using extract username and then it checks if that username is same as the username and the user details that's passed in write checks if that's equal and it also checks that the token has not expired all right couple of handy methods here that we will use in order to both create chat abilities and to validate existing chat abilities okay now that we have a foundation for JWT let's look at what we need to do to get this application to work with Jade ability right now we have a form base login and default credentials that are created from the user data service that we have seeded in now the first thing we need to do is to create an authenticate endpoint okay now we don't need a user ID and password farm anymore we need some API where we can post our user ID and password that API endpoint does not redirect anywhere what it should do is return back or GWT in the payload ok the response needs to contain the JWT and now the client we're gonna assume that the client holds on to that JWT and sends it in subsequent requests in the header okay now we also need to handle that so we need to create a way where we can examine the incoming requests for the header and then get the JWT out of it and then verify that it's valid if it's valid we need to make sure that that's in the security context as the currently logged in user okay there's a lot to do we'll take it one step at a time the first thing we're gonna do is create an authenticate API which takes a user ID and a password and then it returns back to GWT so before I create the API what I'm gonna do is create a couple of classes which form the input and the output for that method that's act as a controller right so I'm gonna create an authentication request in the marginals package and this is going to contain a couple of member variables use it I username and password all right so this authentication request is going to define the input argument to my authenticate method right so this is what the user is gonna send in the post request and I need a class to define what that structure is okay now what I'm gonna do is create getters and setters for both and then I'm going to create a constructor which takes in both as an argument so that it's easy for me to construct something I'm also gonna create a constructor with no arguments because I need this for serialization okay now have a authentication request I'm also going to create an authentication response new Java class authentication response what do I need in my response I just need the JSON web token alright so we're gonna have one string then the variable and then I'm going to create a getter for this and then of course I'm gonna use a constructor think this is an argument okay so now I have the input structure for my authenticate method which takes in the username and the password in the post request and have the output structure from our education method which is just a a property called JWT in the response with the actual treatability value now what's left to do is to create that authentication endpoint I'm gonna go here to the hello resource and then I'm going to create this request mapping slash authenticate this is gonna take in a username and a password as an input argument it's gonna return the Jade 3t okay what does this method look like the annotation needs to be authenticate with the request method being post okay it's not a get now it's a post request because the user is gonna be sending the username in the password in the post body okay next I'm going to create this method definition called create authentication token which takes in the authentication request an instance of the authentication request and it's annotated with request body so that we know that it's parsing the request body to get the username and the password from the request body and then the response is the response entity and we are going to be creating a response entity out of the authentication response class that we've created okay next I'm able to get the username and the password from the authentication request right spring MVC is going to set this in my instance now I need to actually authenticate it in order to authenticate I need to get a handle to the authentication manager so what I'm going to do here is create an instance of a sorry a member variable of authentication manager which is going to be auto wired alright I'm going to get the authentic manager instance water wire then and then I'm going to use this authentication manager instance in order to authenticate a new username and password authentication token and I'm gonna get it the authentication request get username authentication request dot get password right so I'm gonna give this username password authentication token which is the standard token that spring MVC uses for username and password okay and I'm gonna it call authentication manager down authenticate now if this authentication fails there is an exception so what I'm gonna do is I'm actually gonna handle the exception here by putting this inside a try-catch block okay now that try catch your maybe this thing over here so what's happening here is if this authentication fails I'm gonna catch it with the bad credentials exception I'm going to throw an exception saying this is an incorrect username or password okay now when you complete this execution this means that the authentication has succeeded what happens next well the authentication is successful then this method needs to return the JWT right now remember in order to return the JWT I need to create a JWT and we have created the yuto which takes in the user details in order to create a Jade ability out of it so I need to get access to the user details which means that I need to fetch the user details from the user details service all right so I'm going to get the user details using use a detail service that load user by user name I have the user name I can get the user details out of it of course I need to auto wire the user details service first which I'm going to do over here okay now have the user detail service I use the user detail service in order to get the user details now that I have the user details I can use the JWT yuto that we have created in order to get the Jade ability out of this user details so I will need to of course or to wire the GWT youto and then I can call the generate token passing the user details and I get the GWT course I'm going to create then the variable here gdb to you - and I'm calling the generate token method of it now that I have the token all I need to do is create a authentication respons instance and pass it back by creating a response entity out of it right this is standard REST API so I call the response entity dot okay which means that spring MVC is gonna return a 200 ok and the payload of the response is going to be new authentication response of jaded DT an authentication response is our class that we've created for this very purpose okay to recap we created an authenticate method an endpoint which is mapped to the create authentication token the stakes in authentication request which is basically the payload in the post body which contains two username and the password I'm using authentication manager in order to authenticate with the username and the password that is passed and if it does not authenticate I throw an exception if it does authenticate all I need to do is create a JWT token the Jade abilityto kanuto needs user details in order to create a GWT so I'm going to call the user details service that load user by user name because all I have is user name at this point right somebody is authenticated with the username and a password and all I have is user name I'm gonna get an instance to the user details and I'm gonna pass that in to the JWT token YouTube to get the JWT and then I'm gonna put that in an authentication response and send it back now with this I have an endpoint which does authentication now here is a problem I cannot call this without authenticating first because remember Spring Security is putting an authentication around everything we couldn't call hello directly we had to authenticate to call the slash hello similarly it will expect us to authenticate to call the slash authenticated which is Nicholas so we need to tell spring security to say hey when somebody calls this slash authenticate and fine don't expect the user to have been authenticated so what I need to do is go to the security configurator and then I need to specify a method override for HTTP security over here all right I'm going to paste this piece of code here and what this does is it disables cross-site request forgery and then it authorizes requests for a slash authenticate this policing permit everybody for slash authenticate and then any other request needs to be authenticated all right so if you're basically saying hey spring security for this particular API feel free to let anybody in for everything else ensure that they are authenticated okay now let me actually execute this and you can see our API actually accepting user name and password which is foo foo and then it returns a JWT if this works you might have an issue with this particular beam you remember I have this auto wire authentication manager okay this used to work in an older version of spring boot but this is one of the backward incompatible updates to the newer version of spring boots specifically spring boot 2.0 so in order to make this to work I need to define a beam of authentication manager earlier there used to be a default implementation of authentication manager that you could inject that's not the case anymore so here's what you need to do go to your security configure which extends web security configure our doctor and then add a method here override the authentication manager beam method and just root on the super all you need to do is add this add beam annotation to the sky so that spring security or spring rather knows that there is a beam called authentication manager it used to be this default beam but it doesn't exist anymore so all you're doing here is creating that beam and then not doing anything special you're just passing the super which is whatever is the authentication manager been in this parent class you're just passing that in okay now that you have done this spring security is gonna say hey I have this authentication manager now I can inject it into my hello resource all right let's run this again and this time if and should be running fine now what I'm gonna do is make a post request to the slash authenticate method using postman so here's my post request I have the methodist post the URL as localhost 8080 slash on the gate and the header has content type application slash JSON and in my body I am passing the username and password as foo and foo because this is what our user details Service expects and this is what the authenticate endpoint is verifying against okay so I'm gonna make a hit Send what's gonna happen this authentication is gonna succeed and it's gonna take that user detail and create a GWT token out of it and return it in the response and there you go we have a response fit or GWT built-in which is awesome okay now this GWT is something that you would hope a client holds on to either in local storage or in the cookie or wherever else and it passes to an API on a subsequent request ok so let's say I make a get request to slash hello this does not work right now because it says access denied what you would hope is that in the headers I can create a authorization header and then bearer and GWT now this should work once you have implemented GWT support right now we don't have JW to support all you have is a separate endpoint which returns a JWT value but it has nothing to do with spring security and what you need to do is tell spring security to listen to every the quest for this particular header authorization header and then there is a bearer and bla take this bla out treat it as a GWT extract the username out of it right verify it's a valid GWT if it's a valid Jade ability then you know that the person who is sending this Jade ability is trustworthy so you can blindly rely on the contents of the GWT get the username and put it into the security context so this is all the stuff that needs to be done now all right now how do I do this the way to intercept a request and look at the header that is by creating a filter there are a bunch of filters that are already available what you need to do is to extend one of those filters and implement the filter method yourself alright I'm going to create a new filter here in the filters package I'm going to call it G the beauty request filter right so this is a filter that is going to intercept every request just once and then examine the header right so I'm going to have this intercept every request only once by extending the right filter and it just so happens there is a filter called once per request filter to create name for a filter that runs once per request this is the filter that I'm going to be extending here there's a method called do filter internal alright so this is the method which actually does the job okay of this method do filter internal ticks in a bunch of arguments takes in a request takes in a response and it takes in the filter chain because it has the option of passing on to the next filter in the filter chain or actually ending the request right there what it needs to do is to examine the incoming requests for the JWT in the header right it's going to look at the right header and see if that GWT is valid if it finds a valid readability it's gonna get the user details out of the user detailed service and save it in the security context this is all that this filter needs to do okay so because of this it needs a bunch of dependencies it needs to use a detailed service in order to get the user details and if it finds a jade ability in the header it means Jade ability yuto in order to verify if it's a valid Jade ability right and all and to also pull up the username from it we actually create these two member variables here and then how to wire them so that spring gives access to them and I'm also gonna make this as a component because again this needs to be in Springs radar in order to or to wire this okay now that I have all the raw materials that I need in order to validate the header me actually get to it is get the header for the authorization when it will request I'd get header and the authorization and I'm going to get the authorization header if this has a valid GWT authorization header the author ID is this header string should contain better space and then the GWT so what I'm going to do next is slice a couple of variables username and GWT and now I'm going to verify if the authorization header is not null and if it starts with bearer space ok that means that what's coming after this in the authorization editor is the JWT so i'm going to do a substring of 7 which is basically leaving out better space which means substring of 7 is going to give you the GWT directly alright now that I have the Jade ability I'm going to use the GWT util dot extract username passing in the GWT and I'm gonna get user name all right they have the username I need to extract the user details from this so what I'm gonna do is the username is not null and there's this one condition which I'm gonna get back to in a little bit okay the username is not now I'm going to get use a detail service dot load user by user name passing in the username I'm gonna get the user details now that I have the user details I will validate the token with the user details remember the JWT Udo has a valid a token method which takes in both the Jade ability and the user details because it needs to know if the JWT is valid for the given user ok so this will verify if the username matches and the cheat ability has not expired okay if it's not expired then I'm going to create the username password authentication token which is the default token we've already seen this right this is what spring security uses for managing authentication in the context of username and password okay so I'm gonna create a new username and password authentication token and I'm going to set the details which is basically what's in the request so what I'm doing here is what would have happened by default but since I have taken over I am doing this only under one condition and the condition is if the chat ability is valid the TDP is valid I'm simulating normal flow of operation all right this is what spring security would have automatically done and then of course I'm setting it into the context which is also another thing that spring security would have automatically done but I'm doing this only in the case of a valid GWT and of course notice here now this should make sense I am verifying that something has not already gone into the security context so even though I get a username from the Jade ability I am going to simulate putting that into the user context only if that user context does not already have an authenticated user all right now I do this and then of course at the end of this all I need to continue the chain so I need to say chain the do filter I'm passing in the request and the response and basically saying okay I've done my job I entered the filter chain and I did my job and now the rest of you filters whoever is doing what you just continue doing your job alright so it's basically handing off the control to the next filter in the filter chain okay so now that I have this the last piece of the puzzle is to go to the security configure and then tell it to use that filter change just putting a filter is not enough I need to interject it into the filter chain add fashion management to be stateless and basically saying hey spring security don't manage sessions alright don't create a session because the whole reason we are doing Jade ability is to make it stateless so this basically tells spring security not to bother creating a session okay well if spring security is not creating a session there needs to be something that works for each request and sets up the security context each time well that's where this line comes in basically adding a filter before the username password authentication filter I am passing in the filter that I created will this filter of course I need to I need to auto wire here okay so this is the filter that we just created basically saying hey spring security make sure this filter is called before the user name/password filter Escott okay now with this we are finally done I think let's run this I'm going to go back to post request for authenticate the header and the body click send I'm going to get back this GWT I'm going to take this JWT make this get request do hello and I'm going to try it without the GWT first okay there's nothing in the header I'm gonna try it without the JWT I'm gonna get access to nine but I'm gonna do authorization and then better and then the JWT and I hit Send this time it works because now our filter is looking at this and setting it in the context and when it comes to this API well user is authenticated now if I were to make another request here just to prove that there are no sessions let's say I remove this guy I make a request it's forbidden again because there is no state on the server it's looking at each request it has no memory of a previous occurrence with this JWT back in the header and this should work again alright so this was setting up a spring boot spring security project from the scratch to work with GWT the only deviation from a real-world application that we have done here is that we are not connecting to a live user resource we are not connecting to a database to get the users we are just hard coding with one user but it should be very easy to see how this gets extended to connecting to a database you would just need to change your use a detailed service to connect to an actual user repository to get user details for a given user name rather than a hard-coded list but in summary this tutorial we created an API endpoint which accepts user name and password and returns a fully-formed shade ability and then we also intercepted each request to our Spring Security API to listen to that JWT in the header bar set verify it and then if it's verified and valid set the security context so that the rest of the spring security framework doesn't know the difference it just assumes itself valid user if the GWT is one [Music]
Info
Channel: Java Brains
Views: 666,440
Rating: undefined out of 5
Keywords: java, java brains, tutorial, brains, koushik, kaushik, brainbytes, explained, java tutorial, learn java, java tutorial for beginners, java programming tutorial, java programming, java programming for beginners, spring, spring security, programming, spring boot, koushik kothagal, beginner, java training, authorization, authentication, spring boot microservices, userdetailsservice, spring framework, spring boot security, spring security tutorial, jwt, json web token
Id: X80nJ5T7YpE
Channel Id: undefined
Length: 39min 28sec (2368 seconds)
Published: Fri Oct 25 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.