backbone.js - handling if a user is logged in or not

31,965

Solution 1

I have a backend call that my client-side code that my static page (index.php) makes to check whether the current user is logged in. Let's say you have a backend call at api/auth/logged_in which returns HTTP status code 200 if the user is logged in or 400 otherwise (using cookie-based sessions):

appController.checkUser(function(isLoggedIn){
    if(!isLoggedIn) {
        window.location.hash = "login";    
    }

    Backbone.history.start();
});

...

window.AppController = Backbone.Controller.extend({

  checkUser: function(callback) {
     var that = this;

     $.ajax("api/auth/logged_in", {
       type: "GET",
       dataType: "json",
       success: function() {
         return callback(true);
       },
       error: function() {
         return callback(false);
       }
     });
  }
});

Solution 2

I use the session concept to control user login state.

I have a SessionModel and SessionCollection like this:

SessionModel = Backbone.Model.extend({
    defaults: {
        sessionId: "",
        userName: "",
        password: "",
        userId: ""
    },

    isAuthorized: function(){
       return Boolean(this.get("sessionId"));
    }

});

On app start, I initialize a globally available variable, activeSession. At start this session is unauthorized and any views binding to this model instance can render accordingly. On login attempt, I first logout by invalidating the session.

logout = function(){
    window.activeSession.id = "";
    window.activeSession.clear();
}

This will trigger any views that listen to the activeSession and will put my mainView into login mode where it will put up a login prompt. I then get the userName and password from the user and set them on the activeSession like this:

login = function(userName, password){
    window.activeSession.set(
        {
            userName: userName,
            password: password
        },{
            silent:true
        }
    );
    window.activeSession.save();
}

This will trigger an update to the server through backbone.sync. On the server, I have the session resource POST action setup so that it checks the userName and password. If valid, it fills out the user details on the session, sets a unique session id and removes the password and then sends back the result.

My backbone.sync is then setup to add the sessionId of window.activeSession to any outgoing request to the server. If the session Id is invalid on the server, it sends back an HTTP 401, which triggers a logout(), leading to the showing of the login prompt.

We're not quite done implementing this yet, so there may be errors in the logic, but basically, this is how we approach it. Also, the above code is not our actual code, as it contains a little more handling logic, but it's the gist of it.

Solution 3

Here is a very good tutorial for it http://clintberry.com/2012/backbone-js-apps-authentication-tutorial/

Share:
31,965
Matthew
Author by

Matthew

Updated on July 09, 2022

Comments

  • Matthew
    Matthew almost 2 years

    Firstly, should the static page that is served for the app be the login page?

    Secondly, my server side code is fine (it won't give any data that the user shouldn't be able to see). But how do I make my app know that if the user is not logged in, to go back to a login form?

  • Matthew
    Matthew almost 13 years
    How would you check before any data is ever received? So that any time the app makes a call for data, it checks to see if they are logged in. if not, it goes to the login page.
  • Sam
    Sam almost 13 years
    If you want to make the check on every single call to the backend, you should do integrate that with your backend code. E.g., if the user is not authenticated for any call, then you can return a 401 Unauthorized from your backend or something you can catch on the client side. This way, you don't have to make a separate call to check authorization before each data request. In this case you would probably have to override the Backbone.sync method to catch that 401 Unauthorized and emit some event that you can use to detect if a backend call was unauthorized.
  • Jens Alm
    Jens Alm almost 13 years
    I actually changed the behaviour a bit. I know create new sessions by sessionCollection.create() and then fire a globally available loginSuccess message that any view can listen to.
  • Duncan Bayne
    Duncan Bayne over 12 years
    You should do it server side as well, but there's nothing wrong with detecting login state on the client provided you don't depend upon it.
  • dbau
    dbau about 12 years
    Your method sounds great. Any chance you can share a gist of your of the updated code? :)
  • Jens Alm
    Jens Alm about 12 years
    Unfortunately we moved away from this solution to an separate authentication mechanism (cookie-based for now) due to issues on the backend (we wanted to use a ready-made authentication system on the backend)
  • montrealist
    montrealist almost 12 years
    Would still be worth it sharing a little tutorial or even a fiddle. And of course thank you for explaining this.
  • jackocnr
    jackocnr over 11 years
    Anyone know how to trigger a DELETE request on logout? window.activeSession.destroy() isn't sending any request for me.
  • jackocnr
    jackocnr over 11 years
    I found the solution: you need to give it an ID first, else BB will think it is not yet persisted in the db, and so wont bother sending a DELETE request: window.activeSession.set("id", 0);
  • SimplGy
    SimplGy almost 11 years
    I've been using a global user model that changes state from not logged in to guest to registered. It's similar to the session model described above but also includes user profile info. This works pretty well in many cases because the event listening in Backbone is a good fit for this use case. Login/register screens listen to error, and any ui element can listen to sync. It can have methods on it like .logOut. So far the only issues have been around timing/order of operations, but I still think the method is sound.