Spring Boot and Spring Security with JWT including Access and Refresh Tokens 🔑

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hat's going on, guys. Assalam Walekum welcome to Amigos Code. In this video, you're going to learn everything you need to know in order to secure your backend. Applications use Spring Boot and JWT. So last year I've posted a complete course on Spring Security, and I've been getting a lot of questions from you guys. Wanted me to teach you about extra security topics on and so forth. So this is one of many, and this course is actually actually this video is actually brought to you by Junior. So Junior from Get Raise has been creating some content for Amigos code, and very soon we're going to join forces and bring you guys so TypeScript, Angular, and a bunch of other cool courses that you guys have been requesting. So go ahead and show some up to Junior Subscribe to this channel, either somewhere here or here. And Yeah. So this video, you're going to learn about Spring Boot, how to set it up using JWT, connecting to a database access tokens, refresh tokens, so on and so forth. And then you can take everything that you learn and then just basically use it within your React application. Angular, Flutter, Swift, Android, whatever. Right. Because the Backend exposes a set of API that any client can use. If you're new to my channel, go ahead and Subscribe. Give me a thumbs up so I can keep on bringing you courses like this. Also, if you're not part of the Amigos Code community, both Discord and the private Facebook group over 30 0 people combined. Yeah. So I would love you to have you there. And Yeah, comment down below as like button and without further Ado, Let's begin this video. So before we dive into the code, Let's go ahead and define why the JSON Web token is. Every time you're trying to learn something new, it's very important that you take some time and try to understand the concepts before you actually start coding anything, because you really need to know what you're doing and why you're doing it. So what exactly is a JSON Web token? You can look online and you will probably see some fancy definition of a JSON Web token. But really, all it is is just a way for an application to transmit information. So you're just a way for application A to talk to application B to transmit information. And the reason it's so popular these days, it's because it's very small and self contained. And it's also very secure because it's small. You can pass it and the request body, you can pass it in the headers. You can pass it informed. So it's very easy to work with. So it's become very popular with APIs for authorization. The way it works is your application that's going to give the token to a user. They're going to create the token, take the user information, and then sign the token. That signature is digital. And whenever the user needs to access the information. The user will then send the token as their authorization. And I'm going to talk more about authorization and authentication. But you have to understand that the token is just a way for the two applications. Let's say the front end and the back end, or two backend applications, or just two applications in general for them to be able to communicate with each other and then exchange information. And JSON web token is mostly used for authorization. Let's say there's an API and I need to access it. So I would provide some sort of authentication. So I'll say, Hey, this is who I am. I provide my username and my password, and the application will verify who I am and this is authentication. And then the application is going to give me a JSON web token or a token, and then the application will give me a JSON web token, and that token will have my information, my permissions, et cetera. When I need to access a resource on the server, I will send this token with the request. So if I send a request to access, Let's say a list of users, then I have to provide this token to the server or to the application that I'm trying to communicate with, and that's going to be my authorization. So whenever the request comes in, the application will take it, look at the token, verify that the token has not been tempered with. So the token is good. And then I will check the permissions on the token to see if you have access to that specific resource. And then if you do, it will give you back the resource. And Adjutant web token has three parts, so there is the header and then the header. Typically you have two fields, so you have the algorithm, and then there's the type, which is always going to be iability because we're working with JSON web token. So the type is JSON Web token, and the algorithm is whatever algorithm that you see, define and the header, and then you have the payload. So the payload is going to contain information about the user or the entity. The token is four. So Let's say my name is John Doe. So this token is for me. You can see my name on it. My username. Let's say the subject. The John 24 is my username. And the time it was issued, the claims that I have are the permissions or the authorities that I have to create. I can edit. And that's just an example that I'm showing you. The point is the payload is going to content information about the owner of the token. And then there's a third part, which is the signature. And to create the signature, you have to take the encoded header. You take the encoded payload, and then you use a secret with the algorithm. You can take all that and then sign the token. So that's going to be the signature. And a JSON web token would look like this. So all the three different parts, we have the header and then the payload, and then the signature. So that's why you need to understand about JSON web token. It's just a way for application to communicate. And it's mostly used with APIs for authorization. When one entity want to access resource and another entity, and you can replace entities here for servers or applications. So when one application needs to talk to another application, they can use JSON web token to verify and authorize the application asking for the resource on the other application. And this is really just a summary. So if you want to know more, you can go ahead and Google this. But at least now you kind of understand what the JSON web token is and what it's used for. You can see on the left, I've already put in all the project meta data, so I put in the group ID, artifact, ID, the name, description, the package name, and everything. And I'm using a Java version 11. You can use any version you want, as long as it's nothing below eight. I think you should be fine. And we're not gonna be deploying this application. So for packaging, you can pick Jar or War. War is kind of like old. I would usually stick with Jar, but you can pick whatever you want. Depends on where you're gonna deploy the application. And then on the right, I have all of the dependencies that I'm gonna be using. First one being the spring data JPA, and then I have the driver for my SQL, and then we have the web dependency, because this is going to be an API that's going to be exposed on the web. So that's why we need the dependency. And then I have spring security. Of course, we need to bring in the spring security dependency because we're going to need it. And then I have Dev tools so that I don't have to rerun the application every time as long as I save, and it's going to be run by itself. And then last, I have Lumbar. And if you look in the bottom left corner, you already see that I have the zip file already downloaded, but I just wanted to show you what I have in terms of dependencies and project metadata. So I'm going to go ahead and open the application. And IntelliJ. You can use any ID you want, but I'm going to be using IntelliJ. I have the application open and IntelliJ, and I'm just going to navigate to the main class, expand everything. And Here's the main application class. So we have the typical spring boot application. So whenever you're designing an application, the first thing you have to do is to think about the design. So you need to know what you want to build and how you want to build it. Because there are many different ways you can build the same thing. Right. You can come up with different design, different ideas, and the list goes on. And this is something that you really have to understand when you're doing really anything in life. Before you start doing it, you need to have some kind of a plan that you can can actually visualize and think about your application in the way that you want it to be in the real world. Now, there's all kinds of fancy tools that you can use that can help you to do that. We're not going to be doing all that in this tutorial, but I'm gonna go ahead and show you a diagram of the two main domains of the application. So the user, which is the domain that we're going to be managing in the role for that user that we're also going to be managing. So if I minimize this real quick, and you can see that I have the user on the left, and then I have the role on the right. Now, the user doesn't really help have a lot of information in it. And that's usually not the case in production or in real world application, because we would probably need to have more information about the user than just the username and the password. In the roles, there's nothing really business related. So we're just sticking to the technical aspect of this. So I give the user an ID, a name, a username, and a password, and the role. So pretty much everything we're going to need for Spring Security to work. And then on the right, I have the role, which has an ID and a name, which is going to be the name of the role. And then we have getters and setters for our methods. It's going to be pretty simple, and that's what we're going to be doing in the application. So Let's go back to the application, and I'm going to create a new package, and I'm just going to call it domain. So new package, and this package, I'm just going to call it domain. Right. So this is where I'm going to have the user in the role, because those are like, domains or models. You could have also named this model, and I'm gonna create the first class, which is gonna be the user class. So I'm gonna go ahead and say user and press enter. Now, there's one thing I have to mention with this user class that I just created. Spring Security has a user as well, like a class or an interface. I don't remember exactly if it's a class one interface. But for Spring Security, there is a user in Spring security. So if you name your user in your application user, then be very careful when you're importing so that you can import direct user. So what you would typically see is developers would name this user app use so that they can differentiate it from the Spring Security user or some other libraries. User. But in that case, I'm going to be careful whenever I'm importing user, so I don't have to worry too much about that. And this is kind of important because sometimes you have very large applications and you have all kinds of developers. Let's say, for instance, you have some application, and it's for a company. So they're going to fire people. People are going to leave and know developers are going to come developers are going to retire and things like that. So sometimes you want to be very clear in what you're doing with the code because you have to think ahead very important. Remember that you might want to rename this to something more specific to your application, because there's a lot of libraries out there, and they already have a class name, user, and that can even create conflict. So just keep that in mind, so that's the user, and I'm going to go ahead and create the role as well. So I'm going to go here and say role pretty simple. And it's also going to be a class. And then I'm just gonna press enter. So now we have the role, and we have the user. So Let's fill in some of the information. So if you guys remember, the first thing we had was the ID of the user, so I can go ahead and say private, and that's going to be up to type long, and then say ID, and we need this ID, because we're gonna map it as the primary key in a database with spring data at JPA. And then we had the name of the user, so that's gonna be of type string, and that's just the name and also the username. So I'm gonna do another private field. It's also gonna be a string and the username, so the username can be, Let's say John 1-2-3, anything with your name or any random username that you have, but it can also be an email. So sometimes I have students asking me, Hey, I want to use the email as the user. Well, the email at list in Java, you can represent emails as string, so the username can be a string as well. Just because I name it username and not email doesn't mean you can't use it for an email address or something, because if you're able to put in an email field in there, you would probably give it a type of string. So you can use email in the back to represent the username. And then in the front end, when you have your login form, you can say provide your email address so that they don't provide a username like John 1-2-3 or something like that. And then you can have I validation on the email to make sure that you're getting an email and not some characters or string of characters. And then the next thing I'm going to need is the password. So Let's do string, and that's just going to be the password. So the password is going to be represented as a string as well. And then Lastly, we need to give the user the role, so we're going to deprive it, and that's going to be a collection. So I'm going to do collection and give it a type of role, which is the class that we just defined. So I'm going to do role, and I'm just going to call it roll. All right, give me the suggestion. And then I want to set this or at least initialize it to a new release. So I'm going to now a release. So this is going to be the user. So the user is going to have an ID, a name, a password, a username, and a list of roles. Now, we also need to manage this relationship with the role. And for this, I'm going to set up a mini, too many annotation, and then we need to define the fetch, because when I fetch all these users or when I load them, I want to also load the roles of the user. So there's no time that I'm going to load a user, and I'm not going to load the role. That's why I set this to eager, because I want to load all of the roles whenever I load the user. So that's what this means. We're going to load a user and at the same time, load all of their roles in the database. Now, we need to add some annotations on this class because we want to map this class as a table in a database, and we can use spring data GPA to do that. Let's go right on top of the class. And the first one that I need to add in is entity. So we're gonna do entity, and I also need to add the data annotation. So I'm gonna do a data. So that's coming from Lumbar, and that's gonna give me getters and setters, and I need the no argument constructor. So I'm gonna do a no arcs constructor also coming from Lumbar, and I need the all or constructor, and Lumbar is just gonna create those for me on the fly. So that's what I need at a class level. Now, for the ID, I need to specify the did notation, and I also need to specify how I want this idea to be generated. So I'm gonna do it generated value. And then here I'm going to pass in strategy, and we can just set this to auto, and that's pretty much everything we have to do for this class. So we have the user class. We just add in everything we're going to need from us security standpoint. But you could have as many other fields as you want in this class, business related information that you want to capture with the user. So what I'm going to do, I'm just going to go ahead and copy all these annotation. Go into the row class, and then just paste this because it's going to be the same. So we need the same information in there. So we're going to map this. We need the constructor and everything. And I also need to grab Let's grab these two, because we know we're going to have those, too. And I'm just going to go on a new line and paste. So we're going to have an ID that's going to represent the ID of the role in the name of the role. So that's going to be a string, and that's going to be the name of the role, and that can be something like role user, role admin, role manager, or something like that. And then I'm going to go ahead and copy the annotations and then paste them on this private ID as well. Okay. So now we have everything we need to map these two classes as table in a database, and we're going to set up the mask database in a minute. So those are the two entities that we're going to have in the actual application. So we're going to have the user. As you can see, we have all these information, and then we're going to have the roll keeping it very simple, just an ID, and then the name of the role. So I'm gonna go ahead and create another package, and I'm gonna call it repo, short for repository. You can name it repository if you want. I just like repo because it's shorter, and we need the user repository. So new class, and we're gonna do user repo, and this is actually gonna be an interface. So I'm gonna choose interface and press enter. And then I'm gonna extend the JPA repository, and I'm gonna tell the GPA, the entity of the class, that I'm gonna try to manage with this repository. In that case, that's gonna be the user class. And then I have to tell it the type of the primary key. And Let's go ahead and import user for class, and it's coming from our domain. Okay. So you can see here there is this user and many different libraries here. So there's one in spring security, which is the user details. There's another one here in spring Security. And then there's another one here coming from Apache. Another one again from Apache Catalina. And this is the one we need. That's the one that we just created. So you have to be careful when you name your class user, because there might be different users and different classes and different libraries that your application already import. So it's like that one. And I only need one method in here, and it's going to return a user. So I'm going to do user, and I'm going to call it Let's do find by username. So find by username, and we're going to pass it the username. So that's going to be a string username, and that's pretty much it. And hopefully you guys are familiar with this fine by username. So spring it at JP smart enough and knows how to interpret this as a select statement to Select the user by their username, which is the username that we're going to pass here. And then we need to do something similar for the role. So I'm going to go back to the repo new class. That's going to be the role repo and also an interface. I'm just going to copy all this and then paste it here, and I just need to change this to the role because we're managing the role. So Select the role, and then I'm going to change this to find by name, because we have this name filled in the role class. I'm going to change this from lowercase to uppercase, and that's all we need and also change the type. So that's going to return a role. So we're going to give it the role name, change this as well, from username to name. So that's the rule repository. It's gonna return a role if we give it the name of the role. And remember, you have to have this field name and this role class, which we do have. And here, as you can see here, so that's the rule repository pretty simple. And I'm gonna clean up this import here, because I'm not using the user in this class, and that's all we have to do. What I want to do next is to create a service. So Let's go ahead and create a service. First, I need to create the package, so that's going to be the service package, and it's out of this package. We need to create a class, and it's actually going to be an interface. So Let's say user service. So in here, we're going to define all of the methods that we need to have in the application so that we can manage the users. So I'm going to go down here and say, I need a method that can save a user, so save user, and it's going to return a user, and I need to accept the user information. So I'm going to say user user. So whenever I call this method, I'm gonna save the user in the database. And Let's go ahead and import this import coming from our domain. Next one that I need is to be able to save a role, and that's gonna return the roll back to me. So the return type is gonna be the role, and I'm gonna call it save roll. And of course, it's gonna take the roll. So I'm gonna say roll and then pass in the role, and we need to import the roll as well. So Let's do import, and that's coming from our domain. And then next, I need to be able to add a role to a specific user, and this method is not going to return anything. So I'm going to say void, and Let's say add role to user. You can come up with a better name if you can think of a better name. But I'm going to go with this, and the first thing we need is the username of the user. So we're going to say username. This is also assuming that we're not going to have any users in the database with duplicate usernames say, for instance, we have a user in the application, and their username is John 1-2-3. So we need to have a mechanism where if we already have a user with that specific username, we don't allow another user to create an account with username. John 1-2-3, because this username is already taken. So this is the assumption here. And then we need to have the role name, and that's also going to be a string, because we need to find that role in the database and then attach that role to the user. So we're going to say role name that we need to have so that we can add this role to a user. And then I need another method, so that's going to return a user. I'm just going to call it get user. And Let's pass in the username of the user because we need something so that we can go fetch that user in the database, so we can pass in the ID or the user name. In this case, I'm passing in the username, assuming that all the usernames are going to be unique. And then I need one last 1 that's going to return a list of all the users. So I'm going to say user, that's the type of the list, and I'm going to name it, get users, and it's not going to take any parameters. And there's one thing I also need to mention here. So whenever you have these kind of methods to get all users or get all rules or something like that, and the real world application, you probably wouldn't hit that, because this is going to try to load everything that you have in your database. In the real world, you would usually return a page to a user. And the reason for this is because you don't want the system to try to load all of the users that you have in a database because they're not even going to be group C, Let's say 50 0 users on the screen. It's just very inefficient, and it's gonna put a lot of stress on your back end, so you don't want to do that. So usually when you have methods that are gonna return, like a list of something, you want to return a page. So if there's a request to see all the users and the applications, Let's say you have 50 0 users, you're not gonna try to retrieve 50 0 users. You say, Hey, give me the first 10 users, and that's going to be page one. And you can say, if you want to see page two, then maybe you can send me another request requesting page to, and I can send you the next 10 users. And you can really set that number to whatever works for your application. So you can send the first 30 or the first 25 or the first 100. It really depends. But the point is you don't want to load, Let's say 50,000,000 users for something like get users, because that's just going to make your application perform very poorly. So now that we have everything we need for the service, so this service, we're going to inject it in our controller so that we can manage the users whenever requests are coming in. But we need to have implementations of the service, because right now we're not really doing anything. We're just defining what we want to do, and anybody can create implementation for this. So in the same service package, I'm going to go ahead and create a new class. I'm going to call it user service implementation. And then I want to implement the user service. I'm going to say implement user service. And then I'm going to go ahead and define all the methods that I need to override or implement. And I'm going to Select all of these and then press enter. So the first thing I want to do is to bring the repositories. So I'm going to say private. And Let's say final user repo. And Let's name this user repo. And I also need to bring in the rule repository. So Let's do something similar. So private, final role repo, and then name it role report. So those are the repository. So those are communicating with JPA directly, which in turn is doing a lot of things in the back end to create those queries for us and inquiry the database for us. And then I want to go on top of the class and make sure this is a service class. So I'm gonna go down here and then put the service annotation. So I'm gonna say service, and that's coming from spring. And I need the required art constructor, which will come from Lombok. And I'm going to explain what this is. It says the required argument constructor, because we have all of this field define, and we need to inject them in this class. So once we have this required our constructor, what Lumbar is going to do is it's going to create a constructor and then make sure all of these arguments are passed into this constructor, and that's how we're going to do our dependency injection. And then I need everything in this class to be transactional. So I'm going to do a transactional. And then there's one last annotation that I need, and that's for logs. I'm gonna do SLF for J. Okay. So I'm gonna be logging things out as we're using this class so that we can see what's going on in the log. So at this point, we can start filling out those methods. So for the save I'm gonna call the user repost. So that's going to be user repo, and we're just gonna call the save and then pass in the user that we're trying to save, and that's all we have to do here. Let's go down to the save roll. We're gonna do something similar. So we're gonna call the roll repository and then call the save method and then pass in the role, and that's gonna save the role. And then for Ed roll to user, first thing we need to do is we need to find the user by the username. So I'm gonna say user, call it user, and then call the user repo. So I'm gonna set this equal to the user repository. So user repo and then find my username and then pass in the user name. So that's pretty straightforward. Once we have the user, we also need to get the role. So I'm going to say role, and I'm just going to name a rule, set it equal to the role repo. So I'm going to say rule repository, and then fine by name, and then we're going to pass in the role name. And at this point, we have both the user and the role. So now what I can do is I can just say, take that user, get the rules of that user, and then add this role in addition to everything else that the user already has. So if the user had some were before, we're just going to add one more to the roles of the user. And here I can just pass in the role. And once this method is done executing, because we have the transaction or annotation, as you can see here, it's just going to go ahead and save everything in a database. So I don't have to call the user repository and then save anything again. And that's what we have to do for Ed role to user. And also, another thing I want to mention here is this application is really simple. If you are building something for real, like for the real world that's going to be deployed and everything, you would probably have more going on here. Like, more logic going on here. You wouldn't just save a user. You would probably we have validation on the name and username and things like that, but we're keeping it simple here. So Let's Scroll down to the get user, and we're going to call the user repo again. So user repo that find user by username, and then just pass in the username. So this is going to return the user and then to get all the users. So I'm just going to come here and then call the user repository again, and then call the fine all. So that's going to return all the users and interface. And that's everything we have to do for the implementation of this specific service or for this specific implementation, because you can have multiple implementation of a single service, but in our case, we only have one, which is just that one. And I noticed that I'm not using the log yet. So Let's go ahead and put in some logs so that we can see what's going on whenever we're using this method. So I see log. And Let's just say saving us a new user to the database, and we need to pass an info here. So I'm going to go ahead and copy this and then paste it down. And I'm gonna say saving new roll the database, and we can log, like the role name. So I can do something like this. I can put open and close care bases, and then I pass in Let's say the role name, so I can go here and say roll a name or something so that we can see the role name, and this is the same here, just so we can see exactly what's being saved. And then I'm going to say use that. Let's say get name or something, and then we're going to do something similar with the role to user. So Let's copy this, and Let's cut down and past it. What I want is I want to say something like adding role and then pass in the role name and say to user, and then pass in the username. Am I? And then I can just plug this in. So here I'm just gonna say, first one is going to be the role name. So I see role name and then username. And then I'm going to copy this one more time, Scroll up a little bit and paste it down here. In this case, I only have the name. So I want to say something like fetching. So Let's say fetching user and then passing the username, and we don't need all of that. And then Lastly, copy this one more time, go down here, and I'm just gonna see fetching all users. So here I'm gonna say fetching all users, and that's what we have to do. So that way, whenever we're calling these methods and from our controller, through our service and everything, we can look in the log and see those methods being called. So now at this point, we can create a controller. We can inject the service in this controller. So the service that's being implemented by this class, we're going to inject it in our controller, and then we're gonna put the MySQL configuration and then run the application and check it out in the browser. So I'm going to go into the main package again and then create a new package, and I'm going to call this package API. So this is going to be the API package. And then in there, I want to create the user resource. So here I'm going to say user resource or controller, whatever you want to call it. So in the user resource, the first thing I need to do is to inject the controller. So I'm going to go ahead and do something similar again that I did in the implementation. So I'm going to do private final, and then I'm going to call the user service user service, and then give it a name of user service. And then I need to make this classic controller. So I'm going to add the controller annotation or rest controller in this case. So rest controller, and also the required Arcs constructor. So Let's do acquired Arcs constructor so that we can inject this filled into the constructor. And then I need the request mapping so that I can give this entire class of Bays path. So here I'm gonna put this second, so I'm going to say it, and then I do request mapping. You can see it coming up here from Spring and then pass in a path, which is going to be a string. So I'm going to say everything in this class or everything in this API, they're gonna leave under API. And Let's create a method to return a list of all the users. So I'm gonna do public, and I'm gonna make this return a response entity. So response entity, and I need to pass in a type to this, and this is gonna be a type list of users. Okay. So you have to just give this a type, because the response entity is a generic, and I'm just gonna give you the same name. So that's gonna be get users. And of course, that doesn't take any parameters. And in here, all we have to do is to go ahead and call the service and then have it return the users from the database. So here I'm going to say return response entity, and I want to return the okay through user to let the user know that everything went well, and then I can add a body, and in the body, I'm going to call the user service, get users. So that's going to return all of the users and the body of the response. And that's really all we have to do for the specific method. So Let's go ahead and import this user, import and also import the list. And then after that, we need to add in the annotation that we need to add on here to determine if this is going to be a post or a get request. So here I want this to be a get request. I'm going to do get mapping and then make this go to Let's say Let's say I want this to go to users. So users. So if we want to access this endpoint, we're going to have to go to whatever the base URL is. So local has eight and 80 in this case, and then go to API and then for users. And if we do that, we should have a list of a bunch of users and the response. So now the only thing we have to do so that we can run the application is to put in the configuration from SQL, and I already have my SQL install. So whatever database that you you have, Let's say you have post Gree or whatever the case might be. As long as it's a relational database, you should be good to go. The only thing is you just have to know how to put in the configuration for it. I have my SQL install, and I've dated for a long time, so I usually just use it. So Let's go into the resource and go into the application properties file. And you can see I already put in the properties that I need to put in. The database that I have running on my local host is in MySQL database. So you can see at the jbcoscousa and the name of the application that I'm gonna be using. And then I passed in my username and my password, and you wouldn't use your root password. But in this case, since this is a demo, so that's the problem, and it's only gonna be on my computer. So there's no vulnerability here. And then I set the DDL to create. So every time we run the application is gonna crash everything and then rebuild all the tables and everything again. And I'm showing all the SQL queries and the log. So that's what this show SQL true is doing. And then I specify the dialect of my SQL. So that's kind of like the version of my scale that you have installed, and I have version eight. So I pass in my SQL eight dialect, and then I pass in a format for the SQL. So the SQL format is to format the SQL log in the log so that we can read them more easily. So I'm going to go ahead and close this. And again, you can check out the source code in the description. If you need to grab this, you can just go ahead and copy and paste it. And Let's go ahead and run the application. So I'm going to go ahead and click on this green arrow and wait for the application to come up. So the application just came up. You can see here we have the password. I was generated by Spring security. And you can see the logs are here. We can see that the tables were created, and you can see everything is here. So we have it's creating the roll table, user table. So we're good to go. We didn't get any errors or anything like that. So Let's go ahead and open the browser or postman. In this case, I'm going to use the browser and see if we can hit API. So API for users. And again, we're running on local host Port 80 because we didn't change that. So Let's go ahead and open the browser and go to locals at eight. And we need to go to for API users and see what happens. Let's click enter. So I'm presented with the login from spring. So that's a default login form that you get when you don't specify anything in the security configuration, and we don't have a configuration yet. So Let's see if we can actually see anything. If I go ahead and grab this password, I'm going to copy it and see if I can use the default user and pass in this password. Click sign in. And if I Zoom in a little bit, you can see we have this empty list here. So that means that we were able to access the API, and we get an empty list bag or an empty array because we didn't have any users. So everything seems to be working perfectly. Let's go back to the controller. So Let's open the application, and I'm going to minimize this for now. Let's go ahead and create the other functionalities that we want to have in this application. So we want to be able to save your user, save, add a role to a user, etc. So Let's go ahead and copy this method here and then paste it down. So I'm going to go ahead and paste it, and this is going to be the method to Siva user. So I'm going to change this from a get to a post, because whenever you're trying to create a resource on a server, you want to send a post request, and I want this to go to a user and then save. Okay. So it's going to go under API user, save. And this is going to return a response entity that's going to have a user inside of the body, and we're going to call this save user. So save user, and I have a typo here. So save user. And then we need to get the user as a request body. So we need to pass in the simple request by the annotation. So Let's say request body, and then pass in the user. So we're going to say user, give it a name of user, and we're going to call the service again. So we're going to return 200 okay. For the user, assuming everything went well, and then call the service, and then we need to call the save user. So here I'm going to do control space, and then call save user and then passing the user. So that's pretty simple. Very similar to what we just did. The only difference is we're calling different methods from the service, and then I need another one to save a role. So I'm going to copy this one more time and then paste it down, and I want this to go to roll and then save. Okay. So we're gonna go from API or roll or save, and this is going to return response entity that's gonna have a role inside of it. And then Let's call this save roll. Make sense, right? Saving a roll. And then here we're gonna say, this is gonna be of type role and name it roll as well for the variable. And then Let's call the save roll on the service. So we're gonna say save, and you can see the save role coming up, and I'm just going to pass in the role. So almost the same thing. It's only the entity that is different. And we're also returning a 200. Okay. And now that I'm thinking about it, this is actually supposed to be a 201. So that should be actually created. So we're going to say created. So the created takes a Uri, and we have to pass in this Uri. So I'm going to put no for now and then see if I can create a specific Uri so that I can pass it in here. So instead of sending a 200, which is a 200, OK, it's more precise to send a 201, which means something was created on the server resource was created on the server, because that's what these methods are doing. So here I'm going to Let's say Uri and call this Uri, and we're going to call the create under Uri. So I'm gonna say Uri that create, and then I can pass in a string here or anything that I want, but what I usually like to do is to get the server path. So I'm gonna say server. So Let's say serve, let Uri, and I want the builder. And then I want the from current from current context path. So that's going to give me the local 80, and then I can pass in another path here. So here I can say this is going to go to API user save, and then turn this into a Uri string. So I'm going to do that to Uri string. So now I have the Uri that I can pass it in. And what spring is going to do is it's going to take this and place it in one of the headers. So I'm going to replace this now passing the Uri and Oops, I missed the equal sign here because I'm setting this variable. And then I'm gonna do something similar for the save roll because we're saving a row, so that's 200 is fine, but it's better to be more precise. So that's going to be created. And I'm going to change this to created and then pass in the same Uri. So here last year and make this go to roll and then save roll, save. Alright. So that we can have everything the way that we want it. And then the last method that I want to have is the one to add a role to a specific user. So I'm going to copy this one more time and then go down, paste it. And I want this to go to, Let's say Ed to user. You can come up with a better name for this, and this is not going to return anything. So I'm going to pass in the question Mark here. We can make it return whatever we want, even though the service call is going to return void, and we need to get the username and the role name so that we can give it to the service. So there's a method and the service. If I do a control space here, Ed, role to user, as you can see, it's expecting the username and the role name. So we need some way to get the username and the role name from the request and then pass those into the service. So I want to still use the request Batty, because it's more convenient. I can just send some adjacent object. So I'm going to go down and say class, and this is going to be role to user form, and then open and close care of the braces. Remember, we need the username, and we need the role name. So I'm going to do private. That's going to be a string, and I'm going to name it username. And then I need another field, so that's going to be private string, and that's going to be the role name. So I'm going to say role name, and I can use the data annotation so that I can have getters and setters, because that's really what I need. I'm going to do a data. So the data annotation from Lum box and then places on this class. So now I can take this class and pass it in here, and then Let's just call it form. Okay. So that's going to be the form, and I'm going to change the name of this method. I'm going to name it a role to user, because that's what it's doing, and we will not be needing the Uri. So I'm going to go ahead and remove that. And this time we're sending you 200. So I'm going to change this to an. Okay, and remove the Uri in here and the bad. I want to call the save role to user. So we're going to say that save Roto user Oops, not save role. What did we call it? So Let's do that. A role to user. So we're going to call this method, and then from the form, we're going to get the username and then get the role name. So we're going to say form that get role name and close everything. So we're going to get an error because this is not returning anything, and we're returning something here, and I'm going to go ahead and copy all this. Shelly, I'm going to cut it and then place it up here. Okay, because this is returning void. So we're just gonna call it up here. And then since we're not going to have the body in here anymore, because we just want to send a response of Kate, the user, we can just call the build. So we're gonna just build this response, and I need a closing parentheses here. All right. So that's what we have to do for the controller. So we have a way to fetch all the users, save a new user seven row, and then add the role to a user. So we should be able to test all of these functionalities. And also, this is supposed to be outside of this class. I'm going to remove it from here, go outside of the main class, and then paste it here. So there are two ways we can test those methods here. We can either run the application and then use postman to test everything, or we can pass in some data in there as the application is starting, so that we can save some stuff in the database, so that when we check it in the browser, we can see something. So I'm going to go with the second approach, and I'm going to go into the main class. So the user service application class. And then I'm just going to create a beam of type command line runner. So I'm going to go down here, and then I'm going to say command line runner, and Let's just call it run, and Let's pass in the user service. I'm going to say user service and name it user service. So we're injecting the service inside of this command line runner. So Let's do return open and closed curly braces. So everything inside of this open and closed curly braces will run after the application has initialized. So we can use the service to save, save user and Ed role to user, so we can do something like user service that save role and then passing a new role. So I'm going to say new role, and the first thing we need to pass is the ID, and we know that it's going to be generated on the fly. So JP is going to manage that for us, so we don't have to pass any ID here. So I'm going to pass it all, and then I'm going to pass in the actual role name. So here I'm gonna say roll underscore user. So that's going to be the first rule that I'm gonna add into the application. I'm gonna go ahead and do that for a few more rules. So role manager, role admin, and then roll Super admin. Now that we have the rules, we can go ahead and start adding some users. So I'm going to see user service again. So calling the user service and then save user, and we need to pass in a new user. So we're gonna see new user. And again for the ID, we pass in all, and we need the name. So the name is going to be a string. Let's say John Travolta, and we need to pass in the username. So we're gonna say the username is John, we need to pass in the password. In this case, I'm just going to pass in the string 1-2-3-4. And then for the rules, I'm just going to pass in a new array, so that's going to be an empty list. So I'm going to go ahead and add in a few more users. I'm not going to sit here and type it all out and bore you out. So I'm just going to type it in then to come back. So I added a few more users. So we have with Smith, Jim Carrey and Arnold stranger. So now what we have to do is to add some rule to user. And all we have to do is to call the service called the Ed role to user and then pass the username and the role name that we want to add to the user. So I'm going to go down here again, call the service again. So user service and then add role to user. So I'm going to pass in the user name. So here I'm going to see John, and then the role that I want to add. So Let's say I want to add in the role user. I just have to copy this role and then paste it here. And I'm gonna go ahead and add in a few more roles to users. And that's what we have to do for all the users so that we can add whatever rules that we want them to have and we can do that multiple times. So if I want to add the role manager to John, I'm just going to have another line like this and then change the role to a role manager. So I'm gonna go ahead and add a few more. All right. So I've edit role for Jean Wheel Arnold. So I've give Arnold three roles so that we can see someone with multiple different rules and we can do John as well. So, in fact, copy John he and then go down past it and change the role name. Let's say he's also a manager. So I'm going to copy this name and then paste it here. All right. So whenever we run the application, we're going to create those roles, and then we're going to create those users, and then we're going to add those roles to these specific users. That way, when we check it out on the browser, we can actually see some data. So Let's go ahead and rerun and stop and rerun. The application is up and running. I'm going to copy this password again. Copy, go back to the browser and Let's try to refresh this. Alright. This is to Zoom in. I'm going to Zoom out a little bit and then it's passing user and the password sign in. So I see that I got no users, which means the code that we just put in it didn't run. And I think I know why. Because we didn't add the Bean annotation, so it didn't get picked up by spring. So Let's go ahead and do Bean and it's supposed to be upper case. So now everything should work fine. So Let's go ahead and rerun the application. So stop and rerun. All right. I can already see in the log that everything has been inserted into the database. Let's Scroll up and see if we can retrieve this password. I'm looking for this. I'm gonna go ahead and Select everything and copy and back to the browser. If I refresh this, it's going to ask me to log in again to Zoom out a little bit and passing the default user. So there's a default user, and then the password and sign in, and you can see we have the data in JSON format. So John has two roles, so Role User, Role Manager, and then we have everyone else. As you can see here, an RN role has three roles, so Role, Super Admin, Role Admin, and also rule user. So everything is working as expected. You notice that when we try to access these API for users, we were asked to provide a username and password, and we didn't use any of our users here. And that's because by default, Spring put in some kind of a configuration in the back that's using Session, and it generates this random password for you that you can see in the log, and you can log in with user. And I think you can also log in with Admin, but user. And then the password that is generated by Spring and Spring is using Session to keep track of voice logged in and stuff like that. But that's not what we want. We want to be able to tell Spring Security that we have our own users, and we want to use those users to be able to log in into the application. And we want to tell Spring security what specific Role in the application have access to. So authorization to specific resources, depending on the role of the user. So we have to do two things. We have to tell Spring Security who can access the system. Those users are the users that can access the application. And then you can tell Spring Security that, Hey, with these roles, that's what's controlling the access to specific resources. So authentication, meaning who a and then authorization, meaning what they can access and the application. And we're gonna control that using the Role. So someone with Role user will have probably less permission or less access to resources on the application, then someone with Role Manager or someone with Role Admin or something like that. And to do this, we need to customize the Spring security a little bit. So we're gonna have to put in a configuration for Spring security where we're gonna specify where the users are. So where Spring should go look for the users when someone tries to authenticate in the system, and then what permission they have, which we're managing using the rules. So Let's go back to the application, and I'm going to minimize this for now. And Let's go ahead and create a new package. So package, and that's going to be the security package. So I'm going to do the security and infer Center and then create the security configuration class. So here I'm gonna say class, and I'm going to call this security config. So in this class, we need to add in some annotations. The first one is going to be configuration because we want this to be picked up by Spring. So we're going to do configuration, and then we need to add an enable Web security. So we're going to say enable Web security, and I'm going to be doing some dependency injection. So I'm going to say required Arcs constructor. And then to tell Spring what we're trying to do, we need to override certain methods from the Web security on adapter, which is the main security class. So I'm going to extend the Web Security configure adapter. So we're going to say Web security configure adapter. So this is the class that we need to extend so that we can override certain methods and then tell Spring how we want to manage the users and the security and the application. So Let's right click and do generate and Let's go to override methods. I'm going to go ahead and extend this, and I want to override the second one. So the figure that takes the authentication manager builder, and I'm going to go down and then override another one. So I'm going to go and do generate override methods, and I'm going to override this one. So the one that takes the http, security. So for the first one, the first one figure that takes the authentication manager builder. I'm going to show you a few things here. So there are many different ways you can tell Spring how to look for the users. And the first one is in memory, so I can Select in memory. And then I pass in a username and a password so that Spring can use to check for users whenever users are trying to log into the application. And I can also use JDBC authentication, so I can create a service class and then passing all the queries and everything, and then use JDBC to make my own request and then override the JDBC user detail manager configure and do all this stuff. But we're not going to do that. We already have JPA, and JP is already doing a lot of work for us. We don't want to have to do that by hand, but the one we're looking for is down there. So the User Details service, Let's go ahead and Select that one. So the User Details service is going to accept a user detail service, which is a beam that we have to override until Spring how to go look for the users. So Let's go ahead and bring in these beans. So I'm going to go on top of the class and then say private, and it's going to be final and then say User Details service. And this is provided by Spring Security. And then Let's name it user details service. And because we have required Arcs constructor, this annotation is going to create a constructor for us on the fly and then inject this guy inside of the constructor, and this will be the way we do our dependency injection. So now we can pass in this user detail service inside of this user detail service, because that's what it's expecting. And then we need a password encoder. So we're going to say password encoder, and we do another bean for that. And I'm going to go up here and then bring in another field, which is going to be the B creep password encoder. So I'm going to say BC, and that's the password recorder that I'm looking for, and I bring it in. It's going to be injected the same way as the first one. And then I'm going to pass it in here as my encoder. So that's all I have to do here for the user detail service. Now, remember, we don't have any configuration or any override for these two beans. So somehow in our application, we need to create two beans in our application until Spring how we want to upload the user and then create a beam for the password encoder. We can create our own password encoder, but we can just use the one from Spot, which is pretty secure. So Let's go ahead and do the second one first, because it's really easy. We just have to create a simple beam of type, create password encoder. I'm going to go into the mid class. So the application class and then create the bean. So I'm going to go here and I'm going to say even I want the password encoder. So I'm going to say password encoder and give it a name of password encoder. And I just want to return the big rip password encoder. So I'm just going to say return a new big rip password encoder. So whenever the application runs, then we will have this being available so that it can be picked up by Spring. So the password encoder is taken care of. Now, we need to do the user details service. And one way we can do this is to implement this user detail service and then override that one met that has that Spring needs to know how to look the users and then check their username and password and everything. So Let's go into the user service implementation where we're already implementing the user service. We can just go ahead and implement the user details service. So we're going to say user detail service. And because we implement this user detail service, if we go inside of it, you can see that we had to override this method. And this is the method that Spring uses to load the users from the database or wherever they might be. So Let's go back and implement this method. So implement that's a load by username and then click okay. And it puts it at the bottom, and I'm just going to go ahead and move it at the top. So I'm going to move it up here, and we're just going to work on it. So this is going to take the username. So I'm going to change this to username. We can just load our user using the user repo by just passing in the username of the user. So we're going to say we're looking for a user. And to get this user, which is the users in our database, you just have to call the user repository and then find my username and then passing the username. That the use case. And we can check to make sure this user is not now. So we can see if if this user is null, then we want to throw an exception to let the user know that there was an exception. Like, something was wrong. We didn't find this user. We got some bad username or something. I'm going to pass in a log in first to log error and then pass in a message user not found in the database, for instance, and then throw the exception. So I'm going to say throw new username an exception, and I can pass in the same message if the user is not null, which means that when we try to retrieve that user in a database using the username, we are able to find the user. So in this case, then I'm gonna have an else statement, and I'm gonna pass in another log here. So just copy this and paste it here and change this to info user found in the database, and then we can pass in the username. Now, what we need to return is the spring security user. So we have to return a user here. That is the spring security user coming from the core user details user. So what I can do is in here, I'm going to say return a new Let's say org, and I need to go to spring framework security. That core that user details that user. Okay. So because we want to differentiate from this user up here, I'm just putting in the full qualified name for that specific class, and we can go inside this user so that we can see what we need to pass. And you can see here we have to pass in the username password and a list of authorities or roles or permissions. So Let's go back and just do that. So here we need to get the user names, and this is coming from our user. So we're going to say user that get username need to pass in the password. So user that I get password, and then we have to D to pass in the authorities. So I'm going to say authorities. We have to define this authorities. So Let's copy this name and go up here. Let's define a collection. So I'm going to say collection, and I want a collection of simple Grand authorities. So I'm going to say simple Grand authority, and this is going to be the authorities set this equal to a new array lease. So I'm going to say no release. So I'm defining a list. And then from my user, from the user that we found in our database, we want to get all of the roles. So I'm gonna say user get roles. And for all those roles, we're going to loop over each one of them. So for every role, we want to add this simple Grand authority inside of it as part of the role name. So here I'm just gonna say dig the authority and then add a simple Grand authority. So I'm gonna say new simple Grand authority. And this takes a string. So I'm gonna say roll that get name. And I'm gonna put this on a new line so that you can see better. And in the semicolon here. So we're looping over all the roles of this user, and then for every single one of them, we're gonna create a simple grant authority by passing in the role name. And then we're gonna edit to this list, and this is the list of rules that we're gonna pass into this user here from Spring Security. And we can go back inside of the user again. You can see the authorities can be any collection that extend the Grand authority. And if we go back and go inside of the simple grant authority, you can see that it's implementing the current authority. So simple grant authority is a valid class to return. Here are a valid type to return here. So now we will have a being of this type, and we have overridden this method. And we have told Spring how to find the user. And we have returned the Spring security user that is expecting to be returned so that it can take this information and then do the password comparison and check all the authorities and everything. Another important concept that you got to understand is the concept of authentication and authorization. So what exactly is authentication and what is authorization? So authentication is verifying who you are. So Let's say you want to access an application, you need to provide some email or username and password. So this is verifying who you are. So what's going to happen is maybe at some point in the past, you sign up with this application or with this website or something, and they're going to go in the database and verify that you are actually who you say you are. So if you're John, your username is John, and then you provide your password. So you're going to take that information and then verify that you are actually John, because you provide the correct information or some correct credential. And some of the ways we do this is by using a login form. So that's, like the most popular, you provide a login form to the user, and then they give you some information that only that user would know. So some username and the secret password or something, and then you go in your back end or in your database, you verify that this information is correct, and then you authenticate the user, which means you let the user into the application. And there's also http, authentication. There's different methods that developers created, custom methods that people don't even know that certain applications have in some organizations. But that would be authentication. Authorization is everybody has access to the application, but they don't have the same access to the resources. So Let's say we have some organization, and they have simple users. They have managers, they have admins. Right. So they can all access the application. So they can all authenticate with the application because they need them to be able to access the application tion to do whatever they need to do in the company. But they can't do the same things. Or they can access the same resources. And you've probably seen something like this at some point where there is a simple user, they're accessing the same application. But then when an admin access the application, you see that the application looks different. Or they can do more things, or they can see more resources and some other ways authorization is done. Or access control URL. So you can control certain URLs. And this is something we do a lot in spring where you say, Hey, for this specific URLs, you need to have this specific permission on. And you can only send this specific type of request and also access control list. So you can have certain list of some sort. Or say, Hey, if you're not part of this list, then you can access this specific resource. So authentication is verifying who you are and make sure you are who you say you are, and then let you into the application. And authorization is, can you access a specific resource on the application? So if we are to tie this with the JSON web token, example, whenever the user logs in the first time, and then we give them the token, this is authentication. And whenever er, they say subsequent request, after they log in with the token, and we verify the token, make sure the token is valid. And then we get all the permissions on that token for that specific user, then that's authorization. So these two concepts that are kind of related, but they're not the same, they don't actually mean the same thing. So authentication verifies, you an authorization determined if you can access a specific resource on the server. And a good example is a building. So can you enter the building? That's authentication. So you can enter the building, but can you access a specific room, or can you access a specific floor? That's authorization. We can go back to the security configuration and then complete this method right here. So earlier, when we were trying to access the application where we had to provide the username user in the password that was generated by spring is using a session policy that was stateful. So he was using session and then save something in memory tracking the user by giving them a cookie. So we don't want to use this system. We want to use a JSON web token system or a token system where the user logs in. We give them a token, and we don't keep track of the user with no cookies or anything like that. The way we can configure this is by configuring the Http security, as you can see here. So the first thing I want to do is to disable cross site request forgery. So I'm gonna do Http and then do CSRF, and then do disable. And then I'm gonna do Http session management session creation policy. I want to specify stateless, and I'm going to see if I can do a static import for this, and Let's go down and do Http that authorize requests and do that. Any request that permit all we're gonna allow everyone to be able to access this application at this point. And then I need to add the filter. So we're gonna have an authentication filter so that we can check the user whenever they're trying to log in. And we need to tell this configuration about this filter. So we're gonna do Http and add filter. But now I'm going to pass a null because I don't have the filter yet. So Let's go ahead and work on this. Right now. I'm going to create a new package and just call it filter. I'm just going to place our filters in this package, and I'm going to create a new class. I'm going to call it custom authentication filter. And inside of this class, I want to extend the username password authentication filter. And once I extend this class, I need to override two methods. I'm going to generate override methods, and I want to get the attempt authentication. So whenever the user tries to log in and I'm going to go down a little bit, I also need to override the authentication successful. So override method. And I'm looking for successful authentication, which is right here. So you can override this unsuccessful authentication as well. If you want to do something, if the login was unsuccessful and usually would use this, if you want to have some sort of cash where you want to stab brute force attack, so you would try to see how many times the user is trying to log in within a specific window. And if they have exceeded the number of times that you give them to log in, Let's say within, Let's say five minutes or something, then you would lock the account or something like that. And if you want to learn how to do this, the security course actually has an implementation for this, so you can go ahead and check that course out. But in this case, we're not going to do this. We want to be able to send the access token and the refresh token whenever the login is successful. So in that case, we're just going to override the successful authentication, which is going to be called when the login is successful. So I'm going to click on this and click. Okay. And I need to import the log so that I can log some stuff out. So I'm gonna add SL for J, and that's all I have to do. And I also need a constructor. So Let's do private, and we need to bring in the authentication manager, because we're gonna be calling the authentication manager to authenticate the user. So we're gonna inject it in this class. So I'm gonna say authentication manager, and give it the name of authentication manager, and then create a constructor. So I'm gonna copy this name and go down here. I'm gonna do public custom authentication filter, and then pass in the authentication manager. So I'm going to copy this and then pass it in the constructor and say, for this authentication manager, set it equal to the authentication manager that we're getting in this constructor. I'm gonna put a space here and another one here. All right. So we have the constructor. We have our field we injected in the constructor. Now we need to work on the tip authentication. So we need to call the authentication manager, passing the user credentials, and then Let's spring to its magic. And then whenever the login is successful, in which case this method will be called, then we had to send in the access token and the refresh token to the user and the headers or and the response or something. So first, Let's work on the attempt authentication. So I'm gonna remove this, and Let's see if we can get the username. So I'm gonna do string username and set this equal to the request, and I'm gonna try to get the parameters, which is gonna be the username. So we're gonna say username. Okay. So we're gonna try to retrieve the username this way, and then we can try to get the password. So I'm gonna change to password and change the variable name as well. And I'm going to log this information so that we can see it. So log that info. All right. So we can see those in the log whenever the user is trying to log in. And then I need to create an object of username password authentication token. So we're going to see username password authentication token. So the second one, and I'm just going to call it authentication token, and then set it equal to a new username password authentication token, and this takes the username and the password, so I can just say username and then password. So we're really not doing much here, so we're just grabbing the information that is already coming with the request and then pass it into the username password authentication token. And then we call the authentication manager. We tell the authentication manager to authenticate the user that is logging in here with this request and this information. So I'm going to go down and to return the manager that authenticate and then pass it in the authentication token. And that's what we have to do in this method. And if you want the user to pass in the body as a decent object, you can use the object Mapper and then grab the information you need from the request that way. But I'm just going to keep it this way because it's simpler. And for the successful authentication, so the flow is the user is going to try to authenticate. This method is going to be called because we're going to try to attempt to authenticate. If the authentication n is not successful, spring is just gonna speed out an air to the user. But if the authentication is successful, then it's gonna call this successful authentication. So in this method is where we have to do all the stuff we need to do so that we can generate the token and then send that token over to the user. And you can already see that this method takes the request, and he also has the response. So we can use that response to passing headers or passing something in the body. And in our case, we're gonna just pass in the token that we need to send to the user. So Let's place this custom authentication filter and the configuration. So ad filter, we're going to say new and then passing the custom authentication filter. And Let's just import this right now. Import. And remember the constructor, it takes a parameter, which is authentication manager. So if we go back to the configuration, and if we look inside of this class, we will see that there is an authentication manager that we can just bring into this class and then pass it into this guy. We can go down and say, we want a bean, and we're gonna override. So override the public, we want the authentication manager. So authentication manager, and I'm just going to call it Authentication manager bin, and it throws an exception. So I'm going to say throw exception, and we want to call the bean or the authentication manager bean from the class that we're extending. So I can just say return and then use the Super keyword to refer to the class that we're expanding. So the parent class, and then call the authentication manager, and you can see it coming up here, and that's all we have to do. Then we can pass this authentication manager being inside of our filter because we know it's expecting an object of that type. But remember, we're not done with the custom authentication filter because we still have to give the user the token or their access token and refresh token whenever the login successfully. So Let's take a quick, simple example of the flow. When you secure application with a JSON Web token, the first thing that's going to happen is there's going to be some client that can be a user, that going to be another application, and they need to access another application to access some resource on that specific application. So what they're going to do is they're going to send a request, usually a post request to log in, and that's authentication. So they're going to send some credentials here. I'm passing in username and password, but it doesn't have to be username and password. It can be some user ID or some combination of a password or user ID or something like that. There might even be two step authentication. So maybe I'm going to send you a code, and then you're going to check it on your phone or something like that or in your email. It depends. But the point is, authentication needs to be done, and that's authentication. The client is going to send some credentials to the application they're trying to access or to some backend application. And then they're going to get a token. So after the application verified that the credentials are correct, it's going to send additional web token to the client. And that token is probably going to have the client information and an expiration day and a lot more information. It depends on the application. And then what's going to happen is whenever the client needs to send a request to the same application, of course, we don't want them to authenticate again. So they're going to have to send us that token that we give them as long as it's valid. So say they want to access the users resource. So they want to access all the users on the system or something. They're going to send some get request to get all these users and also send us the JSON Web token to the application. And then the application is going to take the request. It's not going to process the request yet. It's going to Eck the JSON web token, make sure the token is valid. And after that, it's also going to check to make sure that the token has permission to access this resource. And when as a token, that means the user, like the owner of the token, has access to the resource that they're requesting. Because even if the token is valid, it's not been tempered with the signature is verified and everything if you don't have enough permission to access the resource that you're requesting, your request will still be denied. And this is really a high level overview. There's a lot more that goes into this, but that's a very nice summary. So you again, you get a token and every subsequent request you send to the application, you have to also send that token so that they can verify who you are and give you authorization to the resources that you're allowed to. And then there's another thing that I didn't show on this slide. And it's the concept of refresh token. And this is another token that you usually give to the user. So whenever the actual access token is expired, they can say that refresh token, and then you can give them a new one. And this is to like smooth the user experience so that you don't keep asking the user login if the expiration date on the actual token. So the access token is not a long period of time. So instead of asking the user login again, you say, Hey, give me the refresh token, which you can give a longer expiration period. And then as long as that token is also good to validate that refresh token, then you can give them a new access token. And you're going to see how I'm going to give you an implementation of this in just a minute. So if that makes sense, and if you guys have any questions, you can reach out to me in a comment or something like that, you can let me know. And then I can try to help you. But for right now, now Let's go ahead and dive into the code. Okay, what we need to do and this method is to give the user their access token and the refresh token after they have successfully logged in, because this method is called once the login is successful, which means that we need to have some sort of way to generate the token, sign the token, and then send the token over to the user. And we can do this all by ourselves. But that's a lot of work and we probably don't want to do that outsell, so we can use some external library to do that for us. So I'm going to go back to the browser and go over to Google and I'm going to search for a zero and a Java JSON web token and I want the Maven dependency so that we can add that Maven dependency in the pump file. And I'm just going to click on the first link here. I think that's the one that I'm looking for and they have a version that came out in July. So this month I'm just going to grab it. So 318 1 and just going to copy all this, go back to the application and I want to navigate to the pump file and I'm just going to place it anywhere in my list of dependencies. Get rid of this comment. Alright. So we have this JSON web token dependency here so that we can use it to generate the token, sign the token, etc. So Let's close this pump file and go back to the configuration. You might want to refresh your pump file. So if you're using IntelliJ, just look for the little M that's going to appear on top of the screen here to the right, or you can just right click and then go to Maven and then go to reload project that should import all the dependencies that you just added so close and go back to the custom authentication filter and to this method. So what we want is to access the user that's been authenticated because we need the user information. And I'm going to rename this variable to authentication. And Let's grab this authentication. So to get the user that's been successfully logged in, we can define a user so that's the user coming from spring security. So that's not the user that will define in our domain, as you can see here, it's the second one that's coming from the user details, and we're going to name it user and then set it equal to the authentication get principle. That principle, as you can see, it's returning an object is the user that's been successfully authenticated. And because it's returning an object, it's going to give us an error, and we just need to do a casting here. So I'm going to say cast this to a user, and that's what we have to do. Now. We have access to the user. So the logged in user, we can grab information from that logged in user to create the JSON web token. So Let's define an algorithm. So I'm going to do algorithm. You can see that this is coming from the library that we just added. So off zero at algorithms, and this is going to be our algorithm, and we want to just create a new algorithm. So I'm going to set this equal to algorithm, and I need to Select the crypt graph that I want. I'm going to Select 256, and you can see that we have 2 256. There's one that takes a string, which is the second one. And then the first one takes an array of bike. So I can just pass in my secret here, so I can say secret and just get the bite. All right. So this is going to be the algorithm that I'm going to use to sign the JSON web token and the refresh token. So the access token and the refresh token that I'm going to give to the user, and you probably wouldn't do this in production. You can see I'm just creating this string here. Secret. This would be something I would be saved somewhere secure, and you would probably encrypt it. And then when you're loaded up, you decrypt it and then pass it in here from some utility class or something like, but we don't have to do all this for this demo. I'm just making sure I bring these things to your attention, because this is not something that you would do at all. So now that we have the algorithm, we can just create the token. So the first token we need is the access token. So we're gonna say access token and then set it equal to the JWT. So I'm going to say T that create, and we need to pass in the subject. So the subject can be really any string that you want. So that can be like, the user ID or the username or something unique about the user, so that you can identify the user by that specific token. And in this case, I'm going to pass in the username. So I'm going to say user that I get username because I know in my application, all the username are unique. My IDs are also unique, but I'm just choosing to use the username, and then I can pass in the expiration, so I can say with expired ad, and that takes in a new date. So I can say new date, and Let's get the system time. So I can do a system, the current time list. And Let's say we want to set this to one minute because it's a token that's going to have a very short time to leave so that they can give us the refresh token, give him a new token. But Let's put 10 minutes for now. So 10, multiply that by 60 and multiply that by 1,000 because it's millisecond. And I need to put the plus sign here. All right. So we're getting the current time of the system. We're adding 10 minutes to it. And I can also pass in the issuer. So say the company name or the author of this token. I'm just going to grab the request and then get the request Uri, actually, Let's get the URL, and then I can just convert this to a string. So this is going to be the URL of our application, and then I can pass in all the claims. So all the roles for that specific user, so I can say with claims, and you can see, I'm going to have to pass in the name of the claim and the list of some sort, which is going to contain all of the claims. So I can pass in a string here, and I'm going to say, Rose, so that's the name that I'm going to give as the key to this list of rules that I'm gonna have. And then I can do user that get authorities, and I can actually use the stream API. So I'm going to do stream and map everything to some kind of a list. I can say map and then use a method reference. So I'm going to do granted authority, double colon, get authority. So that's going to give me a simple string, and then I can just collect this to a list to collect to list, and that's gonna be all the claims of the user. So whatever permissions or authorities or roles that we put in for that specific user, we're gonna pass those into the token as the rules of that specific user. And then we can just sign this token with the algorithm, and that's all we have to do. So this is the access token. Remember, we also have to pass in the refresh token, so I can copy all of this, go down, paste it, and change this to refresh token. So refresh token in. And for the refresh token, I need the subjects. So passing the username. So we're gonna give this more time. So you can give this a week or a month or even six months or a year. It depends on the application and the security concern. So I'm just gonna say 30 minutes, and I don't need to pass in the rolls, so I'm gonna remove that, and that's all we have to do. So now we have the access token. We had the refresh token. We can use the response to send those to the user in the front end. So I can do response that set header, and we can just pass them as headers. So I'm gonna say access token, this is the access token, and then do the same for the refresh token. So whenever the user logs in successfully, we can check the headers in the response, they should have the access token and the refresh token. There's another thing we need to do. So Let's go back to the user service implementation. So because we're saving these users here, we're saving the raw passwords because we're using the password encoder. So we have to encode the user password and then save the user in the database. So Let's go back to the user service implementation and Let's inject the password encoder. So I'm going to go up here at another field that's going to be private final, and I want the password encoder, and then I'm going to Scroll down, and before I save the user, I can do user that, set password, set password, and then call the password encoder that encode, because we want to encode the password and then do user that get password. So we're going to get the password of the user encoded and then set it as the password of the user. So at this point, we're ready to test the login, at least so that we can check the headers and make sure we can actually see the access token and the refresh token. So I'm going to go ahead and run the application and use postman to send the request. So I have postman as my API client, but you can use any API client that you like. And I need to go to local host 8 80 login, and we need to pass in the username and the password. And because we're using the so if we go back for one second, you can see that we're using request at get parameters. So that means that we have to send our credential, and the body is www form encoded URL. So here I'm just going to say, I'm going to pass in a username and John, and then the password that's going to be 1-2-3-4, that's the password for all the users that we have in the application. And this is going to be a post request. So change this to a post and let me double check to make sure the application is up and running. Okay. So it looks like the application is up and running. So Let's go ahead and give this a try. So send we get the 200. Okay. As you can see here. So everything went well. And if we go into the headers and Scroll up a little bit, you can see we have the access token and the refresh token. So Let's go ahead and copy this to make sure we have the information that we're expecting. And Let's go to JWT. I think that IO. Alright. And then Let's Zoom in a little bit and paste this in. And there you have it. You can see that the subject is John, the role is roll user the issuer. So the owner or whoever gives you this token, so that's the URL, and then the expiration. You can see it's right here. The data is here. So the token is working. And we can also check the refresh token. So Let's go back here and Select the refresh token back to the browser. Paste this. You can see it's for John and his expiration. He's so sure. So everything is working as expected. You can use the object Mapper to pass in Jason here. So from the request, you can transform this. But what I want to do instead of setting headers here, I want to actually send something in the response Batty. So what I'm gonna do is I'm gonna go ahead and comment on these two lines out. And then I'm going to create a map. So I'm going to say map, and that going to be a map of string and string. And then I'm going to call it Let's say tokens, right. So you can give this any name you like. And then I want to set it to a new hash map. And then I'm gonna add the tokens inside of it. So I'm gonna say tokens that put. And then I'm gonna say, Let's just copy this and then paste it in here. So that's going to be the access token. And then I'm going to do the same for the refresh token. So then after we do that, we need to set the content type on the response. So we're gonna say response that set content type. And I want this to be Jason. So we're gonna say application underscore Jason, underscore value. And make sure we can import this. So more option import. And we want to import this one. Let's make sure this is the correct one. Yep. So applications, Jason, and then we can just do new object Mapper and then write value. And we want the response output stream. So we're going to say response that get output stream. And then we pass in the tokens. So that's going to return everything in the body and a nice adjacent format. So Let's go ahead and refresh run actually have Dev tools, and I completely forgot. So I've been rerunning the application manually. So Let's go and make sure this is running. Okay, so now if we log in again, we're going to log in again. All right. So send the request. You can see. Now we have the access token and the refresh token. So Let's go ahead and configure the Http security so that we can use those token to test them out to see if we can actually access resources on the server. Let's go back to the application and go to the security configuration. So at this point, it's almost like we didn't even have any security because I have permit all on this and we really don't want to do that. So we can do Http. And then Let's say authorize requests and then pass in some it matches. And we can see things like for a get request. So we're gonna say for a get, we can allow specific path. So for instance, I can do something like, Hey, if this is coming for API, Let's say star star. That means everything that comes after that. Then they need to have Let's say user role. So I can do that has authority, and then I can pass in the user role. So I can do role underscore user. So it can be very flexible and you can have very granular security in your configuration. And this is supposed to be a matches, so it matches. And we can keep doing this so you can say Hey for us post request. So Let's do another one just for the sake of this demo. Let's go here and say Hey, they need to have the role. Let's say admin if they need to access. Let's see, what route do I have in this application? Let's go to the API resource. So I have API users. Let's say user save. Right. So for saving a user, you need to have admin permission. So we can go back to the security configuration and then say API and do API user save whatever comes after that. As long as they have this role admin admin, then they can send this post request. So I can change this to a post request. And there's a lot of resources out there about this. You can go ahead and check it out. Alright. So Let's import this as well. So it can be very granular with the configuration in your security. And then we don't want to do permit all because that just means that we just throw our security out of the window. We want to do authenticate, so we want everyone to be authenticated. Now, if we want to allow certain path, we can do something like this. We have to do it before these two lines, by the way, the order and this matters. So we can do something like Http and then do authorize requests and then do it matches and then passing whatever path that we don't want to secure. And then after that, we can say something like that. Permit all. Okay, so we can do something like this. So if you don't want to secure, Let's say login or something like that, then that's going to be here. Spring is already taken care of this because you can see that this login path is not defined in our resource. You see that I don't have anything log in here. But if you want to see where this is coming from, I can actually show you. So Let's go into the custom authentication filter and then go inside here. You can see this slash login is coming from the class that we're inheriting. And also, if you want to change this, by the way, you can. And I can show you how to do this real quick in the security configuration or passing in this custom authentication filter. And you can see that this class, which is our custom class, it's extending this class which has the four login. So we can actually override this with our own custom authentication filter. And one way to do this is to go to your configuration. And then Let's define this at the top. Let's do custom authentication filter. So that's the custom authenticom filter, and then create the constructor here. So we're gonna copy this guy right here and just create the constructor. So we're going to pass this here like this. Now, we can use this object to change the URL, and there's a few other things we can customize as well. So we can go here and say, set filter, process URL. And since everything in our application starts with API, so we're going to say API for login. All right, so now instead of going to the base URL, which is everything after 880 and then log in, we have to go now to our API login. All right. So that's how you would overwrite this. And then you probably have to make sure this is not being blocked by the security. So you want to just copy this and then say, Hey, permit all on this specific path or whatever comes after it like this. Okay. So if it's API login and whatever else, then we're gonna allow it. And again, the order is important. So you probably want to put this first and then put the second and then put your authenticate below. Let's just test this out, make sure it didn't break anything. So I'm gonna rerun and then bring up postman and I'm just going to send the same actually, let me use Arnold. I want to see something different. All right. Application is up and running. Send the request. So I got a 404 and I think I know why. So we need to pass this object inside of this filter, because that's what we have now. Alright, so refresh and let this come up, and then we're going to test it again. Alright, Let's go back to postman, and Let's send it again. You can see we logged in successfully with a different user this time, so everything seems to be working as expected. We're able to give the user an access token and a refresh token when they log in successfully. So what we have to do now is to be able to take this token from the user and give them access to the application. So whenever the user give us this token as their authentication, then we should be able to verify this token and then allow them into the application. After we verify that this token is valid. And to do this, we need to create something called an authorization filter. And this filter is going to intercept every request that comes into the application, and then look for that specific token and then process it and then determine if the user has access to certain resources or not. So Let's go ahead and create this authorization token. It's some of the filters. So I'm going to create it in the same filter package. So in this package right here, and I want to do a new class, and I'm going to call it custom authorization filter. All right. And then I want to extend another class here. So I'm going to do extend once per request filter. And once we extend this class, then we need to implement this method called do filter internal. So all the logic we're going to put to filter the request coming in and determine if the user has access to the application N or not, it's going to be done. And this method right here, which is the two filter internal, because this one per request filter, it's going to intercept every request that comes into the application. Let's rename those two requests and rename these two response. And the first thing I want to do is to check to see if this is not the login path, because if this is the case, then I don't want to try to do anything here. I just want to let it go through so I can do it and then access the request, get the server the path. So I'm going to do get server that, and then see if it equals the for API login. Right. So this is the login path. If this is the case, then I don't need to do anything. I know that the user is just trying to log in, so I'm just gonna call the filter chain. So I'm gonna say filter chain, that do filter, and then pass in the request and the response. So that's not going to do anything. It's just going to make this filter pass the request to the next filter and the filter chain, which means we're not doing anything. If it's API login, then we know the user is trying to login. Don't do anything. Let the request go through if this is not the case. So I'm going to have an L statement. Then that's when I need to start checking to see if this has an authorization and then set the user as the logged in user and the security context. So the first thing I need to do do is to try to access the authorization header. So I'm going to say authorization header. I'm looking for that specific authorization header that should be the key for the token. So I'm going to do requests that get header and then passing the key that I'm looking for, and I'm looking for the authorization key. So I'm going to pass in authorization, and I need to import this more option and Port constant. And you can see if we go inside of this authorization. It's only the word authorization header key for the value of the authorization. And then I'm gonna check to see if I have the header in there. So I'm gonna do if that authorization header that I'm looking for, if it's not in all. And also, I want to check that the header start with bar. So I'm gonna do end and then authorization that start with, and then I want to make sure it starts with the word bear. Okay, because we're going to pass in this word in a space, so there in a space. So whenever we need to from the front end, sending a request to the back end, we're going to send the token after we have authenticated successfully. So we log in. You are successful. We get the token, we're going to send another request with that token. So whenever we send the request with the token, we're going to put the word bearer and in the space, and then the token. And that simply means that whoever is sending the request passing in this token, once we verify that the token is valid, you don't have to do anything. Give this person all the permission and everything that comes with their token. There's no further check. There's no further validation that is needed, because they're like the bearer of the token, like it's their own token. So then if this is the case, then we're going to start putting in the logic that we need to put in. I'm going to say get me the token. So I'm going to define another string, and that's gonna be the token. The way I'm gonna get this is by calling the header and then remove the bearer. So I'm gonna see some string and then pass in the I can actually copy this and then do that. Lent, what we're doing online 26 is to just remove their space, because we only need the token, and we can just do this by calling this substring and then pass in the how many letters we want to remove. And then we're gonna define the algorithm again. So I'm gonna go into the custom authentication filter and just copy this line and then paste it. You can see that this is becoming redundant, so that means that we need to use some utility class or something. We're just not doing this. So it's going to be kind of like your job to go ahead and refactor this. Just make sure you don't break anything. You should be good to go. But I'm not going to go ahead and spend too much time with Factoring and also make sure that you keep the same secret. So the same secret that you use to sign the algorithm, so you can see here, we use the secret to create the algorithm and then sign the token with that algorithm. So you have to also use the same secret here. So now we have the algorithm, we can actually verify the token. So I'm going to do JWT verifier, and I'm just going to call it Verifier, and then do JWT that require and then I need to pass in the algorithm to that just fine. And then I need to call build. Okay. So that's how we're going to create the Verifier. We need the algorithm, the same secret that we use to encode the token and then pass that algorithm to the Verifier. And then now I can do the coded token. So I'm going to do the coded JWT and give you the name, the code called the Verifier, and then verify the token. So I'm gonna say verify and then give it the token. And I want to do this, and they'll try catch black, just in case I get in there so that I can return an exception so I can catch. And Let's just say this is gonna be an exception, and I'm gonna call it exception and open and close the braces. Alright. So I'm gonna move everything that I just put in here and the Tri box like that. All right. And we're gonna work on this catch in a minute. And then once we verify that the token is valid, we can then grab the user name of the user. So I'm gonna go down and do string username and set this equal to the decoded token. So I'm gonna do decoded token that gets subject. So this is gonna give me the username that comes with the token. And then I need to get the rules. So the rules, they're like an array of strings. So I'm gonna do string array rolls, and I want the decoded token. And then I want to say get claim. And then here I have to pass in the key of the claim. So if we go back to the browser, you remember the key for the. Well, that's the old one. If I can do control Z on that one, you can see that the key is roll, which is the string that would define whenever we were giving them the token. You can see here I pass in rolls. So we need to say get the claims and the key as a rule, it's going to look at the JSON web token look at the roles and then grab all of the collection that is there. And then we have to tell it, what kind of collection is this? How we want to collect it. So I'm going to do as array, and then that's all string. So I'm going to do string that class. Now we have the user. We have the rules. We don't need the password, because at this point, the user has been authenticated, and their JSON web token or their access token is valid. We just need to set them in the authentication context. So now we can pass in collection. So I'm gonna do a collection that's gonna be a collection of simple granted authority, and I'm just gonna call it thirties and then define it as a new array list. And you're gonna see why I'm doing this, and then I have to do stream. I'm gonna stream over all of the roles. So I'm gonna do roles, and Let's go ahead and import this so that I don't have an error. Yep. That's what I need. I want to do a loop. So I'm gonna do that for each. So for every role inside of that role, right. I want to do is on a new line. And then I'm going to do authorities that ad and then pass in a new simple Grand authority and then passing the role. So I have the username, and then I had role. The reason we have to do this conversion, it's actually a conversion, is because we need to get those roles and convert them into something that extends Grand authority is simple. Grand authority extends this Grand authority like I showed you earlier, because that's what Spring Security is expecting as the rules of the user, like something that extends Grand authority. We can't pass those rules as an array of strength. Now we're going to call the username password authentication token. So username password authentication token, and Let's just call this authentication token again, set it equal to a new user, any password or institution token, and then pass in the user name. We don't need the password. We don't have it either. So we're gonna pass now and then pass in the authorities. All right. And I'm going to put this on a new line so you can see it better. And then we have to set this user and the security context holder. So I'm gonna call the security context holder or selling security, and then do get context text, set authentication, and then pass in the authentication token. All right. So that's how we tell Spring security. Hey, this is the user Here's, their username Here's, their roles, and this is what they can do in the application. So Spring is going to look at the user, look at their role, and determine what resource they can access and what they can access, depending on the roles. And then after we do all that, we're going to go ahead and call the filter chain, because we still need to let the request continued course, and then we pass in the request and then the response. So this is what we're going going to do when we look in the header and we see that it's an authorization header. And then we check again, we see that it has the word bear in front of it. So we know that this is our one token, and that's the only time we're going to do all of this processing with this if statement. We also need another else statement. So I'm going to add another else here, and then just let the request continue. So I'm going to copy this line and inside of this else statement, I'm going to go ahead and paste it. Now, we need to handle any exception that can occur. Let's say the token was not valid. We weren't able to verify it or it expires or something like that. So we need to send something back to the user so that they know what happens, which is going to happen in this exception here. So in there, I can do something like log. I didn't break the login. So Let's go on top of the class and then do ads for J, and then Scroll back down log info. Well, this is actually an error. So we're gonna see error, and then we're gonna see error logging in and then pass in the error message. So we're gonna put the open and closed care braces, get the exception that get message. Okay. So whatever message that happens whenever this exception occurs, then we're gonna capture it in this log right here, and then we can do, like, response header, and we can pass in something like error and then passing the message again. So I'm gonna do exception get message. Okay. So we're just setting some header, and then we can send an error so we can see response that and take its an error. You can see it here, and then we can pass in, like, four or 4 or whatever the case might be. So Let's do Let's see forbidden, because that's kind of what this is. So that's a forbidden that value, which will give us the forbidden code. So we need to import this more action and static import. And if we go inside of this forbidden, you can see it right here. It's 4 3, and it's just say you're forbidden, like you don't have access to this resource. So we can send an area like this. Instead of sending this forbidden, we can do what we did. So Let's go and copy these two lines. Actually, let me copy all this and then go back to the authors filter, go down and paste this down. So I'm going to leave this and just comment it out. So this line, we can have it. If we send a response, then we can't do what we do below. It's not going to work. So I'm in the error if we send the error like this. So I'm going to comment this out so you can still have it. The header is not going to hurt anything, so we can just leave it there, and then I only need one of those. So I'm going to delete this and passing the error message. So I'm going to call this error, and then we're gonna put the error in there. So Let's see error message or something. So error underscore message. So whatever message that we get from the exception, we're just going to pass it as an error or an error message like this. And then remember to set the application that Jason Valley, because this is really important, and then we pass in the error in here. All right. We need to set the status, so copy this, go back down that status, and we can grab the same thing. So the forbidden just like that. Now we can add this filter and our configuration. So I'm going to copy, and then I'm gonna do Http again, that and add filter before. Okay. So we need to make sure that this filter comes before the other filters, because we need to intercept every request before any other filters. And then I'm gonna pass in a new custom authors in filter. So that's the class that we just created. And then I want to tell it what it's for, which means username password authentication filter. That class. Okay, so it's for that specific class. All right. So now we have the authentication filter, and then we have the authorization filter. So Let's go ahead and refresh the application or rerun it. And again, I have Dev tool. I keep forgetting, so every time I rerun everything, but I don't really have to do that anyways. All right. The application is up and running, so Let's go to Postmen, and I'm just going to copy this and go to a new tab, paste it in. Let's go to API user. Okay. So we're going to attempt to access all the users and not sending in any token or anything like that. So I click on send, and you can see that we get the forbidden for three, which is something that we're expecting. But if we try to pass in some headers and we pass in the authorization header, so we're gonna see authorization and then do bear. So we're gonna do bear space and then put some random string. Okay. So we're sending some authorization header, but it's not valid. And then send this a you can see the token was expected to have three parts, but got one. And this exception is coming from the library, and you can see we have all nice message here. So that means that everything is working, and we can also check that message in the log. So if I go here and you can see it here. So definitely, if you don't want to just send this error like this. If you want to send some JSON to the user, what I usually do when I build application, I have a specific A response class that I can just build and then pass in my error message. So this is all working as expected. Well, we have to work on. Next is the refresh token. So all of this seems to be working fine. You can go ahead and test it more if you want to, but everything should be working properly. And if something is not working, you can just contact me and let me know. You have to be careful with this, because there are many different steps in this, and I can only do it the way that I'm doing it because I've done it so many times, and I am kind of familiar with this process and how it works. If you're new to this, you really have to take it slow and make sure you understand what the logic is doing. So what I want to do is I want to be able to use this refresh token, right. If we were to take a scenario in the real world, it would be something like this. So I would come into the browser and the application and log in. I get the access token and I get the refresh token. The developer building the front end. It will take the access token and the refresh token, save them somewhere on the client. And then when I need to access any resource, I'm going to send the access token. Right. Because that's how I get access to resources on that specific server or application. Developers in the the front and do is whenever the access token expires, they wait for the response to get something like a forbidden or something like that. And then they look at the code or some specific message, and then they determine that it's because they're token as expired. So they look for the refresh token in the front end and then send another request immediately. So everything happened seamlessly, like the user even realize that their token was expired, and there was another request that was made to actually get them an access token. So everything is done seamlessly. And that's just a very good user experience where security is a top priority. So that means that we need to have a way to take this token, verify, confirm that it's valid, and then send them another access token so that they can keep using our application and access resources with the access token because they can access resources with this token. So Let's go ahead and work on this. Let's go back to the app and we're going to go into the close all the tabs that I have opened, and Let's go into the resource. All right. So the resource is right here, and we want to create another endpoint where the user can set up request so that they can renew their token. So they're going to send the refresh token, and then we're going to take that refresh token, validate it, and then give them another access token. So I'm going to copy this method go down, and I'm going to change this to get requests. So get requests. And I'm going to name these two, Let's say refresh token, refresh, and we can pass in or inject the servlet request in the service response in this. So Let's go to any of those filters, and Let's just grab the issue service request and the response. Okay. So that's the thing with Spring. You can inject those everywhere you are or in most places. So I've I injected the request in the response that we can have access to them. And I'm going to make sure this returns forward because we're not returning anything and we're turning something thing, but not as a response entity. And I'm going to remove all this. So I'm going to be copying some code from here because it's going to be something similar that we're going to be doing well, not the authentication, but in the authorization. So Let's go in through the authorization. So I need to do this because I need to check for that. So I'm going to place this here. So we're going to say and the request get header, check the authorization. So when they send the refresh token, they're going to send it with the same bear. Right. So let me see if I can show you guys an example. So if I go to users, send a get request, I sent it token has expired. Right. So Let's see, Arnold, I'm going to send this request, and I have this token, so I can copy this token. Right. And then go back so I can paste this token in here. I'm going to Uncheck this and send a request. You can see that I don't have access to this resource, but if I send the authorization with the bear and my token, send the request, you can see that I have all the resource that I wanted. Okay. So you see that this is all working. What we need to do when we need to refresh our token is we're going to go to send a get request, go to refresh token or something. I don't have a passport yet, but it's probably going to be like refresh token. We're going to send the same authorization header with the word bear space, and then the refresh token. All right. So Let's go back. And after we do this, line 55, we're going to do something like this. So I'm going to copy all this and then go back and paste it here. Okay. So we can check to see if the EFT authorization, make sure it's not null or the header starts with bear. And if that's not the case, then we don't want to do filter chain here. We're not doing anything with filter chain. So I can just say if we don't have this. Then Let's just throw an exception so I can do throw, and I can do runtime exception and then passing the message. I can say refresh token is missing. All right, so we're telling them, Hey, you send this request, but we need a refresh token. We can't work without the refresh token, and we need to throw new here. All right, so we're going to throw a new runtime exception, just like that. So go back up and gonna remove this filter chain line, because we're not going with that anymore. So we're gonna look for the header authorization. So passing the string header looking forward, which is the key for the authorization header. We check to see if it's not an all, and if it starts with bar, so we know that this is ours, and then we get the token, so we remove the word bear, or remove the characters bar space, and then get the token. Crn algorithm, use the same secret, get the verifier, the code token, and get the username. Now, once we get the username, we need to load that user. Right. So Let's do user. So this is the user from our domain, and then call the user, and then we're going to call the user service. So use service and call get user. Okay, so we're going to pass the username. So we need to find this user in our database to make sure that this user actually exists in our system. So once we find this user, and I don't need this line, and Let's go back to the authorization, I need this line. So this line right here is the line that I need and the resource. We can pass it in here. So I don't need these two lines. I can remove those, actually, Let's go ahead and grab in the authentication. Let's go ahead and grab all of this, because that's what we're going to do again. Let's go back. So we get the token, get the algorithm, verify it decoded. Get the username, find the user. We're not going to do any authentication. We're just going to send them another token, so I can remove these lines. The paste all this. So we're going to create another token, and we don't need to create a refresh token, because we're going to use the same refresh token that they gave us and send it back to them. So I'm going to delete that, and I'm going to rename this to refresh token. So rename these two refresh token. Oops, I'm going to do it like this. Refactor. Rename refresh to can enter. So Let's see here. So we check the header. It's not an all. Start with bear. Get the refresh token, get the algorithm, verify the code, get the username, find the user in the system, then use the user to create the token. So passing the user name the date again, or giving them 10 minutes. And again, these 10 minutes. That depends on your application that's just really random. So don't use this as a reference issuer is us again. And the claim. So we're not gonna get the authorities this time because this is the user in our class. We need to get the role. So that's gonna be get roles. And then here we can change this to just role get name, because that's the method that we have, and then collect it to our list and then sign it with the same algorithm. Again. You can see there is a lot of redundancy with this algorithm code. That's because I didn't create a utility class, but in your case, you would create some utility class. So make sure you clean that up. And once we hit that, so we can get rid of these two lines, we can create a token passing the access token and the refresh token. Set the media type and send the token again as you can here. And in case there's an error, I don't have the log, but you can edit. And if you want, I'm gonna do the same thing. So here I'm gonna call the response, get out for stream. It throws an exception. So make sure you edit this. I exception to the metal signature, and then, Yeah, do everything else. So error message, get the error. So whatever the air is, we're gonna send that and then send it over. So that should work. And we need to give this a different path. So I'm gonna do token and refresh. So took in refresh, and we need to allow this path on the application. So Let's go into the configuration, and we're going to allow this. All right. And I'm going to do four star star. So everything that comes after that. And I also need to do this for the authorization filter. So Let's go into the custom authorize filter, and we're going to say if this is equals this and do an or and check for this as well. So I'm going to do or, and I'm going to paste it here, copy all this, and then paste it here, grab all that, and then change it in here. So if the request comes in and the surface path is token for a refresh token, then we're just gonna let it go through. We're not going to do anything. So Let's go back to the resource. We get an error here. Is this coming from remove not using any of these imports, and remove all this. Remove the stream, and everything looks good. So Let's go ahead and run the application and then see if this refresh token works. So the application is up and running. So Let's go back here if I send this request again. So the token is expired. Right. So I got these two tokens. I was using the first one, the access token, and it's expired. You can see the message here is token has expired. So Let's go ahead and grab the refresh token and copy it to duplicate this tab. And then go into the headers authorization, remove all this and then passing the refresh token. And let me double check this path. So it's token, refresh. So API Oops, that was wrong token. And this can be whatever you want as long as it makes sense to your application token and then refresh. So I need to remove the word token in the end and this is a get request and send it over. Cannot read a Ray length of now. So the reason that we're getting this error is because it goes into the authorization filter. So we didn't pass in the path correctly. So I'm going to copy it again, go into the authorizing filter. We actually put in the wrong URL here. So I'm going to change it. All right. Because we have the authorization header, we had the word bear. So it goes into this logic and then it tries to do this to get the role, and then I cannot find it because there's no array with the name roles in here. And that's what's throwing this exception. That's what this exception means. So we don't want this to happen. So we check to make sure that the path is not API took in refresh and we had the wrong path here. So I'm going to copy this and do the same in the configuration. So I need to change this guy here. All right. So this is the correct path. So now whenever the request comes in, this filter will intercept it still because it's going to intercept everything. And then it's going to see that it's this path. So it's just going to let it go through. So Let's refresh and try it again. So the application is up and running. Let's go back and send the refresh token. And I got the same error message again. And I know why. That's my mistake. This is supposed to be exact. So we don't need to do this. So it has to be exactly what this is. So it's going to be API token, refresh token, Let's refresh. And then we're going to try it again. Alright. So we're back and running and you can see we have the access token again and then the same refresh token. So eventually the refresh token is going to expire and the user is going to be required to log in again. And this really comes down to your application. Some organizations, they give the refresh token for like a month or six months or a year, sometimes two years. It's going to come down to you and your security concern and your application and then determine how long you want to give them the refresh token and the access token. So it seems like all the functionalities are working. And again, you can go ahead and test more if you want, but everything should be working at this point. So we have the login. We can get the token, so I can try this again. You can see I got all the tokens. So if I try to access with an expired token, you can see I get the message. And if I use my brand new token copied, go back and change it to this token, paste it in. Send the request. This is not the one get request. So this was to API's users. I'm on the headers authorization. And you can see we have the data back and you can test the different permissions that we have for different roles. So in the configuration you remember, we have Role user. They can get requests to API user, and only admin can send a post request. So you can go ahead and test those. This should work as expected. And also you can check this out. You can see we have different things that we can pass in here, so you can use as Role as well as role in our situation, since we're only checking for Role all 30 and both of them will work. And then you have a IP address, so you can go ahead and play around with this. So that's all I have for you guys. And if you enjoyed this video, go ahead and like and Subscribe to this channel. There's going to be new content coming out regularly. And if you have any questions, you can go ahead and ask me. Obviously, you see that this is something that I did really on the fly. There's some organization, there's some architecture, but not really. There's a lot of code that's repeated here. As you can see, this code is repeated a lot, so you would probably have some utility and clean this up. Make sure we don't hit this. And the configuration, you can actually customize this a little bit. I it more I didn't focus on a lot of the different things in the configuration. I was mostly focusing on how you can work with the configuration and JSON web token. I'm sure if you guys are taking this course, you're interested in spring security. So you know that you can really customize this a lot, so feel free to do that, set up your application the way you want to set it up. And again, any questions? Let me know. I mean, there's so many other things that we can talk about when it comes to spring security, but I just wanted to give you a quick rundown on how you can generate token and then generate a refresh token. There's a lot more that goes into security like this, because the token you have to keep it in a very secure way. And the secret that you use the generator token also has to be kept very securely. And sometimes they use servers in the middle. So instead of keeping the token on the client application. So somewhere in the client local storage or something like that, they don't even do that. They use a server in the middle, and then they save everything there and the database. And then the request go through the server, and then the server contacted back end. So it gets really be complicated. It can get really complicated, and it actually gets really complicated in real life. But this is a quick one down, and you can use this in your application. Check out the link in the description. I'm going to give you guys the code, and if you have a question, you get stuck. Go ahead and reach out to me with any questions. And if you're really new through this, make sure you go a little bit slow, because this course is kind of long, but actually rush this a lot. So you have to take it really slow because there's a lot of little tricks here and there that you might not notice. And then you get an error, and then your application is not working. So make sure you look at the code and make sure you understand why every line is doing and why every line is there. And if you have any questions again, reach out to me. I'll be happy to help. So I'll see you guys in the next one. And don't forget to like and Subscribe. I hope you had fun and lend a ton from this video. Let me know what you want to see next. Like, so usually I take the comments and suggestions, and I try to bring your comment actually content from what you guys request. So let me know what you want to see next and comment down below. Give me a thumbs up so I can keep on recording these videos. Yeah, if you're not part of the Migos core community, as always, go ahead and join the community is growing. And Yeah, I'll catch you in the next one.
Info
Channel: Amigoscode
Views: 65,315
Rating: 4.9704795 out of 5
Keywords: amigoscode, java tutorial, learn how to code, learn java, spring boot, spring security in spring boot, spring boot tutorial, spring boot microservices, jwt, jwt token, jwt authentication
Id: VVn9OG9nfH0
Channel Id: undefined
Length: 126min 49sec (7609 seconds)
Published: Sun Jul 25 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.