Script Valley
REST API Development: Complete Course from Beginner to Production
Authentication and Security in REST APIsLesson 4.2

API Key Authentication and Role-Based Access Control

API keys, API key generation, API key middleware, RBAC, role-based access control, permissions, admin middleware, resource ownership

API Key Authentication and Role-Based Access Control

JWT is ideal for user-facing authentication, but machine-to-machine API communication often uses API keys — long random tokens that identify and authenticate a service or client application. Role-Based Access Control (RBAC) then determines what authenticated users or services are allowed to do.

DiagramRole-Based Access Control (RBAC)

IMAGE PROMPT (replace this block with your generated image):

Flat access control matrix diagram on white background. Title: Role-Based Access Control (RBAC). Left column: three user role icons stacked vertically — a basic user icon labeled User, a star icon labeled Moderator, a crown icon labeled Admin. Each row is a different color: User row light gray, Moderator row light #3A5EFF (#e8ecff), Admin row solid #3A5EFF with white text. Right side: a grid of API endpoint columns — GET /posts, POST /posts, DELETE /posts, GET /admin/stats, DELETE /users/:id. Each cell shows either a green checkmark circle (allowed) or a red X circle (not allowed). User: can GET /posts, cannot POST, DELETE, admin routes. Moderator: can GET and POST /posts, cannot DELETE or admin routes. Admin: can do everything. Below the matrix: a small legend — green = allowed, red = forbidden. Brand color #3A5EFF for admin row and column headers. White background.

API Key Design

A good API key is a cryptographically random string of sufficient length (at least 32 bytes). Prefix it with a service identifier for easier identification: sk_live_a1b2c3d4e5f6.... Never send API keys as URL query parameters (they end up in server logs). Send them in the Authorization header or a custom X-API-Key header.

const crypto = require('crypto');

const generateApiKey = () => {
  return 'sk_live_' + crypto.randomBytes(32).toString('hex');
};

API Key Middleware

const apiKeyAuth = async (req, res, next) => {
  const key = req.headers['x-api-key'];
  if (!key) return res.status(401).json({ error: { code: 'API_KEY_MISSING' } });

  const hashedKey = crypto.createHash('sha256').update(key).digest('hex');
  const client = await ApiClient.findOne({ keyHash: hashedKey, isActive: true });

  if (!client) return res.status(401).json({ error: { code: 'API_KEY_INVALID' } });
  req.client = client;
  next();
};

Store only the hash of the API key in the database — never the plaintext. This way, a database breach does not expose active keys.

Role-Based Access Control

const authorize = (...roles) => (req, res, next) => {
  if (!roles.includes(req.user.role)) {
    return res.status(403).json({
      success: false,
      error: { code: 'FORBIDDEN', message: 'Insufficient permissions' }
    });
  }
  next();
};

router.delete('/:id', protect, authorize('admin'), deleteUser);

Up next

REST API Security: CORS, Helmet, Rate Limiting, and Input Sanitization

Sign in to track progress