API autentifikatsiyasi


ULASHISH

API autentifikatsiyasi nima?

API autentifikatsiyasi - bu Node.js API-ga kiruvchi mijozlarning shaxsini tekshirish jarayoni.

Ushbu keng qamrovli qo‘llanma Node.js ilovalaringizni samarali himoya qilish uchun turli autentifikatsiya usullari, xavfsizlikning eng yaxshi amaliyotlari va amalga oshirish usullarini qamrab oladi.


Nima uchun API autentifikatsiyasi muhim?

Bugungi o‘zaro bog‘liq dunyoda API xavfsizligi ixtiyoriy emas - bu zarurat. To‘g‘ri autentifikatsiya sizga yordam beradi:

Xavfsizlik imtiyozlari

  • Kirish nazorati: API ruxsatini faqat ruxsat berilgan foydalanuvchilarga cheklash
  • Ma’lumotlarni himoya qilish: Maxfiy ma’lumotlarni ruxsatsiz kirishdan himoya qiling
  • Identifikatorni tekshirish: Foydalanuvchilar o‘zlarini kim ekaniga ishonch hosil qiling

Biznesning afzalliklari

  • Usage Analytics: API foydalanishni foydalanuvchi/ilova bo‘yicha kuzatish
  • Monetizatsiya: Foydalanishga asoslangan hisob-kitob modellarini joriy qiling
  • Muvofiqlik: me’yoriy talablarga javob bering (GDPR, HIPAA va boshqalar).

Autentifikatsiya usullariga umumiy nuqtai

Turli xil autentifikatsiya usullari turli xil foydalanish holatlariga xizmat qiladi. Mana tez taqqoslash:

Metod Eng yaxshisi Murakkablik Xavfsizlik darajasi
Sessiyaga asoslangan An’anaviy veb-ilovalar Past O‘rta
JWT (Token-Based) SPA, mobil ilovalar O‘rta Yuqori
API kalitlari Serverdan serverga Past Past-O‘rta
OAuth 2.0 Uchinchi tomon ruxsati Yuqori Juda yuqori


Autentifikatsiya usullari

Node.js da API autentifikatsiyasiga bir nechta yondashuvlar mavjud


Seansga asoslangan autentifikatsiya

Seansga asoslangan autentifikatsiya foydalanuvchi holatini saqlash uchun cookie-fayllardan foydalanadi:

const express = require('express');
const session = require('express-session');
const bodyParser = require('body-parser');
const app = express();

// Parse request bodies
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

// Configure sessions
app.use(session({
  secret: 'your-secret-key',
  resave: false,
  saveUninitialized: false,
  cookie: { secure: process.env.NODE_ENV === 'production', maxAge: 24 * 60 * 60 * 1000 } // 24 hours
}));

// Sample user database
const users = [
  { id: 1, username: 'user1', password: 'password1' }
];

// Login route
app.post('/login', (req, res) => {
  const { username, password } = req.body;
 
  // Find user
  const user = users.find(u => u.username === username && u.password === password);
 
  if (!user) {
    return res.status(401).json({ message: 'Invalid credentials' });
  }
 
  // Store user information in session (excluding password)
  req.session.user = {
    id: user.id,
    username: user.username
  };
 
  res.json({ message: 'Login successful', user: req.session.user });
});

// Protected route
app.get('/profile', (req, res) => {
  // Check if user is logged in
  if (!req.session.user) {
    return res.status(401).json({ message: 'Unauthorized' });
  }
 
  res.json({ message: 'Profile accessed', user: req.session.user });
});

// Logout route
app.post('/logout', (req, res) => {
  // Destroy session
  req.session.destroy((err) => {
    if (err) {
      return res.status(500).json({ message: 'Logout failed' });
    }
    res.json({ message: 'Logout successful' });
  });
});

// Start server
app.listen(8080, () => {
  console.log('Server running on port 8080');
});

Tokenga asoslangan autentifikatsiya (JWT)

