5/4 FT Rails login with Google Oauth

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
awesome so we are going to start today we're going to continue to build onto this app we already have so we have stuff to work with and we're going to think about how we can go back through and add a user and then add a user to interact with these these shoes and how it might actually look for your rails project and so getting started first of all first thing we're going to need is we're going to need a user model and anytime i'm adding a model to my project i tend to do a generator if you are going to have associated routes with that model i tend to just skip ahead and do the resource generator and so we are going to use rails generate resource uh and we are going to generate a user you have a lot of options what attributes you want to be in play for a user same thing as sinatra it is going to be important whatever they are logging in with is a unique attribute you can decide that's their email or you can decide that's a username it's up to you but you need to make sure that there's at least one unique attribute plus a password digest that your user has and so we will add we're going to add a username and an email why not i would recommend doing emails just because there's some really cool things you can do in rails it's pretty easy to send out emails to people who have signed up for your app and so it's kind of fun to think through those pieces like how do i send an email for someone to confirm their account or something like that you can easily actually implement that into your project if you wanted to um so we'll have username email and then we'll add in password digest just like we did before because we're never going to store raw string passwords in the database um now can i debate it if we want to do this all at once or come back to it but i think we're going to go ahead and do it all at once for us to use omniauth today there are going to be a few other things in play so you're when we log in with omniauth through github through facebook through google through any of these other things they all have um unique identifiers so that you know who that user is through google and when we implement our oauth we need a column in our database that says this user's unique identifier is x so this person has logged in with google and their unique identifier from google is this id i have seen before sometimes people will say oh i'll just get the unique identifier from google and set it at this person's id and that actually is a really big deal because the unique identifiers are usually like you know a crazy long string and if you think all the way back to sql when i said what if we just set their id to something really large then it messes up your whole database because then the next number has to start one number above that so just keep that in mind we still never set ids that's a a no-go and so what we'll need to do instead is we'll add an attribute called uid um and even though most of the time this is an integer i personally like to leave it as a string because the string's a little bit more flexible in length and i have run into an issue before where the uid was like longer than my integer wanted to accept and i just leave it more flexible in case there is a unique identifier with letters in my opinion so i will do a uid as a string and then i'm going to add one other piece in play and it's going to be a provider attribute and the reason that we add a provider attribute which will also be a string is so that we can tie that unique identifier to the site that it came from so we're only going to add in one type of oauth but you could imagine most sites they give you the option log in with google log in with facebook log in with github and it could be a problem if your unique identifier from facebook happened to be the same as someone else's unique identifier from google and then they try to log in and all of a sudden they're you and your your persona that you already created for yourself and so it is actually pretty important you'll see some examples where they don't include both of these i would just recommend it set yourself up sets you up for success in the future if you want to ever add extra options to go ahead and say uid and provider here and then we'll go ahead and we'll generate this so we'll have a lot of strings in here for our user and we'll see the uid in play if you already had your user set up and you were going back to at oauth you could have just simply done this with like a generate migration add columns essentially and you should see now if we look in our database we are going to end up with a users table username email password digest uid and provider so it looks good so far i'm going to go ahead and migrate it so we have it available to us after migrating it the next thing we want to do is we're going to basically need to set up our credentials so that we can use google to log in and the way that i start this there's a lot of ways and actually my thing has specific steps that tell you to go to google first but i'm actually going to kind of set up some of the bare bones that we're going to need here and part of that is we're going to have to add a lot of things to our gem file so in our gem file and good news is you guys already have experience with this we are going to be using that dot env gem because it would be a really big deal if google gives you credentials and then you basically push them to github for anyone else to steal and use your credentials could be revoked or it could be that someone else takes them and runs up your account and creates a whole bunch of requests that then you're on the hook for paying for so just be really careful when you're using credentials and third-party logins we never want to push them to github and the way we avoid that is with the dot env gem um we also are going to have to add in our gem be correct here because we're going to be basically using our secure password system in the way we have before so we'll add the gem dot env oh that's known as quote technically dot env is only needed for development and test like i really could put it here because once we push it to heroku our env file isn't in play anymore so i suppose it's actually more accurate to put this down here sometimes i just like grouping them together so it's easier to see what we're adding for omni off um the other gems that we're going to need to be able to log in with google correctly is we're going to need the gem omni off and we are going to need the gem um actually i i'm going to adjust this we are in a rails project so we're going to use the dot env for rails version sorry about that i almost forgot and then we'll use our gem omni off and then we have two more gems that we're going to need so if you have done any of the omnioff labs i don't think they've added a fix in you might have noticed that github actually really complains about you using omnioff and says hey you have these major security vulnerabilities there's a chance that you could have a cross cross site um forgery request sent to you and so they haven't fixed the omniauth gem but what they did is they came out with another gem that will essentially fix that for you and so we're going to include that other gem in here today and this is where i actually need to cheat and look at my blog that i wrote because i always forget what i write this gem as but don't worry i left it for you guys all in one place um oh so it's just our omniauth rails protection this makes sense we'll include this and this is basically a gem that will work with our omni off to make sure we don't have that vulnerability in our code and then the final one and this will be true for anything so if you're doing facebook google twitter github we have to add a specific gem for that provider's on there so in this case we're going to be using google and it's called like google oauth2 so we will say omniauth google off to and it should look something like that and then we have all of our gems in play of course after we've added the these one two three four five gems we're going to want to bundle um which will add these in to our program also make sure you guys stop me at any point if you have questions cameron question i mean this i was just wondering what is the difference between bundle running bundle and running bundle install nothing something um i don't think so okay i feel like i should know the answer to that i use them interchangeably yeah i just kind of go wherever the wind takes me on that one yeah yeah um yeah you can use either one uh so when i sorry yeah uh when i was looking at dot m it says uh we need to place it before uh the the other gems that we are gonna use it for like i probably didn't understand what that instruction meant so i would just put dot em at the end of my gym fi at the beginning of my gym file i wonder if maybe you can let me know if my understanding of the instruction is correct or not oh it does say that it says you use gems that require environment variables to be set before they are loaded so actually here's the tricky thing this is saying before the gem is loaded so if we had a gem that needed our env variables then it would matter so even though when we do omni-auth we're using env variables the gem omni-off to be installed doesn't need an enb variable oh okay got you yeah that is the way it works that's more like if we had to load a gem that specifically needed um like this is uh well that's actually a different example but yeah if we needed if we had a gem that specifically needed it i will so we'll keep that in mind if for some reason something doesn't work we'll change it um but yeah but i was just thinking probably my understanding of the instruction was totally wrong yeah making me question it but but we'll see we'll see um it's a good thing to keep in mind i'm pretty sure it's that if these need an env configuration to be installed which i haven't seen before so i don't know we'll we'll test it out i don't think so i think we'll be okay um okay um okay so now we've got our gems in play they have all been added the next piece that we're gonna do um is we're gonna go ahead and we're gonna get our variables from google so the website that i have linked in that blog i sent you we will start there um where is it here we go sorry i have too many tabs open and you guys aren't seeing what i'm seeing so we'll go ahead and this is just basically where our your google developer console and this something like this exists for pretty much any app that you're using in github it's just in your settings um you can find it in different places for each type of you want to do i'd encourage you if you're really interested in a walk maybe like go down the side road and try to add in a different one i will say there was some sort of a lot that i actually had a lot of trouble with trying to find good documentation on i want to say it was twitter it was oddly really difficult to actually try to do oauth for but a lot of a lot of other sites have created apis to make it really easy to do oauth the first thing you're going to end up doing is you're going to create a new project you are limited on how many projects you have um but i'm still not that close to my thing so we're fine i'm going to name it so i can keep track of it and remember what this was for you might not have this option this is just because i'm using my flatiron school gmail account if you don't have it no worries just make a project name once we create this project it's going to take forever i forgot about that takes a second there we go and we'll go ahead and click view and so this is going to take us to a different page where we're able to actually set stuff up there's a lot of information on this page for the sake of what we're doing we're going to need very little of it if you are curious about trying to integrate other things with google like this is kind of your go-to spot so if you wanted to integrate other things there are a whole bunch of apis that they have and i think it would be a cool road to go down if you had extra time at the end of your project um we are going to just work with explore and enable apis in this getting started tab and specifically we're only going to be dealing with credentials and our oauth cred consent screen if i go to credentials what you're going to notice is it's actually going to first make us configure a consent screen and the consent screen is just what pops up that says would you like to log it like which google account would you like to log in with and so we'll choose that um you have the option internal versus external truly for testing purposes a lot of times i use internal but it's also fine if you want to use external it's up to you if my other account my gmail i actually can only use external the big difference is for internal for testing purposes only my flatiron school email accounts would work and so that's kind of just a way to limit it and get it up and running off the ground really really quickly and just for testing purposes so that even if my credentials went out and about in the world other people couldn't actually use it because only flatiron school users could log in with it which maybe i'll change it to that after this so that because my credentials will probably be displayed on the screen to you guys um we'll go ahead the only thing we have to fill in here is an application name we could add a logo if we wanted to um i think i have a picture of my dog that i have ready for us to use he looks like in it he's in jail but he's actually very happy on our outdoor couch and then he snuck out to go beyond and there are other things you can add as well so these are the scopes that google is going to go ahead and give us if you wanted other pieces of information we could add more we just want login stuff so that's fine we only need the email and the profile and you can ignore actually all of the stuff down here for now in fact if you try to put in like a local host address it won't accept it it doesn't want ports here this is specifically for like a website so if you were um hosting this on heroku then you would come back here and you would add your your website in but at the moment when we're in development mode and we only have a local website we don't have anything we can put here so go ahead and save what we've got we now have at least a very basic oauth consent screen and now we're ready to actually get our credentials sorry i know this is a lot of just walking you guys through step by step but i think it's important to see so um we'll come over here i could switch this later if i wanted to and this just tells me how many requests i get in a day before they cap it or charge me for it and so we'll come over here to credentials and i'm just going to say creed create new credentials and we're specifically going to create oauth create credentials we are making web applications so go ahead and choose that again i'll put in my my name shoe collection i really should have a better better name for this application but that's okay um and the only thing that we're going to be adding in here is an authorized redirect uri so we are not making our request with javascript we are making our request with a true like um with a true like http request to the google site so this is where we're gonna add our callback and a few of you guys i think if you're on pcs when you run rails s your your server isn't actually local host 3000 but if it is localhost 3000 you will end up typing in localhost 3000. if you use something else like if it's actually numbers that's what you're going to put into here so it's really important that whenever you run rails s whatever you actually get as your web address and your server is what you type in here and then we have to add what our callback is going to be and you actually don't really have a lot of choices here there's a really standard set way that we write this so we first write the word off and then it's going to be whatever thing that you're using you're off with so if we were using facebook it would be facebook here since we're using google oauth 2 it's going to be google oauth2 and then we say callback to say this is the response that they're going to send back to us and this is an authorized redirect uri we'll add that and that's actually all we need at the moment i shouldn't have said add we just need this one and we'll say create and we're going to be ready to go so i use localhost because that's what i have here if for some reason you actually had something else you would use that and now i have my credentials which is awesome and you shouldn't be sharing these out so i shouldn't have these in a recorded thing but that's okay i'm going to copy these and this is where our dot enb comes into play of we want a dot env to be at the highest level of our application and we want it to not be pushed to github i would encourage you to start your dot to create this in the terminal and here's the reason why i've had so many students like i can't even tell you how many that think they've made their env at the highest level but have accidentally made it inside of the app folder because you know your app folder has a lot of stuff in it so it feels like it's at the highest level and then it basically stops everything from working you won't be able to read your enb variables so make sure when you close all of your folders that you're able to see it listed with your git ignore config gem file lock all of those guys and then the next step we want to do is we want to add it to our get ignore this is probably your most important step and we'll save and then it turns it into grayed out because it will not get pushed to github please make sure you do that right away because otherwise you're going to run into issues so we'll save these in here and we you guys do have a little bit of experience using this which is great in that on the left hand side is going to be like our key in our env hash and we set it equal to the value they give us we don't use quotes and we use all caps just as the convention for this file and then we'll have a google client secret you can name this whatever you want i'm only naming it this because actually in the documentation they refer to it this way but there'd be no issue if i said google secret and google id as long as later when i want to reference it i call it the exact same thing so it's just like any other variable you have control over it as long as you're consistent when referencing that variable and then we'll go back here and we'll add our secret in to here one thing i do want to point out is after you've looked at them um actually maybe it's not that hard anymore they changed these things all the time i was going to say i used to have trouble like going back and looking at my client secret again and i'm trying to see if it's but it's not that hard you just go to edit okay um and so we could also change this if we needed to but we should be all set on the google google side um yes you're right i just saw your comment this is our git ignore because it ignores pushing it to github so it's very useful and then this is all set um any anything so far that seems weird or confusing i feel like it's pretty straightforward i just want to check in cool um what we will do now is and i do apologize this is just so many steps what we're going to do now is we're going to actually set up some middleware so that when we click a link that says sign in with google we're not actually processing the request so most of the links in our app they go to somewhere else inside of our application we're going to make a link that actually gets gets caught by this middleware and sends a request to google and what that middleware looks like is we go into our config and our initializers and we are going to add a new file called omniauth.rb and this is one of those few places we go back and forth on should you copy and paste should you memorize this is a copy and paste moment in my opinion and so what we'll do you can come over to my guide or you can go to your learn lessons because they have them there as well and we're basically going to just set up our middleware here so i'm going to copy and paste this and the only part that i really want to emphasize is that line two is going to be different based on whatever um oauth you want to do and you can list more than one oauth inside of here so if we also were using github i could just go ahead and say provider github and then list my variables for github and that and you could have as many as you wanted to inside of here the important thing that i was mentioning is that whatever we list as our key and our value for our env need to exactly match here so the second big mistake that i see a lot of students make is they have a typo and they don't realize it and so even if you want to just be extra careful copy and paste these from one to the other to make sure that they are identical because it's it is a really really common error that i see students make and we can even see what it would look like if we were making that error in a little bit um actually maybe i will maybe we'll we'll we'll mess up we'll take out the eye in there and we'll see what happens later when we try to make this work um so next step that we want is we are actually getting ready to we want to send our request to github and we want to set up a route for it to come back so our route going out we actually don't have to add to our routes file but our route coming back in we do so we're going to go over here and that route that we listed for our redirect uri is the route that we need to be ready for it to come back in so i'm going to say so many things here i'm going to say get off and it was google oauth 2 slash callback and i need to send this somewhere and you have and i i'll write it with it too you have a lot of places a lot of flexibility over this and i've seen people do it in different ways the number one thing we're going to need to do is we'll need to send it to a sessions controller and we kind of are doing this a little bit out of order because we don't have a sessions controller even in play yet but we can add a sessions controller and your sessions controller responsibility is going to be responsible for logging the user in logging a user out and logging a user out and omni off so it's it's creating or destroying a session at the end of the day this is also a good controller to handle maybe like a welcome page or something of that nature where you just kind of wanted to um i really can't write and type at the same time a welcome page where you wanted to say like click here to log in click here to sign up or something like that like maybe have a welcome page in your sessions controller as well is a good catch-all but so we're going to be ending up in a sessions controller because that's where it's just most appropriate we're not technically always creating a user most of the time we're just going to be logging in a user and so we'll send them to the sessions controller and this is where i say it varies so we could stick really restful and we could send them to a create action but when we send a post request and we log someone in we're also going to send them to a create action so then it means we have to have more logic in our create action to say if they're logging in via auth handle it this way otherwise handle it this way i think it reads nicer to actually send them to separate actions personally you will not it will not count against you if you set it to create i've actually set it up many times this way in my applications i'm a bigger fan though of sending it to something like on the auth or create i i don't like to make them long so i'll just actually say on the auth and then this is like my catch-all of this is a non-restful like custom route where inside of this route is where we will log users in with omni off and so just to kind of like keep it from something separate from something else that is actually my preferred way of doing it my other preferred way of doing it is i think it's better to go big and to prepare your app for what if we're gonna let them log in with oauth or with google oauth or github or facebook and we're just gonna give them all the options if we wanted to give them a lot of options a better way to write this line of code would actually be to make this piece dynamic because this is going to be dependent on what provider they're using so even if you're doing your omni auth from facebook this callback is going to be the same the only difference is inside of here it would say facebook and if it's from github the only difference is this says github and so i actually like to make this a dynamic url that says provider and the reason for that is just for future thinking to make it really flexible no matter what they put in there it's going to take me to this omniauth route and then in my controller i can control for oh it came from google it came from facebook it came from github i can handle those in different ways now the nice thing is a lot of those guys kind of um follow convention and structure their self their stuff the same so that what we do for google usually applies to all the rest and we can actually have one method that handles any of the login requests usually so um so this is one setup of how we do this in here and then the other piece we need so just as a clarification this is not our going out route this is our coming back from google route and we will look at it in a little bit our going out route we actually don't define in our routes because it's handled by middleware our going out route we just need to add to one of our views and i don't think we have um we've got an application page we'll add it here why not um we'll we'll come back and we'll fix this so if we're logged in it says some things if we're logged out it says something else but for right now we're just going to add it here and remember that gem i added that was about cross site forgery requests basically um there is a csrf token that comes through every form that is submitted in your application and if you just have like a normal like when we create a shoe we actually are sending through this this forgery this this token to make sure that that request came from our application and so by turning this into a post request we are then able to actually send that token to google so that google knows about it and when google sends back their response they can include the token so that we can authenticate yes this full cycle request started with our app and ended at our app instead of starting at a different app and somehow making their way to our app and so what we're going to do instead of a link to is we're going to use a button to because that is going to make a post request rather than a get request and our button 2 is going to say login with google and then we are going to make our route be off and then the name of the provider that we want to use so it's going to be like the same as our callback just mine it minus the callback part because this is just the going out request now we're almost ready to take a look at it if this it's not going to work because i remember i messed up that typo but when this does work the thing that i want us to do is we're actually just going to pause here uh and i don't do i have buy bug or did i have pry in here i should remember that i've looked at it enough times oh i did have prime okay cool so we'll do a binding.pray and we'll go check this out in the browser also really any questions just ask them so is buy bug just like pry kind of it comes built in with with um rails version like five and above whereas pry used to come built in with rails versions four and less and i don't know why they switched but they did and you can still use either one it's just by bug comes built into the gem file and so i actually went through this gem file and i commented out by bug and put in pi which i should have just left it so either one was in there but no big deal um so now we have this button it looks kind of ugly but we could we could fix all of this with some css and we'll click log in with google and what's happening here is it did not like our route that we did it didn't catch on is it google auth2 or google it is google oauth too yes i was like did i mess that up in my routes too i don't know because that one's provider but i wrote oauth yeah thanks cameron that is the issue so good to know because it said just just so you guys know so this is actually set up to match with what is ex like your middleware is expecting a certain route so if we don't exactly match that route we're going to get this this error message that we just saw so let's refresh this page so that it reloads our new code this should now be sending a different request okay this looks better and i say it looks better one thing that i really like about google compared to some of the other oauth apps is they actually give you some really good error messages so this error message says we didn't send them the client id and so if you think you did send them the client id that's where you need to go through and check to make sure you had no typos anywhere in your code so coming back over here this is where i'd want to check oh yeah i spelled client id wrong which is why it wasn't going through another reason it might not be going through is because you put your emv in the wrong place and if you put it in the wrong place it won't be able to read from it and so just keep in mind this is a pretty common error that people run into usually it's an easy fix of it's a typo or they put your dot e and d in the wrong place we might have to restart the server to get this to work but we're just going to try it and see yeah we do i was afraid of that um usually things outside of the app folder we have to restart our server to see client id env or this could be what sheen was originally talking about and maybe my order does matter in my gems we'll see so we'll reload this we'll try and log in with google one more time and this looks much better we're getting our correct response up here so that looks great and now i have any of these accounts that i can choose to log in with and when i choose to log in with one of these accounts we're going to now be in our pry because i sent us to our pry if we go into the right spot and no we are not in our pry huh i wasn't expecting this guys um why did it not like that i think i know how to solve this maybe not actually huh this is so odd because i did this yesterday and i didn't run into any of these issues um let me see okay let's see what we get when we just google this omniauth google family all i haven't thought of what i think i can add in but i just want to see what they give us so we'll look at these i think we have to do this skip jwt true yep okay so this if you're experiencing issues just add this to our options and you might be like well i don't know where it was talking about i've seen this before like what should wear like that's not a very helpful thing um keep reading and it's going to be in your middleware so we're going to go ahead and we're going to add this to our middleware this is odd because i did use this yesterday and i didn't need to add this in well we'll try it again i'm going to restart my server because these initializers in our config are outside of our app folder and to get them to reload we have to kill our server and then we'll try this again so if you do get an error like that your first step just google it maybe you'll find some helpful information so let's go back and that was a really good sign like where we got to i could tell that we at least got to the app correctly i had confirmation that my env was working correctly because it allowed us to get that far and i had confirmation that my middleware at least got me there which is also important so now let's click log in with google again let's cross our fingers that it works i think it's working cause i think we're on our pry hooray okay so now that we're in our pry now we can actually look at the response that we get back and i'm gonna close a few of these because we're really just gonna be dealing with our sessions controller now um and our response that comes back it actually is written as request and i have to always look this up because i always forget where is my blog um here we go is we're going to have our request.env on the off so this is how we'll look at what we got back env like i said you don't have to memorize everything just some of the things and we'll go ahead and click on that and we'll get back our all of our information if you have trouble like seeing this correctly like and mine is actually fine but when i was doing it the other day it was really hard to read you can always add the words pp in front of it which is a pretty print to make it look a little bit cleaner but this is actually really clean to read i don't know what why it prints out so nicely this first time around and a few things that you'll notice that are pretty standard is when you are using any of your responses you're going to get these two at the highest level of your hash and so those two your provider and your uid are going to be really really easy to reference we're going to take this and you can just say like uid and we can access that key in the hash and we'll get that number back out of it any info about the user is actually going to be stored in this this hash um that the key info is is referencing and so a really common mistake is people will see the word name in there and they'll just go oh let me go name right here and that's going to give you nothing because name is in a key for this hash it's a key for once we type in info so if we wanted to grab out the name we would actually have to first say info and just kind of as a standard like this goes back to just using caches but essentially you want to you kind of just need to figure out which hash is it nested inside of and then go down each key until you get to the info that you want um you can also do other things with the credentials and the token here as well um i'm not really going to go into that there are a lot of tutorials it's a little bit extra but you can do some things with um expiring tokens and keeping them logged in based on what their tokens say and then refreshing we're not going to really deal with that we're just going to deal with logging them in kind of the straightforward standard way so one thing you'll notice is this is going to have to be written for every single time i want to get information out of here and it's quite long so and also this is why i haven't memorized it is because usually we make sure we only write it once and then we never write it again and you'll see some places they decide to put it as a private method where they call it off and they list this here just so they have an easier way of referring to it that's fine to do i've also done it in other ways where i just pass it to the user model basically and then in my user model i deal with something smaller it's up to you how you want to handle it but this would work as well so our next step once we have this info is now we can actually think about logging this user in this is where our logic comes comes into play and we need to think about a few things if they've already come to our app using this google email address we should not force them to create a new user like every time they click login with google we want to make sure they're the same user logging in not duplicate user copies we also want to make sure that if they haven't logged in with us before we are able to create a user so based on kind of that logic what what active record method do you think we'll need to use here to make sure we could either create or find the user could you find or create by uid so we will we'll do exactly that we'll do a find or create by and we will do it by the uid but we're actually going to do it even one more step beyond the uid because like i said we could cameron you could have the same uid from facebook that i might have from google and the nice part about finder create buy is we can actually send in two arguments so we'll also add the provider here and our provider is going to be off um uh provider and i i can you can see that if you scroll up here that we just have provider and it will say google oauth2 so those two pieces of information are going to be recorded solely for the purpose of finding that user again it's not really for the purpose of displaying anything for your app it's so that we can find them next time they try to log in with that same thing um you may also um we're going to end up eventually moving this but i just want to say one thing that is kind of cool about a finder create by that you might not have seen before any of your lessons on here is that you can actually send it a do block and what we can do is we can actually basically add in some code to say if you are creating the user we're going to assign other user attributes and so this is like our argument to find them by or create them by but then if we have to create them we can send in a do block and anything inside of here are the attributes that we're going to give them when we create them so we can go through and say okay well i would like their username to be and then you're going to need to figure out what that google is giving you what do you want to use is the username and i might just want to use the first name i don't know you can kind of decide what you would like to use there remember this one is a nested hash so info points to this hash that has first name so here i might want to say info and then first name and i would encourage you in your own project you need to stop in this pry as well like don't skip this step and just copy code that's written look at what you're getting and look at what you want for your application your user might have different attributes in my user your user might have an image and we could use this image and so there are some helpful things that you might want to use that are different from what i'm using um the next thing we're going to want to do is we also have an email so we'll give them their email and here with the email address um a good thing to keep in mind is we might have already had validations in our user model that said email must be unique number one issue that students run into is they have tested their app doing a regular signup and login and one of their sign up attempts they use their true gmail account and then they go through omniauth and their omni auth sign up tries to assign their true gmail account to their email address and it fails and it doesn't create the user because it sees that they're going to have two duplicate users with the same email address and so i want you to keep that in mind as you're going is that actually is a really really common error is that you're doing everything right omni auth wise but you already have users in the system that conflict with some of your uniqueness checks so be careful when you add those in there's one other piece that we're going to need to add in here and i'm going to add it but i want to wait because i really want to demonstrate what i mean by these validations failing i have a question yes so what is the sort of workaround for that like i know most sites you could either log in you can create your own username or you could log in through another site but they don't like say i created a username for a website but then one time i went on it and i just decided to log in via google instead normally it wouldn't give me an error right so is that just like a lot of steps that we're not trying to do um no it's not it's not terrible so some site it depends on the site um a lot of sites handle it in the idea of if you've logged in from google or from oauth in general that means that you don't want to add a username and password for their site and your only way of going in and out is through this oauth third party because the idea is you're trying to minimize how many places have your password recorded gotcha so even when you do it like that through their site it's still going to be using the oauth yeah so usually if you if you think about it i've seen sites handle it like where they might have found you in the system and they give you a message that's like oh you can't sign up with that email because it looks like you've already used oauth like you've already used your google to log in try logging in with google and they give you like a helpful error message to kind of like direct you as the way to go because we actually really think of those two users as two separate entities right the user that logged in with an email should be totally separate than this person coming in with google another option although i feel like there's just a lot of security vulnerabilities with it so i don't like to emphasize it is we could find or create by email here at the end of the day um and that would mean if i logged in with google and it had this email address associated with it and then i logged in with facebook and it also had this email address associated with it both of those would bring me to be the same person and in some ways that actually i think is kind of cool to to have that match the reason i say it creates a little bit of vulnerability uh in case someone faked fake made a facebook account using your gmail to then like get into this secure site so it kind of depends on how how much security is important for your site because it could be a site where security really doesn't matter and it's more important that they can really easily find their profile whether they're logging in with any of their types um in general though i would probably handle it going this route and then handling your error message as well so if it's a duplicate email and we're coming out of omniof giving them an error message saying oops look like you it looks like you already created an account with that email address okay log in this way instead or something like that gotcha all right thank you yeah great question um so i do want us to see what it looks like when this fails so we're there is another piece we need to add in here but we're not going to put it yet and then just because we are dealing with users and i should have done this at the beginning keep in mind that when we are working with users in rails it's very similar to sinatra in that it is crucial that we have our house secure password here does anyone remember because you might be able to predict what i'm about to try to show you has secure password oh my gosh i didn't even realize how much time has gone by has secure password what does it do for us what are some things that it gives us validation uh-huh what does it give us a validation for that uh it's present and it matches with confirmation so it does a validation for password presence and a validation for confirmation if you've provided a confirmation attribute the really nice part about this is it's actually only checking for a validation of presence on create so please don't go in and add your own validates presence of password this is doing it for you but what is that gonna what's gonna happen here when we try to sign up as a user it's not really a password is there there's not a password so watch what happens so we're going to say user equals and then i'm going to say if user dot valid um then we'll redirect them i want to make it really obvious we'll redirect them to the new shoes path i don't know they're going to make a new shoe if they're valid um otherwise we are going to redirect them to we don't really have a lot of pages in here um this shoes past because i kind of skipped some of this stuff and we'll see that we end up not making it but just because i like to be um a little bit more helpful if we're not if we have to get redirected let's add a flash message and cool part remember how much of a pain flash messages were in sinatra they're very easy in rails and that's why we said don't sweat it in sinatra because all we have to do is write flash message equals and what i'm going to do is i'm going to say dot user.errors.full messages dot join because i want them to be one one thing joined together and now on our page on our shoes path page our shoes index view all i have to do is say um flash message and this will display something here at the top it's not going to look pretty we don't care about the prettiness right now but if it fails we'll see it actually get displayed here i think you left out a bracket in that view you are absolutely correct thank you good catch um so let's go ahead and we will remove this pry okay it's out of here sorry i keep my terminal so so long does i have to say for a message or messages yeah errors yes you're right andrew i'm glad i have you guys helping me debug okay so let's go back over here and we'll just try this again it didn't like that we got caught for so long and that that thing i'm gonna go all the way back just so it's a brand new request and we'll say log in with google here's our page awesome i'll choose my name fingers crossed what happens here and i told you it's going to look really funky because all of this at the top is from our layout um but here we get password can't be blank and so we realized we actually failed to sign in even though google did its part because we had validations that mess it up on our end and so what we can do instead is we can actually assign them a password this is where i said like if they sign up with oauth the idea is they are not keeping track of another password this should always be the way they log in and we are not going to check their password later so we're actually going to give them a random password so we're going to say secure random hex and choose it of some length be careful and the password digest field can actually only be so long so you can actually potentially have too long of a password but so i always set their password just to something totally randomly generated that won't be the same as any other users um this right here is just saying how long the password is going to be and now this time around it should work so let's go back i think we should be able to see it from another page cool we'll log in with google we'll click it this time i can't believe that took as long as it did but that's okay is it going is it going no because i can't type correctly but the good news is it made it through is user valid so we were actually valid and we would have actually been signed in our final step that we would have needed to do is we would have of course actually had to sign in our user so we would have to say our user id equals user.id a lot of people skip this for omniauth i don't know why they feel like it's not important to do control flow logic it is especially for debugging but just in case you have a weird situation come up maybe someone is logging in and they don't have an email or they don't have a first name and so it fails this validation like you want to have a check for it you don't ever want to just like send them on to the new shoe path even though they're not logged in because it's a lot harder to catch your error messages because what will happen is it won't error it just will be they're not logged in even though they went through your login process and so this would be ready to work the last thing that i wanted to ask you guys about is do you think i wrote this in the most appropriate spot let's see if this finally works way we are in and we are actually logged in and we will add helper methods tomorrow to show you guys that because tomorrow is really like prepping you guys for the project so it's going to be all full of like tips and tricks and things for your project to make it look better and also how to think about your object relationships that you're going to do for your project so anything we didn't get to today that i wanted to cover will cover tomorrow um but the last little pit last little bit is we want to keep our controllers skinny and we want to keep our controllers with just stuff that deals with redirect control flow does it feel appropriate to have the code i have highlighted here in our controller it does not it would be more appropriate because this is dealing with the database and creating a user for us to come up with a cool little method that's like user dot um create from omniauth or you can name it whatever you want and then we pass in the information that we got from omniauth so we can pass in off here and then we steal all of this stuff and we're going to actually move it to our user model and we're going to make a class level method so we'll say self dot create from on the auth and we're basically just going to drop all of that code in here and pass in our auth as an argument the big difference is now we don't really need need to save this guy we don't really care about it we'll just let this run this could also say self if we wanted it to or it could say user and that's just a way to separate our concerns of this doesn't really belong in the controller it belongs over here that took way longer than i meant for it to i apologize any questions that you guys might have is this a similar setup to when we're using device uh device is very different um not very different device is different i think device is really good to know i actually don't like people using it for their rails project though unless with with rare exceptions um only because there's a lot that happens in device that's really behind the scenes like you can use devise and it basically creates all of your login sign up sign out routes for you and does everything and i feel like it's really important that you understand what's going on under the hood so i actually i think devise is important to learn i would not encourage you to use it on your project unless you were really really curious um the way you would do it with devise is similar but it is different in that you're going to have actually like um you're going to have a configuration for devise and that's where you're going to add all of this stuff that we put here so you won't have this file if you're using device and there's a few other things that will be different but yeah it's it's you can do it if you really want to andrew but i i shy away from demonstrating it because what i've noticed is people will see it and go oh it just does everything for me and then it's actually kind of harder to debug and so if they run into any issues and they were doing it because they wanted the easy road they're actually like end up in trouble but if you want it because you're just really curious and you want to learn how to do it and you're okay with handling the challenges then go with device i actually actually have thought about doing an extra study group on device i don't know if i will or not i'm on the fence so i'll let you know um but tomorrow we'll cover the pieces we didn't get to cover and if you guys have anything specific you want to make sure you you see let me know and i'll make sure i include it in tomorrow's study group uri were you going to ask a question yeah just a small question this was bugging me so line two the env google client id is that a variable or if it is where is it getting that from or so env is um like an environment it is like a variable uh but it's it's like a variable that's storing a hash of information and it is set it is tied through our.env and it works only because we included that gem real like dot env dash rails and it's tied to this file so when we mention env it's basically looking at our env variables that we set in here and this is our variable client id or our key client id that points to a value i lost where we were you can always pause it anywhere like in your code you can pause it in a binding pry and actually look at the enb so let's let's you have to jump off feel free to jump off but let's put a binding i wish i could spell today let's put a binding pry on the most expensive shoes page let's go here and we'll be in the pry in two seconds and inside of this pry if we just type in enb you're gonna see we actually have like a lot of stuff in here except that we haven't even added it just contains a lot of information but specifically it does contain our env of google client id and so it's it's like a a variable that contains like a hash of information i guess it's the best way to put it okay and so like that it's in the the get ignore basically means that it's not going to go to github so people can't see that information is that for like development or maybe i don't have it right like when it's in production like you said i guess it's different when it's in production like heroku or any other provider actually has a places where you list your your like secret authentication credentials and so that they load them in the nice thing about writing it with the env is actually this the way it's set up in heroku will still find it um there is another way of dealing with secrets and it's actually like the built built-in rails secrets file the secrets yammo file i feel like people make more mistakes with this file which is why i didn't show you guys that way but if anyone's curious i can show you how to use this file instead um so it's just another way of doing it but yeah you'll push them up to heroku a little bit differently so you won't have to use your env for heroku if you want to host it in production okay thanks for clearing that up there's always those little extra things that i guess they don't get to ask questions about because it's just focused on a lot of the main code like the controllers and models and stuff yeah and uriah when you finish your rails project and you want to host it i can help you you'll kind of see where those variables go cool okay well have a great rest of your day guys and good luck let me know if you have any questions thanks ken bye
Info
Channel: Jennifer Hansen
Views: 2,454
Rating: 5 out of 5
Keywords:
Id: 9pD0uXLI5uE
Channel Id: undefined
Length: 59min 49sec (3589 seconds)
Published: Wed Jul 22 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.