API authentication is the foundation of API security. It verifies which users, apps, or systems can call your endpoints, then blocks everything else. This guide shows how common API authentication methods work, when to use them, and how to implement and test them in real API workflows.
What is API Authentication?
API authentication is the process of verifying the identity of a client before allowing it to access an API.
A client can be:
- A frontend application
- A mobile app
- A backend service
- A third-party integration
- An internal microservice
- A developer using your API directly
Unlike traditional web apps, APIs usually do not rely on an interactive login screen for every request. Instead, clients send credentials programmatically, such as:
- API keys
- Basic Auth credentials
- Bearer tokens
- OAuth 2.0 access tokens
- JWTs
- Client certificates
The API server validates those credentials before processing the request.
A typical authenticated request looks like this:
GET /v1/data HTTP/1.1
Host: api.example.com
Authorization: Bearer <access_token>
If the credentials are valid, the API continues processing. If not, the API should return an error such as:
HTTP/1.1 401 Unauthorized
Why API Authentication Matters
API authentication helps you:
- Prevent unauthorized access to protected endpoints
- Protect sensitive data from leaks or misuse
- Apply access control based on users, apps, roles, or scopes
- Audit API usage by tracking who accessed what and when
- Build trust with users, partners, and internal teams
Without authentication, any exposed endpoint can become a security risk. Even internal APIs should be authenticated because network boundaries are not enough protection on their own.
How API Authentication Works
Most API authentication flows follow the same basic pattern:
- Issue credentials
The API provider or identity provider issues credentials to the client.
Examples:
- API key
- OAuth client credentials
- JWT
- TLS certificate
- Send credentials with the request
The client includes credentials in each API request, usually in an HTTP header.
Authorization: Bearer <token>
- Validate credentials
The API server validates the credential by checking:
- Signature
- Expiration time
- Issuer
- Audience
- Scope or permissions
- Revocation status
- Allow or reject the request
If authentication succeeds, the API processes the request. If it fails, the API returns an error.
HTTP/1.1 401 Unauthorized
Authentication confirms identity. Authorization decides what that identity is allowed to do.
Common API Authentication Methods
1. API Key Authentication
API keys are unique strings assigned to clients. The client sends the key with every request.
Example:
GET /v1/data HTTP/1.1
Host: api.example.com
x-api-key: 12345abcdef
You can also see API keys passed as query parameters:
GET /v1/data?api_key=12345abcdef HTTP/1.1
Host: api.example.com
However, headers are usually preferred because query parameters can appear in logs, analytics tools, browser history, and proxies.
When to use API keys
Use API keys for:
- Internal tools
- Simple server-to-server integrations
- Public APIs with low-risk data
- Usage tracking and rate limiting
Pros
- Easy to implement
- Easy for developers to use
- Useful for identifying calling applications
Cons
- Often all-or-nothing unless paired with permissions
- Can be leaked or shared
- No built-in user identity
- No automatic expiration unless you implement it
Implementation checklist
- Store API keys hashed, not as plaintext
- Send keys in headers, not URLs
- Add key rotation support
- Add rate limits per key
- Log key ID, not the raw key
- Support revocation
Example server-side validation logic:
app.get("/v1/data", async (req, res) => {
const apiKey = req.header("x-api-key");
if (!apiKey) {
return res.status(401).json({ error: "Missing API key" });
}
const keyRecord = await findApiKey(apiKey);
if (!keyRecord || keyRecord.revoked) {
return res.status(401).json({ error: "Invalid API key" });
}
return res.json({ data: "protected resource" });
});
2. HTTP Basic Authentication
Basic Authentication sends a username and password encoded with Base64.
Example:
GET /v1/data HTTP/1.1
Host: api.example.com
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
The encoded value is not encrypted. It is only Base64-encoded, so Basic Auth must always be used over HTTPS.
When to use Basic Auth
Use Basic Auth for:
- Simple internal systems
- Development or testing environments
- Low-complexity service authentication
Avoid it for production public APIs unless you have a specific reason and strong transport security.
Pros
- Simple
- Supported by most HTTP clients
- Easy to test with cURL, Postman, or API tooling
Cons
- Sends credentials with every request
- No built-in token expiration
- No session management
- Not ideal for production APIs
Example with cURL:
curl -u username:password https://api.example.com/v1/data
3. Bearer Token Authentication
Bearer token authentication uses a token issued after a successful authentication flow. The client sends that token in the Authorization header.
Example:
GET /v1/data HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
The server grants access to whoever presents a valid token. Because of that, bearer tokens must be protected like passwords.
When to use bearer tokens
Use bearer tokens for:
- User login flows
- Mobile apps
- Single-page applications
- Backend APIs
- OAuth 2.0 access tokens
- JWT-based authentication
Pros
- Supports expiration
- Can support revocation
- Works well with modern auth systems
- More flexible than API keys
Cons
- Requires token issuing and validation infrastructure
- Leaked tokens can be used until they expire or are revoked
- Requires careful storage on the client side
Example request with JavaScript:
const response = await fetch("https://api.example.com/v1/data", {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
const data = await response.json();
4. OAuth 2.0
OAuth 2.0 is a protocol for delegated access. It allows an application to access resources on behalf of a user without handling the user’s password directly.
A typical OAuth 2.0 flow:
- User clicks “Connect”
- User authenticates with the OAuth provider
- User grants requested permissions
- Provider issues an access token
- Client calls the API using that token
Example API request:
GET /v1/profile HTTP/1.1
Host: api.example.com
Authorization: Bearer <oauth_access_token>
When to use OAuth 2.0
Use OAuth 2.0 for:
- Third-party integrations
- User-delegated access
- Social login flows
- SaaS integrations
- APIs requiring granular scopes
Pros
- Supports scopes and delegated permissions
- Avoids sharing passwords with third-party apps
- Widely adopted
- Works well for partner ecosystems
Cons
- More complex than API keys or Basic Auth
- Requires token lifecycle management
- Requires redirect flows for some grant types
- Misconfiguration can create security gaps
Example scopes:
read:profile
write:posts
delete:comments
Your API should validate that the access token includes the required scope before allowing the request.
Example authorization check:
function requireScope(requiredScope) {
return (req, res, next) => {
const tokenScopes = req.user?.scopes || [];
if (!tokenScopes.includes(requiredScope)) {
return res.status(403).json({ error: "Insufficient scope" });
}
next();
};
}
app.delete("/v1/comments/:id", requireScope("delete:comments"), deleteComment);
5. JWT Authentication
JWT stands for JSON Web Token. A JWT is a compact token format that contains claims and is cryptographically signed.
A JWT commonly contains information such as:
- Subject/user ID
- Issuer
- Audience
- Expiration time
- Roles
- Permissions
- Metadata
Example:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
A decoded JWT payload might look like this:
{
"sub": "user_123",
"iss": "https://auth.example.com",
"aud": "https://api.example.com",
"role": "admin",
"exp": 1735689600
}
When to use JWT
Use JWT for:
- Stateless API authentication
- Microservices
- APIs that need signed identity claims
- Systems where services validate tokens independently
Pros
- Stateless validation
- Can include roles and permissions
- Works well in distributed systems
- Often used with OAuth 2.0 and OpenID Connect
Cons
- Revocation can be difficult
- Large tokens increase request size
- Claims can become stale
- Must validate signatures and expiration correctly
JWT validation checklist:
- Verify the signature
- Check
exp - Check
iss - Check
aud - Reject unsigned tokens
- Do not trust decoded claims before verification
- Use short expiration times
Example JWT validation in Node.js:
import jwt from "jsonwebtoken";
function authenticateJwt(req, res, next) {
const authHeader = req.header("Authorization");
if (!authHeader?.startsWith("Bearer ")) {
return res.status(401).json({ error: "Missing bearer token" });
}
const token = authHeader.slice("Bearer ".length);
try {
const payload = jwt.verify(token, process.env.JWT_PUBLIC_KEY, {
algorithms: ["RS256"],
issuer: "https://auth.example.com",
audience: "https://api.example.com",
});
req.user = payload;
next();
} catch {
return res.status(401).json({ error: "Invalid token" });
}
}
6. Mutual TLS Authentication
Mutual TLS, or mTLS, requires both the server and the client to authenticate each other using certificates.
Normal TLS verifies the server to the client. mTLS also verifies the client to the server.
When to use mTLS
Use mTLS for:
- Service-to-service authentication
- Financial APIs
- Internal microservices
- High-security partner integrations
- Zero-trust infrastructure
Pros
- Strong client authentication
- Resistant to credential replay
- Useful for machine-to-machine communication
Cons
- Certificate management can be complex
- Not ideal for public consumer APIs
- Requires operational maturity
mTLS is often combined with other methods, such as OAuth 2.0 or JWT, for layered security.
API Authentication Best Practices
1. Always Use HTTPS
Never send API keys, passwords, or tokens over plaintext HTTP.
Use:
https://api.example.com
Avoid:
http://api.example.com
HTTPS protects credentials in transit.
2. Never Log Raw Credentials
Do not log:
- API keys
- Access tokens
- Refresh tokens
- Passwords
- Authorization headers
Instead, log safe identifiers.
Bad:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Better:
token_id=tok_123
user_id=user_456
3. Apply Least Privilege
Give each client only the permissions it needs.
For example, do not give a reporting tool write access if it only needs to read analytics data.
Use scopes or roles:
read:orders
write:orders
admin:orders
4. Rotate Credentials
Support regular key and token rotation.
A practical rotation flow:
- Client creates a new key
- Client deploys the new key
- Client verifies traffic works
- Client disables the old key
- Server rejects the old key
Avoid forcing clients to rotate credentials with downtime.
5. Use Short-Lived Tokens
Access tokens should expire.
Example:
{
"access_token": "...",
"expires_in": 3600
}
Use refresh tokens when longer sessions are required.
6. Support Revocation
You need a way to revoke compromised credentials.
Support revocation for:
- API keys
- Refresh tokens
- OAuth clients
- Certificates
- User sessions
7. Monitor Authentication Events
Track events such as:
- Failed login attempts
- Invalid token usage
- Expired token usage
- API key usage spikes
- Requests from unusual IPs or regions
- Repeated
401or403responses
Authentication logs help detect abuse before it becomes a larger incident.
8. Return the Right Status Codes
Use clear HTTP status codes.
401 Unauthorized
Use when authentication is missing or invalid.
403 Forbidden
Use when authentication succeeded but the client does not have permission.
Example:
{
"error": "insufficient_scope",
"message": "The token does not include write:orders"
}
9. Avoid Hardcoding Credentials
Do not commit credentials to source control.
Bad:
const API_KEY = "abc123xyz";
Better:
const API_KEY = process.env.API_KEY;
Use environment variables or a secrets manager.
10. Test Authentication Before Deployment
Test these cases:
- Missing credentials
- Invalid credentials
- Expired token
- Revoked token
- Valid token with insufficient scope
- Valid token with correct scope
- Malformed authorization header
- Requests over HTTP if applicable
- Rate limits for authenticated clients
Implementing API Authentication with Apidog
Apidog is a spec-driven API development platform for designing, documenting, and testing APIs, including authentication flows.
You can use Apidog in your API workflow to:
- Define authentication schemes in your API specifications
- Document how clients should authenticate
- Test authenticated requests
- Debug authentication failures before deployment
- Mock authenticated API responses for frontend or integration testing
This is useful because authentication should be part of the API contract, not an afterthought.
For example, when documenting an endpoint, include:
- Required authentication method
- Required headers
- Token format
- Required scopes or roles
- Example success response
- Example
401response - Example
403response
Example endpoint documentation:
GET /v1/orders HTTP/1.1
Host: api.example.com
Authorization: Bearer <access_token>
Required scope:
read:orders
Possible authentication error:
{
"error": "unauthorized",
"message": "Missing or invalid access token"
}
By designing and testing authentication as part of the API lifecycle, you reduce integration errors and make your API easier for developers to consume.
Real-World API Authentication Examples
Example 1: Public API Secured with API Keys
A weather data provider exposes a public API. Developers register and receive an API key.
Request:
GET /weather/today?city=London HTTP/1.1
Host: api.weather.example
x-api-key: abc123xyz
The server should:
- Validate the key
- Identify the calling app
- Apply rate limits
- Log usage
- Reject revoked keys
Example response:
{
"city": "London",
"temperature": 18,
"condition": "Cloudy"
}
Example 2: OAuth 2.0 for Third-Party Integrations
A social media platform allows users to connect third-party apps.
Flow:
- User clicks “Connect with SocialMedia”
- User authenticates with SocialMedia
- User grants permissions
- SocialMedia issues an access token
- The third-party app calls the API
Request:
GET /v1/me/posts HTTP/1.1
Host: api.socialmedia.example
Authorization: Bearer eyJhbGciOi...
The API validates:
- Token signature
- Token expiration
- User identity
- Granted scopes
Example 3: JWT for Internal Microservices
A microservices system uses JWT for stateless authentication.
Flow:
- User logs in
- Auth service issues a signed JWT
- API gateway validates the JWT
- Internal services validate or trust the forwarded identity depending on the architecture
Request:
GET /v1/account HTTP/1.1
Host: api.internal.example
Authorization: Bearer <jwt>
Services should validate:
- Signature
- Expiration
- Issuer
- Audience
- Required role or permission
Example 4: mTLS for Financial APIs
A bank exposes APIs to fintech partners.
Both sides use certificates:
- The client verifies the bank API server certificate
- The bank verifies the client certificate
- Requests from unknown clients are rejected before application-level processing
This approach is useful when API access must be restricted to trusted systems.
Common API Authentication Pitfalls
Avoid these mistakes:
- Hardcoding credentials in source code or frontend bundles
- Sending API keys in URLs where they can leak through logs
- Using API keys alone for sensitive user data
- Ignoring token expiration
- Failing to validate JWT signatures
- Trusting decoded JWT claims before verification
- Not supporting revocation
- Logging raw tokens
- Returning vague errors that make debugging impossible
- Returning overly detailed errors that leak security information
- Skipping monitoring for authentication failures
API Authentication Implementation Checklist
Before shipping an authenticated API, verify that you have:
- [ ] HTTPS enforced
- [ ] Authentication required on protected endpoints
- [ ] Credentials sent through headers
- [ ] Token expiration configured
- [ ] Revocation supported
- [ ] Least-privilege permissions or scopes
- [ ] Safe logging
- [ ] Rate limiting per client or identity
- [ ] Monitoring for failed authentication attempts
- [ ] Clear
401and403responses - [ ] Authentication documented for developers
- [ ] Authenticated requests tested before deployment
Conclusion
API authentication is required for securing modern APIs. Choose the method based on your use case:
- Use API keys for simple app identification and basic access control.
- Use Basic Auth only for simple or limited scenarios, always over HTTPS.
- Use Bearer tokens for modern authenticated API access.
- Use OAuth 2.0 for delegated third-party access.
- Use JWT for signed, stateless identity claims.
- Use mTLS for high-security service-to-service authentication.
Start by reviewing your current authentication setup. Then document the required credentials, test failure cases, add monitoring, and make credential rotation and revocation part of your API lifecycle.
Top comments (0)