Maintenant que l'on a vu le principe des tokens JWT, je vous propose de découvrir comment les utiliser à travers un cas concret : La mise en place d'un système de présence basé sur les websockets. Le principe va être de faire communiquer une application Laravel avec une application websocket écrite avec NodeJS
Emettre le JWT
Pour la partie Laravel nous allons utiliser le système d'authentification par défaut (ce n'est pas le point qui nous intérèsse aujourd'hui).
php artisan make:auth
Les utilisateurs peuvent maintenant s'inscrire et se connecter. Nous allons ensuite permettre aux utilisateurs de se connecter au serveur de websocket et d'envoyer les informations le concernant. Nous allons donc générer un token JWT qui contiendra les informations essentielles :
public function index(\Illuminate\Contracts\Auth\Guard $auth)
{
$user = $auth->user();
$token = [
'user_id' => $user->id,
'user_name' => $user->name,
'exp' => time() + 60
];
$token = \Firebase\JWT\JWT::encode($token, getenv('JWTSECRET'));
return view('home', compact('token'));
}
Ce token sera placé dans notre vue afin d'être récupéré depuis le JavaScript :
<ul id="presence" data-websocket="{{ getenv('WEBSOCKET') }}" data-token="{{ $token }}"></ul>
Maintenant, nous pouvons nous connecter au serveur de websocket et identifier l'utilisateur.
import io from 'socket.io-client'
let presence = document.querySelector('#presence')
if (presence) {
// On récupère l'adresse du serveur depuis l'html
let socket = io(presence.dataset.websocket)
// On se connecte au serveur de websocket
socket.on('connect', () => {
// On demande l'identification avec le token reçu
socket.emit('identify', {
token: presence.dataset.token
})
})
}
Recevoir et vérifier le JWT
Côté NodeJS nous allons recevoir le token et nous allons avoir besoin de le vérifier. On utilisera la librairie jsonwebtoken
pour cela.
npm i --save jsonwebtoken
Cette librairie possède une méthode verify
qui permet de vérifier le token et qui renvoie le contenu du payload décodé.
io.on('connection', socket => {
let currentUser = null
socket.on('identify', ({token}) => {
try {
let decoded = jwt.verify(token, process.env.JWTSECRET, {
algorithms: ['HS256']
})
currentUser = {
id: decoded.user_id,
name: decoded.user_name,
count: 1
}
let user = users.find(u => u.id === currentUser.id)
if (user) {
user.count++
} else {
users.push(currentUser)
socket.broadcast.emit('users.new', {user: currentUser})
}
socket.emit('users', {users})
} catch (e) {
console.error(e.message)
}
})
socket.on('disconnect', () => {
if (currentUser) {
let user = users.find(u => u.id === currentUser.id)
if (user) {
user.count--
if (user.count === 0) {
users = users.filter(u => u.id !== currentUser.id)
socket.broadcast.emit('users.leave', {user: currentUser})
}
}
}
})
})