web-dev-qa-db-fra.com

Comment stocker le jeton du porteur d'authentification dans le cookie du navigateur à l'aide d'AngularJS

J'ai créé un jeton au porteur en utilisant l'identité ASP.net. Dans AngularJS, j'ai écrit cette fonction pour obtenir des données autorisées.

$scope.GetAuthorizeData = function () {
  $http({
    method: 'GET',
    url: "/api/Values",
    headers: { 'authorization': 'bearer <myTokenId>' },
  }).success(function (data) {
    alert("Authorized :D");
    $scope.values = data;
  }).error(function () {
    alert("Failed :(");
  });
};

Donc je veux stocker ce jeton dans les cookies du navigateur. Si ce jeton est présent, prenez le jeton et récupérez les données du serveur IIS Sinon, redirigez-le vers la page de connexion pour vous connecter afin d'obtenir un nouveau jeton.

De même, si l'utilisateur clique sur le bouton de déconnexion, il doit supprimer le jeton du cookie du navigateur.

Comment faire cela? Est-ce possible? Est-ce un bon moyen d'authentifier et d'autoriser un utilisateur? Que faire s'il y a plusieurs jetons d'utilisateurs?

12
Bimal Das

Un service $cookies Est disponible dans l'API AngularJS à l'aide du module ngCookies. Il peut être utilisé comme ci-dessous:

function controller($cookies) {
    //set cookie
    $cookies.put('token', 'myBearerToken');

    //get cookie
    var token=$cookies.get('token');

    //remove token
    $cookies.remove('token');
}
controller.$inject=['$cookies'];

Pour votre cas ce serait:

//inject $cookies into controller
$scope.GetAuthorizeData = function () {
    $http({
        method: 'GET',
        url: "/api/Values",
        headers: { 'authorization': 'bearer <myTokenId>' },
    })
    .success(function (data) {
        $cookies.put('token', data);
    }).error(function () {
        alert("Failed :(");
    });
};

Vous devrez également ajouter le code du module angular-cookies . Et ajoutez-le à votre angular: angular.module('myApp', ['ngCookies']);. Documents pour Angular.

Je voudrais également suggérer l'utilisation d'un Http interceptor Qui définira l'en-tête du porteur pour chaque demande, plutôt que d'avoir à le définir manuellement vous-même pour chaque demande.

//Create a http interceptor factory
function accessTokenHttpInterceptor($cookies) {
    return {
        //For each request the interceptor will set the bearer token header.
        request: function($config) {
            //Fetch token from cookie
            var token=$cookies.get['token'];

            //set authorization header
            $config.headers['Authorization'] = 'Bearer '+token;
            return $config;
        },
        response: function(response) {
            //if you get a token back in your response you can use 
            //the response interceptor to update the token in the 
            //stored in the cookie
            if (response.config.headers.yourTokenProperty) {
                  //fetch token
                  var token=response.config.headers.yourTokenProperty;

                  //set token
                  $cookies.put('token', token);
            }
            return response;
        }
    };
}
accessTokenHttpInterceptor.$inject=['$cookies'];

//Register the http interceptor to angular config.
function httpInterceptorRegistry($httpProvider) {
    $httpProvider.interceptors.Push('accessTokenHttpInterceptor');
}
httpInterceptorRegistry.$inject=['$httpProvider'];

//Assign to module
angular
    .module('myApp')
    .config(httpInterceptorRegistry)
    .factory('accessTokenHttpInterceptor', accessTokenHttpInterceptor)

Une fois le http interceptor En place, vous n'avez pas besoin de définir le Authorization header Pour chaque demande.

function service($http) {
    this.fetchToken=function() {
        //Authorization header will be set before sending request.
        return $http
            .get("/api/some/endpoint")
            .success(function(data) {
                 console.log(data);
                 return data;
            })
    }
}
service.$inject=['$http']

Comme l'a déclaré Boris: il existe d'autres moyens de résoudre ce problème. Vous pouvez également utiliser localStorage pour stocker le jeton. Cela peut également être utilisé avec l'intercepteur http. Changez simplement l'implémentation des cookies en localStorage.

function controller($window) {
    //set token
    $window.localStorage['jwt']="myToken";

    //get token
    var token=$window.localStorage['jwt'];
}
controller.$inject=['$window'];
15
cbass

Je déconseille de conserver les données dans un cookie, pour des raisons de sécurité, vous devez définir les cookies pour sécuriser et HttpOnly (non accessible depuis javascript). Si vous n'utilisez pas SSL, je vous suggère de passer à https.

Je passerais le jeton du point de terminaison d'authentification dans une réponse json:

{
    tokenData: 'token'
}

Vous pouvez enregistrer les données de jeton dans sessionStorage en utilisant le $window un service:

$window.sessionStorage.setItem('userInfo-token', 'tokenData');

Il sera effacé une fois que l'utilisateur ferme la page, et vous pouvez le supprimer manuellement en le définissant sur une chaîne vide:

$window.sessionStorage.setItem('userInfo-token', '');

Éditer:

Implémentation d'intercepteur pour la capture de données, adaptée de cbass (non testé, vous pouvez inspecter les objets pour réponse/demande pour jouer avec les informations):

//Create a http interceptor factory
function accessTokenHttpInterceptor($window) {
    return {
        //For each request the interceptor will set the bearer token header.
        request: function($config) {
            //Fetch token from cookie
            var token=$window.sessionStorage.getItem('userInfo-token');

            //set authorization header
            $config.headers['Authorization'] = 'Bearer '+token;
            return $config;
        },
        response: function(response) {
            //if you get a token back in your response you can use 
            //the response interceptor to update the token in the 
            //stored in the cookie
            if (response.config.url === 'api/token' && response.config.data.tokenData) {
                  //fetch token
                  var token=response.config.data.tokenData;

                  //set token
                  $window.sessionStorage.setItem('userInfo-token', token);
            }
            return response;
        }
    };
}

accessTokenHttpInterceptor.$inject=['$window'];
18
Boris