Skip to main content
RapidDev - Software Development Agency
weweb-tutorial

WeWeb Firebase Integration: Auth, Firestore, and Manual Setup

WeWeb has no native Firebase plugin. You connect Firebase manually by injecting the Firebase JavaScript SDK into your project head, using the REST API plugin for Firestore CRUD, the Token-based Auth plugin for Firebase Auth, and Custom JavaScript workflow actions to manage authentication state. This advanced setup takes about 45 minutes and works for both Firestore and Firebase Auth.

What you'll learn

  • How to inject the Firebase JavaScript SDK into WeWeb via App Settings → Custom Code → Head
  • How to use the Token-based Auth plugin with Firebase Authentication REST endpoints
  • How to create REST API collections that query Firestore via the REST API
  • How to manage Firebase auth state using Custom JavaScript workflow actions and page variables
  • When to use Firebase versus the native Supabase plugin for WeWeb projects
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Advanced11 min read40-60 minWeWeb Free plan and above; Firebase Spark (free) or Blaze planMarch 2026RapidDev Engineering Team
TL;DR

WeWeb has no native Firebase plugin. You connect Firebase manually by injecting the Firebase JavaScript SDK into your project head, using the REST API plugin for Firestore CRUD, the Token-based Auth plugin for Firebase Auth, and Custom JavaScript workflow actions to manage authentication state. This advanced setup takes about 45 minutes and works for both Firestore and Firebase Auth.

Manual Firebase Integration in WeWeb

Unlike Supabase, Firebase has no native WeWeb plugin — there is no one-click OAuth connection. You must integrate it manually using three WeWeb systems working together: the App Settings Custom Code head injection for the Firebase SDK, the Token-based Auth plugin for handling Firebase login/logout, and the REST API plugin for Firestore database operations. This tutorial covers all three layers and explains the significant limitations compared to native integrations. If you are evaluating backends for a new WeWeb project, consider Supabase first — but if you already have a Firebase project or need Firebase-specific features like Firebase Storage or Firebase Cloud Messaging, this tutorial shows you the full manual path.

Prerequisites

  • A WeWeb project open in the editor
  • A Firebase project created at console.firebase.google.com with Firestore and Authentication enabled
  • Your Firebase project's web configuration object (apiKey, authDomain, projectId, etc.)
  • Firebase Authentication enabled with Email/Password sign-in method activated
  • Firestore security rules configured to require authentication for private data

Step-by-step guide

1

Inject the Firebase SDK into your project head

In the WeWeb editor, click the gear icon in the left sidebar to open App Settings. Navigate to the 'Custom Code' tab. You will see two injection points: 'Head' and 'Body'. Click the 'Head' section. Paste the Firebase SDK script tags here. Use Firebase v9 compat scripts (CDN) to keep it simple without a build step. After the scripts, add a second script block that initializes Firebase with your project config and exposes the app instance on window for access from workflow JavaScript actions. Click Save. Note: Custom Code in the Head section is injected into every page of your application.

typescript
1<!-- Injection point: App Settings Custom Code Head -->
2<script src="https://www.gstatic.com/firebasejs/9.23.0/firebase-app-compat.js"></script>
3<script src="https://www.gstatic.com/firebasejs/9.23.0/firebase-auth-compat.js"></script>
4<script src="https://www.gstatic.com/firebasejs/9.23.0/firebase-firestore-compat.js"></script>
5<script>
6 const firebaseConfig = {
7 apiKey: "YOUR_API_KEY",
8 authDomain: "YOUR_PROJECT_ID.firebaseapp.com",
9 projectId: "YOUR_PROJECT_ID",
10 storageBucket: "YOUR_PROJECT_ID.appspot.com",
11 messagingSenderId: "YOUR_SENDER_ID",
12 appId: "YOUR_APP_ID"
13 };
14
15 // Initialize and expose globally for workflow JS actions
16 window.firebaseApp = firebase.initializeApp(firebaseConfig);
17 window.firebaseAuth = firebase.auth();
18 window.firebaseDb = firebase.firestore();
19
20 console.log('Firebase initialized');
21</script>

Expected result: After publishing and visiting your app, open browser dev tools Console — you should see 'Firebase initialized' logged.

2

Install and configure the Token-based Auth plugin

