Using Passport for Authentication of API Endpoints

2019-03-30 16:12发布

问题:

Following a couple tutorials on adding authentication using jsonwebtoken, passport, and passport-local I've become stuck on integrating it into my project. I want it so that any requests to any of the API endpoints require authentication, and also any requests to the front end which touch the API require authentication.

What is happening now is I can get a user to log in and register but once they are logged in they are still unable to visit a page which is requiring authentication. The user gets a 401 error. It's like the token isn't being passed correctly in the request.

I tried adding an 'auth interceptor' too

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

But this didn't seem to do the trick either.
What am I forgetting or missing?

EDIT:

After entering creds and clicking log in I get this error in chrome console

GET http://localhost:3030/members/ 401 (Unauthorized)

But my nav links show up as they're supposed to after I've successfully authenticated.
I also get this error in my terminal where I'm running Node

UnauthorizedError: No authorization token was found
    at middlware (/ncps-mms/node_modules/express-jwt/lib/index.js)
    ...

EDIT:

It has a lot to do with this line of my server routes when I inject my auth object. Basically I think my auth token isn't getting sent with my GET request. But I thought that this is what happens when I pass my auth object into the GET request.

EDIT:

Added image of GET request.

EDIT/UPDATE:

I believe I've made my way past my authentication problem but the issue of my members-view state continues to fail to render after authenticated. I've pushed my latest changes to github and if you pull the latest and run you will see that you can authenticate but clicking the View link fails to load the view.

回答1:

https://github.com/gh0st/ncps-mms works fine for me after a few fixes for resolve...

See https://github.com/gh0st/ncps-mms/pull/2

client/src/routes.js

/* jshint esversion: 6 */
/* jshint node: true */
import angular from 'angular';
import 'angular-ui-router';

angular.module('ncps.routes', ['ui.router'])
.config(($stateProvider, $urlRouterProvider) => {
    $urlRouterProvider.otherwise('/members/login');

    $stateProvider
    .state('login', {
        url: '/members/login',
        templateUrl: 'members/members-login.html',
        controller: 'AuthController',
        onEnter: ['$state', 'auth', function($state, auth) {
            if (auth.isLoggedIn()) {
                console.log('Going to /members/...');
                $state.go('members', {
                    // 'headers': {
                    //     'Authorization': 'Bearer ' + auth.getToken()
                    // }
                });
            }
        }]
    })
    .state('register', {
        url: '/members/register',
        templateUrl: 'members/members-register.html',
        controller: 'AuthController',
        onEnter: ['$state', 'auth', function($state, auth) {
            if (auth.isLoggedIn()) {
                $state.go('members');
            }
        }]
    })
    .state('members', {
        url: '/members',
        templateUrl: 'members/members-view.html',
        resolve: {
            members: function($http, auth) {
                console.log('Trying to get /members....');
                return $http.get('/members', {
                    headers: {
                        'Authorization': 'Bearer ' + auth.getToken()
                    }
                }).then(function(response){
                    return response.data;
                });
            }
        },
        controller: 'MembersController as membersCtrl'
    })
    .state('new', {
        url: '/members/add',
        templateUrl: '/members/members-add.html',
        controller: 'MembersSaveController as newMemberCtrl'
    })
    .state('test', {
        url: '/members/test',
        template: 'This is a test.'
    });
});

client/src/controllers/controllers.js

/* jshint esversion: 6 */
/* jshint node: true */
import angular from 'angular';
angular.module('ncps.controllers', [])

.controller('MembersController', ['$http', 'auth', 'members', function($http, auth, members) {
    console.log('Members retrieved');
    this.members = members;
}])

.controller('MembersSaveController', function($stateParams, $state, $http) {
    this.member = $state.member;

    this.saveMember = function(member) {
        $http.post('/members', member).then((res, member) => {
            $state.go('members');
        });
    };
})

.controller('NavController', ['$scope', 'auth', function($scope, auth) {
    $scope.isLoggedIn = auth.isLoggedIn;
    $scope.currentUser = auth.currentUser;
    $scope.logOut = auth.logOut;
}])

.controller('AuthController', ['$scope', '$state', 'auth', function($scope, $state, auth) {
    $scope.user = {};

    $scope.register = function() {
        auth.register($scope.user).error(function(error) {
            $scope.error = error;
        }).then(function() {
            $state.go('members');
        });
    };

    $scope.logIn = function() {
        auth.logIn($scope.user).error(function(error) {
            $scope.error = error;
        }).then(function() {
            $state.go('members');
        });
    };

    $scope.logOut = function() {
        auth.logOut().error(function(error) {
            $scope.error = error;
        }).then(function() {
            $state.go('members');
        });
    };
}]);


回答2:

Sorry, didn't actually have time to debug the problem but I suspect your issue could be with the header of your HTTP request.

Looking at the trace produced by my chrome browser, your client currently do not supply the "Authorization" key value pair to the HTTP request header?

Something like;

Key: Authorization Value: Bearer [TOKEN_VALUE]

Tried debugging using the Postman rest application by providing the http request with the Authorization key/value pair specified in the header and the server could tell me that the token value I was trying to give is a malform Json web token.

Whereas If I take away the Authorization key/value pair (which is what your client is using to communicate, I could reproduce the same error.

U might want to try modifying your client to include the authorization key and see if it works. Let me know if it doesn't, we can then look at other solution.

Check out my postman screenshots.