Skip to content

Bootcamp Part 5: User Authentication

ashleyzhuang edited this page Oct 6, 2021 · 1 revision

This week, we will be covering user authentication. This is all about user creation and logging in, how to manage if the user is logged in or not in our React application, and eventually logging out. As usual, if you're stumped, try to come out to one of my office hours to ask questions! Let's get into this week's material.

Video

Again, the videos are split up as follows (they are also linked in their respective sections below):

  • Part 1: What is User Authentication? Getting user registration to work.
  • Part 2: Walkthrough of User Authentication in the browser and making sure our React application waits for authentication data to load before it renders.
  • Part 3: Implement logout, Login page, and adding usernames to the user registration flow.

You can find the slides here: Slides

User Authentication Intro + Register Page

Link to Video on User Auth/Register: Video

The code for this video can be found here: https://github.com/harvard-datamatch/bootcamp/commit/c2fc089e09b987b32dd3636c38b450cfb8553339

Authentication is a buzzword, just fancy for managing user login and making sure the user is who they claim to be. We use Firebase Authentication to manage our users, creating new accounts, logging in, logging out, and validating that validity of our users.

We also talked about Promises in Javascript. Promises seem very daunting at first, but once you've started working with them more and understanding that they just represent data traveling over the internet that takes an unknown time and will ultimately succeed or error makes them much more simple. If there's a Promise, you're gonna have to await for it to finish in an async (asynchronous) function.

Additional Resources

Register Browser Walkthrough + Waiting for User Auth to Load

Link to Video

The code for this video can be found here: https://github.com/harvard-datamatch/bootcamp/commit/b6a2cf1422962c9f262fc40dcb88f232c23632a6

I used a lot of different browser tools and developer tools to walkthrough what exactly happens when a user registers for an account. We used the Network tab (with the XHR filter) to peek into the outbound network requests our React application makes. We also used the Application tab to look into the browser's local storage and see what data is being stored locally in our browser that ultimately allows us to keep account identity data around in our browser even after closing all our tabs and windows.

Since validating a user (the getAccountInfo request) takes time over the network, we have to make sure to wait for the authentication data (account identity data) to load in our Redux store before using it. And since many of our components will be using the authentication data, it's nice to make sure it's loaded at the highest possible React component in our React tree as possible, which is our App component.

Resources

Logout/Login/Usernames for Registration

Link to Video

The code for this video can be found here: https://github.com/harvard-datamatch/bootcamp/commit/eaf5283fcf73a6b0e1e40955d35a288bb4fd12b7

Finally, we've implemented the logout and login functionalities bringing our user authentication full circle. The Login page is very similar to the Register page. We also dealt with React-Redux-Firebase package deleting our homepage data on logout by updating our rrfConfig. Finally, we added a username field to allow our users to have usernames. The second parameter of createUser allows us to pass in the user's initial, starting user profile, which is saved to Firebase Realtime Database (which is synced to the profile attribute in the Redux store).

Resources

Week 5 TASK

We want to give ownership to every flashcards deck and allow flashcards to be public or private.

  1. On CardEditor, allow the user to specify if they are creating a private or public deck. This is the visibility attribute on a flashcard deck. It can be a string, boolean, whatever you want to represent private/public. You will want to save this attribute in both /flashcards and /homepage.

    • To create a checkbox, use the type prop for an input: https://www.w3schools.com/tags/att_input_type_checkbox.asp
    • You'll have to create a new handleCheckboxChange function, and you'll be able to access event.target.checked, which is a boolean that tells you if the checkbox is checked or not.
  2. Similarly, when saving a flashcards deck, make sure to save the owner of the deck (the uid of the user) to both /flashcards and /homepage. This is the owner attribute on the a flashcard deck.

  3. You'll have to manually add the visibility and owner attribute to your existing flashcard decks (or just be aware that some of your decks will not have these attributes and may break your code).

  4. Then using this new information, on the Homepage, you should only render the flashcards deck that are either public or that user’s private decks. So, if visibility is public on the deck or if it's private, make sure the owner attribute is the current user's uid (unique user id).

  5. Finally, in the CardViewer component, add the username of the user who owned/created the deck, something like "Created by <username>". You'll have to use the populate recipe from React-Redux-Firebase to get this to work since the owner attribute on the flashcard deck is only the uid. So, you'll need to populate the owner attribute with that user's profile.

    • The documentation can be found here: http://react-redux-firebase.com/docs/populate.html and http://react-redux-firebase.com/docs/recipes/populate.html
    • Note that the documentation uses object deconstruction in the mapStateToProps function passed into connect. So, the following are the same.
      ({ firebase }) => ({
        todos: populate(firebase, 'todos', populates),
      })
      
      state => ({
        todos: populate(state.firebase, 'todos', populates),
      })
    • Hint I gave in email: The populates array is the same as the documentation. You only need to add populates to the object returned in the function passed into firebaseConnect. And you only need to call populate(state.firebase, <the Redux path to deck you want to populate>, populates) in mapStateToProps.
    • Definitely reach out to me over email/Slack if populate is still confusing to you!

Additional Tasks

  1. (Medium) Create a profile page, which should only be accessible if the user is logged in. The profile page should show the user's personal information and allow them to update their username only. (Updating email is finicky and much more complex than expected.) Instead of the update function, you should use the updateProfile function.

  2. (Hard) Email confirmation. Only let email-confirmed users create new flashcard decks. This requires you to understand React Router relatively well and how to parse a query string in the URL (and do some research and understanding of email confirmation on your own). To start off, you should go to the Templates page in the Authentication section of Firebase and look at the email address verification template. You should customize the Action URL to test locally to be localhost:3000/auth. Then, you'll see in the email address verification template that the link for users to verify their email is in the form: localhost:3000/auth?mode=<action>&oobCode=<code>.

Once you're done

Fill out this form when you're done! Make sure to deploy your app, so I can take a look. It'll notify me to review your work and let me know you finished.

Form link: https://forms.gle/GEynjg1kfaHsHhTM9