Lexik vous présente aujourd’hui LexikJWTAuthenticationBundle, destiné à vous aider à mettre en place rapidement un système d’authentification entre votre API REST Symfony2 et d’éventuels clients Javascript (AngularJS, Ember.js, Backbone.js) ou mobiles.

Contexte

Les bonnes ressources concernant la mise en place d’une API REST Symfony2 ne manquent pas :

Mais peu d’informations claires sont disponibles sur l’authentification auprès d’une telle API. Et les stratégies dans ce domaine ne manquant pas, il va falloir faire un choix… Et chez Lexik on a  choisit le petit standard qui monte : le Json Web Token (JWT).

Pourquoi JWT ?

Les arguments en faveur de cette méthode sont nombreux : stateless, cross-domain, SPA et mobile ready, standardisé, testé et approuvé par une large communauté notamment AngularJS.

De plus, des projets PHP existent déjà pour nous faciliter le travail, notamment l’excellente libraire namshi/jose dont nous allons nous servir.

Bref, revenons au sujet de l’article ! Après l’avoir testé et mis en place sur plusieurs projets, nous sortons donc aujourd’hui le LexikJWTAuthenticationBundle.

Installation et configuration

Voir la marche à suivre indiquée dans le README du projet github.

Exemple d’utilisation avec AngularJS

Voir l’excellent post sur le blog de Auth0.

Test

Un projet sandbox est aussi disponible pour vous permettre de tester rapidement le système.

Previous ArticleNext Article

This post has 9 Comments

9
  1. Hi. this is **exactly** what I need – but could not get it to work.

    1. using the code to generate the keys as you suggested, i got this whenever I logged in:
    Warning: openssl_sign(): supplied key param cannot be coerced into a private key

    The resultant token was missing the final part so nothing worked from then on.

    2. So I generated the keys differently:
    openssl genrsa -out app/var/jwt/private.pem 4096

    this then permitted login and produced a correctly formatted token

    3. However, could not get authentication to work. When I passed the token as a header, it was ignored completely (Authorization: Bearer ), when I passed it in the querystring it was picked up and processed, but always failed verify() in RSA.php – i checked and it was correctly loading the public key resource.

    Any tips?

    Thanks

    Chris

  2. Hi. Further work showed the problem – if you are using a querystring at least (not sure about the headers). The passed token has escaped slashes, so if you pass that token back again it needs to be unescaped (eg stripslashes)

  3. Bonjour Chris,

    J’ai eu exactement les mêmes problèmes que toi.
    Le premier je l’ai résolu en mettant :
    private_key_path: %kernel.root_dir%/var/jwt/private.pem
    public_key_path: %kernel.root_dir%/var/jwt/public.pem

    Au début j’avais mis : app/var/jwt/public.pem

    Par contre je n’arrive toujours pas à m’authentifier via Authorization.
    Est-ce qu’il serait possible d’avoir un exemple de code côté front ?
    J’ai essayé avec jquery beforeSend (xhr.setRequestHeader) :
    Authorization : login:password
    Authorization : Basic login:password
    Authorization : Basic base64(login:password)

    De même une fois le token obtenu, j’ai renommé mon Bearer en Token :
    Authorization : Token valeurDuJwt

    Merci pour votre aide.

  4. Me again. Please delete my posts. My bad! I think really there’s only two things one needs to be careful of:
    (i) if you generate the public/private keys as suggested in the readme docs, you need to make sure you populate the passphrase in config.yml

    (ii) you need to make sure you urlencode the passed token when you put in in the querystring.

    Thanks. Its a great piece of code!

  5. Bonjour Laurent,

    Il y a deux étapes à distinguer : 1) la récupération d’un token et 2) l’utilisation de celui-ci.

    La récupération d’un token se fait au moyen d’une authentification standard identifiant / mot de passe via un POST de formulaire (XHR).

    Si l’authentification réussi, vous obtenez une réponse JSON contenant le JWT à renvoyer à chaque future requête au serveur en tant que Authorization Header.

  6. Tout comme Laurent, je pense avoir un soucis de configuration et/ou de compréhension de tout ca.

    J’utilise en front une app angular.js ou je gère le formulaire de login. Par contre j’ai un doute si je dois envoyer directement sur /login ou /login_check.

    De plus si je dois vérifier que pour chaque chargement de route, l’utilisateur n’a pas déclencher un timeout, quel en serait l’idée ?

    Merci pour votre aide

  7. Salut Phil,

    Les identifiants doivent être envoyés en POST sur le check_path du form_login de ton firewall (/login_check par défaut et dans l’exemple du README).

    $http({
    method: ‘POST’,
    url: ‘/login_check’,
    headers: {‘Content-Type’: ‘application/x-www-form-urlencoded’},
    transformRequest: function (obj) {
    var str = [];
    for (var p in obj) {
    str.push(encodeURIComponent(p) + « = » + encodeURIComponent(obj[p]));
    }
    return str.join(« & »);
    },
    data: {
    username: ‘secret’,
    password: ‘secret’
    }
    });

    En ce qui concerne la gestion de l’expiration du token dans ton application AngularJS, tu peux te baser sur ce module : https://github.com/witoldsz/angular-http-auth qui fourni tout le nécessaire.

  8. Bonjour,

    j’ai un soucis, aucun token n’est envoyé j’ai l’erreur suivante : « net::ERR_CONNECTION_RESET » pourtant dans les logs symfony j’ai bien « User « admin » has been authenticated successfully ».
    Une idée?

    merci

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *