I am trying to create an authenticated website using FastAPI as a backend.
Because of my skills in JS, I am looking to limit as much as possible the use of javascript ans do as much as possible in HTML.
I created the following app in FastAPI.
app.py
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
app = FastAPI()
templates = Jinja2Templates(directory="templates")
#app.get("/index/", response_class=HTMLResponse)
async def index(request: Request):
return templates.TemplateResponse("index.html", context={"request": request})
I used the following page from the firebas ui doc to try to add the Firebase UI.
templates/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Sample FirebaseUI App</title>
<script src="https://www.gstatic.com/firebasejs/9.1.3/firebase-app-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/9.1.3/firebase-auth-compat.js"></script>
<!-- *******************************************************************************************
* TODO(DEVELOPER): Paste the initialization snippet from this dialog box:
* Firebase Console > Project Settings > Add App > Web.
***************************************************************************************** -->
<script type="module">
// Import the functions you need from the SDKs you need
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.6.11/firebase-app.js";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: "my-api-key",
authDomain: "my-auth-domain",
databaseURL: "my-database-url",
projectId: "my-project-id",
storageBucket: "hmy-storage-bucket",
messagingSenderId: "my-id",
appId: "my-app-id"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
</script>
<script src="https://www.gstatic.com/firebasejs/ui/6.0.1/firebase-ui-auth.js"></script>
<link type="text/css" rel="stylesheet" href="https://www.gstatic.com/firebasejs/ui/6.0.1/firebase-ui-auth.css" />
<script type="text/javascript">
// FirebaseUI config.
var uiConfig = {
signInSuccessUrl: 'www.google.com',
signInOptions: [
// Leave the lines as is for the providers you want to offer your users.
firebase.auth.GoogleAuthProvider.PROVIDER_ID,
// firebase.auth.FacebookAuthProvider.PROVIDER_ID,
// firebase.auth.TwitterAuthProvider.PROVIDER_ID,
// firebase.auth.GithubAuthProvider.PROVIDER_ID,
// firebase.auth.EmailAuthProvider.PROVIDER_ID,
// firebase.auth.PhoneAuthProvider.PROVIDER_ID,
// firebaseui.auth.AnonymousAuthProvider.PROVIDER_ID
],
// tosUrl and privacyPolicyUrl accept either url string or a callback
// function.
// Terms of service url/callback.
tosUrl: 'www.google.com',
// Privacy policy url/callback.
privacyPolicyUrl: function () {
window.location.assign('www.google.com');
}
};
// Initialize the FirebaseUI Widget using Firebase.
var ui = new firebaseui.auth.AuthUI(firebase.auth());
// The start method will wait until the DOM is loaded.
ui.start('#firebaseui-auth-container', uiConfig);
</script>
</head>
<body>
<!-- The surrounding HTML is left untouched by FirebaseUI.
Your app may use that space for branding, controls and other customizations.-->
<h1>Welcome to My Test App</h1>
<div id="firebaseui-auth-container"></div>
</body>
</html>
I replaced the confidential information to authenticate, but I have the following error when I connect to the index.html page on the browser.
error
firebaseNamespaceCore.ts:102 Uncaught FirebaseError: Firebase: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp() (app-compat/no-app).
at s (firebaseNamespaceCore.ts:102:27)
at Object.e [as auth] (firebaseNamespaceCore.ts:153:31)
at (index):116:54
Related
I am using Stripe in a web project and in a PHP file at a web hook URL (i.e. https://something/flutter_web/index.php) of Stripe, I am trying to access the Firebase database
in Javascript. But that does not do anything in the firebase database i.e. no entry recorded in Firebase. But if I just run the PHP file even in my localhost server, it works i.e. records an entry in the Firebase database.
MY full code in index.php follows:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Firebase app</title>
</head>
<body>
<h1>FIREBASE APP</h1>
<script type="module">
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.10.0/firebase-app.js";
import { getFirestore,collection, addDoc, getDocs, doc, setDoc } from "https://www.gstatic.com/firebasejs/9.10.0/firebase-firestore.js";
const firebaseConfig = {
apiKey: "...KGG7P0",
authDomain: "....2.firebaseapp.com",
projectId: "...e-81e62",
storageBucket: ".....appspot.com",
messagingSenderId: "..115",
appId: "....df3c8960b7a1b6"
};
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);
var product_id ='oooprod_MYeB8eh6i00qyz_ppppppppppp';
var product_info =JSON.parse('{"id":"prod_MYeB8eh6i00qyz","object":"product","active":true,"attributes":[],"created":1664973567,"default_price":"price_1LpWsoSCaGUwBkx9pFbkbJrh","description":"description for Demo 1111","images":[],"livemode":false,"metadata":[],"name":"Demo 1111","package_dimensions":null,"shippable":null,"statement_descriptor":null,"tax_code":null,"type":"service","unit_label":null,"updated":1664973572,"url":null}');
await setDoc(doc(db, "subscriptions", product_id), product_info);
</script>
</body>
</html>
How to make the code execute in the web hook URL ?
Hey everyone I am learning firebase phone authentication in web app. I have an error that I can not find the solution. I imported the browser module for firebase authentication as show in the first picture but when I checked the console I got an error that said my app not connected to firebase authentication module. How can I solve this problem ?
Import from firebase browser module
console error
I couldn't reproduce your error, but I was successful in connecting to the authentication module that can run, which is the point of the matter.
Steps:
Enable Phone Number sign-in for your Firebase project https://firebase.google.com/docs/auth/web/phone-auth#enable-phone-number-sign-in-for-your-firebase-project
Initialize Firebase
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.6.11/firebase-app.js";
// TODO: Replace the following with your app's Firebase project configuration
const firebaseConfig = {
apiKey: "A#######YOUR#API#KEY#BUT#RESPONSE##SUCCESSFULL###############",
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
Testing connection with the authentication module
// TEST MODULE AUTH
const auth = getAuth();
console.log("LOADED FIREBASE-AUTH", auth);
// overwrite DOM with the version used from response CDN
document.getElementById("content").innerHTML = auth.config.sdkClientVersion;
Some observations:
phoneAuth => make sure to import RecaptchaVerifier
https://firebase.google.com/docs/auth/web/phone-auth#use-invisible-recaptcha
`import { getAuth, RecaptchaVerifier } from "https://www.gstatic.com/firebasejs/9.6.11/firebase-auth.js";`
Well what I can deduce from the error, is as it says: internet disconnected.
It may also be related, here: Import firebase firestore from CDN JS not working Import firebase firestore from CDN JS not working.
I hope to be helpful!. Or can you provide more details if the error continues.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<!-- Add a container for reCaptcha -->
<button id="sign-in-button">sign-in-button</button>
<p id="content">SHOW INFO CONNEXION AUTH</p>
<script type="module">
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.6.11/firebase-app.js";
import { getAuth, RecaptchaVerifier } from "https://www.gstatic.com/firebasejs/9.6.11/firebase-auth.js";
// TODO: Replace the following with your app's Firebase project configuration
const firebaseConfig = {
apiKey: "A#######YOUR#API#KEY#BUT#RESPONSE##SUCCESSFULL###############",
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
// TEST MODULE AUTH
const auth = getAuth();
console.log("LOADED FIREBASE-AUTH", auth);
// overwrite DOM with the version used from response CDN
document.getElementById("content").innerHTML = auth.config.sdkClientVersion;
// phoneAuth => make sure to import RecaptchaVerifier
// Ref: https://firebase.google.com/docs/auth/web/phone-auth#use-invisible-recaptcha
window.recaptchaVerifier = new RecaptchaVerifier(
"sign-in-button",
{
size: "invisible",
callback: (response) => {
// reCAPTCHA solved, allow signInWithPhoneNumber.
// onSignInSubmit();
// ...
},
},
auth
);
</script>
</body>
</html>
I was trying to set firebase for and I follow all the procedures. But After running the app it went all white and showed this error
‘TypeError: Cannot read property ‘app’ of undefined’ In Flutter Web
I then went on to google to search for solution and did everything the way they asked but I ended up having the null safety error. After that I remove the null safety and this is now the error I am getting
Running with unsound null safety
For more information see https://dart.dev/null-safety/unsound-null-safety
Debug service listening on ws://127.0.0.1:57090/YI8fSoqgm_w=/ws
FirebaseError: Firebase: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp() (app/no-app).
at Object.u [as app] (https://www.gstatic.com/firebasejs/8.6.1/firebase-app.js:1:18836)
at Object.app$ [as app] (http://localhost:57026/packages/firebase_core_web/src/interop/core.dart.lib.js:31:101)
at new cloud_firestore_web.FirebaseFirestoreWeb.new (http://localhost:57026/packages/cloud_firestore_web/src/write_batch_web.dart.lib.js:934:64)
at Function.registerWith (http://localhost:57026/packages/cloud_firestore_web/src/write_batch_web.dart.lib.js:834:73)
at Object.registerPlugins (http://localhost:57026/packages/tembea/generated_plugin_registrant.dart.lib.js:18:46)
at main (http://localhost:57026/web_entrypoint.dart.lib.js:31:35)
at main.next (<anonymous>)
at runBody (http://localhost:57026/dart_sdk.js:40666:34)
at Object._async [as async] (http://localhost:57026/dart_sdk.js:40697:7)
at main$ (http://localhost:57026/web_entrypoint.dart.lib.js:30:18)
at http://localhost:57026/main_module.bootstrap.js:19:10
at Array.forEach (<anonymous>)
at window.$dartRunMain (http://localhost:57026/main_module.bootstrap.js:18:32)
at <anonymous>:1:8
at Object.runMain (http://localhost:57026/dwds/src/injected/client.js:8452:21)
at http://localhost:57026/dwds/src/injected/client.js:24130:19
at _wrapJsFunctionForAsync_closure.$protected (http://localhost:57026/dwds/src/injected/client.js:4461:15)
at _wrapJsFunctionForAsync_closure.call$2 (http://localhost:57026/dwds/src/injected/client.js:11511:12)
at Object._asyncStartSync (http://localhost:57026/dwds/src/injected/client.js:4425:20)
at main__closure3.$call$body$main__closure (http://localhost:57026/dwds/src/injected/client.js:24142:16)
at main__closure3.call$1 (http://localhost:57026/dwds/src/injected/client.js:24069:19)
at StaticClosure._rootRunUnary (http://localhost:57026/dwds/src/injected/client.js:4823:18)
at _CustomZone.runUnary$2$2 (http://localhost:57026/dwds/src/injected/client.js:12879:39)
at _CustomZone.runUnaryGuarded$1$2 (http://localhost:57026/dwds/src/injected/client.js:12826:14)
at _ForwardingStreamSubscription._sendData$1 (http://localhost:57026/dwds/src/injected/client.js:12416:19)
at _ForwardingStreamSubscription._add$1 (http://localhost:57026/dwds/src/injected/client.js:12362:15)
at _ForwardingStreamSubscription._add$1 (http://localhost:57026/dwds/src/injected/client.js:12695:12)
at _MapStream._handleData$2 (http://localhost:57026/dwds/src/injected/client.js:12756:12)
at _ForwardingStreamSubscription._handleData$1 (http://localhost:57026/dwds/src/injected/client.js:12721:20)
at Object.eval (eval at Closure_forwardCallTo (http://localhost:57026/dwds/src/injected/client.js:1701:14), <anonymous>:3:44)
at StaticClosure._rootRunUnary (http://localhost:57026/dwds/src/injected/client.js:4823:18)
at _CustomZone.runUnary$2$2 (http://localhost:57026/dwds/src/injected/client.js:12879:39)
at _CustomZone.runUnaryGuarded$1$2 (http://localhost:57026/dwds/src/injected/client.js:12826:14)
at _ControllerSubscription._sendData$1 (http://localhost:57026/dwds/src/injected/client.js:12416:19)
at _ControllerSubscription._add$1 (http://localhost:57026/dwds/src/injected/client.js:12362:15)
at _SyncStreamController._sendData$1 (http://localhost:57026/dwds/src/injected/client.js:12201:32)
at _SyncStreamController.add$1 (http://localhost:57026/dwds/src/injected/client.js:12082:15)
at Object.eval (eval at Closure_forwardInterceptedCallTo (http://localhost:57026/dwds/src/injected/client.js:1781:14), <anonymous>:3:45)
at StaticClosure._rootRunUnary (http://localhost:57026/dwds/src/injected/client.js:4823:18)
at _CustomZone.runUnary$2$2 (http://localhost:57026/dwds/src/injected/client.js:12879:39)
at _CustomZone.runUnaryGuarded$1$2 (http://localhost:57026/dwds/src/injected/client.js:12826:14)
at _ControllerSubscription._sendData$1 (http://localhost:57026/dwds/src/injected/client.js:12416:19)
at _ControllerSubscription._add$1 (http://localhost:57026/dwds/src/injected/client.js:12362:15)
at _SyncStreamController._sendData$1 (http://localhost:57026/dwds/src/injected/client.js:12201:32)
at _SyncStreamController.add$1 (http://localhost:57026/dwds/src/injected/client.js:12082:15)
at _GuaranteeSink.add$1 (http://localhost:57026/dwds/src/injected/client.js:23581:25)
at HtmlWebSocketChannel_closure1.call$1 (http://localhost:57026/dwds/src/injected/client.js:23874:60)
at _EventStreamSubscription_closure.call$1 (http://localhost:57026/dwds/src/injected/client.js:18042:26)
at StaticClosure._rootRunUnary (http://localhost:57026/dwds/src/injected/client.js:4829:16)
at _CustomZone.runUnary$2$2 (http://localhost:57026/dwds/src/injected/client.js:12879:39)
at _CustomZone.runUnaryGuarded$1$2 (http://localhost:57026/dwds/src/injected/client.js:12826:14)
at _CustomZone_bindUnaryCallbackGuarded_closure.call$1 (http://localhost:57026/dwds/src/injected/client.js:13016:25)
at invokeClosure (http://localhost:57026/dwds/src/injected/client.js:1524:26)
at WebSocket.<anonymous> (http://localhost:57026/dwds/src/injected/client.js:1543:18)
Below is my main function
void main() async{
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MyApp());
And the pubspec
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
flutter_signin_button: ^2.0.0
firebase_auth: ^3.1.4
firebase_core: ^1.8.0
cloud_firestore: ^2.5.4
provider: ^6.0.1
firebase_analytics: ^7.0.1
Finally the index.html
<!DOCTYPE html>
<html>
<head>
<!--
If you are serving your web app in a path other than the root, change the
href value below to reflect the base path you are serving from.
The path provided below has to start and end with a slash "/" in order for
it to work correctly.
For more details:
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
This is a placeholder for base href that will be replaced by the value of
the `--base-href` argument provided to `flutter build`.
-->
<base href="$FLUTTER_BASE_HREF">
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="A new Flutter project.">
<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="tembea">
<link rel="apple-touch-icon" href="icons/Icon-192.png">
<title>tembea</title>
<link rel="manifest" href="manifest.json">
</head>
<body>
<!-- This script installs service_worker.js to provide PWA functionality to
application. For more information, see:
https://developers.google.com/web/fundamentals/primers/service-workers -->
<script>
var serviceWorkerVersion = null;
var scriptLoaded = false;
function loadMainDartJs() {
if (scriptLoaded) {
return;
}
scriptLoaded = true;
var scriptTag = document.createElement('script');
scriptTag.src = 'main.dart.js';
scriptTag.type = 'application/javascript';
document.body.append(scriptTag);
}
if ('serviceWorker' in navigator) {
// Service workers are supported. Use them.
window.addEventListener('load', function () {
// Wait for registration to finish before dropping the <script> tag.
// Otherwise, the browser will load the script multiple times,
// potentially different versions.
var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion;
navigator.serviceWorker.register(serviceWorkerUrl)
.then((reg) => {
function waitForActivation(serviceWorker) {
serviceWorker.addEventListener('statechange', () => {
if (serviceWorker.state == 'activated') {
console.log('Installed new service worker.');
loadMainDartJs();
}
});
}
if (!reg.active && (reg.installing || reg.waiting)) {
// No active web worker and we have installed or are installing
// one for the first time. Simply wait for it to activate.
waitForActivation(reg.installing || reg.waiting);
} else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) {
// When the app updates the serviceWorkerVersion changes, so we
// need to ask the service worker to update.
console.log('New service worker available.');
reg.update();
waitForActivation(reg.installing);
} else {
// Existing service worker is still good.
console.log('Loading app from service worker.');
loadMainDartJs();
}
});
// If service worker doesn't succeed in a reasonable amount of time,
// fallback to plaint <script> tag.
setTimeout(() => {
if (!scriptLoaded) {
console.warn(
'Failed to load app from service worker. Falling back to plain <script> tag.',
);
loadMainDartJs();
}
}, 4000);
});
} else {
// Service workers not supported. Just drop the <script> tag.
loadMainDartJs();
}
</script>
<script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-analytics.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-firestore.js"></script>
<script type="module">
// Import the functions you need from the SDKs you need
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.2.0/firebase-app.js";
import { getAnalytics } from "https://www.gstatic.com/firebasejs/9.2.0/firebase-analytics.js";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
apiKey: "AIzaSyAQYkB8TMTJKMmdzmjVQwsyiQrfMaXqOao",
authDomain: "tembea-4d3c6.firebaseapp.com",
projectId: "tembea-4d3c6",
storageBucket: "tembea-4d3c6.appspot.com",
messagingSenderId: "909705170922",
appId: "1:909705170922:web:d034fefe33c9d0d2026c93",
measurementId: "G-11NNW6J10N"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);
</script>
</body>
</html>
I do not know what I may have done wrong. Any help would be welcomed.
You have two seperate imports for Firebase, which may cause issues. Remove your <script type="module">... import...</script> and replace it with the different style of initialization like this:
<script>
const firebaseConfig = {
apiKey: "AIzaSyAQYkB8TMTJKMmdzmjVQwsyiQrfMaXqOao",
authDomain: "tembea-4d3c6.firebaseapp.com",
projectId: "tembea-4d3c6",
storageBucket: "tembea-4d3c6.appspot.com",
messagingSenderId: "909705170922",
appId: "1:909705170922:web:d034fefe33c9d0d2026c93",
measurementId: "G-11NNW6J10N"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
</script>
This is currently recommended way that can be found in Flutter Firebase docs.
Since you are initializing Firebase in the main function you may also want to move your app startup script below the script of Firebase initialization.
I'm trying to run my mobile flutter app on web, i think i did all of the config i needed to do but i get the error: "FirebaseError: Firebase: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp() (app/no-app)." Does anyone know what should i do to fix it? I am initializing the firebase in main, i couldn't find what else i can do.
Here is my main.dart:
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:untitled1/quiz_app/sign_in.dart';
void main() async{
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MaterialApp(
//initialRoute: '/SignIn',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.indigo
),
routes: {
'/SignIn' :(context) => SignInPage(),
},
home: Scaffold(
resizeToAvoidBottomInset: false,
body: SignInPage()
),
));
}
And here is index.html:
<!DOCTYPE html>
<html>
<head>
<!--
If you are serving your web app in a path other than the root, change the
href value below to reflect the base path you are serving from.
The path provided below has to start and end with a slash "/" in order for
it to work correctly.
For more details:
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
This is a placeholder for base href that will be replaced by the value of
the `--base-href` argument provided to `flutter build`.
-->
<base href="$FLUTTER_BASE_HREF">
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="A new Flutter project.">
<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="ahmett">
<link rel="apple-touch-icon" href="icons/Icon-192.png">
<title>ahmett</title>
<link rel="manifest" href="manifest.json">
</head>
<body>
<!-- The core Firebase JS SDK is always required and must be listed first -->
<script src="https://www.gstatic.com/firebasejs/8.6.8/firebase-app.js"></script>
<!-- TODO: Add SDKs for Firebase products that you want to use
https://firebase.google.com/docs/web/setup#available-libraries -->
<script src="https://www.gstatic.com/firebasejs/8.6.8/firebase-analytics.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.6.8/firebase-storage.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.6.8/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.6.8/firebase-firestore.js"></script
<script>
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
var firebaseConfig = {
apiKey: "cencored",
authDomain: "cencored",
projectId: "cencored",
storageBucket: "cencored",
messagingSenderId: "cencored",
appId: "cencored",
measurementId: "cencored"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
firebase.analytics();
</script>
</script><script src="main.dart.js" type="application/javascript"></script>
</body>
</html>
For Flutter web, There is a new setup for Firebase Plugins.
First of All, follow all the steps mentioned here https://firebase.flutter.dev/docs/installation/web
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>example</title>
</head>
<body>
<script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-messaging.js"></script>
<script>
// Your web app's Firebase configuration
var firebaseConfig = {
apiKey: "...",
authDomain: "[YOUR_PROJECT].firebaseapp.com",
databaseURL: "https://[YOUR_PROJECT].firebaseio.com",
projectId: "[YOUR_PROJECT]",
storageBucket: "[YOUR_PROJECT].appspot.com",
messagingSenderId: "...",
appId: "1:...:web:...",
measurementId: "G-...",
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
</script>
<script src="main.dart.js" type="application/javascript"></script>
<script>
var serviceWorkerVersion = null;
var scriptLoaded = false;
function loadMainDartJs() {
if (scriptLoaded) {
return;
}
scriptLoaded = true;
var scriptTag = document.createElement('script');
scriptTag.src = 'main.dart.js';
scriptTag.type = 'application/javascript';
document.body.append(scriptTag);
}
if ('serviceWorker' in navigator) {
// Service workers are supported. Use them.
window.addEventListener('load', function () {
//register firebase-messaging service worker
navigator.serviceWorker.register("/firebase-messaging-sw.js");
// Wait for registration to finish before dropping the <script> tag.
// Otherwise, the browser will load the script multiple times,
// potentially different versions.
var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion;
navigator.serviceWorker.register(serviceWorkerUrl)
.then((reg) => {
function waitForActivation(serviceWorker) {
serviceWorker.addEventListener('statechange', () => {
if (serviceWorker.state == 'activated') {
console.log('Installed new service worker.');
loadMainDartJs();
}
});
}
if (!reg.active && (reg.installing || reg.waiting)) {
// No active web worker and we have installed or are installing
// one for the first time. Simply wait for it to activate.
waitForActivation(reg.installing ?? reg.waiting);
} else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) {
// When the app updates the serviceWorkerVersion changes, so we
// need to ask the service worker to update.
console.log('New service worker available.');
reg.update();
waitForActivation(reg.installing);
} else {
// Existing service worker is still good.
console.log('Loading app from service worker.');
loadMainDartJs();
}
});
// If service worker doesn't succeed in a reasonable amount of time,
// fallback to plaint <script> tag.
setTimeout(() => {
if (!scriptLoaded) {
console.warn(
'Failed to load app from service worker. Falling back to plain <script> tag.',
);
loadMainDartJs();
}
}, 4000);
});
} else {
// Service workers not supported. Just drop the <script> tag.
loadMainDartJs();
}
</script>
</body>
</html>
View this setup at
https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_messaging/firebase_messaging/example/web
In my app, for the web version, I use package firebase 7.3.0.
I first instantiate Firebase app with a singleton and then instantiate Messaging() as I have done with all other Firebase services I use in my app :
App firebase = FirebaseWeb.instance.app;
var firebaseMessaging = messaging();
I have subscribeToTopic() method which first calls getMessagingToken() method as it needs the returned token, but getMessagingToken() throws the error:
PlatformPushNotificationWeb.getMessagingToken() getToken error: FirebaseError: Messaging: We are unable to register the default service worker. Failed to register a ServiceWorker for scope ('http://localhost:5000/firebase-cloud-messaging-push-scope') with script ('http://localhost:5000/firebase-messaging-sw.js'): A bad HTTP response code (404) was received when fetching the script. (messaging/failed-service-worker-registration). (messaging/failed-service-worker-registration)
Future<String> getMessagingToken() async {
String token;
await firebaseMessaging.requestPermission().timeout(Duration(seconds: 5)).then((value) {
print('PlatformPushNotificationWeb.getMessagingToken() requestPermission result is $value');
}).catchError((e) => print('PlatformPushNotificationWeb.getMessagingToken() requestPermission error: $e'));
await firebaseMessaging.getToken().then((value) {
print(' PlatformPushNotificationWeb.getMessagingToken() token is $value');
token = value;
}).catchError((e) => print('PlatformPushNotificationWeb.getMessagingToken() getToken error: $e'));
return token;
}
I checked and in my index.html firebase-messaging is present:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>fixit cloud biking</title>
<!-- <meta name="google-signin-client_id" content="YOUR_GOOGLE_SIGN_IN_OAUTH_CLIENT_ID.apps.googleusercontent.com">-->
<meta name="google-signin-client_id" content="xxxxxxxxxx.apps.googleusercontent.com">
<!-- <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">-->
</head>
<!--<body>-->
<body id="app-container">
<script src="main.dart.js?version=45" type="application/javascript"></script>
<!-- The core Firebase JS SDK is always required and must be listed first -->
<script src="https://www.gstatic.com/firebasejs/7.15.5/firebase-app.js"></script>
<!-- TODO: Add SDKs for Firebase products that you want to use
https://firebase.google.com/docs/web/setup#available-libraries -->
<script src="https://www.gstatic.com/firebasejs/7.15.5/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.15.5/firebase-analytics.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.15.5/firebase-messaging.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.15.5/firebase-storage.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.15.5/firebase-database.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.15.5/firebase-remote-config.js"></script>
</body>
</html>
Now, the error says 'http://localhost:5000/firebase-messaging-sw.js' not firebase-messaging.js as the library in the index.htmlfile. I noticed that Messaging()is not directly available through firebase app instance as it would be for other services, for Storage would befirebase.storage()`.
Am I missing to setup something else for messaging?
Found this article https://medium.com/#rody.davis.jr/how-to-send-push-notifications-on-flutter-web-fcm-b3e64f1e2b76 and discovered that indeed there is a bit more setup for Firebase Cloud Messaging on web.
In index.html there is a script to add:
<script>
if ("serviceWorker" in navigator) {
window.addEventListener("load", function () {
// navigator.serviceWorker.register("/flutter_service_worker.js");
navigator.serviceWorker.register("/firebase-messaging-sw.js");
});
}
</script>
In project web folder create a new file firebase-messaging-sw.js where you import the firebase packages (match index.html versions), initialize Firebase app , and set the BackgroundMessageHandler.
If I initialize Firebase app with the singleton then instantiating messaging() throws a syntax error, so it needs to be initialized with all parameters, otherwise on background messages won't work.
importScripts("https://www.gstatic.com/firebasejs/7.15.5/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/7.15.5/firebase-messaging.js");
//Using singleton breaks instantiating messaging()
// App firebase = FirebaseWeb.instance.app;
firebase.initializeApp({
apiKey: 'api-key',
authDomain: 'project-id.firebaseapp.com',
databaseURL: 'https://project-id.firebaseio.com',
projectId: 'project-id',
storageBucket: 'project-id.appspot.com',
messagingSenderId: 'sender-id',
appId: 'app-id',
measurementId: 'G-measurement-id',
});
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function (payload) {
const promiseChain = clients
.matchAll({
type: "window",
includeUncontrolled: true
})
.then(windowClients => {
for (let i = 0; i < windowClients.length; i++) {
const windowClient = windowClients[i];
windowClient.postMessage(payload);
}
})
.then(() => {
return registration.showNotification("New Message");
});
return promiseChain;
});
self.addEventListener('notificationclick', function (event) {
console.log('notification received: ', event)
});
So now, getToken() and subscribeToTopic() and onMessage() work as expected.
In my bloc I have a listener on onMessage() which (on web) Stream I convert to a Stream<Map<String,Dynamic>> as the firebase_messaging(on device) returns from :
Stream<Map<String, dynamic>> onMessage() async* {
print('PlatformPushNotificationWeb.onMessage() started');
handleData(Payload payload, EventSink<Map<String, dynamic>> sink) {
Map<String,dynamic> message = {
'notification': {
'title': payload.notification.title,
'body': payload.notification.body,
'sound': true
},
'data': payload.data
};
sink.add(message);
}
final transformer = StreamTransformer<Payload, Map<String, dynamic>>.fromHandlers(
handleData: handleData);
yield* firebaseMessaging.onMessage.transform(transformer);
}
Hope it helps others.
Cheers.
It turns out you can just create a file called firebase-messaging-sw.js in your web project folder and have some commented out JavaScript in it and then Flutter stops complaining.
Also modify index.html with this:
<script>
if ('serviceWorker' in navigator) {
window.addEventListener("load", function () {
navigator.serviceWorker.register("firebase-messaging-sw.js");
});
window.addEventListener('flutter-first-frame', function () {
navigator.serviceWorker.register('flutter_service_worker.js');
});
}
I really don't know why this works, but it's better than having some useless JavaScript code laying around.
As of December 2022, just creating an empty firebase-messaging-sw.js file at the root of the web directory in your flutter app will fix the issue.
Before that you of course follow the steps to add Firebase to your app: https://firebase.google.com/docs/flutter/setup
dart pub global activate flutterfire_cli
flutterfire configure
Then
In your lib/main.dart file, import the Firebase core plugin and the configuration file you generated earlier:
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
Finally
Also in your lib/main.dart file, initialize Firebase using the DefaultFirebaseOptions object exported by the configuration file:
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);