2

I'm using expressjs and angularjs for an app. Basically, expressjs just returns one .html that has an angular single-page-application. All routing is done with angularjs, and expressjs just exposes some web services (GET, POST).

So, if I'd do just a regular expressjs app, I'd use passportjs and store user in session on server-side that'd be it. When user tries to access /admin pages, I'd use passport middleware to check if route is allowed and so forth. Plain and simple.

But with angular, all routing is done on client side - even evaluating if user is logged in. Now, of course, a lot has been written about this, but almost all solutions store any kind of token key in localStorage or angular's $cookie. Now I'm wondering - is that safe?

If anyone would ran such an application on a public computer, and forgot to logout, anyone would be able to look at the localStorage or angular's $cookie and get the token, right?

So what is the theoretical process of implementing a safe authentication on client side, using angularjs?

2 Answers 2

4

Quote:

So, if I'd do just a regular expressjs app, I'd use passportjs and store user in session on server-side that'd be it.

While the session data is stored on the server, the session identifier is stored on the client in a cookie. If the cookie is stolen (such as in the public computer example), then the session can be used by someone else. Client-side applications CAN use the cookie-session-identifier scheme. When Angular makes XHR requests of your server, it will supply the cookie.

As you’ve seen, JSON Web Tokens (JWTs) have emerged as a new scheme. They replace the session identifier, but not the cookie. You may see local storage being used instead, but this is not safe. Cookies are in fact the most secure place to store an authentication token, if you set the HttpOnly; Secure flags. This prevents the JS environment from reading the cookie, and prevents the browser from sending it to the server over non-secure channels.

I’ve written about JWTs and Angular apps at length, in these two articles:

Build Secure User Interfaces Using JSON Web Tokens (JWTs)

Token Based Authentication for Single Page Apps (SPAs)

If you’re concerned about public computers, you have to avoid storing the token altogether. This means retaining the token in javascript memory, and supplying it via HTTP headers (typically Authorization: Bearer <access_tken>). As soon as the tab is closed, the token is lost and the session is dead. Of course that requires the user to close the tab, so you can take it a step further and set a very low “time to idle” on your token, such as five minutes. If the user does not use the token within five minutes, it is considered in valid and they have to login again.

P.S. I work at Stormpath and we have a user management service which makes it incredibly easy to add authentication to your Angular apps. You can read about it in our AngularJS Guide

Sign up to request clarification or add additional context in comments.

Comments

0

I have done this by create an Angular Service called MyAuthentication which presents the methods

  • Authenticate(un, pwd)
  • Logout()

In order to get proper separation I have a separate user proxy which makes my user HTTP requests.

angular.module('myNgApplication').service('MyAuthentication', function ($rootScope, $cookies, $log, UserProxy) {

    var self = this;
    self.user = null ;

    (function(){
        UserProxy.retrieveSession().then(function(authResponse){
            self.user = authResponse
        }, function() {
            self.user = null
        })
    }).call(this)

    this.isLoggedIn = function() {
        return self.user != null ;
    }

    this.login = function (email, password) {
        return UserProxy.login(email, password).then(function(authResponse){
            self.user = authResponse
            return self.user
        })
    }

    this.logout = function () {
        return UserProxy.logout().then(function(response){
            self.user = null ;
            return response
        })
    }

    // this is never used externally. because the HTTP request to gte the user may be in progress when this is called and therefore self.user is null
    this.getUser = function()  {
        return self.user
    }

    this.bootstrapUser = function(callback){
        if(self.isLoggedIn()){
            callback(self.user)
        }
        else {
            $rootScope.$watch(self.getUser, function(newUser, oldUser) {
                if(newUser != oldUser) {
                    callback(self.user)
                }
            });
        }

    }

})

The user object stays in memory the entire time... Then entitlement could look something like this:

angular.module('myNgApplication').service('MyEntitlments', function (MyAuthentication) {



   this.isEntitled = function(feature)  {

        return MyAuthentication.bootstrapUser(function(user){
            // check users role and feature            
            return true || false
        })

    }

})

AND on the server I am still using Passport.

5 Comments

ok, so this is not stored in a cookie or localstorage? but what happens if user closes the browser and then goes back to the page - he must login again,right?
Well, yeah. You can't have it both ways. The other thing you can do is add a cookie that identifies the session on the server. The only thing in the user cookie is the session id. The self invoking function in the MyAuthentication service tries to retrieve the session... So you could work something there.
The reality is that you will either need to store something local, OR require them to re-login if they close the browser. IF you store something local, then you are better off storing as little as possible.
I still don't feel like I understand your solution enough; how, for example, would you make /#/admin/user/1 private in angularjs? Even if you setup routeChangeStart in run, anyone can edit .js file on client side and remove the restriction. Is it even possible to completely secure a view in angular only?
I see, I thouhgt you were more referring to the cookie aspect - then you want to add authentication to the route change event. stackoverflow.com/questions/20969835/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.