JSON Web Tokens (JWT) ixcham va mustaqil bo‘lgan stateless (ichki state saqlamaydigan) (stateless) autentifikatsiya mexanizmini ta’minlaydi.

Seansga asoslangan autentifikatsiyadan farqli o‘laroq, tokenga asoslangan autentifikatsiya (JWT) seans ma’lumotlarini saqlash uchun serverni talab qilmaydi.

Bu uni stateless (stateless (ichki state saqlamaydigan)) API arxitekturasi va mikroservislar uchun ideal qiladi.

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

app.use(bodyParser.json());

const JWT_SECRET = 'your-jwt-secret-key';

// Sample user database
const users = [
  { id: 1, username: 'user1', password: 'password1', role: 'user' }
];

// Login route - generate token
app.post('/login', (req, res) => {
  const { username, password } = req.body;

  // Find user
  const user = users.find(u => u.username === username && u.password === password);

  if (!user) {
    return res.status(401).json({ message: 'Invalid credentials' });
  }

  // Create payload for JWT
  const payload = {
    id: user.id,
    username: user.username,
    role: user.role
  };

  // Sign token
  const token = jwt.sign(payload, JWT_SECRET, { expiresIn: '1h' });

  res.json({ message: 'Login successful', token });
});

// Middleware for JWT verification
const authenticateJWT = (req, res, next) => {
  // Get auth header - The Authorization header is commonly used to send authentication tokens
  const authHeader = req.headers.authorization;

  if (!authHeader) {
    return res.status(401).json({ message: 'Authorization header missing' });
  }

  // Extract token from "Bearer <token>"
  const token = authHeader.split(' ')[1];

  if (!token) {
    return res.status(401).json({ message: 'Token missing' });
  }

  try {
    // Verify token
    const decoded = jwt.verify(token, JWT_SECRET);

    // Attach user to request
    req.user = decoded;

    next();
  } catch (error) {
    return res.status(403).json({ message: 'Invalid or expired token' });
  }
};

// Protected route
app.get('/profile', authenticateJWT, (req, res) => {
  res.json({ message: 'Profile accessed', user: req.user });
});

// Role-based route
app.get('/admin', authenticateJWT, (req, res) => {
  // Check if user has admin role
  if (req.user.role !== 'admin') {
    return res.status(403).json({ message: 'Access denied: admin role required' });
  }

  res.json({ message: 'Admin panel accessed' });
});

// Start server
app.listen(8080, () => {
  console.log('Server running on port 8080');
});

OAuth 2.0 autentifikatsiyasi

OAuth 2.0 avtorizatsiya uchun sanoat standarti protokoli bo‘lib, ilovalarga HTTP xizmatlaridagi foydalanuvchi hisoblariga cheklangan kirish imkonini beradi.

U foydalanuvchi autentifikatsiyasini foydalanuvchi hisobiga ega bo‘lgan xizmatga topshirish orqali ishlaydi.

OAuth 2.0 oqimining umumiy ko‘rinishi

  1. Foydalanuvchi ilovangizdagi “[Provayder] bilan kirish” tugmasini bosadi
  2. Foydalanuvchi provayderning kirish sahifasiga yo‘naltiriladi
  3. Foydalanuvchi ilovangizni autentifikatsiya qiladi va avtorizatsiya qiladi
  4. Provayder avtorizatsiya kodi bilan ilovangizga qayta yo‘naltiradi
  5. Ilovangiz kodni kirish tokeniga almashtiradi
  6. Ilovangiz endi foydalanuvchi ma’lumotlariga kira oladi (ruxsat etilgan doirada)

Passport.js bilan amalga oshirish

1. Kerakli paketlarni o‘rnating:

npm install passport passport-google-oauth20 express-session

2. OAuth 2.0 ni Google bilan sozlang:

const express = require('express');
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const session = require('express-session');
const app = express();

// Configure sessions for OAuth 2.0
app.use(session({
  secret: 'your-secret-key',
  resave: false,
  saveUninitialized: false,
  cookie: { secure: process.env.NODE_ENV === 'production' }
}));

