Proxy Firestore with Firebase User Credentials

See the full example project on Github

This sample demonstrates how to expose Firestore documents through a REST API using the Zuplo URL Rewrite Handler and the Firebase User Auth Policy.

1/ Create Route

Create a route that uses the URL Rewrite Handler. The rewrite points to the Firestore REST API.

In this example, a POST request will accept an {name} parameter in the URL and a body for a new document. This document will be scoped to the authenticated user. The request will be mapped to the Firestore REST API endpoint to create a document.

{
  "/todos/{name}": {
    "post": {
      "x-zuplo-route": {
        "corsPolicy": "none",
        "policies": {
          "inbound": [
            "set-user",
            "firebase-user-auth"
          ]
        },
        "handler": {
          "module": "$import(@zuplo/runtime)",
          "export": "urlRewriteHandler",
          "options": {
            "rewritePattern": "https://firestore.googleapis.com/v1/projects/${env.FIREBASE_PROJECT}/databases/(default)/documents/todos/${request.user.sub}/${params.name}"
          }
        }
      },
      "operationId": "51985ae4-9cf9-4fbd-a617-ecb4e648b8f1"
    }
  }
}

2/ Add Authentication Policy

This demo uses a mock authentication policy that is a custom policy. This policy just takes the value of the user-id header and sets the authenticated user to that value. A real API would use the API Key or one of the JWT policies to authenticate the user.

{
  "name": "set-user",
  "policyType": "custom-code-inbound",
  "handler": {
    "export": "default",
    "module": "$import(./modules/set-user)"
  }
}

3/ Add Policy

The Firebase User Auth Policy will create an token for the current user that will be added to the outgoing request's Authorization header. This token is scoped to a specific user so any Firebase rules that are in place will be enforced.

{
  "name": "firebase-user-auth",
  "policyType": "upstream-firebase-user-auth-inbound",
  "handler": {
    "module": "$import(@zuplo/runtime)",
    "export": "UpstreamFirebaseUserAuthInboundPolicy",
    "options": {
      "serviceAccountJson": "$env(SERVICE_ACCOUNT_JSON)",
      "userIdPropertyPath": ".sub",
      "webApiKey": "$env(WEB_API_KEY)"
    }
  }
}

4/ Set Environment Variables

There are two environment variables used in the sample:

  • SERVICE_ACCOUNT_JSON - The Firebase Service Account token
  • FIREBASE_PROJECT - The Firebase project ID
  • WEB_API_KEY - The Firebase web api key

5/ Call the API

The API can now be called to retrieve a document from Firestore.

curl -X POST https://API_URL/todos/my-doc-name
   -H "Content-Type: application/json"
   -H "Authorization: user123"
   -d '{"fields": { "name": { "stringValue": "my-list" } } }'

Response:

{
  "name": "projects/project-demo-8/databases/(default)/documents/todos/user123/list1/U7HlIJnAJdKDJeaF8Bmn",
  "fields": {
    "name": {
      "stringValue": "my-list"
    }
  },
  "createTime": "2023-06-02T18:17:39.041624Z",
  "updateTime": "2023-06-02T18:17:39.041624Z"
}