Firebase Database - Login - javascript

I have a register page working well, this is my database.
enter image description here
Each one has an ID and you Login using Username and password,
And I am using this code, to verify if the username is in database.
ref.child("accounts").orderByChild("lowerun").equalTo(username.toLowerCase()).once("value",snapshot => {
if (snapshot.exists()){
const userData = snapshot.val();
console.log(userData)
}
})
But how do I get the password for the username?

Dudis! Welcome to SO! It looks like you're using Firebase Realtime Database? I think you're using the database API incorrectly if you're trying to fetch user number 1 in your accounts. Here is something you could try:
database
.ref("main/accounts")
.child(userId)
.once("value", snapshot => {
// check if snapshot exists
// log your snapshot.val()
})
Also, as Doug suggested, I would strongly suggest using Firebase Authentication.

Related

How do I fetch user information to display in a feed of posts using firebase storage solutions?

I'm building a forum-style application where users post content that displays on a global feed. I want to display information about the user in posts (photoURL, displayName) similar to Twitter.
I have firebase v9 using the authentication and firestore for the posts. The reason I want to reference the auth is that I can catch changes to the user's information as it happens, this way the feed is up to date.
I save the user's unique ID with the post so I am able to reference who to display. I can successfully reference the post title and description with doc.title & doc.description however I get stuck when retrieving user information. I'm trying doc.UserID.displayName for the display name but I know this is incorrect. I can't find anything in the docs for this specific use case, is this something that I can do with just firestore and auth?
Do I need to create a reference to the auth storage with doc.UserID?
Here is the code:
// add a new post
addPostForm.addEventListener('submit', (e) => {
e.preventDefault();
onAuthStateChanged(auth, (user) => {
const colRef = collection(db, 'Posts');
console.log(hiddenURL.value);
addDoc(colRef, {
UserID: user.uid,
beatURL: hiddenURL.value,
title: addPostForm.postTitle.value,
description: addPostForm.postDescription.value,
})
.then(() => {
console.log("Document written with ID: ", doc.id);
addPostModal.classList.remove('open');
addPostForm.querySelector('.error').textContent = "";
})
.catch(error => {
addPostForm.querySelector('.error').textContent = error.message;
alert(error);
})
})
});
export const initApp = async () => {
initFirebaseAuth;
const posts = await collection(db, 'Posts');
// render data to the page
return renderPosts(posts);
};
const renderPosts = (posts) => {
const main = document.getElementById("feed");
onSnapshot(posts, (snapshot) => {
let cardsArray = []
snapshot.docs.forEach((doc, user) => {
cardsArray.push({ ...doc.data(), id: doc.id })
name.textContent = `${doc.UserID.displayName}`; // users display name
avatar.src = doc.UserID.photoURL; //user's image
description.textContent = `${post.description}`;
title.textContent = `${post.title}`;
});
console.log(cardsArray);
});
};
There are two cases and approaches at first sight:
1. Your users profiles are only available in the Auth Service
In this case, via the JS SDK, a user X cannot "query" the Auth profile of a user Y.
This means that you need to save the author's displayName together with the author uid when the post is created.
2. Your users profiles are also available in a users collection (a common pattern)
In this case, when you display a post, you could fetch the user's document to get the author's displayName.
However, in the NoSQL world, you should not be afraid to duplicate data and denormalize your data model. When designing your data-model you should think about it from a query perspective, trying to minimize the number of queries for a given screen/use case. So approach #1 is recommended, even if you maintain a user's collection.
In case of changes in the user's profile, in order to synchronyse the post documents and user's data a common approach is to use a set of Cloud Functions (which are executed in the back-end) to update the post documents. The link between the posts and the users profile being the user's uid.

Firebase - check if user created with Google Account is signing up or logging in?

I'm trying to create a web application, where you can log-in and register an account with a google account. I have managed to make it so they can log-in with the signInWithPopup(provider), but not sure how to Implement the sign-up. Any suggestions? or know of any functions in firebase i can use?
There aren't any separate methods to login and sign up when using Google Sign-In or any other provider. If a user with that credential exists then user will be logged in else a new user account will be created. You can then use additionalUserInfo.isNewUser property from the result received from signInWithPopUp method to check if the user is new.
firebase.auth().signInWithPopup(provider).then(function (result) {
const {additionalUserInfo: {isNewUser}} = result;
console.log(isNewUser ? "This user just registered" : "Existing User")
})
For the new Modular SDK (V9.0.0+), the same can be written as:
import { signInWithPopup, getAdditionalUserInfo } from "firebase/auth"
const result = await signInWithPopup(auth, googleProvider);
// Pass the UserCredential
const { isNewUser } = getAdditionalUserInfo(result)
So far, as I understood, you have two options to log in to your website: one is to make a local username/password account on your website, and the other option is to use your google account. I suppose the best way would be to check if the Google account is linked to any existing user using additionalUserInfo.isNewUser, and then linking up your google account with the account that is created via your website locally by following this article: https://firebase.google.com/docs/auth/web/account-linking?hl=lt
Once you have Firebase dependency inside your application. You can use createUserWithEmailAndPassword method to do that.
firebase
.auth()
.createUserWithEmailAndPassword("email#domain.com", "123123")
.then(data => {
data.user.updateProfile({
displayName: this.form.name
}).then(() => {});
})
.catch(err => {
this.error = err.message;
});

