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
Inject the Firebase SDK into your project head
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.
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 };1415 // Initialize and expose globally for workflow JS actions16 window.firebaseApp = firebase.initializeApp(firebaseConfig);17 window.firebaseAuth = firebase.auth();18 window.firebaseDb = firebase.firestore();1920 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.
Install and configure the Token-based Auth plugin
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.
Build the login workflow with Firebase Auth REST
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.
1// REST API Request body (JSON)2// Set in the Body field of the REST API Request action3// Injection point: Workflow action body (login page button workflow)4{5 "email": "{{formContainer.formData.email}}",6 "password": "{{formContainer.formData.password}}",7 "returnSecureToken": true8}Expected result: Submitting the login form authenticates the user and navigates to the dashboard. The Token-based Auth plugin stores the idToken.
Create Firestore REST API collections
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.
1// Firestore REST API collection config (reference)2// Method: GET3// URL: https://firestore.googleapis.com/v1/projects/YOUR_PROJECT_ID/databases/(default)/documents/items4// Headers:5// Authorization: Bearer {{plugins['token-based-auth'].idToken}}6// Result key: documents78// To write a document, use a workflow REST API Request action:9// Method: POST10// URL: https://firestore.googleapis.com/v1/projects/YOUR_PROJECT_ID/databases/(default)/documents/items11// 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.
Track Firebase auth state with a workflow
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.
1// Injection point: App-level workflow → On app load → Custom JavaScript action2// Purpose: Initialize Firebase auth state listener34return 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: idToken14 };15 // Store in WeWeb variable using the wwLib global16 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.
Implement Firebase sign-out
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.
1// Injection point: Button click workflow → Custom JavaScript action (sign-out)2await window.firebaseAuth.signOut();3// Next workflow step: Token-based Auth - Logout action4// Next workflow step: Navigate to login page5return { 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.
Restrict pages to authenticated users
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
1// Injection point: App-level workflow → On app load → Custom JavaScript action2// Full Firebase auth state management for WeWeb + Firebase integration3// Prerequisites: Firebase SDK injected in App Settings → Custom Code → Head45return new Promise((resolve, reject) => {6 // Ensure Firebase is initialized7 if (!window.firebaseAuth) {8 console.error('Firebase Auth not initialized. Check head script injection.');9 return resolve({ user: null, error: 'Firebase not initialized' });10 }1112 // 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 init1617 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.refreshToken28 };2930 // Persist to window for workflow access31 window.currentFirebaseUser = userData;3233 // Update WeWeb Token-based Auth plugin token34 // This keeps the plugin in sync with Firebase's auto-refreshed token35 if (typeof wwLib !== 'undefined' && wwLib.wwPlugins) {36 const authPlugin = wwLib.wwPlugins.tokenBasedAuth;37 if (authPlugin) {38 await authPlugin.updateToken(idToken);39 }40 }4142 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 user49 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.
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.
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.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation