NodeJS: JWT autorizace

JWT je docela jednoduchá metoda použitelné k autorizaci. Princip fungování asi nejlépe popíše samotný obrázek s diagramem:

Součástí vráceného tokenu mohou být jakákoliv data získaná při autorizaci na serveru, protože jsou vráceny zakódovaná. Data si takto můžete předávat v aplikaci dál. Každá zabezpečená routa může dostat do svého requestu dekódovaná data a dál s nimi pracovat

Opravdu jednoduchá implementace

Samotnou práci s JWT zajišťuje NPM balíček jsonwebtoken. Nejdůležitější je asi samotná funkce verifyToken jako Expressjs midleware funkce, ktará zajišťuje JWT autorizaci. Vše ostatni je jen obsluha jednotlivých rout…

// index.js

const express = require('express');
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken');

const jwtPassword = 'heslokterymsevsekryptuje';
const server = express();
server.use(bodyParser.json());

/**
 * Tohle je midleware funkce, ktera zjistuje pritomnost a spravnost tokenu v kazem requestu.
 * V pripade, ze je token OK, pak se provadi nasledno zpracovani.
 * @param {Request} req - HTTP request 
 * @param {Response} res - HTTP response
 * @param {Function} next - next function in processing
 */
function verifyToken(req, res, next) {
    if (!req.body.token)
        return res.status(403).json({
            auth: false,
            msg: 'missing token'
        });

    try {
        const decode = jwt.verify(req.body.token, jwtPassword);
        req.email = decode.email;
        next();
    } catch (error) {
        return res.status(500).json({
            auth: false,
            msg: 'failed authenticate token'
        });
    }
}

/**
 * POST /login
 * body JSON s klici 'email' a 'password'
 * Pokud je OK, vraci v odpovedi (JSON) s klicem 'token', ktery pak musi byt predavan v kazdem requestu
 */
server.post('/login', (req, res) => {
    // TODO: naimplementuj vlastni logiku pro overovani, ktera bude vracet token
    if (req.body.email === 'root@google.com' && req.body.password === 'supertruper') {
        return res.status(200).json({
            auth: true,
            token: jwt.sign({ email: req.body.email }, jwtPassword, {
                expiresIn: 86400
            })
        });
    } else {
        return res.status(401).json({
            auth: false
        });
    }
});

/**
 * Funkce pro ziskavani samotnych dat.
 * Protoze vyuziva midleware funkco verifyToken, nevrati data bez tokenu :)
 */
server.post('/data', verifyToken, (req, res) => {
    res.status(200).json({
        user: req.email,
        data: {
            id: 44,
            value: 'pepa'
        }
    });
});

/**
 * Start HTTP serveru, ktery ma 2 routy:
 * POST /login pro ziskani tokenu
 * POST /data pro zasilani dat po autorizaci (se ziskanym tokenem)
 */
server.listen(process.env.PORT || 8080, () => {
    console.log(`server running on http://localhost ${process.env.PORT || 8080}`);
});

POST /login – získání tokenu, kde v body je email a password
POST /data – zabezpečené načítání dat, kde v requestu musí být ‚token‘ získaný z /login a pak v odpovědi jsou požadovaná data.

Routa /data samozřejmě může fungovat i na metodě GET, ale pak by bylo potřeba přepsat autorizačni funkci midlewaru tak, aby token hledala například v hlavičce requestu. Nic složitého…