// Initialize Passport
app.use(passport.initialize());
app.use(passport.session());

// Configure Google OAuth 2.0 strategy
passport.use(new GoogleStrategy({
    clientID: 'YOUR_GOOGLE_CLIENT_ID',
    clientSecret: 'YOUR_GOOGLE_CLIENT_SECRET',
    callbackURL: 'http://localhost:8080/auth/google/callback'
  },
  (accessToken, refreshToken, profile, done) => {
    // In a real app, you'd find or create a user in your database
    const user = {
      id: profile.id,
      displayName: profile.displayName,
      email: profile.emails[0].value,
      provider: 'google'
    };
   
    return done(null, user);
  }
));

// Serialize user for session
passport.serializeUser((user, done) => {
  done(null, user);
});

// Deserialize user from session
passport.deserializeUser((user, done) => {
  done(null, user);
});

// Routes for Google OAuth
app.get('/auth/google',
  passport.authenticate('google', { scope: ['profile', 'email'] })
);

app.get('/auth/google/callback',
  passport.authenticate('google', { failureRedirect: '/login' }),
  (req, res) => {
    // Successful authentication
    res.redirect('/profile');
  }
);

// Middleware to check authentication
const isAuthenticated = (req, res, next) => {
  if (req.isAuthenticated()) {
    return next();
  }
  res.redirect('/login');
};

// Protected route
app.get('/profile', isAuthenticated, (req, res) => {
  res.json({ user: req.user });
});

// Logout route
app.get('/logout', (req, res) => {
  req.logout();
  res.redirect('/');
});

// Start server
app.listen(8080, () => {
  console.log('Server running on port 8080');
});

API kaliti autentifikatsiyasi

API kalitlari mijozlarni API-ga autentifikatsiya qilishning oddiy usulidir.

Ular server-server aloqasi uchun yoki foydalanuvchi kontekstisiz chaqiruvchi loyihani aniqlash kerak bo‘lganda eng mos keladi.

API kalitlari uchun eng yaxshi amaliyotlar:

  • Store keys securely (environment variables, secret management services)
  • Tugmalarni muntazam ravishda aylantiring
  • Kalit ta’sirini oldini olish uchun HTTPS dan foydalaning
  • Har bir kalit uchun tezlikni cheklashni amalga oshiring

Amalga oshirish misoli

1. API kaliti oraliq dasturi

const express = require('express');
const app = express();

// In-memory storage for API keys (use a database in production)
const apiKeys = new Map([
  ['abc123', { name: 'Mobile App', permissions: ['read:data'] }],
  ['def456', { name: 'Web Client', permissions: ['read:data', 'write:data'] }]
]);

// API key authentication middleware
const authenticateApiKey = (req, res, next) => {
  const apiKey = req.headers['x-api-key'] || req.query.apiKey;

  if (!apiKey) {
    return res.status(401).json({
      error: 'API key is required',
      docs: 'https://your-api-docs.com/authentication'
    });
  }

  const keyData = apiKeys.get(apiKey);
  if (!keyData) {
    return res.status(403).json({ error: 'Invalid API key' });
  }

  // Attach key data to request for use in route handlers
  req.apiKey = keyData;
  next();
};
// Protected route using API key
app.get('/api/data', authenticateApiKey, (req, res) => {
  res.json({
    message: 'Access granted',
    client: req.apiKey.name,
    timestamp: new Date().toISOString()
  });
});

// Route to generate a new API key (protected by admin auth in real apps)
app.post('/api/keys', (req, res) => {
  const { name, permissions } = req.body;
  const apiKey = generateApiKey(); // Implement your key generation logic
  apiKeys.set(apiKey, { name, permissions });
  res.status(201).json({ apiKey });
});
// Helper function to generate API keys
function generateApiKey() {
  return [...Array(32)]
    .map(() => Math.floor(Math.random() * 16).toString(16))
    .join('');
}
// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});
// Export for testing
module.exports = { app, apiKeys };

