I'd like to add user authentication to our app. And to get a sense of the different authentication providers that we can use, I can search the Meteor Package system by typing Iron Search. And we'll search for all the packages that begin with word Accounts. And notice there's quite a few here. And what these are are different authentication packages. So we can authenticate with Facebook, GitHub, Google, Meetup, and so on.
What we're going to use for our application is the Meteor Developer accounts. And so that's Meteor's OAuth service that lets users authenticate to our app using their Meteor credentials. The other thing we're going to add is Accounts UI, which gives us some out-of-box user interface components that we can use to build our login very, very quickly. So we don't have to build them from scratch.
Now, we've already added these packages in a previous video. So what we'll do is just add them again in case you missed it. So I'll say Iron Add Accounts Meteor Developer. And once that's done, we'll add the Accounts UI Packages as well. Then we'll open up the application and go to our Master Layout where we'll put the HTML for This
So I have a placeholder here for Login button, so we'll replace that with the actual buttons. Now, the accounts-UI package gives us a component we can use out of the box. And I can render it by saying Login Buttons. And when I save that, you notice over in the browser, we should get a button that says Configure Meteor Login.
And it looks like this dialing is a little bit wonky. And so to fix that, what we need to do is to wrap this login div inside of a row. And that'll tell Bootstrap to make sure that this gets cleared and appears on top. So once I make that change, our Login button should look a little bit better. OK, great.
Next, what we can do is to click on this button, and Meteor will give us instructions on how to configure the OAuth provider. Now, you can follow these instructions and Copy in the details here, but we're going to do things a little bit differently, because we want to configure this in our code. And that way, when we deploy our application, we don't have to configure the authentication provider through user interface it'll just happen automatically.
But what you need to do is to take this URL here and copy it to the clipboard, because we're going to use it later. So I'll Command Z and copy that. And next, we'll go over to the Meteor homepage. In the upper right, click the Sign In button. And if you haven't created a Meteor account yet, go ahead and create one now. And when you have one, you can login with your username and password.
Once you're logged in, click on the Apps Using Media Developer Account Services, and we'll create a new app at this point. Now, we're going to create an app called To Dos. But because of the redirect URL down below that we need to provide, this is what you just copy to the clipboard. So you can paste that in with Control V.
It looks like I didn't grab it, so let's go back here and try again. So this time, we'll copy and I'll paste it in. Now, notice that this redirect URL is for local host 3000. So this is what we're going to use in development. But in production, we'll have an actual URL here for our website, like eventedmind.com. So we're going to create an app for To Dos, but I'm going to see this one is for development, and we'll create a separate one for production.
Now, when I press Save, we're going to get an app ID and App Secret which we're going to use to configure our application. So keep this handy so that we can cut and paste the values or copy and paste our values into our config.
To configure our OAuth provider on the server, we're going to follow the instructions on the meteor docs here and login with service. And we need to put this block of code here into a server file in our app. Now, it looks like what we need to do is to add one more package called Service Configuration, and that will allow us to programmatically configure our OAuth provider. So right here, I'm going to say Iron Add Service Configuration.
Once that completes, the place that we can put this code is in Bootstrap.js. And so that's where we can put any code that needs to run when we start up the server. I've pasted in some code to save some time. And what I've done is use the upsert method of configuration. So this is a collection, and we use the upsert method, which will insert the record if it doesn't exist-- otherwise, just update the existing record if it does. And this is going to be our query selector.
So we're going to look in this collection for a record where the service is equal to Meteor Developer. And if we find it, we'll update it with this document here. Otherwise, we'll just create a new record. Then I've taken the client ID and the secret that we got from the Meteor Homepage when we created the app, and I've pasted them in here. And I've said that I want the login style to be a pop up.
Now, we can hard code these values directly here if we want. So the client ID and client secret could go right here. But it makes it a little bit more difficult when we deploy to production. So a better way to do this is to make these environment variables, and those environment variables can change depending upon what environment we're in. So we can take both of these values and put them into our emp.sh file.
So down below, I've opened up the emp.sh file for development, and I went ahead and created two new environment variables-- one for the Meteor ID and another for the secret. And then up above in the Bootstrap.JS file, I'm now setting the client ID to the value of that environment variable by using the process Node.js keyword Environment, which gives us the environment hash, and then getting the value for the key, Accounts Meteor ID. So that will evaluate to this value here.
And likewise, we're doing the same thing for the secret. This way, now when you go to production, all we need to do is to change the value of this environment variable instead of changing the hard coating inside of this configuration. Now, once we do this, we're going to need to restart the Meteor server so that it can pick up the new environment variables. So we can just stop that server and type Iron again. And now this should pick up our new configured environment variables.
Great. In the browser, it looks like we don't have any errors, so we can try out the New button. We'll click the Sign In With Meteor button. And we should be presented with a dialogue that says we're currently logged in as CMather, and do we want to grant this application permission. And we should say yes. So click the Use This Account button. And when the authorization process completes, it now shows that we're logged in with my login name and a button to sign out.
Let's head over to the database. I want to show you what these records look like inside of Mongo. Type Iron Mongo. That'll drop us into a Mongo shell for the current database. And we can type Show Collections, which will show us the different collections in our database currently.
The two I want to draw your attention to are Login Service Configuration and Users. So I'm going to say DB.Meteoraccountsloginserviceconfiguration. And we'll just grab all the records, and I can call the Pretty method so that it's easier to read. So here's the service record that we just created with our client ID and our secret. And this is what the Meteor Accounts package uses to authenticate with a Meteor Accounts OAuth provider.
Next up, let's look at the Users table. So I'll say DB Users Defined. And again, we'll call the pretty method and take a look at the new user record that was just created by logging in. The Meteor Accounts package automatically created this record when we logged in with our Meteor user account. And notice that the profile name is the name of our login for the Meteor account. And then there's the Services attribute that contains information about the authentication service.
And so for this service, we're using Meteor Developer. And here's the access token we got back. Emails, that came back from the service, and user name that we're using on the Meteor Login service. And then we have a resume attribute, which has the actual token that will be sent up from the browser to log us in.
All right. The last thing to do here is to customize the Login buttons. These Login buttons look OK, but I think most of the time in your application, you'll be customizing this to fit the look and feel of your app. It's pretty straightforward to do. We'll start off by getting rid of the standard Login buttons button, and I'll press Save.
And we need to account here for three different cases. So we'll use an if statement and say if the user is currently logged in-- and we can tell that if there's a current user-- and so if they're currently logged in, then we'll go ahead and print out their username. So we can get that from profile.name. And then we'll show them a Logout link. So I'm going to say A, we'll create an anchor tag called Logout. And I'm going to give this a data attribute of Logout so that we can query for it later. And let's make sure that works.
Great. Now, it looks like this profile.name is not quite right, and that's because we need to say currentuserprofile.name. So now we have a username and a Logout button.
Now, if the user is not currently logged in, there's actually two more cases. So one case is that we're in the process of logging in. So remember that since we're working with a reactor framework, when you're logging in, the login process could be underway, but it hasn't completed yet. And if that's the case, we want to show the logging in spinner or some text that says we're logging in.
So this is pretty easy to do. We can just say if we're logging in-- this is a helper that's provided to us by Meteor-- if we're logging in, we'll just show the fact that we're logging in. So I'll say logging in dot dot dot. And if we're not logging in, it means we must not have started the login process, and we're just not logged in at all. So we'll show a link here. And I'll give it an attribute of Data Login so we can query for it. And I'll say login with Meteor. And you could show a nice icon or something here, or style this however you would like.
Next up, we'll create a click handler for the Login button. So this time, we'll handle the click event for an element that has the Data Login property. And all we need to do here is to tell Meteor to log in with a particular service. And in this case, we only have one. So we're going to say login with Meteor Developer Account.
And that should be all we need to do. And if we click on this button now, that will trigger the authentication process that we saw previously. So now we've replaced the out-of-the-box buttons that Meteor provides with our own custom user interface for logging in logging out.
Now, one last thing to show you about authentication-- I want to show you where this information is stored in the browser. Normally, when you authenticate in a web application, you store some kind of login token or user ID inside of a cookie. And if you click on the Resources tab of the Chrome Debugger, you could go down and click on the cookie for the host that we're on and see the cookie.
But in Meteor, currently at least, they store the login information in local storage instead. And so you can click on Local Storage for this host, and you can see the login token and the expiration date as keys, and then the values over here. So every once in a while, this is useful. Because if you're going back and forth between production and development or different environments, you might have to come in here and clear these out. And you can do that quite easily by just right clicking and clearing out specific keys.
So if I come in here, for example-- let me get rid of the pen-- and right click and say Delete, the ones that I've selected should delete. Now, notice the user interface updates above automatically, saying that we need to log in again. And if I log in with Meteor and complete this process again, you'll see the new user ID login token and expiration keys and values in local storage.