简体   繁体   中英

AngularJS token based authentication header

I am somewhat new to angular and have an app that I have started. The start of this is just a simple login that will hit a REST API and authenticate the user and send back a JSON token validating the user. Every subsequent request made will send an authentication header containing the token in order to make sure they are logged in of course.

Here is my code so far -

AngularJS:

;(function(){

function authInterceptor(API, auth) {
  return {
    request: function(config) {
      return config;
    }
  }
}


function authService() {

}


function userService($http, API, auth) {

    $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;';
    $http.defaults.transformRequest = [function(data) {
        return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data;
      }];

  var self = this;

  self.login = function(username, pwd, ctrl) {
      ctrl.requestdata = API + '/winauth' + '; with ' + username;
    return $http.post(API + '/winauth', {
        username: username,
        pwd: pwd
      })
  };

  var param = function(obj) {
    var query = '', name, value, fullSubName, subName, subValue, innerObj, i;

    for(name in obj) {
      value = obj[name];

      if(value instanceof Array) {
        for(i=0; i<value.length; ++i) {
          subValue = value[i];
          fullSubName = name + '[' + i + ']';
          innerObj = {};
          innerObj[fullSubName] = subValue;
          query += param(innerObj) + '&';
        }
      }
      else if(value instanceof Object) {
        for(subName in value) {
          subValue = value[subName];
          fullSubName = name + '[' + subName + ']';
          innerObj = {};
          innerObj[fullSubName] = subValue;
          query += param(innerObj) + '&';
        }
      }
      else if(value !== undefined && value !== null)
        query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';
    }

    return query.length ? query.substr(0, query.length - 1) : query;
  };

}


  function MainCtrl(user, auth) {
    var self = this;

    function handleRequest(res) {
      self.responsedata = res;
      self.message = res.data.message;
    }

    self.login = function() {
      this.requestdata = 'Starting request...';
      user.login(self.username, self.pwd, self)
        .then(handleRequest, handleRequest)
    }
  }

  angular.module('app', [])
  .factory('authInterceptor', authInterceptor)
  .service('user', userService)
  .service('auth', authService)
  .constant('API', 'http://development-server.com:8080/ecar/api')
  .config(function($httpProvider) {
    $httpProvider.interceptors.push('authInterceptor');
  })
  .controller('Main', MainCtrl)
  })();

Let me now say that this is NOT JWT and that this IS working. It hits the server and after the authentication succeeds (words from my boss follow) ** the response sent back is a JSON array containing a field name "auth_token", which contains the token to be sent back with subsequent requests. That token must be sent with any subsequent requests as a custom request header named X-PCC-API-TOKEN. **

Here is the response the server returns:

    http://appsdev.pccportal.com:8080/ecar/api/winauth; with  myUsername
      {"data":{"status":"Authentication has succeeded.","auth_token":"qidn0pwcuvl4jbml73qls94hk4"},"status":200,"config":{"method":"POST","transformRequest":[null],"transformResponse":[null],"url":"http://development-server.com:8080/ecar/api/winauth","data":{"username":"myUsername","pwd":"myPassword"},"headers":{"Accept":"application/json, text/plain, */*","Content-Type":"application/x-www-form-urlencoded;"}},"statusText":"OK"}

As you can see it is succeeding and returning a JSON array with the field name "auth_token" that contains the token.

What I need to do is hopefully save that token to their local storage and like my boss stated to me (he is the one who designed the API) "the token needs to be sent back with every subsequent requests and the token must be sent as a custom request header named X-PCC-API-TOKEN"

This was in the tutorial that I was going through:

function authService($window) {
  var self = this;

  self.parseJwt = function(token) {
    var base64Url = token.split('.')[1];
    var base64 = base64Url.replace('-', '+').replace('_', '/');
    return JSON.parse($window.atob(base64));
  }

  self.saveToken = function(token) {
    $window.localStorage['jwtToken'] = token;
  }

  self.getToken = function() {
    return $window.localStorage['jwtToken'];
  }

  self.isAuthed = function() {
    var token = self.getToken();
    if(token) {
      var params = self.parseJwt(token);
      return Math.round(new Date().getTime() / 1000) <= params.exp;
    } else {
      return false;
    }
  }

  self.logout = function() {
    $window.localStorage.removeItem('jwtToken');
  }
}

and This for the interceptor:

function authInterceptor(API, auth) {
  return {

    request: function(config) {
      var token = auth.getToken();
      if(token && config.url.indexOf(API) === 0) {
        config.headers.Authorization = 'Bearer ' + token;
      }

      return config;
    }
  }

}

But that is obviously for JWT. I need it to conform to my bosses guidelines and also not use JWT.

So sorry for all the code. I hope that's not a bad thing. But to wrap up this authenticate fine and sends back a JSON array containing a token that I need to send back to as a custom header named X-PCC-API-TOKEN with every following request and hopefully save the token to their local storage.

I really need help on this. And don't really know how to do this.

Thanks

Basically you got your login method somewhat working. You hit the API server and you get the response with a token. So far so good. You just need to save the token in localStorage and add it to every API call's X-PCC-API-TOKEN header.

You could create another service that handles the storage, but if you don't want/need that kind of complexity, you can just add

var authToken = res.data.auth_token;
localStorage.setItem('token', authToken);

wherever you handle the returned data from login - in your case it's your handleRequest function.

After that, you just need to add your interceptor. Your example with JWT is really close to what you need actually. (JWT is just setting the Authorization header instead the one you need.)

function authInterceptor() {
    return {
        request: function (request) {
            request.headers = request.headers || {};
            request.headers['X-PCC-API-TOKEN'] = localStorage.getItem('token');
            return request;
        }
    };
}

Obviously if you used a service to handle the storage, you could get the token through that. Also, you should only add the custom header to your API calls, so just put it in a simple if where you check whether it's one or not.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM