Firebase Cloud Functions - Function triggered when user logged in [duplicate] - android

I see how execute a Cloud Function on user account creation:
exports.myFunction = functions.auth.user().onCreate(event => {
But I need my function to execute when the user logs in. Is there a onLogin trigger?
And can someone with 1500 points create a tag for firebase-cloud-functions?

There's no event for login, because only the client side can define exactly when a login happens. Different clients may define this in different ways. If you need to trigger something on login, figure out when that point is in your app, then trigger it from the client via a database or HTTP function.

This worked in the controller:
firebase.auth().onAuthStateChanged(function(user) { // this runs on login
if (user) { // user is signed in
console.log("User signed in!");
$scope.authData = user;
firebase.database().ref('userLoginEvent').update({'user': user.uid}); // update Firebase database to trigger Cloud Function
} // end if user is signed in
else { // User is signed out
console.log("User signed out.");
}
}); // end onAuthStateChanged
And this is the trigger in the Cloud Function:
exports.getWatsonToken = functions.database.ref('userLoginEvent').onUpdate(event => { // authentication trigger when user logs in
I made a location in Firebase Database called userLoginEvent.
One confusing bit is that in the functions console it's /userLoginEvent but in your code you must leave out the slash.

You can create your own analytics event, like login and used it as the trigger for your cloud function.
Then in your app, when the user successfully authenticate you use firebase analytics to send an event with the name you defined, like login
exports.sendCouponOnPurchase = functions.analytics.event('login').onLog((event) => {
const user = event.user;
const uid = user.userId; // The user ID set via the setUserId API.
});

You can trigger an https onCall firebase cloud function on login
ex: This is your login button trigger function which calls an https onCall function after authenticating the user.
_login() {
firebase
.auth()
.signInWithEmailAndPassword(this.state.email, this.state.password)
.then(function (user) {
var addMessage = firebase.functions().httpsCallable('myCloudFunctionName');
addMessage("whatever variable I want to pass")
.catch(error => {
console.log("I triggered because of an error in addMessage firebase function " + error)
)}
}).catch(error => {
console.log(error);
});
}

There is also another way you can do this inside Google Cloud if you enable Identity Platform for a project. Then you can follow this guide:
https://cloud.google.com/functions/docs/calling/logging
And trigger cloud functions for any of these Firebase Authentication events:
https://cloud.google.com/identity-platform/docs/activity-logging?authuser=1&_ga=2.226566175.-360767162.1535709791#logged_operations
The only problem I've just noticed is that the logs generated for Sign In event do not include the firebase app id or anything to determine which client the user logged in on which is really annoying as this was the main reason we needed to do this!

Related

Firebase google auth automatically selecting user. How to force it to pop up gmail accounts

I want to let the user select his gmail while loging in second time but it is taking previous one and not letting the user change his gmail.
Firebase google auth automatically selecting user. How to force it to select account
This question explains my problem correctly but the solutions given are outdated (I think).
I'm working on react-native android app.
here is my code for sign in and sign out
login: async () => {
try {
// Get the users ID token
const {idToken} = await GoogleSignin.signIn();
// Create a Google credential with the token
const googleCredential =
auth.GoogleAuthProvider.credential(idToken);
/* auth.GoogleAuthProvider.setCustomParameters({
prompt: 'select_account', //setCustomParameters is not a function(Error says)
}); */
// Sign-in the user with the credential
return auth().signInWithCredential(googleCredential);
} catch (e) {
console.log(e);
}
},
logout: async () => {
try {
await auth().signOut();
// await GoogleSignin.signOut(); //not working
} catch (e) {
console.error(e);
}
},
There is not proper article on how to use setCustomParameters() in this case.
Note: sometimes it is asking to select gmail when more than one account is logged in(that too rarely).
I want to show popup to change(add another) gmail even when one account is logged in.
Any help is greatly appreciated
Thank you.
Finally this worked for me in signout function.
await GoogleSignin.revokeAccess(); // added now
await auth().signOut();

How to perform Firebase scheduled function only if value from realtime database is equal X?

I'm starting my adventure with Firebase cloud functions in my adnroid app in Android Studio and I have no experience with it. What is more I have never used javascript before so everything seems to be new for me. I would like to know if I can make a scheduled function that works like this :
At first function checks if value from realtime databse isn't zero.
If not, function checks if another value from realtime database is not bigger than 7.
If not, the value in database is increased by 1.
And then the notification is send.
I made test function to check if data from database are taken corectly but it execute with error "Firebase is not defined".
exports.scheduledFunction = functions.pubsub.schedule('every 5 minutes').onRun((context) => {
var user = user.uid;
var myRef = firebase.database().ref(user + "/CurrentChallenge/numOfActiveChallenge");
myRef.on('value', (snapshot) => {
const data = snapshot.val();
console.log(data);
});
In a Cloud Function, if you want to interact with the Firebase services, you need to use the Admin SDK.
Also, if you want to read a database node in a Cloud Function, it is more appropriate to read once the node (with get() or once()) instead of setting a listener with on(). As a matter of fact the CF has a short life time and setting a listener is therefore not the correct approach.
It is nor clear how you get the value of the user variable. There is no user in a Scheduled Cloud Function. You need to adapt this line, because, as such it will not work.
Finally, it is important to note that you need to terminate a Cloud Function when all the asynchronous work is completed, see the doc. In the case of a background triggered Cloud Function (e.g. a Pub/Sub schedules Cloud Function) you must return the entire chain of promises returned by the asynchronous method calls. Another possibility is to use async/await, as shown below, and return a value (e.g. null) when all the asynchronous work is completed.
So, the following code skeleton should do the trick:
// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require('firebase-functions');
// The Firebase Admin SDK to access Firestore.
const admin = require('firebase-admin');
admin.initializeApp();
exports.scheduledFunction = functions.pubsub.schedule('every 5 minutes').onRun(async (context) => {
var user = ... // Set the value of user
const db = admin.database(); // Admin SDK
const snapshot1 = await db.database().ref("...").get();
if (snapshot1.val() !== 0) {
const snapshot2 = await db.database().ref("...").get();
if (snapshot2.val() <= 7) {
await db.ref("...").update({
fieldName: firebase.database.ServerValue.increment(1)
});
//send the notification
// See https://github.com/firebase/functions-samples/blob/main/fcm-notifications/functions/index.js
} else {
return null;
}
} else {
return null;
}
});
Cloud functions are secure environment just like any server. Generally you use the Firebase Admin SDK when using Firebase in Cloud functions or your own servers. To add firebase admin, open terminal and go to the function directory and run the following command:
npm install firebase-admin
The important thing to note is admin sdk doesn't obey any database security rules as the name says. It has privileged access.
You can try the following code.
const admin = require("firebase-admin")
admin.initializeApp()
exports.scheduledFunction = functions.pubsub.schedule('every 5 minutes').onRun(async (context) => {
const myRef1Value = (await admin.database().ref("path/to/resoures").once("value")).val()
if (myRef1Value > 0) {
//make another request
}
}
Similarly make multiple requests as needed (sorry for throwing bunch of JS concepts but feel free to ask any queries)
Another thing I noticed is you are trying to get user ID in it. Scheduled Cloud Functions are not invoked by any user so you can't get any UID in that Cloud function. Can you clarify what is your use case so we can figure out a work around for this?
But what you want to achieve is simple chain if else statements and doing stuff.
You'll need to import and initialize the Firebase Admin SDK as shown here:
// The Firebase Admin SDK to access the database
const admin = require('firebase-admin');
admin.initializeApp();
With that, you can then use it with:
var myRef = admin.database().ref(user + "/CurrentChallenge/numOfActiveChallenge");
myRef.once('value', (snapshot) => {
...

How can I get Realtime update from firestore in my react-native application? I want to prevent multiple logs in from same user from different devices

I am working on one app in react-native. I want to do this kind of functionality.
1)When the user will log in from 1st device with their credential at that time I am storing device ID in my firestore database.
now, If the user will do sign in from 2nd device with the same credential at that time I am going to log out that user from 1st device. I have implemented that logic.
But the issue is this is not happening in real-time. When I will restart the 1st device's application at that time this logic works.
Is there any type of method that triggers when my database updates?
I want this logic to works immediately when the user logs in from another device with the same ID.
const onAuthStateChanged = async (user) => {
setUser(user);
if (user) {
//here i am checking for token
await firestore()
.collection('Users')
.doc(user.email)
.get()
.then((documentSnapshot) => {
const data_device = documentSnapshot.data();
if (device_id != data_device.device_token) {
alert('you are signned in other device'); //and if not as same then logout
logout();
}
});
}
if (inisiallizing) setInisiallizing(false);
};
The onAuthStateChanged only run when the authState changed (Login, logout, register) and its state is run on it own (not run in multiple environment, devices).
As your usecase, I think you should listen to a documents on Firestore that store your deviceId
firestore()
.collection('Users')
.doc(user.email)
.onSnapshot((doc) => {
// Your logic to logout here
})
The above code will run everytime document firestore().collection('Users').doc(user.email) has update

How to maintain session in React Native Apps?

Can anybody tell me how to maintain session for a user login. For example when the user sign-in to an application they have to be signed in unless the user logouts or uninstall the application.
Use AsyncStorage.
Example:
For save:
AsyncStorage.multiSet([
["email", userInfo.email],
["password", userInfo.password]
])
For Delete:
let keys = ['email', 'password'];
AsyncStorage.multiRemove(keys, (err) => {
console.log('Local storage user info removed!');
});
For Get:
AsyncStorage.multiGet(['email', 'password']).then((data) => {
let email = data[0][1];
let password = data[1][1];
if (email !== null)
//Your logic
});
Important - password should be encrypted
Normally,there will be a session duration maintained in the server.Like for example say 1 hour.So every time when the app launches,call the login api and create a session.When the user first login,save the email and password in NSUserDefaults and whenever the session expires,the next api call will return a session specific error code (say like for example:401 error),Then get the values from NSUserDefaults and login automatically.
Also clear the NSUserDefaults and all other user related values on logout.

Firebase facebook popup returns null onAuth

My firebase facebook popup login on ionic was working correctly but suddenly it stop working (well, i was modifiying the app but i didnt touch the service). The process still works on browser (when i use ionic serve) but not running on ionic app.
var auth = $fAuth(ref);
// login with Facebook
auth.$onAuth(function(authData){ // authData -> null
console.log("Auth..", authData); // Auth.. null
/* refresh user data on firebase and registering push */
});
auth.$authWithOAuthPopup("facebook").catch(function(error) {
console.log("Authentication failed:", error);
});
When it was working, $onAuth cb function was recieving an object in authData variable with properties like uid and facebook.
when i run:
ref.authWithOAuthPopup("facebook",function(){console.log(arguments)})
or:
ref.authWithOAuthPopup("twitter",function(){console.log(arguments)})
the callback function never fires.
I run the auth process on $ionicPlatform.ready event.
I already uninstalled and reinstalled the app, and cleaned app data.
thanks!
Are you sure it doesn't fire?
A callback function that will be called when authentication has completed. On failure, the first argument will be an Error object indicating the failure, with a machine-readable code attribute. On success, the first argument will be null and the second will be an object containing the fields uid (the unique user id), provider (string identifying the provider), auth (the auth. token payload), and expires (expiration time in seconds since the Unix epoch) - and more, depending upon the provider used to authenticate.
You didn't put the arguments there.
I think it should work if you try it again.
Example code from firebase:
ref.authWithOAuthPopup("facebook", function(error, authData) {
// ^^^^^ ^^^^^^^^
if (error) {
console.log("Login Failed!", error);
} else {
console.log("Authenticated successfully with payload:", authData);
}
});

Categories

Resources