Apr 5, 202612 min read
API Security: Fundamentals You Shouldn’t Ignore
Learn the fundamentals of API security, including authentication, authorization, OAuth, JWT validation, rate limiting, secret management, input validation, logging, and testing.

APIs are supposed to make things easier.
A mobile app talks to a backend. A sales platform exchanges data with accounting software. One service sends information to another. Different systems work together without someone manually moving data between them.
But that convenience comes with another reality:
An API is often one of the most direct paths to your business data and logic.
If that path is not properly protected, a polished frontend or secure-looking application will not help much.
API security is not simply about putting a token in front of every endpoint. You need to know who is making the request, what they are allowed to access, which actions they can perform, how often they can do it, and whether unusual behavior will be noticed when it happens.
OWASP’s current API Security Top 10 places risks such as Broken Object Level Authorization, Broken Authentication, Broken Object Property Level Authorization, Unrestricted Resource Consumption, and Broken Function Level Authorization near the top of the list.
So a good place to start is with one simple question:
Should this request actually be allowed to do this?
Authentication and Authorization Are Not the Same Thing
These two concepts are often mentioned together, but they solve different problems.
Authentication answers:
Who are you?
For example:
- This request belongs to a specific user.
- This client belongs to the finance system.
- This service presented valid credentials.
Authorization asks a different question:
Now that we know who you are, what exactly are you allowed to do?
A user may be fully authenticated and still have no right to view another customer’s order.
An employee may be allowed to view customer records but not delete them.
An API client may be valid but only need access to one narrow scope.
This distinction matters because many serious API vulnerabilities are not caused by failed authentication.
They are caused by valid users being allowed to do too much.
A Valid Token Does Not Mean a Valid Action
Imagine an API endpoint like this:
GET /orders/18427
The user is logged in.
The access token is valid.
Is that enough?
No.
The backend still needs to verify that order 18427 actually belongs to that user, or that the user has permission to view it.
If someone can change:
18427
to:
18428
and suddenly see another customer’s order, you have a classic Broken Object Level Authorization, or BOLA, problem.
This is one of the most common and important API security risks.
The rule should not be:
The user is authenticated, so access is allowed.
A better rule is:
The user is authenticated. Now verify that they are allowed to access this specific object and perform this specific action.
Endpoint-Level Access Control Is Not Enough
Security is not only about whether someone can access /admin.
Sometimes the object itself contains fields that different users should not see or modify.
Imagine a customer API returns:
- Name
- Phone number
- National ID
- Role
- Account status
- Internal risk score
The frontend may only display the first three.
But if the API returns everything, hiding fields in the interface is not security.
The same problem appears with updates.
If a user can send:
role=admin
along with a normal profile update, and the backend accepts it, the application has a property-level authorization problem.
APIs should explicitly define:
- Which properties can be read
- Which properties can be modified
- Which roles or scopes are allowed to do so
The frontend is not a security boundary.
Apply Least Privilege From the Beginning
If an integration only needs to read inventory, why should it be able to delete products?
If a reporting service only reads data, why does it need write permissions?
If an access token is issued for one API, why should it automatically work against five others?
The principle of Least Privilege means every user, service, and token receives only the minimum access required to do its job.
In OAuth-based systems, scopes and resource-specific authorization can help make these boundaries more precise.
Extra permission may not create a visible problem today.
But if a credential is exposed tomorrow, every unnecessary permission increases the blast radius.
If You Use OAuth, Do Not Copy Old Patterns Blindly
OAuth 2.0 has been around for years, which means there is a huge amount of old example code and outdated guidance online.
Some of it is no longer considered good security practice.
In January 2025, the IETF published RFC 9700: Best Current Practice for OAuth 2.0 Security, updating OAuth security guidance based on years of real-world implementation experience.
A few points matter in particular.
Authorization Code + PKCE
PKCE should not be treated as something only mobile applications need.
Modern OAuth security guidance applies PKCE broadly, including web applications where appropriate.
For code challenges, S256 is the recommended approach.
Implicit Grant
The Implicit flow exposes access tokens more directly in authorization responses and carries additional token leakage and replay risks.
Modern guidance recommends moving away from it in favor of Authorization Code flow.
Resource Owner Password Credentials Grant
The recommendation here is even clearer:
Do not use it.
This flow requires the client to handle the user’s username and password directly, which expands the attack surface and weakens the separation OAuth is supposed to provide.
The practical lesson is simple:
If you are designing authentication today, a five-year-old blog post should not be your security standard.
JWT Is Not Magic
JWT is a common way to carry claims between systems.
Using JWT does not automatically make a system secure.
A common misconception is:
The information is inside a JWT, so it must be protected.
Not necessarily.
A JWT can be signed, encrypted, or both.
A signed JWT can still expose its payload to anyone who receives it.
So sensitive data should not be placed in a token simply because the token is signed.
Secure JWT validation should also go beyond checking that a signature exists.
Depending on the architecture, you may need to validate claims such as:
iss— Who issued the token?aud— Which service was the token intended for?exp— Has it expired?nbf— Is it valid yet?- And is the signing algorithm one that the application explicitly allows?
A secure implementation should never blindly accept whichever algorithm the token itself asks for.
Do Not Turn an API Key Into a Universal Password
API keys are useful in the right context.
They can identify clients, meter usage, restrict access to a service, or support rate limiting.
But an API key alone is not always enough for high-value or sensitive resources.
More importantly, keys should not live in places where they are easy to leak.
- Not in source code.
- Not in a Docker image.
- Not in client-side JavaScript.
- Not in configuration files passed casually between teams.
Secrets such as API keys, database credentials, certificates, and SSH keys should be stored centrally, access-controlled, audited, and rotated when necessary.
A good secret is not one that never changes.
It is one that you can control and rotate safely.
Treat Every Input as Untrusted
Even requests coming from internal systems, partners, or trusted vendors should not bypass validation.
External data is still external data.
Validation should usually happen at two levels.
Syntactic Validation
Is the data structurally valid?
For example:
- Is this field really an integer?
- Is the date in the expected format?
- Is the string too long?
- Does the JSON match the expected schema?
Semantic Validation
Does the value make sense in the business context?
For example:
- Can order quantity be negative?
- Can an end date come before a start date?
- Can a discount be 800%?
- Is this user actually allowed to move the order into that status?
Framework validators and JSON Schema help with structure.
Business rules still need to be enforced by the backend.
Rate Limiting Is Not Just About DDoS
Imagine a login endpoint with no limit.
An attacker can try thousands of credentials.
An OTP endpoint can send thousands of messages.
A report-generation API can consume large amounts of compute.
An AI endpoint may create real cost every time it is called.
OWASP groups this kind of risk under Unrestricted Resource Consumption.
Rate limiting can be designed around:
- IP address
- User
- API key
- Client
- Tenant
- Endpoint
- Or even the cost of an operation
A simple GET request and a request that consumes several minutes of CPU do not necessarily deserve the same limit.
Rate limiting is not just infrastructure protection.
It can be part of the business logic of the API.
Protect Sensitive Business Flows Too
Sometimes every individual request is valid, but the overall behavior is abusive.
For example:
- Buying all available stock of a limited product automatically
- Creating large numbers of fake accounts
- Reserving every available time slot
- Generating thousands of coupon requests
- Abusing a password recovery process
Authentication may work correctly.
Authorization may also work correctly.
The problem is abuse of a sensitive business flow.
This is why OWASP includes Unrestricted Access to Sensitive Business Flows as a separate API risk.
Depending on the scenario, protection may require:
- Rate limiting
- Anti-automation controls
- Risk scoring
- Behavioral detection
- Or human verification
The protection should match the value of the workflow being abused.
Do Not Blindly Trust Other APIs
Your own API may be secure and still depend on ten external services.
- A payment gateway
- A CRM
- A shipping provider
- An AI API
- A webhook
- An identity provider
- A partner integration
Data returned by those systems still needs to be treated carefully.
One of the risks OWASP highlights is Unsafe Consumption of APIs: developers sometimes trust external services too much and apply weaker validation, transport security, authentication, or response handling.
A third-party response is not automatically a trusted response.
Be Careful When APIs Accept URLs
Some APIs accept user-supplied URLs.
Examples include:
- Webhook URLs
- Image URLs
- Callback URLs
- Import-from-URL features
- PDF generators
- Preview services
- Integration endpoints
If your server blindly makes requests to whatever URL it receives, an attacker may be able to reach internal resources that are not normally exposed to the internet.
This is known as Server-Side Request Forgery, or SSRF.
For any feature that accepts URLs, you should carefully control:
- Allowed destinations
- Protocols
- Redirect behavior
- Private network ranges
- And outbound network access
The fact that your server can reach something does not mean the user should be able to make it do so.
Do Not Forget Old API Versions
APIs have a habit of surviving longer than expected.
A new version appears:
/api/v3
But:
/api/v1
is still available on the public internet.
Nobody is quite sure who still uses it.
Nobody wants to turn it off.
This becomes an inventory problem.
You should know:
- Which APIs exist?
- Who owns each one?
- Which versions are active?
- Which are public?
- Which are internal?
- Which are deprecated?
- When should they be retired?
Documentation is not only a developer-experience feature.
It is part of security.
An API you do not know exists is much harder to protect.
Production Is Not the Place for Debug Mode
A secure application can still become vulnerable through bad configuration.
Examples include:
- Debug mode enabled
- Default credentials
- Overly permissive CORS
- Public administrative endpoints
- Unnecessary HTTP methods
- Weak TLS configuration
- Stack traces in error messages
- Overly broad default permissions
Production should have production-specific configuration.
Not a development environment with a new domain name.
HTTPS Is Still Non-Negotiable
Tokens, cookies, API keys, and sensitive data should not travel over unprotected connections.
TLS should protect API communication end to end where appropriate.
And this is not only about login endpoints.
If an API carries credentials or sensitive data, the entire communication path must be protected.
Log What You Will Need During an Investigation
Security is not only about preventing incidents.
You also need to understand what happened after something suspicious occurs.
Useful API security logs may include:
- Who made the request?
- Which endpoint was called?
- What operation was attempted?
- Did it succeed or fail?
- Why was authorization denied?
- Which object was targeted?
- Where did the request come from?
- When did it happen?
- What is the correlation ID?
But logging can create its own security problem if you record too much.
Do not casually log:
- Passwords
- Full access tokens
- Secrets
- Private keys
- Or unnecessary sensitive personal information
Logs are security data.
They need protection too.
Do Not Leave API Security Testing Until the End
If security testing only happens one week before release, an architectural issue can become extremely expensive to fix.
Security checks should be part of the development lifecycle.
Useful tests may include:
- Unit tests for authorization
- Integration tests for roles and permissions
- BOLA tests using two separate identities
- Schema validation tests
- Rate-limit tests
- JWT validation tests
- Dependency scanning
- Secret scanning
- SAST
- DAST
- Tests for deprecated or forgotten endpoints
Security should not be the final gate at the end of the pipeline.
It should be part of the Definition of Done.
A Practical API Security Checklist
| Area | Question |
|---|---|
| Authentication | Is the identity of the user or client verified appropriately? |
| Authorization | Is every request checked at both function and object level? |
| Properties | Can users only read and modify allowed fields? |
| Least Privilege | Do tokens and services have only the permissions they need? |
| OAuth | Are current security best practices being followed? |
| JWT | Are signature, algorithm, issuer, audience, and expiry validated? |
| Secrets | Are API keys and credentials managed outside source code? |
| Input | Is external data validated syntactically and semantically? |
| Rate Limiting | Is resource consumption and abuse controlled? |
| Business Flows | Are sensitive workflows protected from automation and abuse? |
| Third Parties | Are external API responses treated as untrusted input? |
| SSRF | Are user-provided URLs and callbacks restricted and validated? |
| Inventory | Does every API and version have a known owner and lifecycle? |
| Transport | Is API communication protected with TLS? |
| Logging | Can security events be traced without leaking secrets? |
| Testing | Is API security testing part of CI/CD and release processes? |
Where Does API Security Actually Start?
Not with buying an API gateway.
Not with JWT.
Not with OAuth.
And not even with a WAF.
Those are tools.
API security begins with defining the trust boundary correctly.
- Who is entering the system?
- What are they allowed to read?
- What can they change?
- How often can they do it?
- Which data is allowed to leave the system?
- And if something unusual happens, will anyone notice?
Secure APIs are rarely the result of one impressive security feature.
They are usually the result of many small decisions made correctly.
Every request should be allowed to do exactly what it needs to do—and nothing more.