{"id":22330645,"url":"https://github.com/rodrigobertotti/api-example-firebase-admin-nodejs","last_synced_at":"2025-06-19T12:37:41.096Z","repository":{"id":183602289,"uuid":"549832452","full_name":"RodrigoBertotti/api-example-firebase-admin-nodejs","owner":"RodrigoBertotti","description":"A Node.js REST API example that uses Firebase Admin, built with Express and Typescript that can be used as template for the creation of new servers.","archived":false,"fork":false,"pushed_at":"2024-06-17T15:36:02.000Z","size":265,"stargazers_count":27,"open_issues_count":0,"forks_count":7,"subscribers_count":1,"default_branch":"dev","last_synced_at":"2024-06-17T17:41:35.444Z","etag":null,"topics":["api","express","firebase","firebase-auth","firebase-auth-rest-api","firebase-authentication","firebase-rest-api","firestore","node","node-js","nodejs","nodejs-typescript","nodejs-typescript-template","rest-api","server"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RodrigoBertotti.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2022-10-11T20:07:59.000Z","updated_at":"2024-06-17T15:36:05.000Z","dependencies_parsed_at":"2023-12-12T15:45:16.754Z","dependency_job_id":null,"html_url":"https://github.com/RodrigoBertotti/api-example-firebase-admin-nodejs","commit_stats":null,"previous_names":["rodrigobertotti/api-example-firebase-nodejs"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RodrigoBertotti%2Fapi-example-firebase-admin-nodejs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RodrigoBertotti%2Fapi-example-firebase-admin-nodejs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RodrigoBertotti%2Fapi-example-firebase-admin-nodejs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RodrigoBertotti%2Fapi-example-firebase-admin-nodejs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RodrigoBertotti","download_url":"https://codeload.github.com/RodrigoBertotti/api-example-firebase-admin-nodejs/tar.gz/refs/heads/dev","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228041290,"owners_count":17860221,"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":["api","express","firebase","firebase-auth","firebase-auth-rest-api","firebase-authentication","firebase-rest-api","firestore","node","node-js","nodejs","nodejs-typescript","nodejs-typescript-template","rest-api","server"],"created_at":"2024-12-04T04:07:27.377Z","updated_at":"2024-12-04T04:07:28.081Z","avatar_url":"https://github.com/RodrigoBertotti.png","language":"TypeScript","readme":"# Firebase Admin NodeJS API Example\n\nA Node.js REST API example that uses Firebase Admin, built with Express and Typescript that can be used as template for the creation of new servers.\n\nThe main aspects of this sample are:\n\n- A project structure that fits well for new API projects that uses **Firebase Authentication** and **Firestore**\n- Access Control: Restricting routes access with custom claims and checking nuances\n- Reject a request outside the controller easily by throwing `new HttpResponseError(status, codeString, message)`\n- Logs: **winston** module is preconfigured to write `.log` files\n\n## Getting Started\n\n### Step 1 -Configure the Firebase Console\n\nIn the Firebase Console\n \nGo to Build \u003e Authentication \u003e Get Started \u003e Sign-in method \u003e Email/Password and enable Email/Password and save it.\n\nAlso go to Build \u003e Firestore Database \u003e Create database. You can choose the option `Start in test mode`.\n\n### Step 2 - Generate your `firebase-credentials.json` file\n\n1) Go to your Firebase Project \n2) Click on the engine icon (on right of \"Project Overview\")\n3) \"Project Settings\"\n4) \"Service Accounts\"\n5) \"Firebase Admin SDK\" and make sure the \"Node.js\" option is selected\n6) Click on \"Generate new private key\". Rename the downloaded file to `firebase-credentials.json` and move it to inside the\n`environment` folder. \n\n⚠️ Keep `firebase-credentials.json` and `environment.ts` local,\ndon't commit these files, keep both on `.gitignore`\n\nAs any Firebase server, the API has administrative privileges,\nthat means the API has full permission to perform changes on the Firestore Database (and\nother Firebase Resources) regardless of how the Firestore Security Rules are configured.\n\n### Step 3 - To test your server locally:\n\nThis command will start and restart your server as code changes are made,\ndo not use on production\n\n    npm run dev\n\nLet's run `npm install` to install the dependencies and `npm run dev` \nto start your server locally on port 3000.\n\n#### Other commands for the production environment\n\n#### To build your server:\n\n    npm run build\n\n#### To start your server\n\n    npm run start\n\n### Step 4 - Use Postman to test it\n\n1. In the Firebase Console \u003e Go to Project Overview and Click on the **Web** platform to Add a new Platform\n\n2. Add a Nickname like \"Postman\" and click on Register App\n\n3. Copy the **apiKey** field\n\n4. Import the **[postman_collection.json](postman_collection.json)** file to your Postman\n\n5. Test creating an account first, after that, go to the Login request \nexample and pass the `apiKey` as query parameter\n\n6. Copy the `idToken` and pass it as header for the other requests, the header name is `Authorization`.\n\n## Authentication\n\nFirebase Authentication is used to verify\nif the client is authenticated on Firebase Authentication,\nto do so, the client side should inform the `Authorization` header:\n\n### `Authorization` Header\n\nThe client's ID Token on Firebase Authentication in the format `Bearer \u003cidToken\u003e`,\nit can be obtained on the client side after the authentication is performed with the\nFirebase Authentication library for the client side. \nIt can be generated by the client side only.\n\n#### Option 1: Generating ID Token with Postman:\n\nFollow the previous instructions on [Step 4 - Use Postman to test it](#step-4---use-postman-to-test-it) and pass\nit as `Authorization` header value in the format `Bearer \u003cidToken\u003e`\n\n#### Option 2: Generating ID Token with a Flutter Client:\n```dart\nfinal idToken = await FirebaseAuth.instance.currentUser!.getIdToken();\n// use idToken as `Authorization` header value in the format \"Bearer \u003cidToken\u003e\"\n```\n\n#### Option 3: Generating ID Token with a Web Client:\n```javascript\nconst idToken = await getAuth(firebaseApp).currentUser?.getIdToken();\n// use idToken as `Authorization` header value in the format \"Bearer \u003cidToken\u003e\"\n```\n\n## Access Control\n\nThis project uses custom claims on Firebase Authentication to\ndefine which routes the users have access to.\n\n### Define custom claims to a user\n\nThis can be done in the server like below:\n```javascript\nawait admin.auth().setCustomUserClaims(user.uid, {\n    storeOwner: true,\n    buyer: false\n});\n```\n### Configuring the routes\n\nYou can set a param (array of strings) on the `httpServer.\u003cmethod\u003e`\nfunction, like:\n\n```javascript\nhttpServer.get (\n    '/product/:productId/full-details', \n    this.getProductByIdFull.bind(this), ['storeOwner']\n);\n```\n\nIn the example above, only users with the `storeOwner` custom claim will\nhave access to the `/product/:productId/full-details` path.\n\nIs this enough? Not always, so let's check the next section [Errors and permissions](#errors-and-permissions).\n\n## Errors and permissions\n\nYou can easily send an HTTP response with code between 400 and 500 to the client\nby simply throwing a `new HttpResponseError(...)` on your controller, service or repository,\nfor example:\n\n```javascript\nthrow new HttpResponseError(400, 'BAD_REQUEST', \"Missing 'name' field on the body\");\n```\n\nSometimes defining roles isn't enough to ensure that a user can't \naccess or modify a specific data,\nlet's imagine if a store owner tries to get full details\nof a product he is not selling, like a product of another store owner,\nhe still has access to the route because of his `storeOwner` custom claim,\nbut an additional verification is needed.\n\n```javascript\nif (product.storeOwnerUid != req.auth!.uid) {\n    throw new HttpResponseError(\n        403, \n        'FORBIDDEN', \n        `Even though you are a store owner,\n        you are a owner of another store,\n        so you can't see full details of this product`\n    );\n}\n```\n\n### 🚫 Permission errors\n\n- #### \"Only storeOwner can access\"\nMeans you are not logged with a `buyer` claim rather\nthan with a user that contains the  `storeOwner` claim.\n\n- #### \"You aren't the correct storeOwner\"\nMeans you are logged with the correct claim, but you are trying to read others storeOwner's data.\n\n- #### \"Requires authentication\"\n\n## Authentication fields on Express Request Handler\n\nThis project adds 3 new fields to the request object on the \nexpress request handler, \nyou can also customize this on `src/@types/express.d.ts` TypeScript file.\n\n### `req.authenticated` \ntype: `boolean`\n\nIs true only if the client is authenticated, which means, the client\ninformed `Authorization` on the headers, and these\nvalues were successfully validated.\n\n### `req.auth` \ntype: [UserRecord](https://firebase.google.com/docs/reference/admin/node/firebase-admin.auth.userrecord) | `null`\n\nIf authenticated: Contains user data of Firebase Authentication.\n\n### `req.token` \ntype: [DecodedIdToken](https://firebase.google.com/docs/reference/admin/node/firebase-admin.auth.decodedidtoken) | `null`\n\nIf authenticated: Contains token data of Firebase Authentication.\n\n## Logs\n\nYou can save logs into a file by importing these functions of the `src/utils/logger.ts` file\nand using like:\n```javascript\nlog(\"this is a info\", \"info\");\nlogDebug(\"this is a debug\");\nlogInfo(\"this is a info\");\nlogWarn(\"this is a warn\");\nlogError(\"this is a error\");\n```\nBy default, a `logs` folder will be generated\naside this project folder, in this structure:\n\n    - /api-example-firebase-nodejs\n    --- /node_modules/*\n    --- /src/*\n    --- (and more)\n\n    - /logs\n    --- /api-example-firebase-nodejs\n    ------ 2022-8-21.log\n    ------ 2022-8-22.log\n    ------ 2022-8-23.log\n    ------ (and more)\n\nEach `.log` file contains the logs of the respective day.\n\nYou can also go to `src/utils/logger.ts` and check `logsFilename` and `logsPathAndFilename` fields\nto change the default path and filename so the logs can be saved with a different filename and\nin a different location.\n\nBy default, regardless of the log level, all logs will be saved in the same file,\nyou can also change this behavior on the `winston.createLogger(transports: ...)` line of \nthe `src/utils/logger.ts` file. \n\n## Getting in touch\n\nFeel free to open a GitHub issue about:\n\n- :grey_question: questions\n\n- :bulb: suggestions\n\n- :ant: potential bugs\n\n## License\n\n[MIT](LICENSE)\n\n## Reference\n\nThis project used as reference part of the structure of the GitHub project [node-typescript-restify](https://github.com/vinicostaa/node-typescript-restify).\nThank you [developer](https://github.com/vinicostaa/)!\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frodrigobertotti%2Fapi-example-firebase-admin-nodejs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frodrigobertotti%2Fapi-example-firebase-admin-nodejs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frodrigobertotti%2Fapi-example-firebase-admin-nodejs/lists"}