Java Tutorial - Complete User Login and Registration Backend + Email Verification

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's going on guys welcome to amigos code in this tutorial i want to teach you how to build a full registration system where we're going to implement this application right here with secure endpoints an application user with some roles the user registration with controllers service and also we're going to have verification links and also send emails so this course is actually um really hands-on on building a back-end system right here so we have a person that wants to become a user in our system so here uh but then it goes through this flow right here and once they verify their email then they become an application user with the role of user so let me quickly give you a demo right here so basically i've got this post request so amigos and then this should be capital c so we want to register this person i'm going to send so right here we should see an email coming through very soon there we go and um i actually have a typo on the email uh right here so hello w amigosco.com and right here hi amigos and then thanks for registering please click on the link below to activate your account and also the link will expire in 15 minutes so basically everything will be working and then i'm going to activate now and you can see that it's confirmed and now which means that i can go back to this application and right here let me just log out first so i'm going to log out and here so the email was so a low w my email is actually a low at no low w so just copy that and then paste that in and then here the password was pass word and then enter and there we go you can see that um we actually get four or four because there is nothing configured under this path here so there's no mapping here but everything worked beautifully so uh yeah so you can also grab the source code for the entire project under the link uh actually under the description of this video uh yeah so if you're new to my channel go ahead and subscribe give me a thumbs up all of the related courses for this little project i'm going to leave some links as well where you can learn about spring spring data jpa some front-end databases so we're going to be using postgres so here you can see that we we have um the registration going on so if i select from the token so you can see that this was a token right now that was issued to myself and then it was confirmed just now so you can see the timestamp there and also if i select uh let me just go up so app users there we go so you can see that basically so right here this is me so hello right here and the password is actually um encrypted uh yeah or actually yeah using bakery by the way uh yeah so this is a complete um tutorial where um i just thought maybe would be fun to build something like this together because learning how to do something like this can be really valuable and hopefully you can learn uh something new here so yeah so um also uh one thing that we're not going to focus in this tutorial is about testing and you know unit testing integration testing if you want to learn about testing i'm also going to leave everything under the description of this video so you learn how to build proper software without further ado let's kick off this video let's go ahead and bootstrap this project with spring initializer navigate to start.spring.io and in here we're going to pick java as the main language and then the version 2.41 basically pick any version that you see here because this will work and then for metadata i'm going to leave as it is for packaging jar and i have java 15 installed now for dependencies i'm going to click on add dependencies and here we're going to pick a couple of dependencies one i want to pick lombok so i'm going to press command and then click on it and i also want spring web and we also need spring security and also we need this one here where we want to connect to a postgres database here so postgres driver and we also need spring data jpa there we go and finally we need a mail so we want to send emails so i think he's right at the bottom actually let me just search for it so mail there we go java mail sender command and then that and i think that's everything so if i press cape and you can see all of the dependencies so lombok so this is to reduce the boilerplate code with all the getters and setters and you'll see this in a second and then spring web for restful applications security to secure our application and we have spring data jpa for persisting data in sql and in java mail for sending emails so basically in here we have all the dependencies for this diagram here so we're going to implement everything so now let me go ahead and actually generate this project and also i'm going to share this with you so let me just generate the project i'm going to say allow and here i can share this i'm going to copy this link and then i'm going to put this in the description of this video so you just so you can just download the zip file all right now let me go ahead and open up my desktop and in here i'm using intellij so go ahead and install intellij with toolbox so toolbox right here so two box so this awesome application where you can pretty much just manage all of your ides so now i'm gonna click on open or actually first i need to extract this so cancel extract there we go and now i can dash this to the bin and i'm going to open desktop demo and then open cool so this will open the project for us so now it's resolving all the dependencies so just give it a second and cool so now open up demo and in here open up source and by the way if i open upon.xml you can see that we have all the dependencies so jpa mail security and right here starter web postgres lombok and this is for testing and also this is for testing with spring security and this is pretty much everything so if i close the palm.xml open up the main file and the first thing that we're going to do here is to create oh actually let me rename this to application and instead of properties this will be dot yamo just like that and in here what i'm going to do is i'm going to paste some code here and basically this contains the configuration for connecting to a database so right here localhost 5432 this is the name of the database you'll see in a second and then this is some jpa specific if you want to learn more about all of this check my courses on youtube and on my website where i teach all of this so now in here in my terminal i'm going to type psql so i'm using postgres for the database and backslash l also if you want to learn more about sql i've got course on sql and postgres so you should definitely check those out and it's absolutely for free by the way so here you can see that i've got a couple of databases so what i want to do is create and then data base and then registration so registration and then semicolon and there we go so if i clear the screen backslash l you can see that we have a registration right here so now this means that this name is my database name and now i should be able to connect to my database so now what we're going to do is i'm going to open up project and then open up main so what we're going to do is the following so basically um in here you see now we have the spring security so this is where we configure the endpoints roles and then registration basically let's actually tackle the application user and then define some roles and also the service for it because everything then will actually um be based on the app user so a person will then become an application user when they actually register to our application so in here what i'm going to do is go back to intellij and let's create a new package so here package and here i'm going to call this app and then user inside here we need to have a class called app and then user so this is the user itself so the application user and then here what we're going to do is say that this implements and then user and then details so the reason why we are implementing user details is to do with security and you'll see this in a second um but there we go so now we actually have to basically um fill these in so what we're going to do here is the following we're going to define so let me actually put this full screen so here we're going to define a couple of properties so here we want we want to have the id so private and then long id we also want name so name or actually string name and basically i've just gone ahead and added a username email and password in here so we also want to have so private and then this will be app and then user and then row and this will be an enum so let's actually create that so here we're going to create this so this will be app user and then row and then enum so here basically we want to have a user and also we want to have an admin so if you want to learn more about spring security go ahead and check my course on spring security where i cover everything that i'm doing here so now you can see that the error went away and here i'm going to say that i also want to have so private and then i want to check basically whether the account is locked so boolean oops not that but boolean and then locked and then private and then boolean and then enabled there we go so now let's go ahead and basically in here let's fill in these fields so for the granted authorities so here so in here return and then no this is a method granted authorities what i want is to return basically this will be simple and then granted authority equals to new and then simple granted authority and now i'm going to grab the role name so here app user row dot and then name just like that and put this on a new line so you can see everything there we go so now i can return a collection so here i'm going to say return and then collections dot and then singleton and then list and then pass the authority there now for the password we're going to return password for username we're going to return username for his account i want to say true for now and basically we're not keeping track for this in it for this course but here you can also manage this and then here um is account non-locked what i'm going to do is actually flip this i'm going to say locked and then here i'm going to reverse this so makes more sense and then is a account non-expired so i'm going to say true and i really don't like the way that they've done this um non-expired and then finally we have is enabled and this will be enabled there we go so now we have all of these being returned as well as the authorities so this is four in here so this is the application user has authority right to basically um access certain api endpoints and do a few things depending on the actual row whether it's an admin or a user so if i go back in here what i need now is the getters and setters so i'm going to be using a lone book for this so at and then getter and then add and then setter and i also want to add equals and ash code and at no r constructor and there we go so i also want to have one constructor without the id and this is because the id will be auto-generated for us when we create um the entity with jpa in a second so here i'm going to say constructor and select everything but id so it would be nice for lombok to have actually um a way of us defining this with annotations uh but i don't think there is so here put this on a new line just like so now here what i'm going to do is i'm going to say add and then entity so this will be a table in our database in a second and then for the id what i want is this to be a sequence so i'm going to say at and then this will be id right here and make sure that this is from persistence basically this package here so persistence right because then we can change the provider easily and then what we need is to say at and then sequence generator and inside i'm going to say name equals to and then student and then sequence and then i also need the sequence name so this will be the exact same thing so there so sequence name just like that and then here allocation size equals to one and now let's also say that the value for this will be at and then generated value right here this will be strategy and then sequence oops just like that and here we need to say generator and then the name so that will be student sequence and i could call it generator but it's fine so there we go so actually um let me just put this right here it doesn't really matter where you put these annotations uh and yeah so there you have it so this is um for the id and also in here so for the application user role because this is a an enum this is an enum we need to say add and then enumerated and then enum type so inside enum type and then string so you will see everything up and running in a second when once we start the application so there you go so this is um the app user now let's also create the service so class and then app user and then service and this class here will implement a a class or an interface specifically for spring security and that is d so it's gonna we're gonna say implements and then user and then details and then service so this is actually how we find uh users once we try to log in you'll see this in a second so load and then user by username so if i put this full screen so there we go and right here we have to find a way for us to find a user by um the username so in our case the username will be the email and what we need is a way for us to have a query against our database so here i'm going to say student and then repository and this will be an interface and for this interface here i'm going to say add and then transactional and then here i've got read only and then true and let's have a an interface here where i'm going to say optional or actually method and this will return an app user and then i'm going to say find and then buy and then email so make sure it's the exact same thing here uh because this will construct the actual query for us so here there we go and here we're going to pass the email just like that and now we need to annotate this also with um at and then repository even though it's not necessary but still good practice so the integration with intellij becomes obvious so now if i go back to the service class in here and put this full screen now i'm going to annotate also this class with add and then service and now let's have a reference to so actually let me put this just like that so you see everything so let's have a reference to the repository so private final and then user repository or actually app user and what did i call it oh my god i call it student uh the reason why i call it shooting is because i've done a video um on students recently so this is app and then user and then repository my bad so there we go so now so app user and then repository and then app user repository now in here i'm not going to add to the constructor because i'm going to use lombok and i'm going to say that this will have at and then all args constructor and you can see the error went away so now i can pretty much just so in here i can say return and then app user repository so app is a repository and lowercase here dot and then or don't and then find by email and then pass s there so this will be the email and here email and then here i'm going to say dot or else throw and then we're going to throw so we're going to throw the um username not found exception right so new username not found exception and then inside so here let me just put this on a new line so you see um oh actually let's let's just uh have a message here so private final static and then the string and then the user not and then found equals two and basically i'm gonna say user read email and then percent s not and then found just like that and now in here what i can do is so let me put this again in here i can say string and then pass the message so user not found and then pass the email just like that and i think we are good so here um let me actually rename this to message just like that and there we go so basically you can see that the reason why i'm putting this on a new line is that you can see everything otherwise i don't have it like that the font is so big which makes it super difficult for you to see um what i'm doing so um yeah so this is pretty much right so now we actually have so we have the app user we have the repository and then we have the row and also we have the service in here now what we're going to do is we're going to basically let me just change the order of this in here so just like that i don't need that in there so basically in here what we're going to do is the following so we have this app user and then we're going to build upon things so here we have the user registration right here user registration so let's actually start from here and then build this sign up and then verify the email as we go so let's create a yet another package and this time we're going to call it registration there we go and right here let's create a class so here we're going to say registration or we could say user registration controller uh it doesn't really matter so registration and then controller there we go this will be at and then rest contact today so rest controller and what we want also is to change the path for this right so we want to say here that this will have at and then request and then mapping and the request mapping for this the path will be so here i'm just saying um api and then forward slash v1 forward slash and then registration there we go so i've managed to spell registration correctly and also let's have the um at and then all rs constructor now that we have this controller we need to have a method to register basically basically we take so in here we take this person along with some information and then we want to register this person so here what we're going to do is we're going to have a method so here i'm going to say public and then here let's say string and i'm going to say register and you'll see why string in a second so i'm going to say register and at and then request and then body from the request body i want to capture so here i'm going to capture the registration and then request and i'm going to call it request and then in here i'm going to say return and then registration service and basically you can see where i'm going with this so service and then dot register and then pass the request so now we don't have neither the request nor the service so let's create both so here so inside of the registration package so here i'm going to say registration and then service and here this registration package also needs the so registration and then request there we go so for the request um when the client sends a request we want to capture a few things so we want to capture so here private final and then string and then first name and if i duplicate this couple of times so there we go so here we want last name we also want password and we also want email so let me just put that in there just like that so now let's generate a couple of things so here we want to generate the getters and also we want to generate the constructor so add and then all our constructor and let's also have the equals and let's also have the add and then to string there we go just like that was finding a bit difficult to find so uh yeah so basically this is the request so now let's go back to the controller and we still have to basically have the reference to our service so private and in here we want the registration and then service just like that and problem solved now the register method we don't have so let's create it so i've just pressed option and then enter and then create the method there we go and here i'm just going to return no for now so basically you can see that how this is coming together now what i want to do is before we go oh actually before we move any further on this so i just want to start the application and configure spring security so that things are working before we actually move on so here let me actually say works so basically we should get to a point where we can see works from our request and then we'll carry on so for the security side of things what we're going to do is create another package here and then i'm going to say security there we go and inside of this package let's go ahead and create the following so when it comes to spring security um we have really one package where we configure things and that is the so inside so here oops so here let me have yet another package and i'm going to call it config not concake so just rename that so con and then fig and inside of this config class i'm going to have a class called uh oh actually package i'm gonna have a class called web and then security config just like that and then enter and there we go so also um i want oh actually i've got typo here so let me just um fix this typo so security just like that and also i want to have another class here um called password and then encoder and you'll see this in a second and this should be really outside so basically i don't want this class inside of security so let me actually in here i'm going to say oh actually config i'm just going to say it's inside of this package i'm going to move to this package just like that and if i open up security i don't know why it did that but here you can see that we have now it's outside of this config package so inside of this web security um the configuration really it's you know once you get used to it it's not that difficult uh but i've covered all of this in my course so i definitely um would advise you to to go and check it out but what we need here is first to annotate this with add and then configuration and then i'm going to add and add all our constructor and the magic really it's when we enable uh spring and then security right here so at enable spring security now here in order for us to customize this we need to extend a class called web and then security and then configure and then adapter just like that so in here what we need is to have the following so we need to override so let's override methods and the method i want to override is the configure method that takes the http security now inside here inside here what i want to do first is i'm going to delete this and here i'm going to say http and then on a new line dot c r f and then dot disable so this is so that i can send the post requests um without being rejected and i've covered why i disabled this and this is just temporarily right so if you are using if you if you are going to use form based authentication as we are using then you should definitely enable this but again go ahead and check my course where i explain um all of this so now i want to say dot authorize and then requests and then here and then ant and then matches and inside i want to say forward slash so this is the pattern so api and then forward slash v1 and this actually would be star so oops not emojis but star and then forward slash registration regis tradition and then forward slash and then star so i want to enable everything within or basically not enable but i want to permit so i want to say dot and then permit all so anything that goes or actually any request that goes through this endpoint we want to allow it sometimes it's best if you have for example a more concrete example um instead of you know basically basically allowing everything maybe you just want to have full control of what you are allowing the client to access but in here i'm allowing everything under registration so i want to permit all in here and then i want to say that dot any request dot authenticated must be authenticated and so and we want to use form oops dot and then form and then login and there we go so this is the configuration needed now we need to basically configure a few things or actually override a few things so the the other thing that we need to override is so override methods we need to override the configure that takes the auth manager builder and basically this guy here um in here we need to say auth dot and then authentication provider and we have to implement we have to basically pass one so here let's go ahead and have a bin so add and then bean and then here we're going to say public and then dao and then authentication so this is one implementation so authentication provider just like that and do provider and here i'm going to say dao oops so dao provider i'm going to call it provider equals to newline new and then dal authentication provider and in here i want to say provider dot and then set and then password encoder and here i'm going to say also provider dot set and then user details service and then i want to return the provider now remember so when we added the user so app user service we implemented user detail service which means that we can use this guy in our provider so here i'm going to say private oh actually private not protect not protected so private and then final and then app user and then service there we go and basically all our constructor adds that so we don't have to do anything here and in here so where we set the user details we pass the service so app user service now for the password encoder so this is why i created this password encoder so in here let's go ahead and basically we have to annotate this with at service so this will be a service oh actually not service but mainly a configuration so at and then configuration and from here what we want is to have the public and then be crypt oops just like that big create password encoder so this is one of many password encoders available to us and here i'm going to say return oops new and then bakery password encoder just like that and obviously we need to annotate this without bean so that this is available for us to use and now i can take this and then go here and let me put this just like that and then i can say private final and then that and there we go so now we can inject it in here and now we can pass the encoder here so be crypt password encoder and now in here we can say dao and then password provider and there we go so this is the configuration needed for security so let me actually show you what we've done so we've done a little bit of this a little bit of this and this is actually fully done so now we are securing the endpoints we haven't done verification links nor email and we'll do that in any second so now in here let's go ahead and so in here if you open up demo application so you see that we have the main class so what we're going to do is so i want to start the application just to make sure things are working so let's run the application together so right click and then run and we have an error so app user required and basically could not find the repository so let's actually have a look so in here i can see why it's not finding and that's because we need to say extends and here we're going to extend um basically jpa so jpa repository so this one and then the type for this is app user and in here the id so the type of the id for our app user is long so let me show you so app user so this is the class this is the entity and then the type for our id is long right here so now if i go back oh actually i can just run it again there we go we also have another error so could not be found so registration service so the registration service could not be found cool so we've missed also the the annotation so i guess so where is it so the controller so registration controller and then the service so here at and then service so there we go so this is why i wanted to check that everything works before we proceed right so with software engineering you know things don't work you know right away so usually you know silly mistakes like this um can happen so there we go so now everything is up and running and you can see that we have our app user here so if i show you so if i connect to registration and then in here backslash dt and then registration or actually black backslash d you can see that we have the sequence as well as the registration so here if i say app user not registration we have the app user in here and the sequence so if i describe up user you can see here that we have all the columns and the types as well all right now let me go back in here and what i want to do first is to send a post request so that we can see this message right here so remember in our registration service we have works or let's say it works i think it's a better message stop and rerun and and now let's open up i'm going to open up i'm going to open up postman and in here i already have a couple requests that i was playing around with so localhost 8080 api v1 and in registration and then on the body here so this is the name so bilal ahmed um let's just change this to bilal for example and then the password so if we send this request you can see that it says not found so most likely we have an error somewhere so let's let's have a look so here so the server started on port 8080 in here and then let's have a look at our controller so api v1 registration right here and again so it doesn't find it because we need to annotate this with at and then post and then mapping so let this be a post and let's restart the application so while this is uh starting let me go back and this now let's change this to a post instead of a put and and then in here let's just send the request and you see that it says it works so we are good to go so here if i try to access for example um let's say hello for example send you can see that we get this page right here which says login so this is spring security in action and in fact if i take this and then go to my web browser in here paste that in you can see that we get redirected to this as login page basically right so um security is actually you know taking care of um spring security is taking care of securing our endpoints which is nice so now let's go back in here so we kind of have the registration kind of working um basically it's not doing anything so now let's implement the logic to basically register someone so let's open up intellij in here and i'm going to cancel this process for now and now let's open up the registration service and instead of saying it works what we want is to basically let's just do some business logic whether the email is valid or not and then if it's valid then we just invoke the app user service to sign up the user so in here what we're going to do is first we want to check whether the email is valid so for this let's create an email so here i'm going to say email and then the data there we go this will um so this implements and then predicate and this will take a string and let me implement the method so test and this will be at and then service so for now let's just return true ideally what you want is to have a regex here so to do regex to validate and then email so i'm just going to assume that everything is valid just for the sake of this tutorial so go back in here and now i can have the add and then all and then our constructor and let's have the private and then email validator just like that so now if i put this full screen i can say um email validator dot and then test and then request dot and then get email so i can say now is and then valid and an email just like this email there we go and no email email come on time today uh and yeah so there we go so now if someone say if and then is and then not so if it's not a valid email i want to throw an exception so for now let's just say throw new and then illegal state exceptions uh just bear in mind that uh there are better ways of handling exceptions but let's say email and then not and then valid for example and you could also add the email if you want so you can have a string format add the email but i'm just going to keep it like this so now what i'm going to do is i'm going to have a method inside of the app user service to sign up users so at this point we actually said right so we can register this user so let's actually forward the request to the app user and then service so in here after load username oops i don't want to exit exit my bad i meant to press command and then one so here what we want is to have a public and then string and basically we want to return the um link where they have to confirm uh actually the uid basically the link that they will have to confirm in a second so here i'm going to say sign up so sign and then up and then user now this will take an app user and for now let's just return an empty string now let's go back to register so register and instead of saying returns oh actually it works we want to basically inject so here let's say private and this should be final and final and then app user and then service there we go and now let's say oops return app user service dot and then sign up and then here new and then app user now the app user remember we had a constructor that takes couple things so here we want to pass the name so request dot and then get first name and then comma so here we have the username for us this will be the email so in fact what we're going to do is if i go back to the app user so let's actually fix something here so basically uh this is actually first name and so this will be first name so first and then name just like that and i want to refactor everything including that and this is not username so this will be a last and then name again okay and then we have email password app user role and then in here let's actually remove these so we don't want to set those as well and we have one problem here it's complaining about right so it's complaining about get username so we need to basically return this getusername and this will be email so there we go and let's just move those two and we have another problem yes right so this is now is is on the other side so i think this uh is more like it so first name last name email password and basically we need to have the get and then first name last name and email is for username just like that and i think that's it so this fixes the problem so let's go back here and by the way none of this is actually planned so i'm just coding as i go so now we have the request dot and then last so get and then last name and what was that so last name email so you need to pass the email so request dot get in an email and on a new line so command p the password so request dot get and then password and last but not least the app row so here we want to register a user and there we go so i think this is everything for this method now we can drill down into sign up user and here we can have more business logic so just before returning the empty string we're going to check whether the user exists so i'm going to say app user repository dot find by email and i want to get the app user dot get email so if is present dot and then is present right here i'm gonna name this exists oh actually user exists just like that and new line here and now i'm going to say if and then user exists so we if we have a user with that given email we want to throw new illegal state exception and we're going to say email already taken if this is not the case then we know that we can proceed so if i scroll up and in here we want to have private final and then be crypt so b and then crypt so password encoder just like that and i'm going to say password encoder dot and then in code and then app user dot get password so now i'm going to say encoded and then password and let me put this on a new line so you see things so usually i don't have formatting like this it's just because the font is too big and i can't fit everything um on the screen so now we have the password encoded in here so let's take the application user so app user dot and then set and then password and then i'm going to say encoded password and to be honest this is pretty much um the logic so again instead of saying um empty strings i want to say it works and what we need to do uh later is let's actually do a couple of things here so here i'm gonna have a to-do and then we need to basically send confirmation and then token so we have the user right so we have the user we encoded a password but now we actually need to save the user so what we're going to do here is so i'm going to say user oh actually app user repository dot and then save and i want to save the app user just like that and now we should have a user in our database so what we're going to do is the following so let's go ahead and rerun the application and we're going to send a request so the exact same request that we sent before and we should see that we have the user in our database there we go application up and running now if i open a postman and remember before let me see if i can put this bigger so you can see um actually bigger makes things worse so i think this should be fine so before we had um a request and this was bilal ahmed and ahmed oh actually not mend ahmed and it should be made just like that so now let's actually send the post request and there we go you can see that it says it works and in here if i say select start from and then we actually have um app user in in here and let me actually press command actually q and then backslash x and there we go so you can see that we have here bilal ahmed and then we have enabled which is um false and then locked which is false so what we're going to do is actually fix this and this so let's go back to intellij and in here if i open up app user so here we want to have defaults so if it is a locked i'm going to say false and then is it enabled i'm also going to say false so these are the default values so let's rerun there we go so let's send the same request and again if i run this we lose everything and that's the way i've configured the database to destroy everything so that we don't basically because we are in testing phase we are just testing whether the code works or not but then if you take this to an environment you should configure in a way that you don't lose your data basically so here and actually let me just quickly show you what is doing it so here if i open up an application.yaml and in here so this is what is doing it so create drop so yeah so now if i send the request it works and if i run the exact same command there we go and check this out enabled false and then locked false so the reason why enable is false and locked and basically it's not locked of his account right but here enabled is because we only want to enable this user once they confirm their email so i think that now so if i open up app user in here oh actually uh the service class so in here so i think that now we are in a good place to implement the email validation uh where we have um a token sent to their email and then they have to click on it and basically their account becomes active so if i show you so remember so this is the email so bilal ahmed so here if i put that in and the password was password if i sign in and [Music] i think my web browser is actually frozen oh actually no it's not so it just took a while and i'm not going to save um this so not now and you can see that user is disabled so this is actually what we want so we want to enable this once they confirm their email so that's what we're going to implement next so let's go ahead and open up intellij and let me collapse this and let me actually just show you the actual diagram so here so we actually have basically the user registration in here um basically we can now register a user and i didn't actually show you the exception so let me actually show you the exception so if i send this request you can see that email already taken so this is also working and now we have to implement the verification link where um it has an expiration date and then also sending emails and then we are done so let's actually tackle this first so let's go back to intellij and in here let's go ahead and inside of registration what we're going to do is create a brand new package and here i'm going to call this as token so this is inside of registration so i'm going to say token and for this token here we want to store this in a database so we want to store the token in the database so let's create the class and this will be an entity so this will be a confirmation oops so confirmation and then token and we're going to have a couple of fields in here so what we want is to have a private and then this will be long id so long and an id we also want to store the actual token so private and then string and then token and we want to store the fact that the token was created at so this will allows us to know whether it's been more than 15 minutes or not so local and then date time and you'll see this in a second we also need um private oops and then local date time and then expired and then add and i don't know why did i say that so this should be created at and then this should be expired expired at and then we also want to know when the user has confirmed the email or actually using the token basically so local date time and then confirmed and then add so confirmed should be like that confirm that and there we go so this is everything so now let's actually annotate this with couple of things so here this will have the at and then getter and and then setter at and then let's say here oops oh um oh actually let's have the no r constructor first and and let's have also a constructor without the id so constructor without the id and let me pull this on a new line so just like that and let me put this full screen just like that so four fields and also let's go back to app user and then take the sequence so we're going to take all of this oops and then go back and then paste that in and here let's annotate the add and then column and here i'm going to say nullable and basically equals to false so we can actually customize everything but let me just put the token because it's the most critical thing but all of these um oh actually this also should be oops wrong copy paste so that and that so they shouldn't be nullable and then expire that and confirm that um they actually um they should be not known as well so confirm that shouldn't be no and here let's actually rename this to expires so expires at so refactor all of that and also let's change the parameter there and i think this is a much better name so there we go so also let's change this so instead of shooting sequence so this will be um let's say confirmation and then underscore token and then sequence just like that and there you have it so i think this is looking good so now so now what we need is basically to type this token to a user so here i'm going to have private and then app and then user just like that and let me also add this to the constructor so this will be app user just like that and then this dot app user equals to app user there we go so this will now be at and then many to one because an application user can have many confirmation tokens and here i'm going to say at and then join and then column and i'm going to say nullable let's also say nullable equals to false and comma there and then name so the name for this will be app underscore user underscore id there we go so now we are sorted so one user can have many confirmation tokens now let's uh quickly implement the service for the confirmation token so open a project and in here i'm going to create a new class i'm going to say confirmation and then token and then service there we go and we also need so let me just take this name because it's kind of long so we also need oops not that we need an interface so class and this will be repository we paul z3 just like that and interface and this will be add and then repository there we go and let me put this full screen i'm going to say extends and then jpa oops and then repository this will be confirmation token and then long so that's the type of the id and put this on your line just like this so obviously we now have to implement a couple of things um but one of them which we definitely need is to find the confirmation token so find by confirmation token so here i'm going to say optional and then this will return a confirmation token and then say find and then buy and what did we call it so here we did call it token so find by and then token there we go and this now um takes the actual token so string and then token and we are sorted so i usually advise people to have the query as well here but let's just move on and if you want to learn more about jpa check my my course on it so now let's go back to the service so confirmation token service and here let's annotate this with add and then service there we go and what we want to do here is to expose the ability for us to basically save a confirmation token so here i'm gonna have a add and then all our constructor and let's say that we want to have the repository so private final and then confirmation token repository and let me put this full screen and here what we want we want to have a method so public void and then save confirmation and then token just like that so here when we save the token we want to pass a confirmation token just like that and let's just say name a token actually so here we want to say confirmation repository dot and then save and then token there we go so now we can go back here to the app user service and remember we had this to do so send confirmation token so here what we're going to do is pretty much just take or actually create a token and then create a token and then save it using the method that we've just written so in here we're going to say confirmation token equals to token and then equals to actually token equals the new token or confirmation token uh put this full screen and here we have to pass the token so the token will be of type u uid just like that and let me name it as token oh actually so this will be token and this will be confirmation token um and then equals to uid and then dot random uid dot to string and this should be string actually there we go so now the um token will be the token that we've just created so token and then created ad will be now and then expires at will be basically the same so now but plus and then minutes and here this would be like coming from a configuration um file but for now let's just say 15 minutes and what else we have we have um in here so we have the token and then we have confirm that so confirm that um will be no so let's actually go back here and then confirm token and we want to remove the confirm that from here just like that and what we have to pass now is the actual user so app and then user oh actually let's see a app oops app user just like that and in this with semicolon there we go format things and it's looking good now so let me remove this to do there and now that we have the token what we have to do is just save it so for that we need a reference to our token service so private final and then confirmation token service so that's why we have the service instead of using the repository directly and here i'm going to say service or actually confirmation service dot and then save token and then confirmation token and there you go so now instead of saying oh actually instead of sending it works we're going to send the token itself so there we go and i think this is actually looking good so now we actually have another to do here so to do send email and we'll tackle this in a second so there we go so now let's actually restart the application and let's just see whether we actually save a token in our database oops we have some errors basically like always right so confirmation token it's not manage type okay cool so let's uh open up confirmation token and of course i've missed the add and then entity start again and there we go so up and running and right here let's actually send bilal ahmed to our system there we go and you can see that we have the token here so status okay 200 if i do a select and then start from and then was um what confirmation token so lowercase confirmation token there we go so you see that we have the token in here so currently it's midnight so midnight for me and it will expire in 15 minutes right here so 15 minutes and this is the actual token and confirm that you can see that this is no and then below so app user id is one right here and this corresponds to this one here so now we have the token next we need a way of us confirming the token so let's implement that so basically um we have the token i said links tokens same thing but basically we have the token now let's actually make sure that the person can verify that token and then we send the actual email as well so now in here in intellij let me stop the server and actually before we we test things um i'm actually missing an annotation i'm actually missing and actually before we test things we need to annotate this with add and then transactional because basically you can see that we have um you know two statements so two update statements and here we want all or nothing again if you want to learn more about database uh actually advanced databases including transactions indexes and more go ahead and check my website where i've got all of those courses there so here now we can start the application so let's just start the application and this should hopefully be fine this time no errors hopefully and yes there we go so no errors so now let's um open up postman and here let's actually um press ctrl l and select star from app user and token 0. that's fine send there we go so you can see that now if i select from confirmation token we have one app user you we have um bilal here and you can see enable is false so what we had there was forward slash and then confirm and actually have an example here already so confirm and then question mark token equals so that's the request param so here let me show it to you so it makes fully sense so inside of registration controller so request param token and this is basically we have to say after confirm so confirm question mark token equals and then the token so in our case this is the token that we get back so let me actually again confirm it to you so if i press command f you can see the token is in our database so here let me just paste that in and instead of post this will be a get request and send and check this out we have confirmed and now if i select from the app using app user actually you can see that enabled is true so it went from false to true which means that now if we try to login using bilal ahmed gmail.com and then the password is password this time it should work password sign in and there you go so you see that it works so i'm actually not going to save this and basically we have a white white label error page because there isn't nothing on localhost 8080 so we haven't configured any mapping to localhost so that's why it's a 404 but it's actually working so there we go so we have secure endpoints application user with roles the registration service verification links the last thing that we have to do is actually send an email and to send emails this is actually straightforward so let's go ahead and implement that so open up intellij and this should be final and right here let's have so here we're going to have um a package let's say mail or actually email and let's have an interface so interface this will be uh email and then sender and the reason why we have an int we want an interface is because we can switch uh implementations so void and then send and then string and then um two and then here the email will just be a string so email there we go and we go and that's it so now in here i'm going to have a class called email and you probably guessed it correct so email and then service and this implements email and then sender and there we go so we implemented that and this class right here we're going to use um the java mail sender so here we can just um actually sorry so here we're going to first annotate this with add service before i forget and then add and then all args constructor and what we want is so first we want to have the private and then final and then java mail sender and let's just say mail sender and also we want to have some logging here so let me put this full screen and private final and then static and then this will be logger so logger from slf4j and i'm gonna call it logger and then equals two and then logger and then factory dot oops so get logger and then email service class so um again new line so you can see probably so now we can have actually uh oh actually now we can use this class to log when we send an email so here what we want is so basically we have this override method and we're going to do the following so here we want to send a rich email so let's say try so we have to put this inside of a try catch block so catch and here this is messaging messe and then jing exception and then e so if an exception throws we want to use our logger dot and then we want to error and we want to say fail to and then send email and then pass e in there and we also want to throw new illegal set exception and then here we actually just say fail to send email so we don't want to send to the user the actual exception that's why we have the logger in here now inside it's very simple so we have to say my message so my message and i think this my message comes from internet and dot my message i think uh yes so here um and then here what we're gonna do is pretty much just have the variable so i'm going to say my message equals to and then java mail sender or we actually call the mail center dot and then create my message and now we can say mime and then message helper and let me just say helper equals to new mime message helper and then pass the my message inside and let me put this on a new line so you can see everything and then the encoding that we want is u t f dash and then eight hopefully you should see this coming together so now we need to basically say helper dot and then set and then text there we go and the text will be email and you can see that we we can pass boolean whether we want this to be an html or not so email and then this will be true so this will be an html email and let's also say helper dot set and then two and this will be two so whatever email that we send and then helper dot set and then subject and here i'm going to say confirm your email just like that and finally the from so helper dot and then set from and this will be hello at amigos code.com and this is pretty much how we send emails so now um what i want to do is actually say that this will be at async so we don't want this to block the client um ideally we should be using like a queue so that we can retry sending emails but for now let's just not block the client and then just say async so this will be an asynchronous method uh yeah so there we go so now let's go to the registration service and i'm going to scroll up so i'm going to scroll up in here and you see where we actually register in here so what we're going to do is the following let's just extract this way variable so here i'm going to say token so this is the token that we receive and now i want to basically inject the email so private final and then email and then sender inject the actual interface there we go and now we can say email sender dot and we can also validate the email have bunch of logic but for now let's just say email.send to and then request dot get email and the email that we want to send is the following so i already i already went ahead and stole some email from a random website and then changed it um specifically for this tutorial so i'm going to leave a link where you can find the actual email that you can copy and paste or you can get it from the repository so what i'm going to do is actually just paste some code here and again you can grab this um i'm going to leave a link where you can find this method build email but basically here we take the name and the link that we want so basically so if i go up so here i'm going to say build and then email and you'll see this coming together so here i want to actually pass the name so request dot and for now let's just say first name and then we also want the actual link so the link will be as follows so here new line and the link that we want is so i'm going to say string and then link equals to and http forward slash forward slash localhost forward slash and then 8080 and basically let me just um take all of this right so all of this all of this let me just space here let me be lazy and then here i'm going to delete this token and then say plus and then token there we go and here this will be the link so this is the html email again you can find this method i'm going to leave a link where you can find this method and you can copy and paste it or you can get it get it from the repository so there you go so this is the email sender bit here so this is the link and then we return the token we could actually also return this but let's just keep the token in here and there we have it so now what we need is an email server to test all of this so there is a there is a nice email server that we can use written in node so in here let me see if i can open a new tab and then let me go to google and i think it's called um mail and then death so let me put the speaker and yeah so this is the mail dev so basically we can test sending emails during development so this is quite nice and it's very straightforward you just run npm install make sure that you have node and then mail dev or if you fancy docker you can try docker so the reason why i'm not going to try docker is because i'm using the new m1 chip and if i run docker right now my computer will just um die basically because i'm using intellij and they're not all compatible yet so i'm just gonna uh basically i already have this installed so i'm going to leave the link for this as well where you can find so let me go to my terminal and here so i'm not going to update for now so here let me just put this full screen so here i'm just going to say mail and then death and you can see that this now says the let me put full even bigger so here web app running at http and then 1080. so let's just take this and open up a new tab paste that in and there we go so we see that we have um this email server up and running so that was super easy so now what we need to do is to configure our application to point to this mail server so let's go back to intellij and if i open a project and then go to application.yaml so in here you see that we have spring and basically under spring if i type so here so make sure it's under spring right so the indentation matches with the ammo so here i can say mail and you can see that we have a bunch of properties so i actually have this on my buffer and again you can find all of this from the repo and basically i'm just saying mail and then host the port 1025 which is this one so the one for our mail server and then username it doesn't really matter you can say hello and then we have uh some ssl stuff going on and then connectivity timeouts and yeah so this is the configuration for our email so now if we refresh or actually restart the application and there you go you can see no errors and now you can see in the logs as well and basically there is nothing in here so now let's send the request so below and wow we have a 500 so let's actually oh right so yeah so token not found right so basically this wasn't the request that i wanted to send so i wanted to send a post in the body i want to send below with the password password and then send there we go that seems to worked you can see the token here and now i was expecting to see some login here but it's fine so let's check this server and let me refresh here nothing so let me go back to intellij and in here it seems that right okay classic we actually forgot to send the email so um mail sender so mail sender dot and then send and then we want to send the my message just like that so yeah there we go so a little little sad or a bit disappointed that we we've done all the setup but we didn't send the actual email which is uh sad so yeah so cool so now let's try again so let's send a new registration there we go so you see that that took a while um but i guess it's because it's trying to connect to the email server or the mail server status 200 and then the token here so in here i was expecting to see some logs but again no logs and check this out so we have an email right here so now let me click on email and you can see that we have this awesome email where it says hi the first name and then thank you for registering please click on the link to activate so here and also it says that the link will expire in 15 minutes so here if i press on activate and this doesn't seem to be working so i think it's because in here so here this should be http just like that column and then forward slash word slash so let me again restart the application cool so now let me send the request again there we go so the request was fine 200 and in here you can see that we have a second email so 1055 click on it now let's activate the account and check this out so this is now confirmed which means that so if i take bilal email so here and then go back here and then um in here let me refresh this so put the actual email email there and then the password was password sign in and there we go so you can see that and this works and we get 404 because we haven't mapped any endpoint to this path in here so awesome so now what i want to do is so basically in here i want to actually select the confirmation token and you can see that it's been confirmed at and this was the time that i could actually confirm the token so if i was two so um if i was to click on the email again so here activate now so this time we actually get an error back and it says email already confirmed so this is actually working so yeah so this is nice so let's actually um try and register someone else so here let's say maria and then jones and then m and then jones and the password just leave a password so i'm going to send and quickly go back we should see an email right here in a second there we go you can see the email and let me show you a database so let's select star from confirmation token so this is the id so right here so you can see that um it hasn't been confirmed and expires in 15 minutes right so what i want to do here is the following i'm going to say update so let me let me actually clear this and then here i want to say update and then confirmation token and then set and i'm going to say expires at and then i'm going to say equals to now so i'm just going to say equals to now where and then id equals to 2. so basically i want to expire this confirmation token so enter you can see that if i now select uh you can see that expires and basically um expires at now and basically right so this time here it's kind of incorrect so what i'm going to do is i'm going to basically just run the exact same command and then i'm going to say now minus so here minus in an interval and then i'm going to say let's say one hour enter and you can see that it did update so if i select again so let me clear the screen ctrl l if i select from confirmation token so expire that um okay i think there is something wrong with my time zone so this is actually meant to go back so create it that basically now is not working for me so let's see one and then day so let's say that the token already expired so let me select again enter and there we go so expires that so this is the previous day right so the 12th and this is the 13th so what i want to do now here is on this email that we've just received for maria jones so hi maria let's go ahead and try to activate and you can see that here token already expired so we can't really um basically you use it so what we need to do is actually send a new one there we go and it says email already taken and this is because inside of this sign up user here so basically the exception which has been thrown is this one here right so here we um probably want to do something like if the user exists and it hasn't and it hasn't and it hasn't confirm its email we we probably want to send the email again right so um i'm going to leave it to do here for you so you can implement this so to do so basically it should be inside here right so try and implement this logic and it should be really straightforward so if email not confirmed send confirmation and then email and probably also you want to check whether um so here let me also say to do it should be like that and so basically if basically if it's the same user which is trying to register and they haven't confirmed their email send another one we throw this exception right so let's actually um say here this will be so let's say ali so ali and then ali ali ali there we go and the email is just ali right so if i send and we should see an email in a second there we go ali and then here let's just confirm confirmed and if i go back in here um basically i want to log out so log out and there was an explosion wow so cool so we've logged out and the email is ali at gmail.com and then password and then sign in and there we go that's really nice so it's actually working so there we have it we actually managed to implement all of this right here so you saw that we actually have a bug in here so i will leave this to you to implement this logic but yeah so this is pretty much it so we've managed to implement the security part of the application the application user with some roles the registration we have verification links right here that expires um after a certain amount of time and then we are also sending emails and then we are storing these oh actually we're not storing the emails into the database but we are storing everything else into the database also you might want to for example uh store the fact that we've sent an email to a person and then you can you know perform some some reporting against it maybe check how many uh emails uh uh you actually send per user so on and so forth all right so it was a pleasure teaching you how to implement this entire back end um yeah so next let me go ahead and actually wrap things up but if you want to find the source code for everything and what i'm going to do actually is implement this for you so i'm going to implement this for you so you see how i do it but yeah but feel free to go and give it a try uh because this um it's been a a really nice exercise next let me go ahead and wrap up things up right it was a pleasure teaching you this awesome registration system and yeah let me know what you thought about this video whether you want to see more videos like this maybe if you have like an idea or a little project that you want me to build go ahead and send a submission or comment down below um or also if you join the private facebook group as well as discord you can let me know what you want to see next yeah it was a pleasure thanks for watching don't forget to subscribe to my channel also join the amigos code community is growing like never before and i'll catch you in the next one you
Info
Channel: Amigoscode
Views: 546,683
Rating: undefined out of 5
Keywords: amigoscode, java tutorial for beginners, java tutorial, spring boot, learn java, spring boot tutorial, spring boot microservices, user login and registration in java
Id: QwQuro7ekvc
Channel Id: undefined
Length: 110min 5sec (6605 seconds)
Published: Sun Jan 17 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.