...

Checklist for Developers to Build Secure APIs

Picture of Apurva Prakash
Apurva Prakash
Marketing Manager @ AppSentinels

APIs were already ubiquitous in driving modern applications. However, the pandemic has further accelerated growth in innovation and expansion of digital services, making APIs even more widespread. In today’s world, rapid innovation would not be possible without secure APIs.

Attacks on APIs are increasing exponentially. Gartner suggests API abuses are the most significant attack vector since 2022. Hence securing APIs is more critical than ever in the past.

OWASP came up with a separate list of techniques used against API called OWASP API Top-10. A revision of the same is planned for 2023. Here’s a developers’ checklist to build Secure APIs based on techniques outlined in OWASP API Top-10.

Broken object-level authorization

APIs tend to expose endpoints that handle object identifiers, creating a broad attack surface Level Access Control issue. Object-level authorization checks should be considered in every function that accesses a data source using input from the user. Checklist:

  • Implement authorization checks for every object access.
  • Do not rely on IDs sent by the client. Instead use IDs stored in session object.
  • Check authorization for each client request to access database.
  • Use random IDs that cannot be guessed (UUIDs).

Broken authentication

Authentication mechanisms are often implemented incorrectly, allowing attackers to compromise authentication tokens or exploit implementation flaws to assume other users’ identities temporarily or permanently. Compromising a system’s ability to identify the client/user compromises API security overall.

  • Validate every APIs for authentication needs. Any API left unauthenticated should be reviewed and signed-off by multiple owners.
  • Use industry standard Authentication mechanism. Use standard authentication, token generation, password storage, and multi-factor authentication (MFA).
  • Check all possible ways to Authenticate APIs and stick to one. Better off to implement a centralized auth module built at the API Ingress (API Gateway or API Management)
  • APIs for password reset and one-time links allow users to authenticate and should be protected just as rigorously.
  • Use short-lived access tokens.
  • Use stricter rate-limiting for authentication and implement lockout policies and weak password checks.

Excessive data exposure

Looking forward to generic implementations, developers tend to expose all object properties without considering their sensitivity, relying on clients to filter data before displaying it to the user.

  • Review all API responses and adapt them to match the API consumers’ needs.
  • Carefully define schemas for all the API responses.
  • Never rely on the client to filter data!
  • Do not forget API Error Responses; define schemas for errors as well.
  • Identify all the sensitive data or Personally Identifiable Information (PII) and justify its use.
  • Enforce response checks to prevent accidental leaks of data or exceptions.
  • Monitor API response data response and exfiltration of sensitive data.

Lack of resources and rate limiting

APIs do not impose any restrictions on the size or number of resources that can be requested by the client/user. Not only can this impact the API server performance, leading to Denial of Service (DoS), but it also leaves the door open to authentication flaws such as brute force.

  •  Must implement rate limiting at a user level.
  • Tailor the rate-limiting to match needs of clients & API methods.
  • Limit payload sizes.
  • Add checks on compression ratios.

Broken function level authorization

Complex access control policies with different hierarchies, groups, and roles, and an unclear separation between administrative and regular functions, tend to lead to authorization flaws. By exploiting these issues, attackers gain access to other users’ resources and/or administrative functions.

  •  Ideally maintain different authentication schemes for Admin functions.
  • Deny all admin access by default.
  • Allow operations only to users belonging to the appropriate group or role.
  • Never rely on the client application to enforce admin access.

Mass assignment

Binding client-provided data (e.g., JSON) to data models without proper filtering properties based on a safelist usually leads to Mass Assignment. Either guessing object properties, exploring other API endpoints, reading the documentation, or providing additional object properties in request payloads, allows attackers to modify object properties they are not supposed to. 

  •  Do not automatically bind incoming data and internal objects.
  • Explicitly define all the parameters and payloads you are expecting.
  • Use the read-Only property set to true in object schemas for all properties that can be retrieved through APIs but should never be modified.
  • Precisely define the schemas, types, and patterns you will accept in requests at design time and enforce them at runtime.

Security misconfiguration

Security misconfiguration is commonly a result of unsecure default configurations, incomplete or ad-hoc configurations, open cloud storage, misconfigured HTTP headers, unnecessary HTTP methods, permissive Cross-Origin resource sharing (CORS), and verbose error messages containing sensitive information.

  • Automate locating configuration flaws using scanners/pen-test tools.
  • Disable unnecessary features in deployed packages/applications.
  • Restrict administrative access.
  • Implement strict authentication, redirects, CORS, and so forth.
  • Define and enforce all outputs, including errors.

Injection

Injection flaws, such as SQL, NoSQL, Command Injection, etc., occur when untrusted data is sent to an interpreter as part of a command or query. The attacker’s malicious data can trick the interpreter into executing unintended commands or accessing data without proper authorization.

  • Never trust your API consumers, even if they are internal.
  • Strictly define all input data, such as schemas, types, and string patterns, and enforce them at runtime.
  • Validate, filter, and sanitize all incoming data.
  • Define, limit, and enforce API outputs to prevent data leaks.