API kaliti autentifikatsiyasi

API kalitlari API so‘rovlarini autentifikatsiya qilishning oddiy usulidir:

const express = require('express');
const app = express();

// Sample API keys database
const apiKeys = [
  { key: 'api-key-1', owner: 'client1', permissions: ['read'] },
  { key: 'api-key-2', owner: 'client2', permissions: ['read', 'write'] }
];

// Middleware for API key authentication
const authenticateApiKey = (req, res, next) => {
  // Get API key from header or query parameter
  const apiKey = req.headers['x-api-key'] || req.query.api_key;
 
  if (!apiKey) {
    return res.status(401).json({ message: 'API key missing' });
  }
 
  // Find API key in database
  const keyData = apiKeys.find(k => k.key === apiKey);
 
  if (!keyData) {
    return res.status(403).json({ message: 'Invalid API key' });
  }
 
  // Attach key data to request
  req.apiKeyData = keyData;
 
  next();
};

// Protected route with API key
app.get('/data', authenticateApiKey, (req, res) => {
  res.json({
    message: 'Data accessed',
    client: req.apiKeyData.owner,
    data: { example: 'API data' }
  });
});

// Route requiring specific permission
app.post('/data', authenticateApiKey, (req, res) => {
  // Check if client has write permission
  if (!req.apiKeyData.permissions.includes('write')) {
    return res.status(403).json({ message: 'Insufficient permissions' });
  }
 
  res.json({ message: 'Data created successfully' });
});

// Start server
app.listen(8080, () => {
  console.log('Server running on port 8080');
});

Asosiy autentifikatsiya

HTTP Basic autentifikatsiyasi Avtorizatsiya sarlavhasida kodlangan hisobga olish ma’lumotlaridan foydalanadi:

const express = require('express');
const app = express();

// Sample user database
const users = [
  { username: 'user1', password: 'password1' }
];

// Basic authentication middleware
const basicAuth = (req, res, next) => {
  // Get Authorization header
  const authHeader = req.headers.authorization;
 
  if (!authHeader || !authHeader.startsWith('Basic ')) {
    // If no credentials provided, request authentication
    res.setHeader('WWW-Authenticate', 'Basic realm="API Authentication"');
    return res.status(401).json({ message: 'Authentication required' });
  }
 
  // Extract and decode credentials
  const encodedCredentials = authHeader.split(' ')[1];
  const decodedCredentials = Buffer.from(encodedCredentials, 'base64').toString('utf-8');
  const [username, password] = decodedCredentials.split(':');
 
  // Validate credentials
  const user = users.find(u => u.username === username && u.password === password);
 
  if (!user) {
    res.setHeader('WWW-Authenticate', 'Basic realm="API Authentication"');
    return res.status(401).json({ message: 'Invalid credentials' });
  }
 
  // Attach user to request
  req.user = { username: user.username };
 
  next();
};

// Protected route
app.get('/api/data', basicAuth, (req, res) => {
  res.json({
    message: 'Data accessed',
    user: req.user.username,
    data: { example: 'Sensitive data' }
  });
});

// Start server
app.listen(8080, () => {
  console.log('Server running on port 8080');
});

Ko‘p faktorli autentifikatsiya (MFA)

Vaqtga asoslangan bir martalik parollar (TOTP) bilan qo‘shimcha xavfsizlik qatlamini qo‘shish:

const express = require('express');
const bodyParser = require('body-parser');
const speakeasy = require('speakeasy');
const QRCode = require('qrcode');
const jwt = require('jsonwebtoken');
const app = express();

app.use(bodyParser.json());

// In-memory database (use a real database in production)
const users = [];
const JWT_SECRET = 'your-jwt-secret-key';

