Event triggered when changing a user Firebase Authentication - javascript

Detect events from a user Firebase Authentication
In my application developed in Angular along with Node.js and Firebase I need to detect events occurring in users. As inclusion, change and exclusion.
Is there a way to detect when a user is deleted, changed, or inserted through a function created in Cloud Functions?
I know that you can detect database events with a function created in Cloud Functions. I would like to detect when a user is changed, deleted or entered when the operation is done through Firebase Console > Project > Authentication.
Something in that sense:
exports.userChanged = functions.user
.onCreate((snapshot, context) => {})
OnDelete()
OnCreate()
OnChange()
What is the best way to do this?

There is onCreate and onDelete, you can read it from the docs.
For the update case, you should rely on the RTD. Actually, you could rely completely on the RTD.
//Create a user on the rtd
functions.auth.user().onCreate((user) => {
return usersRef.child(user.uid).set(user);
});
//Update the user by listening to a change on the RTD
functions.database.ref('/users/{uid}')
.onWrite((change, context) => {
//If you needed it you can update the user
admin.auth().updateUser(uid, {
});
//if some condition, then delete it
admin.auth().deleteUser(uid)
//do more
});
Using the update user option you can even disable the account, take a look at this other answer
You can use the admin sdk inside of Functions directly, this is the doc

Related

Firebase how to createUserWithEmailAndPassword and a user record at the same time?

Using Firebase, I'd like to do the following:
Create a new user using FirebaseAuth (using createUserWithEmailAndPassword)
Create a record for this new user in FireStore, where the document ID = user ID (adding fields such as name, role, gender etc.)
The problem is that once createUserWithEmailAndPassword is successful, an authStateChanges is triggered, and It's impossible to create the user record now...
How can I achieve this rather basic flow using Firebase's API?
Can I only achieve that using the Firebase Admin SDK?
The problem is that once createUserWithEmailAndPassword is successful, an authStateChanges is triggered, and It's impossible to create the user record now...
Generally you would unsubscribe from the observer if you want to run some actions after registration like this:
const unsub = onAuthStateChanged(...);
const register = async () => {
unsub(); // observer will not trigger on state changes
// create user
// add document to Firestore
}
Alternatively, you can use Firebase Authentication Triggers to create document for user using Cloud Functions.

Firebase user's details change listener in Javascript

so if a user logs into your app, you can check that by
firebase.auth().onAuthStateChanged((user)=>{});
but if the user is already logged in and his user has a property change, how do you see that?
in my case, I have the user verify his email address and when done, he should be able to see a change instantly on his app after verifying his email. So I am using react native, which is pretty much javascript with ES6 syntax in it and I am doing a firebase.auth().onAuthStateChanged(); but its not working, I even have a button on the screen that checks if verified like this:
if (!firebase.auth().currentUser.emailVerified) { firebase.auth().currentUser.sendEmailVerification(); }
else if (firebase.auth().currentUser.emailVerified) { this.setState({ showVerifier: false }); }
but even that isn't working, as if the firebase.auth().currentUser doesn't update if the email is verified, what can be done here?
As far as I understand your question, I would like to give you an idea.
I think onAuthStateChanged() gets triggered only when your Auth State Changes (login, logout) and not when the user properties change.
As they have mentioned in the documentation,
Adds an observer for changes to the user's sign-in state. Prior to
4.0.0, this triggered the observer when users were signed in, signed out, or when the user's ID token changed in situations such as token
expiry or password change. After 4.0.0, the observer is only triggered
on sign-in or sign-out.
function isVerified(){
var user = firebase.auth().currentUser;
if(user != null){
var status = user.emailVerified;
if(status)
{
// Verified
}else{
// Not Verified
}
}
else{
// User didn't login!
}
}
So, you have to manually check it by defining a function like above and you can call this function when the user clicks the button
If you are using react-native-firebase (highly recommended, since it is supports the latest firebase features), you can listen on user changes as stated in this doc
From the doc
Adds a listener to observe changes to the User object. This is a superset of everything from auth#onAuthStateChanged, auth#onIdTokenChanged and user changes. The goal of this method is to provide easier listening to all user changes, such as when credentials are linked and unlinked, without manually having to call User#reload.
onUserChanged(listener: AuthListenerCallback): () => void;

How multi-tab logout can be managed in reactJS?

