Authentication for Node.js App with Angular.js and iOS Clients

前端 未结 3 1121
甜味超标
甜味超标 2020-12-22 23:08

I\'ve tried to read as many different answers and posts as possible, but I still can\'t quite settle on a solution that fits my needs. I\'m trying to work out the best (most

相关标签:
3条回答
  • 2020-12-22 23:37

    Have a look to the yeoman generator for angular and node? The generator-angular-fullstack have a very nice structure for user authentification using passport.

    You can see an example here :

    the code: https://github.com/DaftMonk/fullstack-demo

    the result: http://fullstack-demo.herokuapp.com/

    Hope it helps!

    0 讨论(0)
  • 2020-12-22 23:49

    I would use a token based authentication where you can send a token (automatically) with each request. You'll have to log in once, the server will provide you with a token which you can then use to send with each request. This token will be added to the HTML header, so that you don't have to modify each request to the browser.

    You can set certain calls in the API so that they always need a token, while others might not be token protected.

    For Express, you can use express-jwt (https://www.npmjs.org/package/express-jwt)

    var expressJwt = require('express-jwt');
    
    // Protect the /api routes with JWT
    app.use('/api', expressJwt({secret: secret}));
    
    app.use(express.json());
    app.use(express.urlencoded());
    

    If you want to authenticate you can create this function in your express server:

    app.post('/authenticate', function (req, res) {
      //if is invalid, return 401
      if (!(req.body.username === 'john.doe' && req.body.password === 'foobar')) {
        res.send(401, 'Wrong user or password');
        return;
      }
    
      var profile = {
        first_name: 'John',
        last_name: 'Doe',
        email: 'john@doe.com',
        id: 123
      };
    
      // We are sending the profile inside the token
      var token = jwt.sign(profile, secret, { expiresInMinutes: 60*5 });
    
      res.json({ token: token });
    });
    

    And for protected calls something that starts with /api:

    app.get('/api/restricted', function (req, res) {
      console.log('user ' + req.user.email + ' is calling /api/restricted');
      res.json({
        name: 'foo'
      });
    });
    

    In your Angular application you can login with:

    $http
          .post('/authenticate', $scope.user)
          .success(function (data, status, headers, config) {
            $window.sessionStorage.token = data.token;
            $scope.message = 'Welcome';
          })
          .error(function (data, status, headers, config) {
            // Erase the token if the user fails to log in
            delete $window.sessionStorage.token;
    
            // Handle login errors here
            $scope.message = 'Error: Invalid user or password';
          });
    

    And by creating an authentication interceptor, it will automatically send the token with every request:

    myApp.factory('authInterceptor', function ($rootScope, $q, $window) {
      return {
        request: function (config) {
          config.headers = config.headers || {};
          if ($window.sessionStorage.token) {
            config.headers.Authorization = 'Bearer ' + $window.sessionStorage.token;
          }
          return config;
        },
        response: function (response) {
          if (response.status === 401) {
            // handle the case where the user is not authenticated
          }
          return response || $q.when(response);
        }
      };
    });
    
    myApp.config(function ($httpProvider) {
      $httpProvider.interceptors.push('authInterceptor');
    });
    

    If you have to support old browsers which do not support local storage. You can swap the $window.sessionStorage with a library like AmplifyJS (http://amplifyjs.com/). Amplify for example uses whatever localstorage is available. This would translate in something like this:

        if (data.status === 'OK') {
          //Save the data using Amplify.js
          localStorage.save('sessionToken', data.token);
          //This doesn't work on the file protocol or on some older browsers
          //$window.sessionStorage.token = data.token;
          $location.path('/pep');
        }
      }).error(function (error) {
        // Erase the token if the user fails to log in
        localStorage.save('sessionToken', null);
        // Handle login errors here
        $scope.message = 'Error: Invalid user or password';
      });
    

    And the authintercepter we swap for:

    angular.module('myApp.authInterceptor', ['myApp.localStorage']).factory('authInterceptor', [
      '$rootScope',
      '$q',
      'localStorage',
      function ($rootScope, $q, localStorage) {
        return {
          request: function (config) {
            config.headers = config.headers || {};
            config.headers.Authorization = 'Bearer ' + localStorage.retrieve('sessionToken');
            return config;
          },
          response: function (response) {
            if (response.status === 401) {
            }
            return response || $q.when(response);
          }
        };
      }
    ]);
    

    You can find everything except AmplifyJS in this article:

    http://blog.auth0.com/2014/01/07/angularjs-authentication-with-cookies-vs-token/

    0 讨论(0)
  • 2020-12-23 00:00

    I use generator-angular-fullstack, the /api services are not secured, get your _id from /api/users/me, logout, and go to /api/users/your_id_here, you will figure out that the /api not secured.

    0 讨论(0)
提交回复
热议问题