// Step 1: Register a user and set up MFA
app.post('/register', (req, res) => {
  const { username, password } = req.body;
 
  // Check if user already exists
  if (users.find(u => u.username === username)) {
    return res.status(400).json({ message: 'Username already exists' });
  }
 
  // Generate secret for TOTP
  const secret = speakeasy.generateSecret({
    name: `MyApp:${username}`
  });
 
  // Create user
  const newUser = {
    id: users.length + 1,
    username,
    password, // In production, hash passwords!
    mfaSecret: secret.base32,
    mfaEnabled: false
  };
 
  users.push(newUser);
 
  // Generate QR code for TOTP setup
  QRCode.toDataURL(secret.otpauth_url, (err, dataUrl) => {
    if (err) {
      return res.status(500).json({ message: 'Error generating QR code' });
    }
   
    res.json({
      message: 'User registered. Please set up MFA.',
      user: {
        id: newUser.id,
        username: newUser.username
      },
      mfaSecret: secret.base32,
      qrCode: dataUrl
    });
  });
});

// Step 2: Verify and enable MFA
app.post('/verify-mfa', (req, res) => {
  const { username, token } = req.body;
 
  // Find user
  const user = users.find(u => u.username === username);
 
  if (!user) {
    return res.status(404).json({ message: 'User not found' });
  }
 
  // Verify token against user's secret
  const verified = speakeasy.totp.verify({
    secret: user.mfaSecret,
    encoding: 'base32',
    token
  });
 
  if (!verified) {
    return res.status(400).json({ message: 'Invalid MFA token' });
  }
 
  // Enable MFA for user
  user.mfaEnabled = true;
 
  res.json({ message: 'MFA enabled successfully' });
});

// Step 3: Login with MFA
app.post('/login', (req, res) => {
  const { username, password } = req.body;
 
  // Find user
  const user = users.find(u => u.username === username && u.password === password);
 
  if (!user) {
    return res.status(401).json({ message: 'Invalid credentials' });
  }
 
  // Check if MFA is enabled
  if (user.mfaEnabled) {
    return res.json({
      message: 'Password verified. MFA token required.',
      requireMFA: true,
      userId: user.id
    });
  }
 
  // If MFA not enabled, generate token directly
  const token = jwt.sign(
    { id: user.id, username: user.username },
    JWT_SECRET,
    { expiresIn: '1h' }
  );
 
  res.json({ message: 'Login successful', token });
});

// Step 4: Verify MFA token and complete login
app.post('/verify-login', (req, res) => {
  const { userId, mfaToken } = req.body;
 
  // Find user
  const user = users.find(u => u.id === userId);
 
  if (!user) {
    return res.status(404).json({ message: 'User not found' });
  }
 
  // Verify MFA token
  const verified = speakeasy.totp.verify({
    secret: user.mfaSecret,
    encoding: 'base32',
    token: mfaToken
  });
 
  if (!verified) {
    return res.status(401).json({ message: 'Invalid MFA token' });
  }
 
  // Generate JWT token
  const token = jwt.sign(
    { id: user.id, username: user.username },
    JWT_SECRET,
    { expiresIn: '1h' }
  );
 
  res.json({ message: 'Login successful', token });
});

// Start server
app.listen(8080, () => {
  console.log('Server running on port 8080');
});

Xavfsizlik bo‘yicha eng yaxshi amaliyotlar

Muhim: Autentifikatsiyani amalga oshirishda xavfsizlik ixtiyoriy emas. Ilova va foydalanuvchilaringizni himoya qilish uchun ushbu eng yaxshi amaliyotlarga amal qiling.

Parol xavfsizligi

  • Hech qachon oddiy matn parollarini saqlamang - Har doim bcrypt yoki Argon2 kabi kuchli xeshlash algoritmlaridan foydalaning
  • Kuchli parollarni kiritish - Minimal uzunlik, maxsus belgilar va raqamlarni talab qiling
  • Parolni aylantirishni amalga oshirish - Foydalanuvchilarga parollarni vaqti-vaqti bilan o‘zgartirishni taklif qiling

