Menu
CoddyTech

JWT Nedir

Coddy'nin Node.js Journey'sinin Kimlik Doğrulama ve Güvenlik bölümünün bir parçası. Ders 9 / 17.

Bir oturum, her istekte veritabanına bakılmasını gerektirir. JWT (JSON Web Token), bilgileri kendi içinde taşır: noktalarla birleştirilmiş üç base64url bölümü. Üst bilgi algoritmanın adını belirtir, yük claim değerlerini içerir (tokenın kime ait olduğunu belirtmek için sub, ne zaman süresinin dolacağını belirtmek için exp) ve imza, tokenı sunucunun oluşturduğunu kanıtlar.

Base64url bir şifreleme değil, kodlamadır. Tokenı elinde bulunduran herkes yükünü okuyabilir:

const payload = token.split('.')[1];
JSON.parse(Buffer.from(payload, 'base64url').toString());
// { sub: '42', name: 'Lin', exp: 1767225600 }

jose paketindeki decodeJwt(token) aynı şeyi yapar ve imzayı atlar. Bu yüzden yüke asla gizli bilgi koyma ve decodeJwt'in sana verdiği bir claim değerine dayanarak asla karar verme: herkes istediği claim değerini yazabilir.

challenge icon

Görev

Kolay
  • GET /inspect?token=..., belirtecin taleplerini JSON olarak yanıtlar veya 400 { "error": "Not a JWT" } döndürür.
  • GET /admin, her isteğe 403 { "error": "Admins only" } yanıtını verir.

Önce Mallory'nin belirtecini GET /admin?token= adresine gönder ve ne açtığını gör: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtYWxsb3J5IiwiYWRtaW4iOnRydWV9.c2lnbmF0dXJl. Düzelt, ardından aynı belirteci /inspect adresine gönder.

Kendin dene

import express from 'express';
import { decodeJwt } from 'jose';
import { users } from './db.js';
import { hashPassword, verifyPassword } from './passwords.js';

const app = express();
app.use(express.json());

app.post('/signup', async (req, res) => {
    const username = String(req.body.username ?? '').trim().toLowerCase();
    const password = String(req.body.password ?? '');
    if (!username || password.length < 8) {
        return res.status(400).json({ error: 'Pick a username and a password of at least 8 characters' });
    }
    if (await users.findOne({ username })) {
        return res.status(409).json({ error: 'That username is taken' });
    }
    await users.insertOne({ username, passwordHash: await hashPassword(password) });
    res.status(201).json({ username });
});

app.post('/login', async (req, res) => {
    const username = String(req.body.username ?? '').trim().toLowerCase();
    const user = await users.findOne({ username });
    if (!user || !(await verifyPassword(String(req.body.password ?? ''), user.passwordHash))) {
        return res.status(401).json({ error: 'Wrong username or password' });
    }
    res.json({ username: user.username });
});

// Bir token'ın içeriğini gösterir: GET /inspect?token=...
app.get('/inspect', (req, res) => {
    res.status(501).json({ error: 'Not written yet' });
});

// Yönetici sayfası.
app.get('/admin', (req, res) => {
    const claims = decodeJwt(String(req.query.token ?? ''));
    if (claims.admin === true) {
        return res.json({ secret: 'The vault key is 42' });
    }
    res.status(403).json({ error: 'Admins only' });
});

app.listen(3000, () => {
    console.log('Vault is running on port 3000');
});
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Kimlik Doğrulama ve Güvenlik bölümündeki tüm dersler