4. Real login | Spring Security with SB3

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so a couple of videos back we've made a fake login that just issues tokens willy-nilly in this video we are going to make it more realistic so that user credentials are actually taken into account to keep the video simple however we are not going to connect it to the database however we are going to do a service which is quite similar to how you would use a database so it will be very easy to connect a database later now let's get back to the code and actually implement it a really cool thing that you can do inside your controller is actually get the logged in user the way that you do that is in your endpoint method do an annotation of authentication principle which comes from Spring framework security core annotation and this is going to be your type of user principle just do the one that you made call this principle and let's uh let's expand this let's say if you see this then you're logged in as user and then let's get their email from get email from the principal and just for good measure let's do user ID principle get oops get user ID and let's make this free so it doesn't go over the margin here always make your code neat now let's try that let's get that token back in and boom if you see this then you're logged in as user test at test.com and that comes from this token from JWT and user ID also comes as a subject from the token let's get that postponara here as you're jumping for joy I hope that you're not forgetting that the login that we've made is actually totally fake if we open our off controller we can see that we have hard coded the information that we issue this token for so if so so anybody can enter absolutely any data in the login and they can still log in so let's fix that and in order for us to fix it we need some sort of a source where we get users from so that is usually going to be your database however I don't want to make this more complicated that it needs to be so I am going to make a fake user service which is just gonna serve users based on their email let's do that let's create a new package in our application package and let's call this service and you will most likely have something named user service so let's mark this as a service so that it gets managed by Spring and usually you would go in and do something like private final user repository blah blah blah but we don't have that so let's just make a public optional method that returns a user entity oops I don't have a user entity yet so let me create that let's create a package called entity and that's where you would place your database entities let's create a user entity let's get some Getters and Setters there and you would do something like entity not doing that right now let's just uh give it an ID let's give it an email let's give it oops let's not make these finals just uh getter Setters they're they're not final let's do a string password and when you're doing something like password always annotated with Json ignore just so you're not leaking any hashes what else is missing let's let's add a single roll and to make it simple Also let's do this as a string let's call this roll and just to get my point across that user principle is not a user let's add some extra info here so this is not going to be representative of anything it's yeah this is just to make user entity different from user principles so that you get that these are totally different concepts are right back into user service we can now import our user entity and let's make this let's call this method find by email we're gonna pass in an email which we're looking for and let's make a to do move this to a database so that we don't forget this but uh let's do it like let's do it like this let's say that private static final string existing email is going to be test at test.com and then if existing email does not equal the email that was passed in then we just return an empty optional this means that the user was not found that's a guard clause now in any other case let's just create our fake entity Let's uh let's call it to our user new user entity let's give it an ID of one let's set email as existing email user set password now this is quite important don't Store Plain text passwords even an example applications because it's very simple to set it up properly with pcrypt so let's do that I want my user password to be test so let me just open a browser and and let's search for be Crypt online the first result that's that's going to come up is probably going to be decrypt generator so this works string of tests encrypt copy the hash put it as your password because this is what would be saved in the database and let's just write a comment test that this means test and let's continue Let's uh let's set a role for this user so a user Set Roll Roll admin user set extra information and let's call this my my nice admin and let's return an optional off this user entity that we've just created so with our user service done let's move on to security and let's connect this to Spring Security inside the Security package let's create another class and let's call this one custom the user detail service now how's that different from our user service well let's see let's create that and let this one implement user details service so that comes from Spring Security so this is what spring uses to load user specific data into the framework so let's do that let's implement the methods and it says load user by username and in our case a username is their email and let's inject our user service into this one so tag this as component require RX Constructor and inject the user service now this load user by username needs to return a type of user details and if you've paid attention you'd know that this user details is actually what is implemented in our user principle so what we can do here is we can just return our user principle and the reason why I've split user service from Custom user service is that this one that we just made user service this returns a user entity and not a user principle so let's do some conversions inside of this method first uh let's get the user so user user service find by email we pass in a username and what if we don't find a user with that email let's do or else throw so if it doesn't find a user this will quit with an exception and as a return I'm gonna build a user principle and I'm going to need to pass in some some parameters like user ID user get ID let's map this one email you uh user get email authorities it's a list of simple granted Authority and user get roll because remember principal authorities is a list of authorities and what we've put in user is just a single role you can expand this into a list of roles as in challenge so there's that but there's one more thing missing and that is the password there's there's no password in our user principle so let's add that let's do a private final string password don't forget to Json ignore just in case somebody prints this out into the wild so make sure that we're not leaking any hashes and here where it says get password to a return password and this is important because a spring under the hood uses user details get passwords to actually compare it compare the hashes and do all the log and stuff so so this is important let's get back to custom user details service and finally let's pass in that password from user get password and that's it now you need to connect this custom user details service to Spring Security let's do that open web security config and inside the config you can just do a prime in check the private final custom user details service let's call it exactly that and now you need to define a couple of new beans so just below uh just below your main application security config being to another bean and Define a password encoder and do a new decrypt password encoder so this will make sure that it's not plain text but it's actually bcrypt and another beam that you need to make and returns an authentication manager and this is what's going to do all the magic for your logins do authentication manager and pass in HTTP security as an argument and now do a return http get shared object and inside that authentication manager Builder make sure it's a builder dot class and now you can set user details service the one that you've injected into your security config so custom user details service the one that we just made and this one might throw an exception so propagate that your method what else do we need we need a password encoder and we can just do an and build so now your Spring Security is wired to actually have login let's make the actual login so go to your off controller and really quickly inside of this controller temporarily we're gonna try and pass the credentials that user has put in the request we're going to pass that through Spring Security so do a private final authentication manager inject that authentication manager and let's let's try to authenticate it do a VAR authentication equals authentication manager dot authenticate inside it we're gonna pass what comes from Spring is a username password authentication token and that takes the arguments of principal and credentials which in this case basically means that it's a request get email and request gets password if user has entered invalid credentials it will fail here if credentials are valid a new authentication will be created with our user principle so just in case somebody is going to call some extra services in the future here we can just do a security context holder get context set authentication we can set it to this authentication now let's extract the principle from that uh principle authentication get principle and that is an object but we know that it's our user principle so let's cast that to user principle that we just made and let's issue a token not for these hard-coded values but for something that comes from our principle so principal user ID email principal and get authorities there we go so that is complaining because as you can see our jot issuer needs a list of string rolls and these are authorities what we can do is we can you can convert that let's do principle get authorities stream map credit Authority granted Authority get Authority and this can be optimized back to this let's do a to list and now here we can pass in rows so now if I've done everything correctly and I run my application a user should be able to log in with correct credentials so let's try that let's go to postman and let's try to log in with uh something fake and ooh it gives a 403 Forbidden but let's try and do a user that actually exists test at test.com and that's still forbidden because we haven't provided a password let's do a password let's do anything still nothing and the correct password was test let's run it and there you have it there is our access token issued by our backend that is valid and that can now be used as a token to reach some secured endpoints and this is how you make a login with Spring Security hopefully it should be pretty easy for you to connect a database later you've also learned how to inject a currently connected user principle into the controller in the next video I am going to show you how to add some more roles to your system so that not only you can have simple users but you can also have admins as always before you click off please leave a like on this video so you can find it later share it with your colleagues if they will find it useful and subscribe if you want some more content like this now let's go to the next video
Info
Channel: Rytis Codes
Views: 586
Rating: undefined out of 5
Keywords:
Id: U8D2MPwNARA
Channel Id: undefined
Length: 17min 45sec (1065 seconds)
Published: Wed Mar 15 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.