Token xavfsizligi

  • Qisqa muddatli kirish tokenlaridan foydalaning - odatda 15-60 daqiqa
  • Yangilash tokenlarini amalga oshirish - Qayta autentifikatsiyasiz yangi kirish tokenlarini olish uchun
  • Tokenlarni xavfsiz saqlash - Veb-ilovalar uchun faqat HTTP, xavfsiz, bir xil sayt cookie-fayllaridan foydalaning

Umumiy xavfsizlik

  • Har doim HTTPS dan foydalaning - Barcha trafikni shifrlash
  • Tezlikni cheklashni amalga oshirish - Qo‘pol kuch hujumlarining oldini oling
  • Xavfsizlik sarlavhalaridan foydalaning - CSP, X-Content-Type-Options, X-Frame-Options kabi
  • Jurnal va monitoring - Autentifikatsiya urinishlarining audit jurnallarini saqlang

OAuth 2.0 xavfsizligi

  • PKCE’dan foydalaning - Ochiq mijozlar (mobil/native ilovalar) uchun
  • Qayta yo‘naltirish URI’larini tekshirish - Ochiq qayta yo‘naltirish zaifliklarining oldini olish
  • Mijoz sirlarini xavfsiz saqlang - Versiya boshqaruvida hech qachon

Misol: bcrypt bilan xavfsiz parolni xeshlash

const bcrypt = require('bcrypt');
const saltRounds = 10;

// Hashing a password
async function hashPassword(plainPassword) {
  return await bcrypt.hash(plainPassword, saltRounds);
}

// Verifying a password
async function verifyPassword(plainPassword, hashedPassword) {
  return await bcrypt.compare(plainPassword, hashedPassword);
}

API autentifikatsiyasini amalga oshirishda xavfsizlikning eng yaxshi amaliyotlariga amal qiling:

  • Faqat HTTPS: tranzitdagi ma’lumotlarni shifrlash uchun har doim HTTPS-dan foydalaning
  • Parolni xeshlash: Faqat xeshlangan parollarni bcrypt yoki Argon2 yordamida saqlang
  • Tokenlarni boshqarish: Tokenlarni qisqa muddatda saqlang va yangilash tokenlarini amalga oshiring
  • So‘rovlarni cheklash (Rate limiting): shafqatsiz kuch hujumlaridan himoya qiling
  • Kirishni tekshirish: Inyeksiya hujumlarining oldini olish uchun barcha foydalanuvchi kiritishlarini tasdiqlang
  • CORS konfiguratsiyasi: o‘zaro kelib chiqish so‘rovlarini mos ravishda cheklang
  • Xavfsiz sarlavhalar: HSTS va CSP kabi xavfsizlik sarlavhalarini joriy qiling
  • Audit jurnali: Xavfsizlik monitoringi uchun autentifikatsiya hodisalari jurnali

Misol: Bcrypt yordamida parolni xeshlash

const bcrypt = require('bcrypt');
const express = require('express');
const bodyParser = require('body-parser');
const app = express();

app.use(bodyParser.json());

// In-memory user database
const users = [];

// Register route with password hashing
app.post('/register', async (req, res) => {
  try {
    const { username, password } = req.body;
   
    // Check if username already exists
    if (users.find(u => u.username === username)) {
      return res.status(400).json({ message: 'Username already taken' });
    }
   
    // Hash password
    const saltRounds = 10;
    const hashedPassword = await bcrypt.hash(password, saltRounds);
   
    // Create new user
    const newUser = {
      id: users.length + 1,
      username,
      password: hashedPassword
    };
   
    users.push(newUser);
   
    res.status(201).json({
      message: 'User registered successfully',
      userId: newUser.id
    });
  } catch (error) {
    res.status(500).json({ message: 'Error registering user' });
  }
});

