How to get logged user with Angular?

10,316

You will need to create a service in Angular that requests the current user, and stores the result so you can retrieve it for use in your controllers. There is nothing built in to Angular for this; you will have to create it your self. However, it's fairly straight forward.

myapp // assume was previously defined using var myapp = angular.module('myapp', []);
   .factory('principal', ['$http', '$q', function($http, $q) {
        var _identity = undefined;

        return {
           // this function returns the current _identity if defined; otherwise, it retrieves it from the HTTP endpoint
           identity: function(setIdentity) {
              if (setIdentity) {
                 _identity = setIdentity;
                 return;
              }

              var deferred = $q.defer();

              if (angular.isDefined(_identity)) {
                 deferred.resolve(_identity);
                 return deferred.promise;
              }

              $http.get('/path/to/endpoint')
                   .success(function(result) {
                       _identity = result;
                       deferred.resolve(_identity);
                   })
                   .error(function() {
                       _identity = undefined;
                       deferred.reject();
                   });

               return deferred.promise;
           }
        };
   }]);

This principal service has one method at the moment, identity(). This method returns a promise. If the identity has already been retrieved, it will resolve with that value immediately. If not, it will attempt to get it from an HTTP endpoint. If the HTTP call succeeds, it will memoize the result to _identity and resolve the promise. If the call fails, the promise will be rejected. identity has a secondary use. If you supply it with a single parameter, it will set that value as the identity and return nothing. This is useful if you already have the identity and want to set it right away, for example, after they successfully sign-in.

You could manage the sign-in page like this:

myapp.controller('SignInCtrl', ['$scope', 'principal', '$http', function($scope, principal, $http) {
     // these two values will be bound to textboxes in the view
     $scope.username = '';
     $scope.password = '';

     // this function will be called when the sign in form is submitted
     $scope.submit = function() {
          $http.post('/path/to/signin', {username: $scope.username, password: $scope.password })
               .success(function(identity) {
                   // assumes /path/to/signin returns a JSON representation of the signed-in user upon successful authentication
                   // presumably the endpoint also sets a cookie representing an auth token or something of that nature. the browser will store this automatically for you
                   principal.identity(identity); // set the identity immediately
                   // do whatever else on successful login, like redirect to another route
               });
     }
}]);

And a controller somewhere else that needs the current identity could do something like this:

myapp.controller('MyCtrl', ['$scope', 'principal', function($scope, principal) {
    // retrieve the identity. when it resolves, set user on the scope
    principal.identity().then(function(identity) {
       // after this, you can use user in your view or later in your controller
       $scope.user = identity;
    });
}]);

Now you have a way of storing the identity immediately after sign-in. I do make an assumption that your code that signs the user in sets a cookie to represent an auth token or whatever in your signin endpoint. The good thing about this is that if the user refreshes their browser, or the cookie is stored for a period of time, the user can just visit your app and the identity will resolve it using that token cookie automatically.

This plunk is a working demo of a more elaborate set up. Some of it may not apply to you (for example, it uses ui-router instead of regular routing), but it should be a reasonable reference point.

Share:
10,316
k88074
Author by

k88074

Updated on June 14, 2022

Comments

  • k88074
    k88074 almost 2 years

    Maybe I am missing something very trivial, but I can't find an answer.

    I am implementing a webapp based on nodejs, express and angular for the client side. I handle my signup and sessions through passport.js. Therefore, server-side, I can access the logged user through request.user. Now, I have a logged user which goes on its profile page, displayed through an angular view.

    Here is the issue: In order to show them user information now I am thinking to send an $http request to the server, which takes the user from request and sends it back to the client where it is displayed. However, this sounds weird to me.

    So here is my question: Is there any way to access the user in the session thruogh angular? If so, what user information is actually stored in the client?

    Thanks in advance, and apologies if this is something too trivial to be asked:/

  • Joel Grenon
    Joel Grenon almost 10 years
    It would be best to encapsultate the signin form submit request in the security service to avoid leaking implementation details (the url) into your controllers. You will also need to intercept route changes ($routeChangeStart) to check if the user is logged and redirect to the signin if not.
  • moribvndvs
    moribvndvs almost 10 years
    @jgrenon I know. I'm working on a simplified non-ui-router version of the plunk that incorporate these elements and will edit the question accordingly. However, I did answer to the scope of the original question.