How to store login information for an api which requires Username - Password for the next session

I'm working with an unofficial n26 API (https://github.com/PierrickP/n26/tree/develop). The api requires the email and password to login to the account.
I don't want the user to login every single time so I need to store these information somehow.
I can't find any way to get a session token or something for later use from the api. (maybe someone of you can find it??)
So my question: How do I store Email/Password for later use in a secure way?
const N26 = require('n26');
// Log into the account
const account = new N26('example#mail.com', 'password');
// Get the last 10 transactions
account.then(account => account.transactions({limit: 10}))
.then(transactions => {
// Do something with it
});
http://www.passportjs.org/ Check out this package.
things to consider:
- json web tokens with refresh token
- API-keys

Best practice: Nested subscriptions to receive user data?

I'm developing an Ionic 2 mobile app using Firebase as backend. With Firebase, some authentication data is stored with firebase automatically (currently logged in user's id, email and password). The other user data (name, address, ...) is stored in my Firebase database.
To get the currently logged in user's data, I have to subscribe to Firebase's auth methode first. Using angularfire2 I do the following:
this.af.auth.subscribe(data => {
... // data.uid gives me the user's id
}
Now I know the user's id and can subscribe to my Firebase database to get the other user data by doing:
this.af.database.object('/users/'+userId).subscribe( userData => {
...
}
If I combine both it's a nested subscription looking like this:
this.af.auth.subscribe(data => {
this.af.database.object('/users/'+user.uid).subscribe( userData => {
...
}
}
This works, however, it doesn't feel right to have two nested subscriptions. How do you guys deal with this? What would be a "best practice approach" here?
This can be done by Rxjs mergeMap operator
this.af.auth.subscribe(user=> {
this.af.database.object('/users/'+user.uid).subscribe( userData => {
...
}
}
to
this.af.auth.mergeMap(user=>this.af.database.object('/users/'+user.uid))
.subscribe(userData){
...
}
To answer your question, mergeMap is used to avoid nested subscription and remaining stuff is your app specific logic.

Firebase retrieve the user data stored in local storage as firebase:authUser:

I am working with Firebase and AngularJS. I am using Auth authentication for google login and i completed the process.Now i need to retrieve the user data that is stored in local storage like firebase:authUser:.
Once i login with google account in local storage you have firebase:authUser:.created and i need to fetch these details.
I used the following method to store user data
firebase.database().ref('users/' + user.uid).set
({
name: user.displayName,
email: user.email,
token: token
});
The documentation for the Web SDK does not mention that upon successfully authentication, Firebase sets the User object in localStorage. The API reference does not mention this either. I discovered this the same way you have by examining localStorage while trying to configure my Vue app with Firebase.
To retrieve the user from localStorage, you can do the following:
const authUser = Object.keys(window.localStorage)
.filter(item => item.startsWith('firebase:authUser'))[0]
You could have multiple entries in localStorage so that's the reason for filter()
Edit: See Metallica's answer below.
Update (2018-02-21): It seems there is now a section (Web) Authentication State Persistence
. Unsure if this was there when I originally posted my answer, but I'm updating this answer to link it since this questions gets moderate attention.
Update 2 (2018-02-21): As stated under Overview of persistence behavior
:
If no user is signed in and no persistence is specified, the default setting will be applied (local in a browser app).
So localStorage is the default which confirms my original answer before the Firebase JS SDK was open sourced.
Just to augment #Franciso Mateo's answer: the mentioned filtering, just returns the key (string) with which the serialized user object is stored in local storage. To get the actual deserialized user object, we need to read the item with this key from local storage:
const userKey = Object.keys(window.localStorage)
.filter(it => it.startsWith('firebase:authUser'))[0];
const user = userKey ? JSON.parse(localStorage.getItem(userKey)) : undefined;
To get a user's profile information, use the properties of an instance of User. For example:
var user = firebase.auth().currentUser;
var name, email, photoURL, uid;
if(user != null) {
name = user.displayName;
email = user.email;
photoUrl = user.photoURL;
uid = user.uid;
}
If you'd like to learn more about how to manage users in Firebase using Web SDK, visit this documentation.

Categories

Resources