Firebase user.linkWithCredential is not a function - javascript

I've followed this tutorial on how to link existing credentials with the new credentials from Facebook and everything is working as expected, except for the last part which is linking the user with the new credentials, I keep getting "user.linkWithCredential is not a function" error.
Here's my code:
$(document).on('click', "#btn-login-fb", function (event) {
//A bunch of code here where I do the login process
}).catch(function (error) {
//Here is where I need to handle the error and link accounts
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;
//
// LINKING FACEBOOK WITH EXISTING EMAIL/PASSWORD USER
//
if (error.code === 'auth/account-exists-with-different-credential') {
// Step 2.
// User's email already exists.
// The pending Facebook credential.
var pendingCred = error.credential;
// The provider account's email address.
var email = error.email;
// Get sign-in methods for this email.
firebase.auth().fetchSignInMethodsForEmail(email).then(function (methods) {
// Step 3.
// If the user has several sign-in methods,
// the first method in the list will be the "recommended" method to use.
if (methods[0] === 'password') {
// Asks the user their password.
// In real scenario, you should handle this asynchronously.
//Abrir modal
document.getElementById("btnPwModal").click();
$(document).on('click', "#btnConfirmPw", function (event) {
document.getElementById("btnFecharModal").click();
var password = $("#inputPassword").val();
firebase.auth().signInWithEmailAndPassword(email, password).then(function (user) {
// Step 4a.
user.linkWithCredential(pendingCred).then(function () {
alert("linko");
// Facebook account successfully linked to the existing Firebase user.
});;
});
})
}
});
}
});
});
Any ideas on why everything else is working but linkWithCredential is not? Thanks.