Improper assets management

APIs tend to expose more endpoints than traditional web applications, making proper and updated documentation highly important. Suitable hosts and deployed API versions inventory also play an important role to mitigate issues such as deprecated API versions and exposed debug endpoints.

  • Keep an up-to-date inventory of all API hosts.
  • Properly retire old versions of APIs or backport security fixes to them.
  • Limit access to anything that should not be public.
  • Limit access to production data, and segregate access to production and non-production data.

Insufficient logging and monitoring

Insufficient logging and monitoring, coupled with missing or ineffective integration with incident response, allows attackers to attack systems further, maintain persistence, pivot to more systems to tamper with, extract, or destroy data. Most breach studies demonstrate the time to detect a breach is over 200 days, typically detected by external parties rather than internal processes or monitoring.

  • Log failed attempts, denied access, input validation failures, or any failures in security policy checks.
  • Ensure that logs are formatted so that other tools can consume them.
  • Protect logs like highly sensitive information.
  • Include enough detail to identify attackers.
  • Avoid having sensitive data in logs — if you need the information for debugging purposes, redact it partially.
  • Integrate with SIEMs and other dashboards, monitoring, and alerting tools.

Frequently Asked Questions

Why should developers be the first line of API security defense rather than the last?+

Developers build API security in or out through their design and implementation choices and retrofitting security after deployment is exponentially more expensive and disruptive than building it correctly initially. Every authorization check not implemented, every field unnecessarily returned in a response, and every missing rate limit creates a vulnerability that downstream security tools must try to compensate for. The cost of a security fix in code review is a few minutes; the cost of fixing a production API with active consumers can involve versioning strategy, migration communications, and extended vulnerability exposure windows. Security as a developer responsibility reduces total organizational security cost dramatically.

What is the most important authorization check developers consistently forget to implement?+

The most consistently missed check is per-object authorization validation that is verifying that the authenticated user requesting object ID X is actually authorized to access that specific object, not just that they’re authenticated to call the API. Developers often implement function-level checks (is this user authenticated to call this endpoint?) but skip the crucial second question (is this authenticated user allowed to access this specific record?). This gap directly enables BOLA – the single most prevalent and dangerous API vulnerability. Every function accessing a data object using user-provided identifiers needs an explicit ownership or permission check before returning data.

How should developers approach implementing rate limiting, and what mistakes are commonly made?+

Effective rate limiting requires setting limits appropriate to legitimate use cases and not so tight that valid users are disrupted, not so loose that automated attacks proceed unimpeded. Common mistakes include: implementing global rate limits only (one limit for all endpoints regardless of sensitivity), applying limits per IP rather than per user (trivially bypassed with rotating proxies), and setting limits without a corresponding response strategy (throttling is more useful than hard blocking for avoiding denial-of-service errors for legitimate users). Different endpoints need differentiated limits: authentication endpoints need much tighter limits than data retrieval endpoints due to their specific attack exposure.

What is the difference between allowlist-based and blocklist-based input validation, and which should developers use?+

Blocklist validation rejects inputs matching known bad patterns (e.g., SQL keywords, script tags), but attackers continuously discover new patterns that bypass blocklists through encoding variations, obfuscation, or novel injection techniques. Allowlist validation accepts only inputs matching explicitly defined valid patterns and rejects everything else example: an unknown input format is rejected by default rather than allowed. Developers should use allowlist validation for all API inputs because it’s fundamentally secure by default. The implementation cost is higher (you must define what valid looks like for every field) but the security guarantee is substantially stronger than blocklist approaches that play perpetual catch-up with attacker creativity.

What does secure API versioning look like, and how should developers plan for deprecation from day one?+

Secure API versioning means explicitly including version identifiers in API paths or headers, maintaining a documented deprecation timeline for each version, and communicating retirement dates to consumers well in advance. From day one, developers should design APIs with versioning in mind and enabling security improvements to be deployed in new versions while maintaining backward compatibility for existing consumers through time-limited old version support. Deprecation plans should include: consumer migration support, firm retirement dates publicly communicated, monitoring of traffic to deprecated versions to catch unmigrated consumers, and ultimately hard shutdowns rather than leaving deprecated versions running indefinitely.

Why should security testing be built into CI/CD pipelines rather than done as a separate, periodic activity?+

Security testing in CI/CD pipelines catches vulnerabilities at the moment of introduction, the specific commit where a developer accidentally removed an authorization check or added an endpoint without authentication. Periodic security testing catches these vulnerabilities weeks or months later, after the vulnerable code has been deployed and potentially exploited. CI/CD-integrated testing also normalizes security as a development activity rather than a compliance event, reducing the psychological separation between “security team work” and “developer work” that leads to security being treated as someone else’s responsibility in the software delivery process.

Table of Contents

Related Content