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:
L'utilisateur clique sur le lien (/auth/facebook
) pour se connecter via Facebook
L'utilisateur est redirigé et affiche le formulaire de connexion Facebook et/ou le dialogue d'autorisation (si nécessaire)
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.
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).
???
À 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.
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:
<script>
qui: localStorage
(É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!
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
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');
}
})
}