web-dev-qa-db-fra.com

Comment fournir à l'interface utilisateur un jeton Web JSON après l'authentification du serveur?

Jusqu'à présent, je n'ai traité que des applications rendues par le serveur. Après qu'un utilisateur se soit connecté via un nom d'utilisateur/mot de passe ou à l'aide d'un fournisseur OAuth (Facebook, etc.), le serveur a simplement défini un cookie de session lors de la redirection vers la page correspondante.

Cependant, je tente maintenant de créer une application en utilisant une approche plus «moderne», avec React sur le front-end et un backend d'API JSON. Apparemment, le choix standard consiste à utiliser un jeton Web JSON pour l'authentification. Cependant, je ne parviens pas à comprendre comment je suis censé fournir le JWT au client afin qu'il puisse être stocké dans une mémoire de session/locale ou ailleurs.

Exemple pour illustrer mieux:

  1. L'utilisateur clique sur le lien (/auth/facebook) pour se connecter via Facebook

  2. L'utilisateur est redirigé et affiche le formulaire de connexion Facebook et/ou le dialogue d'autorisation (si nécessaire)

  3. Facebook redirige l'utilisateur vers /auth/facebook/callback avec un code d'autorisation, le serveur l'échange contre un jeton d'accès et des informations sur l'utilisateur.

  4. Le serveur recherche ou crée l'utilisateur dans la base de données à l'aide de l'information, puis crée un JWT contenant un sous-ensemble pertinent des données de l'utilisateur (par exemple, un ID).

  5. ???

À ce stade, je souhaite simplement que l'utilisateur soit redirigé vers la page principale de l'application React (disons /app) avec le JWT en remorque, afin que l'interface puisse prendre le relais. Mais je ne peux pas penser à un moyen (élégant) de le faire sans perdre JWT en cours de route, mis à part le mettre dans la chaîne de requête pour la redirection (/app?authtoken=...) - mais cela s'affichera dans la barre d'adresse jusqu'à ce que je le supprime. manuellement à l'aide de replaceState() ou de quoi que ce soit, et cela me semble un peu bizarre.

Vraiment, je me demande comment cela se fait habituellement, et je suis presque sûr que je manque quelque chose ici. Le serveur est Node (Koa avec Passport), si cela peut vous aider.

Edit: Pour être clair, je demande quel est le meilleur moyen de fournir un jeton au client (afin de pouvoir le sauvegarder) après un flux de redirection OAuth using Passport.

11
Inkling

J'ai récemment rencontré ce même problème et, ne trouvant pas de solution ici ou ailleurs, j'ai écrit cet article de blog } _ avec mes pensées profondes.

TL; DR: J'ai proposé 3 approches pour envoyer le fichier JWT au client après les connexions/redirections OAuth:

  1. Enregistrez le fichier JWT dans un cookie, puis extrayez-le sur le serveur ou le serveur lors d’une étape ultérieure (par exemple, extrayez-le sur le client avec JS ou envoyez une demande au serveur. Le serveur utilise le cookie pour obtenir le fichier JWT. le JWT).
  2. Renvoyez le JWT en tant que partie de la chaîne de requête (que vous suggérez dans votre question).
  3. Renvoyez une page HTML rendue par le serveur avec une balise <script> qui:
    1. Enregistre automatiquement le JWT incorporé dans localStorage
    2. Redirige automatiquement le client vers la page de votre choix par la suite.

(Étant donné que la connexion avec JWT équivaut essentiellement à "enregistrer le JWT à localStorage, mon option préférée était la 3e, mais il est possible que je n’aie pas pris en compte certains inconvénients. Je voudrais savoir ce que les autres pensent ici.)

J'espère que cela pourra aider!

7
GT2000
  1. Client: Ouvrez une fenêtre contextuelle via $ auth.authenticate ('nom du fournisseur').
  2. Client: Connectez-vous avec ce fournisseur, si nécessaire, puis autorisez l'application.
  3. Client: une fois l'autorisation obtenue, la fenêtre contextuelle est redirigée vers votre application, par exemple. http: // localhost: 3000 , avec le paramètre de chaîne de requête de code (code d'autorisation).
  4. Client: le paramètre de code est renvoyé à la fenêtre parente qui a ouvert la fenêtre contextuelle.
  5. Client: la fenêtre parente ferme la fenêtre et envoie un paramètre POST à/auth/provider withcode.
  6. Serveur: le code d'autorisation est échangé contre un jeton d'accès.
  7. Serveur: les informations sur l'utilisateur sont retransmises à l'aide du jeton d'accès de l'étape 6.
  8. Serveur: Recherchez l'utilisateur par son identifiant de fournisseur unique. Si l'utilisateur existe déjà, récupérez l'utilisateur existant, sinon créez un nouveau compte utilisateur.
  9. Serveur: dans les deux cas de l'étape 8, créez un jeton Web JSON et renvoyez-le au client.
  10. Client: Analysez le jeton et enregistrez-le sur le stockage local pour une utilisation ultérieure après le rechargement de la page.

    Connectez - Out

  11. Client: Supprimer le jeton du stockage local
0
sabarinathan u

voici une demande de connexion du côté serveur. il stocke le jeton dans l'en-tête:

router.post('/api/users/login', function (req, res) {
  var body = _.pick(req.body, 'username', 'password');
  var userInfo;

models.User.authenticate(body).then(function (user) {
      var token = user.generateToken('authentication');
      userInfo = user;

      return models.Token.create({
        token: token
      });
    }).then(function (tokenInstance) {
      res.header('Auth', tokenInstance.get('token')).json(userInfo.toPublicJSON());
    }).catch(function () {
      res.status(401).send();
    });
});

voici la demande de connexion du côté réactif, où je récupère le jeton de l'en-tête et le configure dans la mémoire de stockage locale une fois que le nom d'utilisateur et le mot de passe ont été authentifiés:

handleNewData (creds) {
    const { authenticated } = this.state;
    const loginUser = {
        username: creds.username,
        password: creds.password
    }
    fetch('/api/users/login', {
        method: 'post',
        body: JSON.stringify(loginUser),
        headers: {
            'Authorization': 'Basic'+btoa('username:password'),
            'content-type': 'application/json',
            'accept': 'application/json'
        },
        credentials: 'include'
    }).then((response) => {
        if (response.statusText === "OK"){
            localStorage.setItem('token', response.headers.get('Auth'));
            browserHistory.Push('route');
            response.json();
        } else {
            alert ('Incorrect Login Credentials');
        }
    })
}
0
jared thomas