0

I'm trying to set up user authentication with Firebase and Twitter. The code from this answer works to a point:

var url = 'https://molovo-comments.firebaseio.com/';
var myDataRef = new Firebase(url);

var dataStore = (function(){
  var user = null;

  var auth = new FirebaseSimpleLogin(myDataRef, function(error, data) {
    if (error) {
      // an error occurred while attempting login
      console.log(error);
    } else if (user) {
      // user authenticated with Firebase
      user = data;          
      console.log('User ID: ' + user.id + ', Provider: ' + user.provider);
    } else {
      // user is logged out
    }
  });

  return {
    getAuth : function() {
      if (auth) return auth;
        // else show some error that it isn't loaded yet;
    },
    getUser : function() {
      if (user) return user;
        // else show some error that it isn't loaded yet;
    }
  };
})();

I can access the auth variable using dataStore.getAuth() and user.id is logged to the console. Calling dataStore.getAuth().login('twitter') also works, and I'm redirected to the twitter login page.

But if I try to return the user id externally using dataStore.getUser().id I get a cannot read property 'id' of undefined error.

I think I'm probably just returning user in the wrong way, so if anyone could shed any light on the issue I'd very much appreciate it.

UPDATE: Thanks to the answers from @BenjaminWarren and @SpinyNorman I've updated the code to use the correct variables as below:

var dataStore = (function(){
  var userObj = null;

  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
      userObj = user;
      console.log('User ID: ' + userObj.id + ', Provider: ' + userObj.provider);
    } else {
      // user is logged out
    }
  });

  return {
    getUser : function() {
      if (userObj) return userObj;
      // else show some error that it isn't loaded yet;
    },
    getAuth : function() {
      if (auth) return auth;
      // else show some error that it isn't loaded yet;
    }
  }
})();

jQuery(document).ready(function($) {
  console.log(dataStore.getUser().id);
});

Console output looks like this:

Uncaught TypeError: Cannot read property 'id' of undefined main.js:37
User ID: 222936694, Provider: twitter main.js:14

So dataStore.getUser().id is being logged before the auth object has been returned, and therefore is undefined. I've tried different setTimout values etc on the getUser() return but it's alsways returned before the auth

Cheers,

James

Community
  • 1
  • 1
James Dinsdale
  • 789
  • 8
  • 23

2 Answers2

0

Try this:

var url = 'https://molovo-comments.firebaseio.com/';
var myDataRef = new Firebase(url);

var dataStore = (function(){
  var user = null;

  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
    }
  });

  return {
    getAuth : function() {
      if (auth) return auth;
        // else show some error that it isn't loaded yet;
    },
    getUser : function() {
      if (user) return user;
        // else show some error that it isn't loaded yet;
    }
  };
})();

Looking at a few other references, function(error, user) seems to be the common format. The way you had it looked like the else if (user) was always returning false because data was being passed instead of user.

Benjamin Warren
  • 529
  • 4
  • 5
  • Cheers, I picked that one up already, but it hasn't solved the issue. Running `console.log( dataStore.getUser().id )` logs the error `cannot get property...` before logging `user.id` and `user.provider` from within the auth function, so it seems as though user is being returned before it has been processed – James Dinsdale Oct 23 '13 at 09:27
0

It seems to me that the current code would not log the user ID at all, since the user variable is never updated. It starts out as null and is only set in (...) if(user) { user = data }, which can never be reached. I think the line should say } else if (data) { instead:

var url = 'https://molovo-comments.firebaseio.com/';
var myDataRef = new Firebase(url);

var dataStore = (function(){
  var user = null;

  var auth = new FirebaseSimpleLogin(myDataRef, function(error, data) {
    if (error) {
      // an error occurred while attempting login
      console.log(error);
    } else if (data) {
      // user authenticated with Firebase
      user = data;          
      console.log('User ID: ' + user.id + ', Provider: ' + user.provider);
    } else {
      // user is logged out
      console.log('Not logged in.');
      user = {id: null}; // for example.
    }
  });

  return {
    getAuth : function() {
      if (auth) return auth;
        // else show some error that it isn't loaded yet;
    },
    getUser : function() {
      if (user) return user;
        // else show some error that it isn't loaded yet;
    }
  };
})();

EDIT: as Benjamin Warren pointed out, this is probably caused by changing the name of the function argument from user to data to avoid collission with the previously defined user variable. I'm assuming the log function stopped working after changing the parameter name from user to data as well.

Spiny Norman
  • 8,277
  • 1
  • 30
  • 55
  • You are correct, and I'd already made that change, but now running `console.log( dataStore.getUser().id )` logs the error `cannot get property...` before logging `user.id` and `user.provider` from within the auth function, so it seems as though user is being returned before it has been processed – James Dinsdale Oct 23 '13 at 09:31
  • Maybe you can try putting an object in the user and logging when nobody is logged in yet? I included an example in the code. Also (I have to ask), are you in fact calling `dataStore.getAuth().login()` before calling `dataStore.getUser()`? – Spiny Norman Oct 23 '13 at 10:02