1

Firestore is amazing for creating serverless applications but I'm currently trying to use firestore as the primary system for my REST API. I'd like to be able to create sessions using a rest endpoint and passing token's to and from the client. I'd like to be able to use these tokens to make Authenticated calls and have firebase auth automatically handle database rules through the rules I've set as if I were using the firestore client sdk.

I am familiar with Firebase Admin but for obvious reasons I can't use that for Authenticated requests, at least not directly. I was wondering if there was a "Firebase-Admin" where I can pass a token.

Dharmaraj
  • 47,845
  • 8
  • 52
  • 84
DucksEatTurtles
  • 194
  • 1
  • 2
  • 10

1 Answers1

1

Yes, there is Firebase Admin SDK which supposed to be used in secure environments like Cloud functions or your own server. It uses a service account and has full access to your Firebase project's resources and does not obey any security rules.

That being said you need to manually authenticate your users and check if they are allowed to access the resource that they are requesting. You must pass the Firebase ID Token in your REST API requests in headers or body (I usually pass it in authorization header as 'Bearer <firebase_id_token>'). You must not pass the UID of user itself under any circumstances.

Follow these steps to get Admin SDK up and running:

1. Installing the Admin SDK:

npm install firebase-admin
# yarn add firebase-admin

2. Create a middleware to verify the ID Tokens:

const express = require("express")
const app = express()
const admin = require("firebase-admin")

admin.initializeApp(...) // <-- use the service account to initialize

app.use(async function(req, res, next) {
  const {authorization} = req.headers
  if (!authorization) return res.sendStatus(401)
  const decodedToken = await admin.auth().verifyIdToken(authorization)
  console.log(decodedToken)
  next()
})

// other endpoints

app.listen(3000)

The decodedToken contains user's UID, custom claims and other metadata. You can read more about that in the documentation.

You can download your Service Account Key from here: https://console.firebase.google.com/project/_/settings/serviceaccounts/adminsdk

Firebase generates the ID Token (Access Token) and a Refresh Token when a user logs in. You just need to pass that access token in your request. You can use the getIdToken method to get it.

async function callAPI() {
  const idToken = await firebase.auth().currentUser.getIdToken()
  const response = await fetch("url", {headers: {authorization: idToken}})
}
Dharmaraj
  • 47,845
  • 8
  • 52
  • 84
  • that's exactly what I needed, could you elaborate on how to get that token (with firebase admin?). My frontend devs would like endpoint {username, password} -> return token -> request {token: 1234567} – DucksEatTurtles Jul 17 '21 at 17:39
  • @DucksEatTurtles you don't use Admin SDK to generate tokens. You get them from the client SDK itself. `const idToken = await firebase.auth().getIdToken()`. This will be a JWT (lives for around an hour) and Firebase refreshes them for you. All you have to do is when you need to call the API, get the token using the line of code above and add it in your fetch request. I'll update the same in my answer. – Dharmaraj Jul 17 '21 at 17:41
  • so the reason we're trying to go this route is to avoid the annoying onAuthStateChanged parameter as while working with a redux provider it causes a lot of issues where we have to wrap entire components in onAuthStateChanged. Your solution should be sufficient though, thank you! – DucksEatTurtles Jul 17 '21 at 17:42
  • 1
    @DucksEatTurtles using the auth listener is upto you. That's not necessary to use the getIdToken method. Check the update answer, I've added an example. – Dharmaraj Jul 17 '21 at 17:44
  • your answer is just about perfect but just for reference I believe you need to call getIdToken on the currentUser field of auth -> firebase.auth().currentUser.getIdToken(). Regardless, thanks for the answer! – DucksEatTurtles Jul 17 '21 at 20:07