window.addEventListener('storage', e => {
if(e.key === 'access_token' && e.oldValue && !e.newValue) {
store.dispatch(userSignOut());
}
})
If this is a suitable solution, then where(lifecycle event) should i paste this?
The best way to do that is by using the BrodcastChannel feature in Javascript. The Broadcast Channel API allows simple communication between browsing contexts (that is windows, tabs, frames, or iframes) with the same origin (usually pages from the same site).
For example:
// Connecting to a broadcast channel
const userChannel = new BroadcastChannel('user');
function signOut() {
// and after that, we have to broadcast a message to the user channel which user has signed out from the application as below:
userChannel.postMessage({
userId: "", // If the user opened your app in multi-tabs and signed-in with multi accounts, you need to put the userId here to identify which account has signed out exactly
payload: {
type: "SIGN_OUT"
}
});
}
}
So we created the user's BrodcastChannel but we need to observe on sent messages by user's channel and do the right actions by payload type.
userChannel.onmessage = data => {
if(data.payload.type === "SIGN_OUT") {
// As I talked before about multi-accounts, we need to check the current user id with the sent userId by the userChannel and if they were the same, we have to dispatch the userSignOut action.
store.dispatch(userSignOut());
}
}
enter link description here
Try with focus Listener isFocused
Also check
React Navigation emits events to screen components that subscribe to them:
willFocus - the screen will focus
didFocus - the screen focused (if there was a transition, the transition
completed)
willBlur - the screen will be unfocused
didBlur - the screen unfocused (if there was a transition, the transition
completed)
I suppose you should create an action, something like CHECK_CREDENTIALS, and dispatch it on every API call. This way, if you are removing user credentials from localStorage, every tab will be logged out on 1st call.
However, this is something your server should be capable of. When the token is expired/deleted, it is logical that you should get some comprehensive error.

What is preferred way to show DOM elements conditioned on firebase authentication

I'm trying to build a small web-page where sign-in is controlled by Firebase Google Auth and is popped up with profile page. What is the secured and preferred way to show the profile page?
Currently I am using onAuthStateChanged to manipulate particular div which holds profile data when user is signed-in. If the user is not logged in I am using removeChild() method to remove that div from DOM and when logged in appendChild() adds back the div.
Supposing you're using firebase's native firebase.auth().onAuthStateChanged function
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
} else {
// No user is signed in.
}
});
As well as firebase.auth().currentUser to check if the user is currently logged in or not.
In that case, it's perfectly fine to use removeChild and appendChild and they do not hold any security threats, as if a user is not logged, after a page refresh all of the information will vanish.
Here's a small firebase application that shows that when the connection to the firebase is closed and removeChild is used, appendChild stops working as firebase is disconnected, thus proving the point that it's safe to use.
https://jsfiddle.net/vh9xay6e/
Note that in this example I'm not testing any authentification, just the use of firebase with removeChild and appendChild.
You can see that once the connection to Firebase is over, nothing on the frontend side can happen to change that.
Using onAuthStateChanged method we can act upon state change (sign in or Sign out)
As an example :
firebase.auth().onAuthStateChanged(user=>{
if(user){
document.getElementById("id").classList.remove('hide')
//this will populate your class which associate with above id.
} else{
document.getElementById("id_of_your_div").classList.add('hide')
}
})
I think it's okay to use removeChild and appendChild method based on firebase auth state changes in your application.
try to wire around your code by:
var userCurrent = firebase.auth().currentUser; in a function.
NOTE: Make sure you need to be sure first you signed in (as its an async operation), followed by the update user data as:
var authenticationRef = firebase.auth();
authenticationRef.onAuthStateChanged(function(user) {
if (user) {
console.log('onAuthStateChanged : '+user.displayName);
_updateUser();
} else {
console.log('Not login');
}
});
fucntion _updateUser(){
var userCurrent = firebase.auth().currentUser;
userCurrent.updateProfile({
displayName: "Karthik.S",
}).then(function() {
var displayName = userCurrent.displayName;
}, function(error) {
});
}

AngularFirebase 2 check if user exists then add to database

I want to add a new user to firebase realtime Database, i have managed to query the databse to find if the email input already exists
onSubmit(form: NgForm){
var user = this._visitorService.getIndividualVisitor(form.value.email);
user.valueChanges().subscribe(list=>{
console.log(list);
if(list.length ===0 ){
console.log('email doesnt exist, creating new user');
this._visitorService.addVisitor(form.value)
} else{
console.log('email existst');
this._visitorService.updateVisitor(form.value)
}
})
}
getIndividualVisitor(email:string){
this.list = this.firebase.list('visitors', ref => ref.orderByChild('email').equalTo(email));
return this.list;
}
The problem i have is that the user.valueChanges() is called every time the database is updated
this means that every time I add a new user the update user function is also called, what would be the correct way to do this.
I am using "angularfire2": "^5.0.0-rc.4", and "firebase": "4.8.0",
I think using Firebase Auth together with Cloud Functions would solve your issue.
Use Firebase Authentication to create a user.
Then deploy a Cloud Function which listens on the user OnCreate event.
exports.newUser = functions.auth.user().onCreate(event => {
// Add something to your database here.
});
Documentation for Cloud Function Triggers can be found here: Firebase Authentication Triggers

Categories

Resources