What you get after calling signInWithEmailAndPassword is a UserCredential object, not a User object. To get from UserCredential to ``, you call user on it.
So:
firebase.auth().signInWithEmailAndPassword(email, password).then(function (cred) {
cred.user.linkWithCredential(pendingCred)...

Related

How do I store the content of a variable for later use in other function (Javascript)

I have been trying to make a simple Register/Login system in JS. I tried to get the username/password values through user inputs and turn them into variables using a register() function. After that, however, these variables no longer hold any value, and I need them to compare with the new login username/password to check if they match in order to login.
Here's what I tried.
The function below attributes the user's input to the respective variables successfully. The ID's are from a text input in a HTML file.
function register () {
var user1 = window.document.getElementById('username')
var pass1 = window.document.getElementById('password')
alert('User registered, user your credentials to login')
}
When I click the 'register' button in the html page, the function is called (onclick="register()"), and I am redirected to the login page.
Here's the code for the login session:
function login () {
let userL = window.document.getElementById('usernameL')
let passL = window.document.getElementById('passwordL')
if (userL === user1 && passL === pass1) {
alert(`${userL} successfully logged`)
}
else {
alert('Invalid credentials')
}
It doesn't work because in the code above, user1 and pass1 are "not defined", according to the console. How do I keep the values of these variables stored after getting them in the first function(register) in order to use it when the second function(login) is used?
You can use Session storage to store temporary data
sessionStorage.setItem('username',username);
sessionStorage.setItem('password',password);
To retreive the data in login page
var user1 = sessionStorage.getItem('username',username);
var pass1 = sessionStorage.getItem('password',password);
then clear
sessionStorage.clear();
Please refer the below code,
<script>
const allUsers = [];
function register() {
// assuming user1 && pass1 are input elements with ids username, password
var user1 = document.getElementById("username").value;
var pass1 = document.getElementById("password").value;
// TODO: always validate the data that is taken as input from the user
// create an object containing user details
const newUser = {
username: user1,
password: pass1,
};
// push the registered user in allUsers array
allUsers.push(newUser);
alert("User registered, user your credentials to login");
}
function login() {
// assuming user1 && pass1 are input elements with ids usernameL, passwordL
let userL = document.getElementById("usernameL").value;
let passL = document.getElementById("passwordL").value;
// TODO: always validate the data that is taken as input from the user
// loop through allUsers array to check whether we already have a user registered with the details given in login form
for(let user of allUsers) {
if(user.username === userL && user.password === passL) {
alert(`${userL} successfully logged`);
return; // exit the function here
}
}
// if user detail not found in allUsers array this alert will be executed
alert("Invalid credentials");
}
</script>
Store all users in array after successful registration
While login, loop through the registered users array to check whether the user has already registered or not and decide how to handle the logic.
As PM 77-1 mentioned in the comment, please be aware that getElementById(ID) returns us the element itself (the tag itself), if we want to access it text content we can use either getElementById(ID).textContent or getElementById(ID).innerText

Trying to use fetchSignInMethodForEmail

I am trying to discover how to make a statement appear when someone registering to the form that I was made but the email address was already used. I am using firebase. I am not familiar with fetchSignInForEmail and am wondering how to use it and implement it.
I am thinking I can use an if statement
if(email exists) {
push firebase user to directed page
} else {
statement.style.display === block
}
I am also curious on how to do this with passwords as well.
Thank you
Listen for that error. However, I prefer to merge the accounts and let the user sign in. Below is an example snippet. I've got this done for you, provided you want to allow email link authentication (no password required). Firebase offers a pre-rolled one as well that supports passwords and federation/oAuth (twitter, facebook, etc).
} catch (error) {
if(error.code === "auth/email-already-in-use"){
// REMEMBER AUTH CURRENT USER OBJECT
previousUser = firebase.auth().currentUser;
// WE MUST HANDLE DB READ AND DELETE WHILE SIGNED IN AS PREVIOUS USER PER FIRESTORE SECURITY RULES
if(localUserDoc){
if(localUserDoc.data().apples){
apples = localUserDoc.data().apples;
}
}
//DELETE CURRENT USER RECORD WHILE STILL SIGNED IN
await firebase.firestore().collection("users").doc(previousUser.uid).delete();
// CLEAN UP DONE. NOW SIGN IN USING EMAIL LINK CREDENTIAL
try {
var firebaseUserObj = await firebase.auth().signInAndRetrieveDataWithCredential(credential);
// FIRESTORE USER RECORD FOR EMAIL LINK USER WAS CREATED WHEN THEY ADDED APPLE TO CART
try {
var doc = await firebase.firestore().collection("users").doc(firebaseUserObj.user.uid).get();
if (doc.exists) {
if(doc.data().apples){
apples = apples + doc.data().apples;
}
}
await firebase.firestore().collection("users").doc(firebaseUserObj.user.uid).update({
apples: apples
});
} catch(error) {
console.log("Error getting document:", error);
}
previousUser.delete();
} catch (error) {
console.log(".signInWithCredential err ", error);
}
}
}

Credential from Firebase EmailAuthProvider not working

I use firebase with react then need to convert anonymous account to permanent. I have follow firebase doc but when I try look like cannot use this function they have error message as undefined
in code
let credential = firebase.auth.EmailAuthProvider.credential(email, pass)
error message
Uncaught TypeError: Cannot read property 'credential' of undefined
Someone please help me to fix a problem
ps. in my package
"firebase": "^4.5.0"
First check whether you are anonymously signed in or not.Below code will be helful to do so.
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
var isAnonymous = user.isAnonymous;
var uid = user.uid;
// ...
} else {
// User is signed out.
// ...
}
// ...
});
If you get some defined values then use EmailAuthProvider to get credentials.
var credential = firebase.auth.EmailAuthProvider.credential(email, password);

Verify user password in Meteor

