So far we've set up a small but functional Firebase app and practiced using some of the Firebase functions for accessing and displaying data. Next, let's set up a user login system using Firebase Authentication and the GitHub API!
✔️ To complete this challenge: follow each step below, check off the checkboxes to track your progress (so we can see your progress too!), and then submit your solution as a pull request.
❓ If you have any questions, post a comment at the bottom of this page or ask us in our Slack chatroom!
1. Set up for local development and testing with a local server
[x] First make sure you're in the pair-partners project folder, and make sure you're on the master branch (use git checkout master if you need to switch).
[x] Download the latest working version of our project code from GitHub with git pull -- remember to do this every time you resume working on any team project, so you'll have all the latest changes before you continue your work!
[x] If you haven't already, make a new local branch called something like gh-login-lk (with your initials at the end) for this new feature.
Note: it's important that we create this new branch from the master branch, because we want this new branch to start out as a copy of the master branch, with the latest agreed-upon version of our project!
[x] Install the http-server package from npm by running this code in your command line: npm install http-server -g (If this step doesn't work, you can develop your app using Cloud9 for now and ask us for help on Slack!)
[x] Make sure you're inside the pair-partners/firebase-test folder (if not, use cd to navigate there via command line), and then start your local server by running the http-server command. (Just literally type http-server into your command line, no other words needed!)
[x] View your app from the local server by going to http://localhost:8080 in your web browser. You should see everything working just like before!
[x] Any time you want to turn off your local server, press Ctrl + C on your keyboard. Then run the http-server command again from inside the pair-partners/firebase-test folder each time you want to restart the server.
Suggestion: If you want to use the command line while running the server, you can open two command line windows at the same time: one to keep the server running, and one to run commands as usual!
Why we need to use a local server
From now on, when testing our app locally, we'll need to run it from a local server every single time! Why's that? Because when users log in to our app through GitHub, they'll be redirected from GitHub's website back to our app -- and for that, we need to provide GitHub with a URL to our app!
The problem is, as you may have noticed, we've previously been running our app directly from our computer's file system. When you open a local HTML file, the URL starts with file:// -- so we're using the file URI scheme instead of HTTP, and that means the URL to our web app points directly to a file on our computer, not to a website on the internet!
GitHub won't allow us to register our app as a link to a file on our hard drive -- not to mention the security issues involved in trying to do that! Luckily, GitHub is totally OK with us providing a URL like http://localhost:8080 -- so, problem solved! (This is a big topic of course, with much more to learn about here! But for now, we'll focus on just getting our app to work.)
2. Create buttons and event listeners for login and logout
[x] In your firebase-test/index.html file, add another paragraph that says "Not currently logged in." and give it an ID of "userinfo".
[x] Then add two buttons to your HTML: one for logging in and one for logging out. Be sure to give them both unique IDs!
Remember: all your IDs and variable names should be specific and descriptive (but also relatively short, if possible). There is an art to this! A good rule of thumb is: just by glancing at its name, can you immediately tell how this element is different from all the other elements of your app?
[x] In your firebasetest.js file, create objects for your new paragraph and buttons. (Use your existing code as a reference, and be sure to use descriptive variable names!)
[x] Create JavaScript event listeners for both buttons, so that every time the user clicks either button, a message should appear in the browser console that says either "User clicked LOGIN" or "User clicked LOGOUT"
OAuth is an open protocol that lets you give certain apps permission to interact with other apps that you use, without needing to enter your password for all of them! We're going to use OAuth to let users log into our web app using their existing GitHub account, so that way our users never need to type their password into our app, and we don't need to store their passwords in our database at all!
When we register our OAuth app with GitHub, we get a unique Client ID and Client Secret. The Client ID is public, sort of like a username but for our application, and the Client Secret is like our password --
never, ever share or publish your Client Secret! (Except when we put it into our Firebase console, which will keep it securely stored on Firebase's server.)
[x] For "Application name", enter something like Pair Partners (Local Test Version)
[x] For Homepage URL and "Authorization callback URL", enter http://localhost:8080
Note: We're going to change the callback URL later to point to Firebase's server. The callback URL is where GitHub will redirect users after they've successfully logged in with GitHub and given permission for our app to access their GitHub account.
[x] Click "Register application" at the bottom to save your app, and keep the tab open! You'll need to copy-paste your Client ID and Client Secret for the next steps.
4. Set up GitHub authentication in the Firebase console
[x] In the Firebase console, go to the "Authentication" page and click on the "Sign-In Method" tab.
Shortcut:Click on this link and then choose your project.
[x] Click on "GitHub" in the list, click the "Enable" switch, and then copy-paste your Client ID and Client Secret from GitHub (the tab you left open after you registered your OAuth app on GitHub).
[x] From the bottom of that page, copy the authorization callback URL (it should look something like https://fir-test-c7763.firebaseapp.com/__/auth/handler) and click the blue "Save" button to save your changes in Firebase.
[x] Switch back to your GitHub OAuth app page again, paste that new callback URL into the "Authorization callback URL" section at the bottom of the page (it will replace the http://localhost:8080 link that was there before), and then click the green "Update application" button to save your changes in GitHub.
Congrats, your app is now all configured to use both the GitHub API and Firebase Authentication! Now all we need to do is write some code to implement the user login feature.
5. Add Firebase Authentication functions to your JavaScript
🏆 The goal: Once the user has successfully logged in with GitHub, display a message on the page showing their GitHub username and profile photo! Then when the user logs out, remove their information and display the message "Not currently logged in."
[x] In your firebasetest.js file, create an instance of Firebase's GitHub provider object: var provider = new firebase.auth.GithubAuthProvider();
Note: It doesn't really matter where you put this in your JavaScript file, as long as you define the provider object before any code that uses it. To keep things organized, it might be best to define this object immediately after you initialize your Firebase app.
[x] Change your login button's event listener so that the following code runs every time the user clicks the login button:
// Use Firebase with GitHub Auth to log in the user
firebase.auth().signInWithPopup(provider).catch(function(error) {
// Log any errors to the console
console.log(error);
});
The Firebase signInWithPopup method will open another website in a pop-up window, asking the user to grant access to our app. It takes a Firebase Auth provider object as its input, so in this case, we're using the GitHub login provider object that we created earlier. That's how it knows to open GitHub's website! (We can also use other providers like Facebook or Google if we want to.)
If you like, you can switch out the signInWithPopup method with the signInWithRedirect method instead, which redirects the user to a new page in the same browser window instead of opening up a pop-up window. (This works better on mobile devices!)
[x] Change your logout button's event listener so that the following code runs whenever the user clicks the logout button:
// Use Firebase with GitHub Auth to log in the user
firebase.auth().signOut().catch(function(error) {
// Log any errors to the console
console.log(error);
});
The Firebase signOut method will sign out the current user, regardless of how they signed in (whether we had them log in with GitHub or Facebook or something else).
[x] Add the Firebase onAuthStateChanged event listener method with the following code:
// When user logs in or logs out:
firebase.auth().onAuthStateChanged(function(user){
// If user is now logged in:
if (user) {
console.log('User successfully logged in to Firebase!');
// HERE: Update the paragraph with ID of "userinfo" to display user's GitHub username and GitHub profile photo!
// Otherwise, if no user currently logged in:
} else {
console.log('User successfully logged OUT from Firebase!');
// HERE: Update the paragraph with ID of "userinfo" to display the message "Not currently logged in."
}
});
The Firebase onAuthStateChanged method is an event listener that is triggered whenever the user's authentication state has changed -- either they've just logged in, or they've just logged out. Its callback function receives a Firebase User object as its input (here we named the parameter user), which contains a bunch of information about the user!
💡 Remember to commit early and commit often! A good rule of thumb is to make a commit with Git after every 15 minutes of coding and at the end of every work session.
✔️ Solutions will be posted later. Try it out by yourself first, and submit a pull request to get feedback on your code! Remember you can post a pull request at any time, not just when your code is all finished!
6. Access Firebase user profile information
First take a look through the official documentation for the Firebase User object to get a sense of what information Firebase stores about a user by default.
[x] Remember, our goal is to display the user's GitHub username and profile photo once they've logged in. Looking at that documentation linked above, identify the two properties of the User object that will give us that information.
[x] In your firebasetest.js file, inside the section of code that runs when the user is successfully logged in, create two new local variables below the // HERE comment -- create one variable for the user's name and one variable for the user's profile photo URL.
Hint: Remember that you can use dot notation to access properties of JavaScript objects. In this case, the user parameter is our object, and we want to access some properties inside of it!
7. Display the user's profile information on the web page
For the next step, we're going to use a new DOM element property called innerHTML! It's very similar to the textContent property, but the main difference is that innerHTML will render HTML elements in your string as actual HTML elements on the page!
[x] First, try a quick test with the textContent property by opening your Firebase app in your web browser, opening the browser console on that page, and running this code in your browser console:
document.getElementById("userinfo").textContent = 'The <strong>username</strong> will go here and the profile photo will go here: <img src="#">';
You should see that message with the literal HTML tags show up as code on your web page! That's because the textContent property does not render HTML.
[x] Next, run the same code as before, but replace textContent with innerHTML, and this time you should see the message with rendered HTML -- the word "username" should be bold, and there should be a broken image icon at the end of the message!
[x] Back in your firebasetest.js file, immediately after where you defined those two new variables containing the user's name and profile photo URL, access your "userinfo" paragraph and use its innerHTML property to display the user's name and their actual profile photo!
Hint: Remember that you can combine variables with literal strings in JavaScript using the + operator, often called the string concatenation operator! For example: "Hello, " + yourNameHere + "! Nice to meet you!"
[x] In the section of code that runs whenever the user's authentication state has changed but no user is currently logged in, change the textContent of the "userinfo" paragraph to contain the message "Not currently logged in" so that once the user logs out, the page will no longer display the user's GitHub name or profile photo.
Note: We can just use textContent this time, because our simple message doesn't contain any HTML tags. It's best to use textContent for simple things like this, because it actually runs much faster in the browser compared to innerHTML!
✔️ Solutions will be posted later. Try it out by yourself first, and submit a pull request to get feedback on your code! Remember you can post a pull request at any time, not just when your code is all finished!
8. Test the app with your local server
Now we're finally ready to see if the app works! Let's try logging in with GitHub!
[x] Remember to first start up your local server with the firebase-test folder as the root! (So in command line, first cd into that folder if you aren't already there.) Then run http-server and navigate to http://localhost:8080 in your web browser.
[x] Test out your app! You should be able to log in, see your GitHub username and profile appear, and then log out and see them disappear!
🏆 Congratulations, you built your first web app with a working user login system! This is the first step towards turning all your wildest ideas into web applications that could potentially have millions of users!
9. Create a pull request to share your code with us
[x] Remember to make a Git commit on your branch for this new feature, and then push your specific branch to GitHub.
[x] Create a new pull request on GitHub's website, and make sure the base branch is set to "master" and the compare branch is set to your new branch.
[x] After reviewing your files to make sure all your changes show up, click "Create pull request" and be sure to write a clear title for your pull request! After adding any comments or questions you have to the description, click "Create pull request" again to publish it.
Congrats, you've completed this challenge!
✔️ Don't forget to check off all the checkboxes in these instructions, so the rest of our team can easily see your progress!
So far we've set up a small but functional Firebase app and practiced using some of the Firebase functions for accessing and displaying data. Next, let's set up a user login system using Firebase Authentication and the GitHub API!
📚 Prerequisites: First complete "Challenge: Practice displaying Firebase data"
✔️ To complete this challenge: follow each step below, check off the checkboxes to track your progress (so we can see your progress too!), and then submit your solution as a pull request.
❓ If you have any questions, post a comment at the bottom of this page or ask us in our Slack chatroom!
1. Set up for local development and testing with a local server
[x] First make sure you're in the
pair-partners
project folder, and make sure you're on the master branch (usegit checkout master
if you need to switch).[x] Download the latest working version of our project code from GitHub with
git pull
-- remember to do this every time you resume working on any team project, so you'll have all the latest changes before you continue your work![x] If you haven't already, make a new local branch called something like
gh-login-lk
(with your initials at the end) for this new feature.[x] Install the http-server package from npm by running this code in your command line:
npm install http-server -g
(If this step doesn't work, you can develop your app using Cloud9 for now and ask us for help on Slack!)[x] Make sure you're inside the
pair-partners/firebase-test
folder (if not, usecd
to navigate there via command line), and then start your local server by running thehttp-server
command. (Just literally typehttp-server
into your command line, no other words needed!)[x] View your app from the local server by going to
http://localhost:8080
in your web browser. You should see everything working just like before![x] Any time you want to turn off your local server, press
Ctrl + C
on your keyboard. Then run thehttp-server
command again from inside thepair-partners/firebase-test
folder each time you want to restart the server.Why we need to use a local server
From now on, when testing our app locally, we'll need to run it from a local server every single time! Why's that? Because when users log in to our app through GitHub, they'll be redirected from GitHub's website back to our app -- and for that, we need to provide GitHub with a URL to our app!
The problem is, as you may have noticed, we've previously been running our app directly from our computer's file system. When you open a local HTML file, the URL starts with
file://
-- so we're using the file URI scheme instead of HTTP, and that means the URL to our web app points directly to a file on our computer, not to a website on the internet!GitHub won't allow us to register our app as a link to a file on our hard drive -- not to mention the security issues involved in trying to do that! Luckily, GitHub is totally OK with us providing a URL like
http://localhost:8080
-- so, problem solved! (This is a big topic of course, with much more to learn about here! But for now, we'll focus on just getting our app to work.)2. Create buttons and event listeners for login and logout
[x] In your
firebase-test/index.html
file, add another paragraph that says"Not currently logged in."
and give it an ID of"userinfo"
.[x] Then add two buttons to your HTML: one for logging in and one for logging out. Be sure to give them both unique IDs!
[x] In your
firebasetest.js
file, create objects for your new paragraph and buttons. (Use your existing code as a reference, and be sure to use descriptive variable names!)[x] Create JavaScript event listeners for both buttons, so that every time the user clicks either button, a message should appear in the browser console that says either
"User clicked LOGIN"
or"User clicked LOGOUT"
✔️ SOLUTION for Part 2: https://gist.github.com/LearningNerd/26e3996aebf800225145c33e512c0d07
3. Register a new GitHub OAuth application
📑 Official documentation: Firebase Authentication Using GitHub with JavaScript and Registering OAuth Apps on GitHub
OAuth is an open protocol that lets you give certain apps permission to interact with other apps that you use, without needing to enter your password for all of them! We're going to use OAuth to let users log into our web app using their existing GitHub account, so that way our users never need to type their password into our app, and we don't need to store their passwords in our database at all!
When we register our OAuth app with GitHub, we get a unique Client ID and Client Secret. The Client ID is public, sort of like a username but for our application, and the Client Secret is like our password -- never, ever share or publish your Client Secret! (Except when we put it into our Firebase console, which will keep it securely stored on Firebase's server.)
[x] First, click here to register a new OAuth app on GitHub.
[x] For "Application name", enter something like
Pair Partners (Local Test Version)
[x] For Homepage URL and "Authorization callback URL", enter
http://localhost:8080
[x] Click "Register application" at the bottom to save your app, and keep the tab open! You'll need to copy-paste your Client ID and Client Secret for the next steps.
4. Set up GitHub authentication in the Firebase console
📑 Official documentation: Firebase Authentication Using GitHub with JavaScript
[x] In the Firebase console, go to the "Authentication" page and click on the "Sign-In Method" tab. Shortcut: Click on this link and then choose your project.
[x] Click on "GitHub" in the list, click the "Enable" switch, and then copy-paste your Client ID and Client Secret from GitHub (the tab you left open after you registered your OAuth app on GitHub).
[x] From the bottom of that page, copy the authorization callback URL (it should look something like
https://fir-test-c7763.firebaseapp.com/__/auth/handler
) and click the blue "Save" button to save your changes in Firebase.[x] Switch back to your GitHub OAuth app page again, paste that new callback URL into the "Authorization callback URL" section at the bottom of the page (it will replace the
http://localhost:8080
link that was there before), and then click the green "Update application" button to save your changes in GitHub.Congrats, your app is now all configured to use both the GitHub API and Firebase Authentication! Now all we need to do is write some code to implement the user login feature.
5. Add Firebase Authentication functions to your JavaScript
🏆 The goal: Once the user has successfully logged in with GitHub, display a message on the page showing their GitHub username and profile photo! Then when the user logs out, remove their information and display the message "Not currently logged in."
📑 Official documentation: Firebase Authentication Using GitHub with JavaScript (the section titled "Handle the sign-in flow with the Firebase SDK") and Manage Users in Firebase
[x] In your
firebasetest.js
file, create an instance of Firebase's GitHub provider object:var provider = new firebase.auth.GithubAuthProvider();
[x] Change your login button's event listener so that the following code runs every time the user clicks the login button:
The Firebase
signInWithPopup
method will open another website in a pop-up window, asking the user to grant access to our app. It takes a Firebase Auth provider object as its input, so in this case, we're using the GitHub login provider object that we created earlier. That's how it knows to open GitHub's website! (We can also use other providers like Facebook or Google if we want to.)If you like, you can switch out the
signInWithPopup
method with thesignInWithRedirect
method instead, which redirects the user to a new page in the same browser window instead of opening up a pop-up window. (This works better on mobile devices!)[x] Change your logout button's event listener so that the following code runs whenever the user clicks the logout button:
The Firebase
signOut
method will sign out the current user, regardless of how they signed in (whether we had them log in with GitHub or Facebook or something else).[x] Add the Firebase
onAuthStateChanged
event listener method with the following code:The Firebase
onAuthStateChanged
method is an event listener that is triggered whenever the user's authentication state has changed -- either they've just logged in, or they've just logged out. Its callback function receives a Firebase User object as its input (here we named the parameteruser
), which contains a bunch of information about the user!💡 Remember to commit early and commit often! A good rule of thumb is to make a commit with Git after every 15 minutes of coding and at the end of every work session.
✔️ Solutions will be posted later. Try it out by yourself first, and submit a pull request to get feedback on your code! Remember you can post a pull request at any time, not just when your code is all finished!
6. Access Firebase user profile information
First take a look through the official documentation for the Firebase User object to get a sense of what information Firebase stores about a user by default.
[x] Remember, our goal is to display the user's GitHub username and profile photo once they've logged in. Looking at that documentation linked above, identify the two properties of the User object that will give us that information.
[x] In your
firebasetest.js
file, inside the section of code that runs when the user is successfully logged in, create two new local variables below the// HERE
comment -- create one variable for the user's name and one variable for the user's profile photo URL.7. Display the user's profile information on the web page
For the next step, we're going to use a new DOM element property called
innerHTML
! It's very similar to thetextContent
property, but the main difference is thatinnerHTML
will render HTML elements in your string as actual HTML elements on the page![x] First, try a quick test with the
textContent
property by opening your Firebase app in your web browser, opening the browser console on that page, and running this code in your browser console:You should see that message with the literal HTML tags show up as code on your web page! That's because the
textContent
property does not render HTML.[x] Next, run the same code as before, but replace
textContent
withinnerHTML
, and this time you should see the message with rendered HTML -- the word "username" should be bold, and there should be a broken image icon at the end of the message![x] Back in your
firebasetest.js
file, immediately after where you defined those two new variables containing the user's name and profile photo URL, access your "userinfo" paragraph and use itsinnerHTML
property to display the user's name and their actual profile photo![x] In the section of code that runs whenever the user's authentication state has changed but no user is currently logged in, change the
textContent
of the "userinfo" paragraph to contain the message"Not currently logged in"
so that once the user logs out, the page will no longer display the user's GitHub name or profile photo.✔️ Solutions will be posted later. Try it out by yourself first, and submit a pull request to get feedback on your code! Remember you can post a pull request at any time, not just when your code is all finished!
8. Test the app with your local server
Now we're finally ready to see if the app works! Let's try logging in with GitHub!
[x] Remember to first start up your local server with the
firebase-test
folder as the root! (So in command line, firstcd
into that folder if you aren't already there.) Then runhttp-server
and navigate tohttp://localhost:8080
in your web browser.[x] Test out your app! You should be able to log in, see your GitHub username and profile appear, and then log out and see them disappear!
🏆 Congratulations, you built your first web app with a working user login system! This is the first step towards turning all your wildest ideas into web applications that could potentially have millions of users!
9. Create a pull request to share your code with us
You know the drill! If you need to review the detailed instructions, see the bottom of the previous challenge ("Practice displaying Firebase data"). Here's a less detailed, quick recap:
[x] Remember to make a Git commit on your branch for this new feature, and then push your specific branch to GitHub.
[x] Create a new pull request on GitHub's website, and make sure the base branch is set to "master" and the compare branch is set to your new branch.
[x] After reviewing your files to make sure all your changes show up, click "Create pull request" and be sure to write a clear title for your pull request! After adding any comments or questions you have to the description, click "Create pull request" again to publish it.
Congrats, you've completed this challenge!
✔️ Don't forget to check off all the checkboxes in these instructions, so the rest of our team can easily see your progress!
👉 More challenges to come, so stay tuned!