// Login route with password comparison
app.post('/login', async (req, res) => {
  try {
    const { username, password } = req.body;
   
    // Find user
    const user = users.find(u => u.username === username);
   
    if (!user) {
      return res.status(401).json({ message: 'Invalid credentials' });
    }
   
    // Compare password with stored hash
    const passwordMatch = await bcrypt.compare(password, user.password);
   
    if (!passwordMatch) {
      return res.status(401).json({ message: 'Invalid credentials' });
    }
   
    // In a real app, generate and return a token
    res.json({
      message: 'Login successful',
      userId: user.id
    });
  } catch (error) {
    res.status(500).json({ message: 'Error logging in' });
  }
});

// Start server
app.listen(8080, () => {
  console.log('Server running on port 8080');
});

Autentifikatsiya usullarini birlashtirish

Haqiqiy ilovalarda siz ko‘pincha bir nechta autentifikatsiya usullarini birlashtirishingiz kerak bo‘ladi:

// JWT authentication with API rate limiting and refresh tokens
const express = require('express');
const jwt = require('jsonwebtoken');
const rateLimit = require('express-rate-limit');
const bodyParser = require('body-parser');
const app = express();

app.use(bodyParser.json());

// Configure rate limiting
const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 5, // 5 attempts per window
  message: 'Too many login attempts, please try again later'
});

// JWT configuration
const JWT_SECRET = 'your-jwt-secret-key';
const JWT_REFRESH_SECRET = 'your-refresh-token-secret';

// Token storage (use a database in production)
const tokenBlacklist = new Set();
const refreshTokens = new Set();

// Login route with rate limiting
app.post('/login', loginLimiter, (req, res) => {
  const { username, password } = req.body;
 
  // Authentication logic (simplified)
  if (username !== 'user1' || password !== 'password1') {
    return res.status(401).json({ message: 'Invalid credentials' });
  }
 
  // Generate tokens
  const accessToken = jwt.sign(
    { id: 1, username },
    JWT_SECRET,
    { expiresIn: '15m' } // Short-lived access token
  );
 
  const refreshToken = jwt.sign(
    { id: 1, username },
    JWT_REFRESH_SECRET,
    { expiresIn: '7d' } // Longer-lived refresh token
  );
 
  // Store refresh token
  refreshTokens.add(refreshToken);
 
  res.json({
    message: 'Login successful',
    accessToken,
    refreshToken
  });
});

// Refresh token route
app.post('/refresh-token', (req, res) => {
  const { refreshToken } = req.body;
 
  if (!refreshToken) {
    return res.status(401).json({ message: 'Refresh token required' });
  }
 
  // Check if token exists and is not blacklisted
  if (!refreshTokens.has(refreshToken)) {
    return res.status(403).json({ message: 'Invalid refresh token' });
  }
 
  try {
    // Verify refresh token
    const decoded = jwt.verify(refreshToken, JWT_REFRESH_SECRET);
   
    // Generate new access token
    const accessToken = jwt.sign(
      { id: decoded.id, username: decoded.username },
      JWT_SECRET,
      { expiresIn: '15m' }
    );
   
    res.json({
      message: 'Token refreshed',
      accessToken
    });
  } catch (error) {
    // Remove invalid refresh token
    refreshTokens.delete(refreshToken);
   
    return res.status(403).json({ message: 'Invalid or expired refresh token' });
  }
});

// JWT verification middleware
const authenticateJWT = (req, res, next) => {
  const authHeader = req.headers.authorization;
 
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({ message: 'Authorization header required' });
  }
 
  const token = authHeader.split(' ')[1];
 
  // Check if token is blacklisted
  if (tokenBlacklist.has(token)) {
    return res.status(403).json({ message: 'Token revoked' });
  }
 
  try {
    // Verify token
    const decoded = jwt.verify(token, JWT_SECRET);
    req.user = decoded;
    next();
  } catch (error) {
    return res.status(403).json({ message: 'Invalid or expired token' });
  }
};

// Logout route
app.post('/logout', authenticateJWT, (req, res) => {
  const authHeader = req.headers.authorization;
  const token = authHeader.split(' ')[1];
  const { refreshToken } = req.body;
 
  // Blacklist the current access token
  tokenBlacklist.add(token);
 
  // Remove refresh token if provided
  if (refreshToken) {
    refreshTokens.delete(refreshToken);
  }
 
  res.json({ message: 'Logout successful' });
});

