Feature: I want to automatically sign in with the user's profile if he or she successfully signed-in the previous web session.
Problem: I'm getting "No Firebase App" error in my React project while trying to execute firebase.auth(). The main firebase object initialization is triggered at the end of my index.js file with firebase.initializeApp(firebaseConfig). From what I can gather the firebase instance isn't properly initialized while executing authentication portion of code. Nomrally I would expect to perform the auth on the callback from the init function but there's none. So my question is what would be the best place to do the aforementioned automatic authentication/signing-in during the webpage load? Currently the authentication is performed on componentDidMount which obviously doesn't do the trick...
componentDidMount = () => {
if (localStorage.getItem("auth") == "google")
this.authenticate();
};
authenticate = () => {
var provider = new firebase.auth.GoogleAuthProvider();
firebase // <- exception
.auth()
.signInWithPopup(provider)
.then(function (result) {
// #ts-ignore
var token = result.credential.accessToken;
user = result.user;
localStorage.setItem("auth", "google");
Add in the body of your index.html:
<!-- Firebase App (the core Firebase SDK) is always required and must be listed first -->
<script src="https://www.gstatic.com/firebasejs/8.1.1/firebase-app.js"></script>
<!-- Add analytics if you need them -->
<script src="https://www.gstatic.com/firebasejs/8.1.1/firebase-analytics.js"></script>
<!--Add firebase dependencies you need (here i added auth and firestore) -->
<script src="https://www.gstatic.com/firebasejs/8.1.1/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.1.1/firebase-firestore.js"></script>
<script>
// TODO: Replace the following with your app's Firebase project configuration
// For Firebase JavaScript SDK v7.20.0 and later, `measurementId` is an optional field
var firebaseConfig = {
// ... You can find config in settings, scroll down and click on cdn
// I use cdn since it allows both external and firebase hosting
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
</script>
Then you are ready to go
Related
I have a React TS browser app with Azure Functions back end that I am trying to implement WebSockets in using Azure Web PubSub.
Following the guide at https://learn.microsoft.com/en-us/azure/azure-web-pubsub/tutorial-serverless-notification?tabs=csharp I can get the Azure Functions to Web PubSub side working, but in the example the client page is within the Azure Functions app. The following code snippets are from the guide.
Azure Function for negotiating PubSub connection and getting access token:
[FunctionName("negotiate")]
public static WebPubSubConnection Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
[WebPubSubConnection(Hub = "notification")] WebPubSubConnection connection,
ILogger log)
{
log.LogInformation("Connecting...");
return connection;
}
Simple client page:
<html>
<body>
<h1>Azure Web PubSub Notification</h1>
<div id="messages"></div>
<script>
(async function () {
let messages = document.querySelector('#messages');
let res = await fetch(`${window.location.origin}/api/negotiate`);
let url = await res.json();
let ws = new WebSocket(url.url);
ws.onopen = () => console.log('connected');
ws.onmessage = event => {
let m = document.createElement('p');
m.innerText = event.data;
messages.appendChild(m);
};
})();
</script>
</body>
</html>
I run this locally on http://localhost:7071 and can successfully negotiate, connect to the WS, and display messages.
If I try and connect my React front end app (http://localhost:3000), I can still hit the negotiate function in my function app, but then get a CORS error when trying to connect to the WS.
Presumably I could handle the negotiate within the React app, but that would mean storing the Azure PubSub access token in React. Any better way to do this?
have any of you used Azure authentication? Link: https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-spa-sign-in?tabs=react, I have a problem logging out. Logging in takes place in the Account microtext and the logout button is in the header, which is a separate frontend. When I want to log out I use this code:
let myStorage = window.localStorage;
let homeAccountId = myStorage.homeAccountId;
async function logout(e) {
const currentAccount = instance.getAccountByHomeId(homeAccountId);
await instance.logoutRedirect({
account: currentAccount,
postLogoutRedirectUri: "/account",
});
}
and I get an error: AuthError.js: 27 Uncaught (in promise) BrowserConfigurationAuthError: stubbed_public_client_application_called: Stub instance of Public Client Application was called. If using msal-react, please ensure context is not used without a provider. For more visit: aka.ms/msaljs/browser-errors
I am trying to upgrade from earlier firebase version to the latest in my ionic project. I followed this tutorial for upgrade. In step 4 from this page I am stuck on the last statement firebase.database().ref();.
Error message
TypeError: firebase.database is not a function
Below is my code. Kindly help.
...
// Initialize Firebase
this.config = {
apiKey: "some-api-key",
authDomain: "myapp.firebaseapp.com",
databaseURL: "https://myapp.firebaseio.com",
storageBucket: "project-somenumber.appspot.com",
};
...
this.authWithOAuthPopup = function(type) {
var deferred = $q.defer();
console.log(service.config); // ---> Object {apiKey: "some-api-key", authDomain: "myapp.firebaseapp.com", databaseURL: "https://myapp.firebaseio.com", storageBucket: "project-somenumber.appspot.com"}
firebase.initializeApp(service.config);
console.log(firebase); // ---> Object {SDK_VERSION: "3.0.5", INTERNAL: Object}
service.rootRef = firebase.database().ref(); //new Firebase("https://rsb2.firebaseio.com"); ---> I am getting error on this line "TypeError: firebase.database is not a function"
service.rootRef.authWithOAuthPopup(type, function(error, authData) {
if (error) {
service.authError = error;
switch (error.code) {
case "INVALID_EMAIL":
console.log("The specified user account email is invalid.");
break;
case "INVALID_PASSWORD":
console.log("The specified user account password is incorrect.");
break;
case "INVALID_USER":
console.log("The specified user account does not exist.");
break;
default:
console.log("Error logging user in:", error);
}
deferred.resolve(service.authError);
} else {
service.authData = authData;
console.log("Authenticated successfully with payload:", authData);
deferred.resolve(service.authData);
}
return deferred.promise;
});
return deferred.promise;
}
var service = this;
Update
After adding latest database library this questions problem is solved.
Updating my code here
this.authWithOAuthPopup = function(type) {
var deferred = $q.defer();
console.log(service.config);
firebase.initializeApp(service.config);
console.log(firebase);
service.rootRef = firebase.database(); //.ref(); //new Firebase("https://rsb2.firebaseio.com");
var provider = new firebase.auth.FacebookAuthProvider();
firebase.auth().signInWithRedirect(provider);
firebase.auth().getRedirectResult().then(function(result) {
if (result.credential) {
// This gives you a Facebook Access Token. You can use it to access the Facebook API.
var token = result.credential.accessToken;
console.log(result);
// ...
}
// The signed-in user info.
var user = result.user;
}).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
// ...
});
return deferred.promise;
}
I ran into this with Ionic and it turned out that I wasn't including everything when using the latest Firebase Client. If you've included Firebase as firebase-app, then the Database and Auth pieces need to be required separately since they aren't bundled when including Firebase in this way.
Add the following to your index.html after you include firebase-app.js
<script src="https://www.gstatic.com/firebasejs/3.1.0/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/3.1.0/firebase-database.js"></script>
Obviously you don't need to use the CDN, you could use bower (probably the preferred way with Ionic) or NPM with Browserify.
// Browserify Setup
var firebase = require('firebase/app');
require('firebase/auth');
require('firebase/database');
Snippet below taken from the Firebase Web Setup Docs
You can reduce the amount of code your app uses by just including the features you need. The individually installable components are:
firebase-app - The core firebase client (required).
firebase-auth - Firebase Authentication (optional).
firebase-database - The Firebase Realtime Database (optional).
firebase-storage - Firebase Storage (optional).
From the CDN, include the individual components you need (include firebase-app first)
A bit late to the party, but in case some one wanted to know the syntax in angular, (or Ionic 4) just add this to your .module.ts file (Note, as peterb mentioned, the /database import)
import { AuthService } from './auth.service';
import { AngularFireAuthModule } from 'angularfire2/auth';
import { AngularFireDatabaseModule } from 'angularfire2/database';
#NgModule({
imports: [
AngularFireAuthModule,
AngularFireDatabaseModule,
AngularFireModule.initializeApp(environment.firebase),
],
providers: [
]
})
i solved this issue by giving the url in the constructor
firebase.database('https://123.firebaseio.com')
First, make sure you are using
<script src="https://www.gstatic.com/firebasejs/3.1.0/firebase.js"></script>
Firebase authWithOAuthPopup has changed a little bit in the new version.
Now you don't use the ref to call authentication methods. You should be using firebase.auth() insted.
var auth = firebase.auth();
var provider = new firebase.auth.TwitterAuthProvider();
auth.signInWithPopup(provider).then(function(result) {
// User signed in!
var uid = result.user.uid;
}).catch(function(error) {
// An error occurred
});
Also faced this problem on #angular/firebase 5.1.2, solved when updated #angular/cli and all dependencies to the latest version.
For people facing similar error(this._database.native.on is not a function) in React-native -
run the pod install - after adding firebase new service(database/auth ...)
terminate the metro bundler and restart it using "npx react-native start"
run "npx react-native run-ios"
This will create a new build and the error should be gone.
Ref: https://github.com/invertase/react-native-firebase/issues/3379
Use
var firebase = require('firebase/app');
require('firebase/database');
npm install --save firebase
Then:
require("firebase/database");
You need to add all of the firebase products you are using by way of require() as shown above.
I have the same error -firebase.database is not a function- but with different situation you just need to add
above and the link of javascript that contain the Firebase configuration.
You may also try to use the defer Attribute in your script as it will not load the scripts until page elements are loaded.
I'm working on an app that uses the Twilio Programmable Chat API using node.js and angular js. I have enabled push configuration inside twilio chat instance. And i have created push credentilals in twilio with the firebase secret key. After this i have fetched the twilio token using chatGrant with the twilio credential sid. I have included the firebase.js file and initialised firebase. After this I got permission from user to show notification. This all works fine. But when I am trying to get device token to register with chatclientinstance, it is getting failed.
Here is my code which initialising the firebase and taking permission,
var config = {
apiKey: "my_key",
authDomain: "example.firebaseapp.com",
databaseURL: "https://example.firebaseio.com",
projectId: "example",
storageBucket: "example.appspot.com",
messagingSenderId: "861813283864"
};
if (firebase) {
firebase.initializeApp(config);
console.log("firbase initialized.");
}
if (firebase && firebase.messaging()) {
// requesting permission to use push notifications
firebase.messaging().requestPermission().then(() => {
// getting FCM token
console.log("got permission for showing notification.");
firebase.messaging().getToken().then((fcmToken) => {
// continue with Step 7 here
console.log("got fcm token.",fcmToken);
// ...
// ...
}).catch((err) => {
// can't get token
console.log("error in getting token for notification.",err);
});
}).catch((err) => {
// can't request permission or permission hasn't been granted to the web app by the user
console.log("error in getting permission for notification.",err);
});
} else {
// no Firebase library imported or Firebase library wasn't correctly initialized
console.log("no Firebase library imported or Firebase library wasn't correctly initialized");
}
}
I got this in console,
firbase initialized.
got permission for showing notification.
The script has an unsupported MIME type ('text/html').
Failed to load resource: net::ERR_INSECURE_RESPONSE firebase-messaging-sw.js
error in getting token for notification.
e {code: "messaging/failed-serviceworker-registration", message: "Messaging: We are unable to register the default s…). (messaging/failed-serviceworker-registration).", browserErrorMessage: "Failed to register a ServiceWorker: The script has an unsupported MIME type ('text/html').", stack: "FirebaseError: Messaging: We are unable to registe…o/polyfills.bundle.js:3152:35)↵ at <anonymous>"}
I have did everything as twilio docs says at PUSH NOTIFICATIONS ON WEB
But I did not added "firebase-messaging-sw.js" in my server. Is there any need to add this js file or twilio will automatically create and initialise it?
Please find me a solution for this. Thanks in advance.
I found this confusing too, since the docs don't explain what the notification support actually does. The code you included (from their chat SDK docs) only does two basic things:
client.setPushRegistrationId('fcm', fcmToken) makes sure the browser is registered with the FCM service and requests Twilio Programmable Chat notifications.
messaging.onMessage(function(payload{client.handlePushNotification(payload);}); seems to do very little--it simply lets the Chat client emit an event when FCM receives a message.
What it does not do, though, is create a service that listens for notifications. That's where the missing file comes in. First, create this file, firebase-messaging-sw.js somewhere. I used the following example from the Firebase docs:
// firebase sample code snippets from https://firebase.google.com/docs/cloud-messaging/js/client
importScripts('https://www.gstatic.com/firebasejs/5.0.4/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/5.0.4/firebase-messaging.js');
// Initialize the Firebase app in the service worker by passing in the essagingSenderId.
console.log("Initializing service worker...");
firebase.initializeApp({
messagingSenderId: "<FILL IN FROM YOUR FIREBASE CONFIG>"
});
// Retrieve an instance of Firebase Messaging so that it can handle background messages.
var messaging = firebase.messaging();
// Listen for push messages and create notifications
messaging.setBackgroundMessageHandler(function(payload) {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Customize notification here
var notificationTitle = "My Notification Title";
var notificationOptions = {
body: "My Notification Text"
};
return self.registration.showNotification(notificationTitle, notificationOptions);
});
This is a basic service worker that listens for notifications and then displays them.
Next, from the error message, you might have noticed that FCM is looking for this file to be served from your web root directory. If that's not the case, tweak your Twilio code slightly to look for this service worker at a specified URL (from https://stackoverflow.com/a/41701594/4006592):
var messaging = firebase.messaging();
if (messaging) {
navigator.serviceWorker.register("<URL FOR firebase-messaging-sw.js>").then(function(registration) {
messaging.useServiceWorker(registration);
// requesting permission to use push notifications
messaging.requestPermission().then(function() {
...
});
});
}
With the above change, you can explicitly specify where firebase-messaging-sw.js is located, and FCM/Twilio Chat will then work as expected.
I start to learn how to use firebase in my app. I follow the instruction in angular website and set the snippet in the index.html like:
<!-- The codes to add firebase -->
<script src="https://www.gstatic.com/firebasejs/3.2.0/firebase.js"></script>
<!-- The core firebase client (required) -->
<script src="https://www.gstatic.com/firebasejs/3.1.0/firebase-app.js"></script>
<!-- firebase-auth - Firebase Authentication (optional) -->
<script src="https://www.gstatic.com/firebasejs/3.1.0/firebase-auth.js"></script>
<!-- firebase-database - The Firebase Realtime Database (optional) -->
<script src="https://www.gstatic.com/firebasejs/3.1.0/firebase-database.js"></script>
<script>
var config = {
apiKey: ...,
authDomain: ...,
databaseURL: "https://...",
storageBucket: "...",
};
firebase.initializeApp(config);
</script>
And then I try to use HTTP request to put data like:
submitForm(personalInfo: PersonalInfo, educationsInfo: Education[], experiencesInfo: Experience[]): Observable<string>{
let body = JSON.stringify({personalInfo, educationsInfo, experiencesInfo});
let headers = new Headers({'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers});
console.log(body);
let url = this.firebaseUrl + 'apply-form.json';
return this.http.put(url, body)
.map((response) => {
return response;
})
.catch(this.handleError);
}
However, I got the following error:
PUT https://XXX.firebaseio.com/apply-form.json 401 (Unauthorized)
I don't know what the problem is. I'm new in using firebase and really need someone to help me. Thank you!
Your Firebase Database is by default only writeable by authenticated users. See the warning in the first blue box on the page on saving data to the database.
To work around this you can of course configure the security rules of your database to allow public access. But while that is typically fine during development, it's a bad idea as you get your app ready for release to people other than yourself.
The proper way to post data securely is to require the user to sign in with Firebase Authentication and then use that information to ensure they can only access data that they're authorized to. By using HTTP to access the Firebase Database, you've made this more difficult for yourself than needed. I recommend using the Firebase JavaScript SDK for both authentication and accessing the database.