There are some irreversible actions that user can do in my app. To add a level of security, I'd like to verify that the person performing such an action is actually the logged in user. How can I achieve it?
For users with passwords, I'd like a prompt that would ask for entering user password again. How can I later verify this password, without sending it over the wire?
Is a similar action possible for users logged via external service? If yes, how to achieve it?
I can help with the first question. As of this writing, meteor doesn't have a checkPassword method, but here's how you can do it:
On the client, I'm going to assume you have a form with an input called password and a button called check-password. The event code could look something like this:
Template.userAccount.events({
'click #check-password': function() {
var digest = Package.sha.SHA256($('#password').val());
Meteor.call('checkPassword', digest, function(err, result) {
if (result) {
console.log('the passwords match!');
}
});
}
});
Then on the server, we can implement the checkPassword method like so:
Meteor.methods({
checkPassword: function(digest) {
check(digest, String);
if (this.userId) {
var user = Meteor.user();
var password = {digest: digest, algorithm: 'sha-256'};
var result = Accounts._checkPassword(user, password);
return result.error == null;
} else {
return false;
}
}
});
For more details, please see my blog post. I will do my best to keep it up to date.
I haven't done this before, but I think you will need something like this on your server
Accounts.registerLoginHandler(function(loginRequest) {
console.log(loginRequest)
var userId = null;
var username = loginRequest.username;
// I'M NOT SURE HOW METEOR PASSWORD IS HASHED...
// SO YOU NEED TO DO A BIT MORE RESEARCH ON THAT SIDE
// BUT LET'S SAY YOU HAVE IT NOW
var password = loginRequest.password;
var user = Meteor.users.findOne({
$and: [
{username: username},
{password: password}
]
});
if(!user) {
// ERROR
} else {
// VERIFIED
}
});
then you can call this function from the client side like this:
// FETCH THE USERNAME AND PASSWORD SOMEHOW
var loginRequest = {username: username, password: password};
Accounts.callLoginMethod({
methodArguments: [loginRequest]
});
I have a project on github for different purpose, but you can get a sense of how it is structured: https://github.com/534N/apitest
Hope this helps,
I have found the best way to validate the users password is to use the Accounts.changePassword command and
pass in the same password for old and new password. https://docs.meteor.com/api/passwords.html#Accounts-changePassword
Accounts.changePassword(this.password, this.password, (error) => {
if(error) {
//The password provided was incorrect
}
})
If the password provided is wrong, you will get an error back and the users password will not be changed.
If the password is correct, the users password will be updated with the same password as is currently set.

How to use Google Dart with Firebase Simple login (pass function inside function)

