Cesa Yazılım
TR EN DE

AMP • TR

API Security 2025: REST, GraphQL, WebSocket Güvenliği

API güvenliği, OAuth2, JWT, rate limiting, API gateway ve GraphQL security best practices 2025.

API Security 2025

API'ler modern uygulamaların bel kemiği. Güvenlik açıkları kritik risk oluşturuyor. Kapsamlı API güvenlik rehberi.

OWASP API Security Top 10

  1. Broken Object Level Authorization - En yaygın
  2. Broken Authentication
  3. Broken Object Property Level Authorization
  4. Unrestricted Resource Consumption
  5. Broken Function Level Authorization
  6. Unrestricted Access to Sensitive Business Flows
  7. Server Side Request Forgery (SSRF)
  8. Security Misconfiguration
  9. Improper Inventory Management
  10. Unsafe Consumption of APIs

Authentication & Authorization

OAuth 2.0 Flow

// Authorization Code Flow
app.get('/auth', (req, res) => {
  const authUrl = `https://oauth.provider.com/authorize?
    client_id=${CLIENT_ID}&
    redirect_uri=${REDIRECT_URI}&
    response_type=code&
    scope=read write&
    state=${generateState()}`;
  res.redirect(authUrl);
});

app.get('/callback', async (req, res) => {
  const { code, state } = req.query;
  
  // Verify state (CSRF protection)
  if (!verifyState(state)) {
    return res.status(401).send('Invalid state');
  }
  
  // Exchange code for token
  const tokens = await exchangeCodeForToken(code);
  
  // Store tokens securely
  storeTokens(tokens);
  
  res.redirect('/dashboard');
});

JWT (JSON Web Tokens)

const jwt = require('jsonwebtoken');

// Generate JWT
function generateToken(user) {
  return jwt.sign(
    {
      sub: user.id,
      email: user.email,
      role: user.role
    },
    process.env.JWT_SECRET,
    {
      expiresIn: '1h',
      issuer: 'api.example.com',
      audience: 'example.com'
    }
  );
}

// Verify JWT
function verifyToken(token) {
  try {
    return jwt.verify(token, process.env.JWT_SECRET, {
      issuer: 'api.example.com',
      audience: 'example.com'
    });
  } catch (error) {
    throw new Error('Invalid token');
  }
}

// Middleware
function authenticateJWT(req, res, next) {
  const token = req.headers.authorization?.split(' ')[1];
  
  if (!token) {
    return res.status(401).json({ error: 'No token provided' });
  }
  
  try {
    const decoded = verifyToken(token);
    req.user = decoded;
    next();
  } catch (error) {
    return res.status(403).json({ error: 'Invalid token' });
  }
}

Rate Limiting

const rateLimit = require('express-rate-limit');
const RedisStore = require('rate-limit-redis');
const redis = require('redis');

const client = redis.createClient();

// Global rate limit
const globalLimiter = rateLimit({
  store: new RedisStore({ client }),
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // 100 requests per window
  message: 'Too many requests, please try again later'
});

// Endpoint-specific rate limit
const strictLimiter = rateLimit({
  store: new RedisStore({ client }),
  windowMs: 60 * 1000, // 1 minute
  max: 5, // 5 requests per minute
  message: 'Rate limit exceeded'
});

// Apply
app.use('/api/', globalLimiter);
app.post('/api/login', strictLimiter, loginHandler);

Input Validation

const Joi = require('joi');

// Validation schema
const userSchema = Joi.object({
  email: Joi.string().email().required(),
  password: Joi.string().min(8).pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/).required(),
  age: Joi.number().integer().min(18).max(120),
  username: Joi.string().alphanum().min(3).max(30).required()
});

// Validate middleware
function validateUser(req, res, next) {
  const { error, value } = userSchema.validate(req.body);
  
  if (error) {
    return res.status(400).json({
      error: 'Validation failed',
      details: error.details.map(d => d.message)
    });
  }
  
  req.validatedData = value;
  next();
}

app.post('/api/users', validateUser, createUser);

API Gateway Security

# Kong API Gateway configuration
services:
  - name: user-service
    url: http://user-service:8080
    
plugins:
  # Authentication
  - name: jwt
    config:
      secret_is_base64: false
      key_claim_name: kid
      
  # Rate limiting
  - name: rate-limiting
    config:
      minute: 100
      hour: 1000
      policy: redis
      
  # IP restriction
  - name: ip-restriction
    config:
      whitelist:
        - 10.0.0.0/8
        - 172.16.0.0/12
        
  # CORS
  - name: cors
    config:
      origins:
        - https://app.example.com
      credentials: true
      max_age: 3600

GraphQL Security

const { ApolloServer } = require('apollo-server');
const depthLimit = require('graphql-depth-limit');
const { createComplexityLimitRule } = require('graphql-validation-complexity');

const server = new ApolloServer({
  typeDefs,
  resolvers,
  
  // Query depth limiting
  validationRules: [
    depthLimit(10), // Max query depth: 10
    createComplexityLimitRule(1000) // Max complexity: 1000
  ],
  
  // Disable introspection in production
  introspection: process.env.NODE_ENV !== 'production',
  playground: process.env.NODE_ENV !== 'production',
  
  // Context with auth
  context: ({ req }) => {
    const token = req.headers.authorization;
    const user = verifyToken(token);
    return { user };
  },
  
  // Error handling
  formatError: (error) => {
    // Don't expose internal errors
    if (error.message.startsWith('Database')) {
      return new Error('Internal server error');
    }
    return error;
  }
});

API Security Testing

# OWASP ZAP API scan
zap-cli quick-scan --spider -r https://api.example.com

# Postman security tests
pm.test("No sensitive data in response", function () {
    pm.expect(pm.response.text()).to.not.include("password");
    pm.expect(pm.response.text()).to.not.include("secret");
});

pm.test("Proper auth required", function () {
    pm.sendRequest({
        url: pm.environment.get("API_URL") + "/admin",
        method: "GET"
    }, function (err, res) {
        pm.expect(res.code).to.equal(401);
    });
});

Best Practices Checklist

Authentication:

Authorization:

Data:

Rate Limiting:

Monitoring:


API security danışmanlığı: iletisim@cesayazilim.com 🔐