Introduction
APIs are now the primary way applications talk to each other — mobile apps, single-page frontends, partner integrations, and internal microservices all communicate over APIs, often exposed directly to the internet. Because APIs are consumed by software rather than viewed by a human in a browser, some of the assumptions that protect traditional web pages don't apply, and API-specific controls are needed.
Cricket analogy: Just as IPL franchises now exchange player data and live scores directly between team apps and broadcasters via feeds rather than a fan reading a scoreboard, APIs let mobile apps and microservices talk machine-to-machine, so they need their own gatekeeping instead of relying on a human noticing a suspicious screen.
Explanation
Authentication for APIs typically uses API keys for service-to-service calls or OAuth access tokens for delegated user access, rather than browser cookies and login forms. Every request to a protected endpoint should present valid, verifiable credentials, and those credentials should be scoped as narrowly as possible — a key that only needs to read data should not also be able to write or delete it. Rate limiting caps how many requests a given client, key, or IP address can make in a time window; without it, an API is exposed to brute-force credential attacks, scraping, and denial-of-service style abuse, and a single compromised key can be throttled rather than allowed to hammer the backend without limit. Input validation matters just as much for APIs as for web forms — every field in a JSON or XML payload, every query parameter, and every path segment is attacker-controlled and must be validated for type, length, format, and business-rule correctness before use, exactly as with any other untrusted input. Finally, 'security through obscurity' — leaving an endpoint undocumented or hard to guess but with no real authentication or authorization check — is not a security control. Anyone who discovers the URL, whether through a leaked mobile app binary, browser dev tools, or simple guessing, gets full access; obscurity can be a minor speed bump at best, never a substitute for enforcing real authentication and authorization.
Cricket analogy: A stadium checks every player's official BCCI accreditation badge before letting them onto the field, and a substitute fielder's pass only permits fielding, not batting, just as scoped API keys should permit only the specific action needed, like read but not write.
Example
# BEFORE: unauthenticated 'hidden' endpoint, no validation, no rate limiting
@app.route("/internal/reset-usage-XJ29") # security through obscurity
def reset_usage(request):
account_id = request.args["account_id"]
db.execute(f"UPDATE accounts SET usage=0 WHERE id={account_id}")
return "ok"
# AFTER: real auth, scoped API key, input validation, rate limiting
@app.route("/api/v1/accounts/<account_id>/usage/reset")
@require_api_key(scope="usage:write")
@rate_limit(max_requests=5, per_seconds=60)
def reset_usage_secure(request, account_id, api_key):
if not account_id.isdigit():
raise ValueError("Invalid account_id")
if not api_key.owns_account(int(account_id)):
raise PermissionError("Not authorized for this account")
db.execute("UPDATE accounts SET usage=0 WHERE id=%s", (int(account_id),))
return {"status": "ok"}Analysis
The 'before' endpoint relies entirely on its URL being hard to guess, has no authentication, builds SQL unsafely, and has no cap on how often it can be called — four independent weaknesses stacked on top of each other. The 'after' version requires a scoped API key (so only clients with usage:write can call it), checks that the key's owner actually controls the target account (authorization, not just authentication), validates the account_id format, uses a parameterized query, and rate-limits calls to stop abuse or brute-force account_id guessing. None of these controls depend on the URL staying secret, which is exactly the point: real security holds even after the endpoint is fully public knowledge.
Cricket analogy: A ground that only relies on fans not knowing the players' entrance, has no ticket check, lets anyone claim any seat, and never limits gate rushes is fixed by adding accreditation checks, seat-ownership verification, and crowd-flow limits, none of which depend on the gate staying secret.
Key Takeaways
- Authenticate every request with API keys or OAuth tokens, scoped to the minimum access needed.
- Rate limit requests per client to prevent brute-force, scraping, and abuse.
- Validate every field, query parameter, and path segment as untrusted input.
- Never rely on an endpoint being undocumented or hard to guess as a substitute for real authentication and authorization.
Practice what you learned
1. What is the main risk of relying on an undocumented, hard-to-guess API endpoint with no authentication?
2. Why is rate limiting important for API security?
3. An API key that only needs to read order data is instead granted full read/write/delete access. What principle does this violate?
4. Why must API input validation be applied even though the client is 'just calling an API' rather than submitting an HTML form?
Was this page helpful?
You May Also Like
Authentication Basics
Learn how systems verify identity through authentication, how it differs from authorization, and the three factor categories used to prove who you are.
Access Control Models
Compare DAC, MAC, and RBAC access control models and understand who decides permissions in each approach.
TLS/SSL Basics
Understand how the TLS handshake establishes a secure session, and why SSL is the deprecated predecessor to modern TLS.
Denial-of-Service Attacks
DoS vs DDoS explained, including botnets, and how rate limiting, scrubbing, and CDNs absorb attack traffic.