-
Notifications
You must be signed in to change notification settings - Fork 5
Bootcamp Part 5: User Authentication
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.
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
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.
- React-Redux-Firebase authentication props: https://react-redux-firebase.com/docs/auth.html
- Promises: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
- Async/await: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
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.
- Interested in local storage? Read about IndexedDB: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
- Redirect component documentation: https://reacttraining.com/react-router/web/api/Redirect
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).
- Definitely check out the authentication methods React-Redux-Firebase provides (if you haven't already in part 1): https://react-redux-firebase.com/docs/auth.html
- If you want to see where I found the
preserveOnLogout
configuration: http://react-redux-firebase.com/docs/api/constants.html#defaultconfig
We want to give ownership to every flashcards deck and allow flashcards to be public or private.
-
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 accessevent.target.checked
, which is a boolean that tells you if the checkbox is checked or not.
- To create a checkbox, use the
-
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 theowner
attribute on the a flashcard deck. -
You'll have to manually add the
visibility
andowner
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). -
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 theowner
attribute is the current user's uid (unique user id). -
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 theowner
attribute on the flashcard deck is only the uid. So, you'll need to populate theowner
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 intoconnect
. 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 intofirebaseConnect
. And you only need to callpopulate(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!
-
(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 theupdate
function, you should use theupdateProfile
function. -
(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>
.- You have access to authentication props with
firebaseConnect
throughprops.firebase.auth().blah
, whereblah
is the method you want. - Docs on sending a confirmation email: https://firebase.google.com/docs/auth/web/manage-users#send_a_user_a_verification_email. You should do this right after a user creates their account for the first time.
- How to validate the
oobCode
in the email validation URL: https://firebase.google.com/docs/auth/custom-email-handler - Finally, once you deploy your application, change your Action URL back to your Firebase deployed URL, like
https://bootcamp-ce748.web.app/auth
.
- You have access to authentication props with
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