// Protected route
app.get('/protected', authenticateJWT, (req, res) => {
  res.json({
    message: 'Protected resource accessed',
    user: req.user
  });
});

// Start server
app.listen(8080, () => {
  console.log('Server running on port 8080');
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({ message: 'Authorization header required' });
  }

  const token = authHeader.split(' ')[1];

  // Check if token is blacklisted
  if (tokenBlacklist.has(token)) {
    return res.status(403).json({ message: 'Token revoked' });
  }

  try {
    // Verify token
    const decoded = jwt.verify(token, JWT_SECRET);
    req.user = decoded;
    next();
  } catch (error) {
    return res.status(403).json({ message: 'Invalid or expired token' });
  }
});

// Logout route
app.post('/logout', authenticateJWT, (req, res) => {
  const authHeader = req.headers.authorization;
  const token = authHeader.split(' ')[1];
  const { refreshToken } = req.body;

  // Blacklist the current access token
  tokenBlacklist.add(token);

  // Remove refresh token if provided
  if (refreshToken) {
    refreshTokens.delete(refreshToken);
  }

  res.json({ message: 'Logout successful' });
});

// Protected route
app.get('/protected', authenticateJWT, (req, res) => {
  res.json({
    message: 'Protected resource accessed',
    user: req.user
  });
});

// Start server
app.listen(8080, () => {
  console.log('Server running on port 8080');
});

Autentifikatsiya uchun HTTP sarlavhalari

API autentifikatsiyasini amalga oshirishda ishlatiladigan HTTP sarlavhalari juda muhim:

  • Authorization header: Bu JWT, OAuth va Basic Auth kabi ko‘pgina API autentifikatsiya strategiyalarida autentifikatsiya tokenlarini yuborish uchun ishlatiladigan standart HTTP sarlavhasi.
  • Umumiy format: JWT va OAuth 2.0 uchun Authorization: Bearer <token>
  • Asosiy autentifikatsiya formati: Authorization: Basic <base64-encoded-credentials>

Turli xil API turlari uchun autentifikatsiya strategiyalari

API turi Tavsiya etilgan autentifikatsiya Mulohazalar
Umumiy API API kalitlari Amalga oshirish oddiy, foydalanishni kuzatish uchun yaxshi
Xizmatdan xizmatga API JWT (stateless) yoki Mutual TLS Minimal yuk, yuqori xavfsizlik
Mobil/veb-ilova API OAuth 2.0 + JWT Yaxshi foydalanuvchi tajribasi, uchinchi tomon autentsiyasini boshqaradi
Bitta sahifali dastur API Yangilash tokenlari bilan JWT Front-end frameworklar bilan yaxshi ishlaydi
IoT Device API Mijoz sertifikatlari yoki API kalitlari Cheklangan qurilma imkoniyatlarini boshqaradi

Xulosa

Node.js API uchun asosiy autentifikatsiya usullari bilan tanishib chiqdingiz. Mana biz ko‘rib chiqqan narsalarning qisqacha tavsifi:

Autentifikatsiya usullari

  • Seansga asoslangan - Server tomonidagi seanslardan foydalanadigan an’anaviy yondashuv
  • JWT Tokens - Taqsimlangan tizimlar uchun stateless (ichki state saqlamaydigan) (stateless) tokenlar
  • OAuth 2.0 - uchinchi tomon autentifikatsiyasi uchun sanoat standarti
  • API kalitlari - Serverdan serverga ulanish uchun oddiy autentifikatsiya

Xavfsizlik asoslari

  • Har doim HTTPS dan foydalaning
  • bcrypt/Argon2 bilan hash parollar
  • Qisqa muddatli tokenlardan foydalaning
  • Tezlikni cheklashni amalga oshirish


W3Schools Pathfinder

Yutuqlaringizni kuzating – bu bepul!