Has anybody figured out how to use the Firebase Simple Login with Google Dart? I am trying to figure out how to define function(error, user){} when calling FirebaseSimpleLogin. Both error and user() are objects.
This is the sample javascript code from Firebase
var myDataRef = new js.Proxy(js.context.Firebase, 'https://johnstest1.firebaseIO.com/');
var myDataRef = new Firebase('https://johnstest1.firebaseIO.com/');
var auth = new FirebaseSimpleLogin(myDataRef, function(error, user) {
if (error) {
// an error occurred while attempting login
console.log(error);
} else if (user) {
// user authenticated with Firebase
console.log('User ID: ' + user.id + ', Provider: ' + user.provider);
} else {
// user is logged out
}
});
This is the code added to the html file for use by both Dart and Firebase
<script type='text/javascript' src='https://cdn.firebase.com/v0/firebase.js'></script>
<script type='text/javascript' src='https://cdn.firebase.com/v0/firebase-simple-login.js'></script>
<script type="application/dart" src="firebasetestlogin.dart"></script>
<script src="packages/browser/dart.js"></script>
<script src="packages/browser/interop.js"></script>
In the .dart file the javascript library has been imported using pubspec.yaml
import 'package:js/js.dart' as js;
In the main() this line of code works fine and I am able to write data to the database. The line that is commented out is the original javascript line while the next line is the Dart version and it works.
js.scoped((){
// var myDataRef = new Firebase('https://johnstest1.firebaseio.com');
var myDataRef = new js.Proxy(js.context.Firebase, 'https://johnstest1.firebaseIO.com/');
});
This is the same code from main with the line for Firebase Simple Login Added. I have been trying to figure out how to write the code for function(error, user).
js.scoped((){
// var myDataRef = new Firebase('https://johnstest1.firebaseio.com');
var myDataRef = new js.Proxy(js.context.Firebase, 'https://johnstest1.firebaseIO.com/');
//var auth = new FirebaseSimpleLogin(js.context.Firebase(myDataRef, function(error, user){}{}));
var auth = new js.Proxy(js.context.FirebaseSimpleLogin(myDataRef, js.context.function(error, user)));
});
When you want to use Dart callback functions in Js you have to create a Callback and use it as paramter.
The dart equivalent of your first pasted js code is :
var myDataRef = new js.Proxy(js.context.Firebase,
'https://johnstest1.firebaseIO.com/');
var auth = new js.Proxy(js.context.FirebaseSimpleLogin, myDataRef,
new js.Callback.many((error, user) {
if (error != null) {
// an error occurred while attempting login
window.console.log(error);
} else if (user != null) {
// user authenticated with Firebase
window.console.log('User ID: ${user.id}, Provider: ${user.provider}');
} else {
// user is logged out
}
}));
Note : you can avoid js.scoped that is not needed since few versions of js package.
This is some sample code to use Dart to log into Firebase. This combines the answers from Alexandre Ardhuin into one post with some additional code.
The example will:
Get firebase reference and checks to see if user is online
Create a new Firebase user using email and password login
Login into Firebase
Adds a child_added listener and prints any data in the database to the console
Push some data to Firebase and trugger the child_added to display data.
Logout of Firebase
Add the js package http://pub.dartlang.org/packages/js to your program
Add these three lines to the HTML file.
<script src="packages/browser/interop.js"></script>
<script type='text/javascript' src='https://cdn.firebase.com/v0/firebase.js'></script>
<script type='text/javascript' src='https://cdn.firebase.com/v0/firebase-simple-login.js'></script>
Put this code in the .dart file.
var YOUR_FIREBASE_PATH = 'https://johnstest1.firebaseIO.com/';
var emailAddress = "emailAddress#xyz.com";
var password = "password";
var myDataRef = new js.Proxy(js.context.Firebase, YOUR_FIREBASE_PATH);
// Firebase
var auth = new js.Proxy(js.context.FirebaseSimpleLogin, myDataRef,
new js.Callback.many((error, user) {
if (error != null) {
window.console.log("Firebase login returned a null");
// an error occurred while attempting login
window.console.log(error);
} else if (user != null) {
// user authenticated with Firebase
window.console.log('User ID: ${user.id}, Provider: ${user.provider}');
} else {
window.console.log("User is logged out");
// user is logged out
}
})
);
Create a new user using email and password to login
// Create a new user using email and password
auth.createUser(emailAddress, password,
new js.Callback.many((error, user) {
if (error != null && user != null)
{
if (!error) {
window.console.log('User Id: ' + user.id + ', Email: ' + user.email);
}
}
})
);
Firebase login.
// Login to firebase
auth.login('password', js.map({'email': emailAddress, 'password': password}));
Add a child_added callback and if a new child gets added to the databes this will get called
// Add a listener for for child_added and gets all the data
myDataRef.on('child_added',
new js.Callback.many((snapshot, String previousChildName) {
try {
final message = snapshot.val();
print("${message.name} : ${message.text}");
}
catch (e) {}
}));
Push some data to Firebase and the child_added callback will print whatever is in the database to the console.
// Push some data to Firebase
myDataRef.push(js.map({"name": 'Mark', "text": 'Works with Dart test 2'}));
Log user out of Firebase
// Logout
auth.logout();
Now there is a dart-team-initiated dart wrapper for Firebase : https://pub.dartlang.org/packages/firebase .
With the usage of Future, dart version is way awesomer than js version.

Categories

Resources