Open the Plugins panel in the left sidebar. Under 'Authentication', click 'Token-based Auth' and click Add. This plugin handles storing and refreshing authentication tokens for custom auth systems. In the plugin configuration, set the 'Get user endpoint' to the Firebase Auth getAccountInfo endpoint: `https://identitytoolkit.googleapis.com/v1/accounts:lookup?key=YOUR_API_KEY`. Set the 'Token key' field to `idToken` — this tells WeWeb which field in your login response contains the JWT. Set the 'User key' to `users.0` to extract the first user from the Firebase response. Set your 'Unauthenticated redirect page' to your login page. Note: This plugin will handle token storage and automatic injection — but Firebase token refresh (every hour) requires additional JavaScript (covered in Step 5).

Expected result: Token-based Auth plugin appears under Plugins → Authentication with status indicators.

3

Build the login workflow with Firebase Auth REST

Add a Form Container to your login page with email and password inputs and a submit button. Select the button and open the Workflows panel. Add a new workflow triggered 'On click'. Add a 'REST API Request' action. Set Method to POST, URL to `https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=YOUR_API_KEY`, and set the Body to a JSON object binding `email` to `formContainer.formData.email` and `password` to `formContainer.formData.password`, with `returnSecureToken` set to `true`. Add a second action: 'Token-based Auth - Login' — set the Token field to the `idToken` from the previous action's response (use formula: `actions[0].idToken`). Add a third 'Navigate to page' action pointing to your dashboard page. Add an error branch to display a login error message if the REST call fails.

typescript
1// REST API Request body (JSON)
2// Set in the Body field of the REST API Request action
3// Injection point: Workflow action body (login page button workflow)
4{
5 "email": "{{formContainer.formData.email}}",
6 "password": "{{formContainer.formData.password}}",
7 "returnSecureToken": true
8}

Expected result: Submitting the login form authenticates the user and navigates to the dashboard. The Token-based Auth plugin stores the idToken.

4

Create Firestore REST API collections

Open the Data panel and click '+ New'. Select 'REST API'. Configure a Firestore collection. The Firestore REST endpoint pattern is: `https://firestore.googleapis.com/v1/projects/YOUR_PROJECT_ID/databases/(default)/documents/YOUR_COLLECTION`. Set Method to GET. For the Authorization header, you need the user's Firebase idToken. Add header `Authorization` with value bound to a formula referencing the auth plugin token: `plugins.token-based-auth['idToken']`. Set Result key to `documents`. Each document in Firestore REST format has a `fields` object with typed values — for example a string field looks like `{ stringValue: 'hello' }`. You will need a formula to extract plain values: use `item.fields.title.stringValue` in your bindings. Name your collection 'firestore-items' and click Save.

typescript
1// Firestore REST API collection config (reference)
2// Method: GET
3// URL: https://firestore.googleapis.com/v1/projects/YOUR_PROJECT_ID/databases/(default)/documents/items
4// Headers:
5// Authorization: Bearer {{plugins['token-based-auth'].idToken}}
6// Result key: documents
7
8// To write a document, use a workflow REST API Request action:
9// Method: POST
10// URL: https://firestore.googleapis.com/v1/projects/YOUR_PROJECT_ID/databases/(default)/documents/items
11// Body:
12// {
13// "fields": {
14// "title": { "stringValue": "My Item" },
15// "createdAt": { "timestampValue": "2026-03-30T00:00:00Z" },
16// "userId": { "stringValue": "{{plugins['token-based-auth'].userId}}" }
17// }
18// }

Expected result: The Firestore collection fetches documents when the user is authenticated. Clicking Fetch in the Data panel returns the documents array.

5

Track Firebase auth state with a workflow

Firebase's onAuthStateChanged listener persists the user session across page refreshes — but the Token-based Auth plugin does not automatically hook into it. Create an App-level variable (Data panel → Variables → New → Object type, name it 'firebaseUser', default value null). Add an App-level workflow (Workflows panel → App workflows → New) with trigger 'On app load'. Add a 'Custom JavaScript' action. In the JS editor, register the onAuthStateChanged listener, extract the idToken from the current user, and store both in a window variable for use by other workflows. This ensures that if a user is already logged in (persistent session from a previous visit), WeWeb picks up their auth state.

