{"id":17816087,"url":"https://github.com/henrytwo/masseyhacks-firebase-workshop","last_synced_at":"2026-01-11T16:49:08.781Z","repository":{"id":110318758,"uuid":"264826042","full_name":"henrytwo/MasseyHacks-Firebase-Workshop","owner":"henrytwo","description":null,"archived":false,"fork":false,"pushed_at":"2020-05-30T01:07:12.000Z","size":52,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-07T23:37:28.236Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/henrytwo.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-18T04:28:52.000Z","updated_at":"2022-05-04T03:31:12.000Z","dependencies_parsed_at":"2023-04-06T04:01:05.625Z","dependency_job_id":null,"html_url":"https://github.com/henrytwo/MasseyHacks-Firebase-Workshop","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henrytwo%2FMasseyHacks-Firebase-Workshop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henrytwo%2FMasseyHacks-Firebase-Workshop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henrytwo%2FMasseyHacks-Firebase-Workshop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henrytwo%2FMasseyHacks-Firebase-Workshop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/henrytwo","download_url":"https://codeload.github.com/henrytwo/MasseyHacks-Firebase-Workshop/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246779485,"owners_count":20832396,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-27T16:35:18.569Z","updated_at":"2026-01-11T16:49:08.742Z","avatar_url":"https://github.com/henrytwo.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MasseyHacks Firebase Workshop (and a tiny bit of app security)\n## By Henry Tu\n\n## Introduction (10 mins)\n\n### Starter code\nSince this workshop will be focused on the Firebase services, I'm going to be working with some website code that I've already baked ahead of time.\u003cbr\u003e\u003cbr\u003e\nFor the web portion of this workshop, check the `web-starter-code` directory. If you need to refer to the completed website, that's available in the `web-demo-finished` directory. Similarly, a small demo for the admin sdk  is available under `python-admin-sdk-demo`.\n\n### What is Firebase?\nFirebase is a development platform by Google that offers services such as Web Hosting, Database, Authentication, etc.\n\n### Why Firebase?\nWith Firebase, you don't have to spend hours configuring a server and worrying about scaling. All of this is handled by Firebase behind the scenes so you can focus on writing awesome code.\n\n### How do I use Firebase?\nHere is the official Firebase guide: [https://firebase.google.com/docs/guides]\n\u003cbr\u003e\nFor this workshop, we'll be focusing on Firebase for Web and a bit on the Firebase Python Admin SDK.\n\n### Firebase CLI Installation\nFor web, you'll need to install the Firebase CLI first. Follow the guide here for more details: [https://firebase.google.com/docs/cli]\n\u003cbr\u003e\u003cbr\u003e\nWindows Install Executable: [https://firebase.tools/bin/win/instant/latest] (Note: You might need node installed first)\u003cbr\u003e\nmacOS/Linux: Run `curl -sL https://firebase.tools | bash`\n\u003cbr\u003e\u003cbr\u003e\nNow, open a console and type `firebase login` to authenticate. After that's setup, you're ready to create your first project!\n\n## Basic application security\nWhen developing any web app, it's always to keep security in the back of your mind. Not only will this save you from headache later on, it could also save you money.\u003cbr\u003e\u003cbr\u003e\nHere are some easy steps to get you started:\n- Add sensitive files (Such as API keys)  to `.gitignore` to  prevent them from being leaked\n- Never trust user input and always sanitize (Keep your hands  clean!)\n- Keep your   packages up to date\n- Use `https` as much  as possible to avoid MITM attacks\n\n\n### Creating a project\nGo to the console at [https://console.firebase.google.com/] and create a new project. Go to the services that you want to use (i.e. Authentication, Cloud Firestore, etc.) and configure them. I'll go into more details when I discuss the individual services.\n\n## Firebase on the web (10 mins)\n\n### Setup\nAfter you configure Firebase on the console, open your editor of choice and create a new directory to house your project. Navigate to this directory through your console and run `firebase init`.\u003cbr\u003e\u003cbr\u003e\nIf you followed the instructions properly, it should ask you to select Firebase CLI features. You can change your selection later on by running `firebase init` again, but let's select everything we need at once to save time.\u003cbr\u003e\u003cbr\u003e\nFor this workshop, select:\n- Hosting\n- Firestore\n\n(Notice that Authentication is missing here, and that's because it isn't something handled by the CLI)\u003cbr\u003e\u003cbr\u003e\nNext, it will ask you to select a project to link to. Go ahead and find the project you just created in the console.\u003cbr\u003e\u003cbr\u003e\nFinally, the CLI will ask to confirm the names of files to generate. If you hit enter a few times it'll use the default settings.\n\n### Firebase Hosting\nA cool feature of Firebase Hosting is their global CDN. This means that Firebase will automatically cache your website in multiple geographic locations to ensure that it can be accessed quickly from anywhere. Additionally, Firebase handles all the scaling so any sudden spikes in usage are no problem.\u003cbr\u003e\u003cbr\u003e\nHere is a partial structure of your project so far:\u003cbr\u003e\n```\nyourProject\n  |-public\n  | |- index.html\n  | |- 404.html\n  |-some other random firebase stuff...\n```\n\nIf you used the default settings, everything under the `public`  folder will be accessible when your website is published. This is your website root.\u003cbr\u003e\u003cbr\u003e\nTo host your own content, simply place it in this directory. After that's done, you can publish it by running `firebase deploy`. Notice that Firebase automatically generates a URL which can be immediately used to access your website. A custom domain can be configured via the Firebase console.\u003cbr\u003e\u003cbr\u003e\nAlternatively,  you can start the local development server by running `firebase serve`. This will come in handy when we need to test our website.\n\n#### Setting up the libraries\nSince we're using Firebase Hosting, we can use the integrated CDN to serve all our libraries. Place these imports in your HTML:\n\n```html\n\u003c!-- update the version number as needed --\u003e\n\u003cscript defer src=\"/__/firebase/7.14.4/firebase-app.js\"\u003e\u003c/script\u003e\n\u003cscript defer src=\"/__/firebase/7.14.4/firebase-auth.js\"\u003e\u003c/script\u003e\n\u003cscript defer src=\"/__/firebase/7.14.4/firebase-firestore.js\"\u003e\u003c/script\u003e\n\u003cscript defer src=\"/__/firebase/init.js\"\u003e\u003c/script\u003e\n```\nA full list can be found here: [https://firebase.google.com/docs/web/setup#available-libraries]\u003cbr\u003e\u003cbr\u003e\nNext, initialize Firebase by creating a Firebase app object:\n```javascript\nlet app = firebase.app();\n```\n\n(Note: Usually you would have to configure your API key here, but since we're using Firebase Hosting your project will be automatically linked!)\n\n### Firebase Cloud Firestore (20 mins)\nA really useful service that Firebase offers is Cloud Firestore. It's a realtime document based database. This means that Firestore will automatically propogate changes in the database to all connected apps in real time.\u003cbr\u003e\u003cbr\u003e\nFirst, we'll setup Firestore in the console. You'll receive a prompt asking whether you want to start in `production mode` or `test mode`. For now, let's select `test mode` so that we have unrestricted access to the DB. In practice, you'll want to lock this down so that people can't mess with your data.\u003cbr\u003e\u003cbr\u003e\n(Tip: For hackathons, it isn't a big priority to secure your DB. Focus on getting your hack working!)\u003cbr\u003e\u003cbr\u003e\nIf you open up the Firebase console to the Firestore tab, you'll be able to see changes pushed to the DB in real time.\n\n#### Database structure\nFirebase has a few different levels in its structure. At the highest level, there are collections which must be uniquely named. Collections contain documents which themselves can contain many fields. This is where you store your conventional data (i.e. strings, integers, or other collections!, etc.)\u003cbr\u003e\u003cbr\u003e\nExample:\n```\n |-cats \u003c- Collection\n |  |-cat1 \u003c- Document\n |  | |- \"location\": \"Toronto\" \u003c- Field\n |  | |- \"social\": \"distance\"\n |  |-cat2\n |    |- \"meaningOfLife\": 42\n |\n |-dogs\n   |-woofer\n   | |- \"color\": \"purple\"\n   |-2020\n     |- \"status\": \"over\" \n```\n\n#### Setup\nCreate a Firestore object:\n```javascript\nvar db = firebase.firestore();\n```\n(Note: Make sure you do this after creating the Firebase app object!)\n\n#### Writing data\nHere is a detailed guide: [https://firebase.google.com/docs/firestore/manage-data/add-data#add_a_document]\u003cbr\u003e\u003cbr\u003e\n\nTo directly set data:\n```javascript\ndb.collection(\"cities\").doc(\"new-city-id\").set({\n    name: \"Tokyo\",\n    country: \"Japan\"\n});\n```\nThis is useful if you know the exact document ID you want.\u003cbr\u003e\u003cbr\u003e\nTo add data with an auto generated document ID:\n```javascript\ndb.collection(\"items\").add({          \n    text: \"Test\",\n    timestamp: new Date().getTime()\n})\n```\n\n#### Reading data\nDetailed guide: [https://firebase.google.com/docs/firestore/query-data/get-data]\u003cbr\u003e\u003cbr\u003e\nWe can read data from a document directly if we know the path:\n```javascript\ndb.collection(\"cities\").doc(\"SF\").get().then(function(doc) {\n    if (doc.exists) {\n        console.log(\"Document data:\", doc.data());\n    } else {\n        // doc.data() will be undefined in this case\n        console.log(\"No such document!\");\n    }\n}).catch(function(error) {\n    console.log(\"Error getting document:\", error);\n});\n```\nFor reading multiple documents at a time, more details are in the documentation.\n\n#### Listening for changes\nDetailed guide: [https://firebase.google.com/docs/firestore/query-data/listen#web]\u003cbr\u003e\u003cbr\u003e\nWe can also automatically listen for changes to the database:\u003cbr\u003e\u003cbr\u003e\nSingle document:\n```javascript\ndb.collection(\"cities\").doc(\"SF\")\n    .onSnapshot(function(doc) {\n        console.log(\"Current data: \", doc.data());\n    });\n```\n\nMultiple documents:\n```javascript\ndb.collection(\"items\")\n  .orderBy(\"timestamp\")\n  .onSnapshot(function(querySnapshot) {\n    var items = [];\n\n    querySnapshot.forEach(function(doc) {\n      items.push(doc.data());\n    });\n\n    console.log(items);\n  })\n```\n\nThis function will fire every time there is a change to the document.\n\n#### Security\nDetailed guide: [https://firebase.google.com/docs/firestore/security/get-started]\u003cbr\u003e\u003cbr\u003e\nSecurity rules are important because they keep your data safe. Without them, people can see all your secrets! Or even worse, they can use all of your quota! Since they are run at every database interaction, they can also be used to validate data.\u003cbr\u003e\u003cbr\u003e\nBy default, these rules live in the `firestore.rules` file and are pushed automatically when `firebase deploy` is run.\u003cbr\u003e\u003cbr\u003e\nDue to limited time, we won't be focusing too much on this.\u003cbr\u003e\u003cbr\u003e\nExample security rule:\n```\nservice cloud.firestore {\n  match /databases/{database}/documents {\n    match /{document=**} {\n      allow read: if request.auth.uid != null;\n      allow create: if request.auth.uid != null \u0026\u0026 request.resource.data.owner == request.auth.token.name \u0026\u0026 request.resource.data.text.size() \u003c= 128;\n      allow update: if false;\n      allow delete: if false;\n      allow write: if false;\n    }\n  }\n}\n```\nBreakdown:\n- `request.auth.token.name` is the `name` of the user initiating request\n- `request.auth.uid` is the `uid` of the user initiating request\n- `request.resource.data` is the object being read/written (All sub attributes are the data itself)\n\nThe rules page has a simulator for testing rules under different environments.\n\n#### Best practices for handling data\nA good general rule of thumb is to never trust data that users provide. Let's say you're making a Twitter clone. Simple enough right? Just take whatever text they give you and add it to your HTML. Well... there's a bit of a problem with that. If you don't sanitize your input and treat it as HTML, a cleaver attacker could do something like submitting:\n```html\n\u003cscript\u003e\n  alert(\"Ahahaha, now I'm running JavaScript on your machine!\")\n\u003c/script\u003e\n```\nHow do you prevent an attack like this? Depending on what you're using to build your website, there are different approaches. Frameworks such as Vue.js and React already have features to escape text and prevent this sort of attack. If you're using jQuery, `$(yourElement).text(userText)` is generally safe. Just be careful to never use `$(yourElement).html(userText)` since this will cause the user input to be treated as HTML.\n\n### Firebase Authentication (10 mins)\nDetailed guide: [https://firebase.google.com/docs/auth]\u003cbr\u003e\u003cbr\u003e\nFirebase Authentication integrates nicely with other services such as Firestore. It allows users to sign in with Email/Password or through other services such as Google, Facebook, etc. No matter which method they choose to use, Firebase handles the complicated OAUTH and links all the authentication methods together. This means you only need to worry about writing one set of code and Firebase will handle the rest.\n\u003cbr\u003e\u003cbr\u003e\nImportant: If you add a custom domain, be sure to add it to the list of authorized domains in order for it to work!\n\n#### Setup\nGo to the Firebase console and visit the Authentication section. Under the `Sign-In method` tab, enable the methods that you want users to be able to log in with.\u003cbr\u003e\u003cbr\u003e\nFor this workshop, we'll focus on `Sign-In with Google` since it's basically set up out of the box.\u003cbr\u003e\u003cbr\u003e\nAfter enabling `Google`, complete the form annd enter a support email and save your settings. Now we'll setup the code.\u003cbr\u003e\u003cbr\u003e\nCreate an auth provider object:\n```javascript\nvar provider = new firebase.auth.GoogleAuthProvider();\n```\n\nDetailed guide: [https://firebase.google.com/docs/auth/web/google-signin]\u003cbr\u003e\u003cbr\u003e\n \n####  Trigger a login window\nTo trigger the  Google sign-in form, run:\n```javascript\nfirebase.auth().signInWithPopup(provider).then(function (result) {\n  // This gives you a Google Access Token. You can use it to access the Google API.\n  var token = result.credential.accessToken;\n  // The signed-in user info.\n  var user = result.user;\n  \n  // This part will run if the login was successful\n\n}).catch(function (error) {\n  // Handle Errors here.\n  var errorCode = error.code;\n  var errorMessage = error.message;\n  // The email of the user's account used.\n  var email = error.email;\n  // The firebase.auth.AuthCredential type that was used.\n  var credential = error.credential;\n  // ...\n});\n```\nAfter logging in, other Firebase services such as Firestore will automatically be updated.\n \n#### Trigger a sign out\nTo immediately sign the user out, run:\n```javascript\nfirebase.auth().signOut().then(function() {\n  // Sign-out successful.\n  // This part will run if the user was signed out successfully\n\n}, function(error) {\n  // An error happened.\n  console.log('Could\\'t logout')\n});\n```\n\n#### Listen for auth state change\nIf you want to run some code as soon as the user logs in/logs off:\n```javascript\nfirebase.auth().onAuthStateChanged(function(user) {\n  if (user) {\n    // User is signed in.\n    var displayName = user.displayName;\n    var email = user.email;\n    var emailVerified = user.emailVerified;\n    var photoURL = user.photoURL;\n    var isAnonymous = user.isAnonymous;\n    var uid = user.uid;\n    var providerData = user.providerData;\n    // ...\n  } else {\n    // User is signed out.\n    // ...\n  }\n});\n```\n\n### Firebase Python Admin SDK (10 mins)\nDetailed guide: [https://firebase.google.com/docs/reference/admin]\u003cbr\u003e\u003cbr\u003e\nThe Python Admin SDK is designed primarily for managing your Firebase app from your backend. Although you aren't supposed to use it for client applications, you can use it to quickly interface with Firebase services.\n\n#### Installation\nUsing pip: `pip install firebase-admin` or `pip3 install firebase-admin` (Note: Might need to run as root)\n\n#### About Service keys\nUnlike using Firebase on the web, the Admin SDK uses service keys to link to your project. It is paramount that you do not publish these keys as anyone who has access to them can control your project.\u003cbr\u003e\u003cbr\u003e\n(During hackathon environments you might push them to version control for convenience, just be aware of the risks involved. Someone could mess with your stuff!)\n\n#### Generating Service keys\nTo generate a service key, go to your Firebase console and click on the gear. Next, under `Service accounts`, find `Firebase Admin SDK` and click `Create service account`. Finally, click `Generate new private key`. This should start a download of a JSON file. This is the file you want to keep safe.\n\n#### Setup\nThe first thing you should do is import the libraries and authenticate:\n```python\nimport firebase_admin\nfrom firebase_admin import credentials\nfrom firebase_admin import firestore\n\ncred = credentials.Certificate(\"path/to/serviceAccountKey.json\")\nfirebase_admin.initialize_app(cred)\n\ndb = firestore.client()\n```\n\n#### Add data to Cloud Firestore\nDetailed guide: [https://firebase.google.com/docs/firestore/quickstart] (Switch to Python tab)\u003cbr\u003e\u003cbr\u003e\n\nThis is the same idea as using Firestore on the web.\n\n```python\ndoc_ref = db.collection('users').document('alovelace')\ndoc_ref.set({\n    'first': 'Ada',\n    'last': 'Lovelace',\n    'born': 1815\n})\n```\n\n#### Get a single document from Cloud Firestore\nDetailed guide: [https://firebase.google.com/docs/firestore/query-data/get-data] (Switch to Python tab)\n```python\ndoc_ref = db.collection('cities').document('SF')\n\ndoc = doc_ref.get()\nif doc.exists:\n    print('Document data: {}'.format(doc.to_dict()))\nelse:\n    print('No such document!')\n```\n\n#### Get multiple documenets from Cloud Firestore\nDetailed guide: [https://firebase.google.com/docs/firestore/query-data/get-data] (Switch to Python tab)\n```python\ndocs = db.collection('cities').stream()\n\nfor doc in docs:\n    print('{} =\u003e {}'.format(doc.id, doc.to_dict()))\n```\n\n#### Getting realtime updates from Cloud Firestore\nDetailed guide: [https://firebase.google.com/docs/firestore/query-data/listen] (Switch to Python Tab)\u003cbr\u003e\u003cbr\u003e\nFor this, we'll need to import the `threading` library. \n```python\nimport threading\n\n# Create an Event for notifying main thread.\ncallback_done = threading.Event()\n\n# Create a callback on_snapshot function to capture changes\ndef on_snapshot(doc_snapshot, changes, read_time):\n    for doc in doc_snapshot:\n        print('Received document snapshot: {}'.format(doc.id))\n    callback_done.set()\n\ndoc_ref = db.collection('cities').document('SF')\n\n# Watch the document\ndoc_watch = doc_ref.on_snapshot(on_snapshot)\n\n```\n\n## Wrapping up\nThere are plenty of useful resources online to get more information about Firebase. They even have a YouTube series to get you started: [https://www.youtube.com/user/Firebase].\u003cbr\u003e\u003cbr\u003e\nIf you have any other questions, feel free to reach out to me on Discord (henrytwo#4997) or via email (henry (at) henrytu.me).\u003cbr\u003e\u003cbr\u003e\nGood luck!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhenrytwo%2Fmasseyhacks-firebase-workshop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhenrytwo%2Fmasseyhacks-firebase-workshop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhenrytwo%2Fmasseyhacks-firebase-workshop/lists"}