typescript
1// Injection point: App-level workflow → On app load → Custom JavaScript action
2// Purpose: Initialize Firebase auth state listener
3
4return new Promise((resolve) => {
5 window.firebaseAuth.onAuthStateChanged(async (user) => {
6 if (user) {
7 // Get fresh idToken (refreshes automatically if expired)
8 const idToken = await user.getIdToken();
9 window.currentFirebaseUser = {
10 uid: user.uid,
11 email: user.email,
12 displayName: user.displayName,
13 idToken: idToken
14 };
15 // Store in WeWeb variable using the wwLib global
16 if (typeof wwLib !== 'undefined') {
17 wwLib.wwVariable.updateValue('YOUR_FIREBASE_USER_VARIABLE_ID', window.currentFirebaseUser);
18 }
19 } else {
20 window.currentFirebaseUser = null;
21 }
22 resolve({ user: window.currentFirebaseUser });
23 });
24});

Expected result: On every page load, Firebase auth state is checked. If a session exists, the firebaseUser variable is populated with uid, email, and a fresh idToken.

6

Implement Firebase sign-out

Add a sign-out button to your navigation. Select the button and add an 'On click' workflow. Add a 'Custom JavaScript' action that calls window.firebaseAuth.signOut(). Add a second action: 'Token-based Auth - Logout' to clear the stored token from the WeWeb auth plugin. Add a third 'Navigate to page' action pointing to your login page. Also add a 'Change variable value' action to reset your firebaseUser variable to null. Test sign-out by clicking the button and confirming the user is redirected to the login page and the auth token is cleared.

typescript
1// Injection point: Button click workflow → Custom JavaScript action (sign-out)
2await window.firebaseAuth.signOut();
3// Next workflow step: Token-based Auth - Logout action
4// Next workflow step: Navigate to login page
5return { success: true };

Expected result: Clicking sign-out clears the Firebase session, clears the WeWeb auth token, resets the user variable, and redirects to the login page.

7

Restrict pages to authenticated users

Go to the Pages panel and select a page that should be private. Open Page settings (gear icon when page is selected). Find the 'Access control' section. Set 'Access' to 'Only authenticated users' — this uses the Token-based Auth plugin to check if a valid token exists. Set the redirect page for unauthenticated users to your login page. Important security caveat: this page restriction is frontend-only. A user who bypasses JavaScript can still access the page URL. True security for your data must be enforced in Firebase Security Rules. In the Firebase Console → Firestore → Rules, ensure all private collections require `request.auth != null`.

Expected result: Unauthenticated users who navigate to a private page are redirected to the login page. Authenticated users can access the page normally.

Complete working example

firebase-auth-state.js
1// Injection point: App-level workflow → On app load → Custom JavaScript action
2// Full Firebase auth state management for WeWeb + Firebase integration
3// Prerequisites: Firebase SDK injected in App Settings → Custom Code → Head
4
5return new Promise((resolve, reject) => {
6 // Ensure Firebase is initialized
7 if (!window.firebaseAuth) {
8 console.error('Firebase Auth not initialized. Check head script injection.');
9 return resolve({ user: null, error: 'Firebase not initialized' });
10 }
11
12 // Listen for auth state changes (fires immediately with current state)
13 const unsubscribe = window.firebaseAuth.onAuthStateChanged(
14 async (user) => {
15 unsubscribe(); // Only need first emission for init
16
17 if (user) {
18 try {
19 // Get fresh ID token (auto-refreshes if within 5 min of expiry)
20 const idToken = await user.getIdToken(false);
21 const userData = {
22 uid: user.uid,
23 email: user.email,
24 emailVerified: user.emailVerified,
25 displayName: user.displayName || '',
26 idToken: idToken,
27 refreshToken: user.refreshToken
28 };
29
30 // Persist to window for workflow access
31 window.currentFirebaseUser = userData;
32
33 // Update WeWeb Token-based Auth plugin token
34 // This keeps the plugin in sync with Firebase's auto-refreshed token
35 if (typeof wwLib !== 'undefined' && wwLib.wwPlugins) {
36 const authPlugin = wwLib.wwPlugins.tokenBasedAuth;
37 if (authPlugin) {
38 await authPlugin.updateToken(idToken);
39 }
40 }
41
42 resolve({ user: userData });
43 } catch (err) {
44 console.error('Error getting Firebase token:', err);
45 resolve({ user: null, error: err.message });
46 }
47 } else {
48 // No authenticated user
49 window.currentFirebaseUser = null;
50 resolve({ user: null });
51 }
52 },
53 (error) => {
54 console.error('Firebase auth state error:', error);
55 reject({ error: error.message });
56 }
57 );
58});

Common mistakes

Why it's a problem: Using Firebase Admin SDK or service account credentials in the client-side head injection

How to avoid: Only use the Firebase client SDK (firebase-app-compat.js) and your web app's config object in the head. Never paste service account JSON or Admin SDK credentials — these give full database access and must stay server-side only.

Why it's a problem: Forgetting to set Firebase Security Rules — leaving Firestore open to all reads and writes

How to avoid: In Firebase Console → Firestore Database → Rules, configure rules before going live. At minimum: `allow read, write: if request.auth != null;`. WeWeb's page access control is frontend-only and not a security measure.

Why it's a problem: Binding the Authorization header directly to a hardcoded string instead of the dynamic token

How to avoid: The Firebase idToken expires every hour. Bind the Authorization header in your REST API collection to a formula referencing the live token variable (window.currentFirebaseUser.idToken), not a static value. Use a workflow action to refresh the token before sensitive operations.

Why it's a problem: Trying to use Supabase-style realtime subscriptions with Firebase in WeWeb

How to avoid: WeWeb has no built-in Firebase Realtime Database listener. Firestore's onSnapshot() listener requires persistent WebSocket connections that are difficult to manage in workflow-based architecture. Use polling (a workflow with Time Delay → Fetch collection loop) or consider switching to Supabase which has a native WeWeb realtime plugin.

Best practices

  • Use Firebase compat SDK (v9 compat) for head injection — it avoids module bundler requirements and works directly in browser scripts
  • Store the Firebase refreshToken in a secure page variable to implement token refresh — Firebase idTokens expire after 1 hour and must be refreshed using the securetoken.googleapis.com/v1/token endpoint
  • Prefer Supabase for new WeWeb projects — the native Supabase plugin handles auth, database, and realtime out of the box without manual SDK injection
  • Configure Firebase Security Rules in the Firebase Console (outside WeWeb) before any data goes live — rules like request.auth.uid == resource.data.userId prevent data leaks
  • Test Firestore REST calls in a tool like Postman before configuring WeWeb collections — confirm the endpoint, headers, and response structure first
  • Use the WeWeb formula window to inspect the Firestore REST response structure — Firestore wraps all field values in typed objects like { stringValue: 'text' } requiring formula extraction
  • For user signup, call the Firebase Auth REST accounts:signUp endpoint and immediately create a corresponding Firestore user profile document in the same workflow

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I'm building a WeWeb app with Firebase as the backend. I need to: 1) inject the Firebase SDK into the page head, 2) handle login/logout using Firebase Auth REST API, 3) fetch Firestore documents with the user's idToken in the Authorization header. Write the complete code and workflow configuration steps.

WeWeb Prompt

In my WeWeb project, I have the Firebase SDK injected in App Settings → Custom Code → Head and the Token-based Auth plugin installed. I want to create a login workflow that calls the Firebase Auth signInWithPassword endpoint and stores the idToken. What actions should I add to my button workflow and what formula should I use to extract the idToken from the REST API response?

Frequently asked questions

Why doesn't WeWeb have a native Firebase plugin like it does for Supabase?

WeWeb's team built a native plugin for Supabase because it is their recommended backend and many WeWeb users already use it. Firebase is a Google product with a more complex SDK and no REST-native auth flow — it requires SDK injection and manual state management. WeWeb officially recommends Supabase as the Firebase alternative for WeWeb projects.

Can I use Firebase Realtime Database (not Firestore) with WeWeb?

Yes, but with the same manual approach. The Firebase Realtime Database REST endpoint is `https://YOUR_PROJECT_ID.firebaseio.com/YOUR_PATH.json?auth=YOUR_TOKEN`. It returns plain JSON without Firestore's typed field wrappers, making it slightly easier to work with. However, realtime listeners (onValue) still require custom JavaScript and cannot be managed through WeWeb's built-in collection system.

How do I handle the 1-hour Firebase idToken expiry in WeWeb?

Call `await user.getIdToken(true)` in a Custom JavaScript action to force-refresh the token before any authenticated operation. Alternatively, set up a periodic workflow using a Time Delay action loop that calls getIdToken() every 50 minutes and updates your idToken variable. The Firebase SDK's onAuthStateChanged also fires with a refreshed token on each page load.

Is it safe to put my Firebase API key in the WeWeb Custom Code head section?

Yes — the Firebase web API key (apiKey in the config object) is intentionally public. It identifies your Firebase project but does not grant any permissions. Security is enforced entirely by Firebase Security Rules and Authentication. What you must never expose is a Firebase Admin SDK service account private key, which is a different credential entirely.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.