DEV Community

Preecha
Preecha

Posted on

API Authentication: Complete Guide & Best Practices

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.

Try Apidog today

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>
Enter fullscreen mode Exit fullscreen mode

If the credentials are valid, the API continues processing. If not, the API should return an error such as:

HTTP/1.1 401 Unauthorized
Enter fullscreen mode Exit fullscreen mode

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:

  1. Issue credentials

The API provider or identity provider issues credentials to the client.

Examples:

  • API key
  • OAuth client credentials
  • JWT
  • TLS certificate
  1. Send credentials with the request

The client includes credentials in each API request, usually in an HTTP header.

   Authorization: Bearer <token>
Enter fullscreen mode Exit fullscreen mode
  1. Validate credentials

The API server validates the credential by checking:

  • Signature
  • Expiration time
  • Issuer
  • Audience
  • Scope or permissions
  • Revocation status
  1. 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

You can also see API keys passed as query parameters:

GET /v1/data?api_key=12345abcdef HTTP/1.1
Host: api.example.com
Enter fullscreen mode Exit fullscreen mode

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" });
});
Enter fullscreen mode Exit fullscreen mode

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=
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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...
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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:

  1. User clicks “Connect”
  2. User authenticates with the OAuth provider
  3. User grants requested permissions
  4. Provider issues an access token
  5. 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>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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...
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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" });
  }
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Avoid:

http://api.example.com
Enter fullscreen mode Exit fullscreen mode

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...
Enter fullscreen mode Exit fullscreen mode

Better:

token_id=tok_123
user_id=user_456
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

4. Rotate Credentials

Support regular key and token rotation.

A practical rotation flow:

  1. Client creates a new key
  2. Client deploys the new key
  3. Client verifies traffic works
  4. Client disables the old key
  5. 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
}
Enter fullscreen mode Exit fullscreen mode

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 401 or 403 responses

Authentication logs help detect abuse before it becomes a larger incident.

8. Return the Right Status Codes

Use clear HTTP status codes.

401 Unauthorized
Enter fullscreen mode Exit fullscreen mode

Use when authentication is missing or invalid.

403 Forbidden
Enter fullscreen mode Exit fullscreen mode

Use when authentication succeeded but the client does not have permission.

Example:

{
  "error": "insufficient_scope",
  "message": "The token does not include write:orders"
}
Enter fullscreen mode Exit fullscreen mode

9. Avoid Hardcoding Credentials

Do not commit credentials to source control.

Bad:

const API_KEY = "abc123xyz";
Enter fullscreen mode Exit fullscreen mode

Better:

const API_KEY = process.env.API_KEY;
Enter fullscreen mode Exit fullscreen mode

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 401 response
  • Example 403 response

Example endpoint documentation:

GET /v1/orders HTTP/1.1
Host: api.example.com
Authorization: Bearer <access_token>
Enter fullscreen mode Exit fullscreen mode

Required scope:

read:orders
Enter fullscreen mode Exit fullscreen mode

Possible authentication error:

{
  "error": "unauthorized",
  "message": "Missing or invalid access token"
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
}
Enter fullscreen mode Exit fullscreen mode

Example 2: OAuth 2.0 for Third-Party Integrations

A social media platform allows users to connect third-party apps.

Flow:

  1. User clicks “Connect with SocialMedia”
  2. User authenticates with SocialMedia
  3. User grants permissions
  4. SocialMedia issues an access token
  5. The third-party app calls the API

Request:

GET /v1/me/posts HTTP/1.1
Host: api.socialmedia.example
Authorization: Bearer eyJhbGciOi...
Enter fullscreen mode Exit fullscreen mode

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:

  1. User logs in
  2. Auth service issues a signed JWT
  3. API gateway validates the JWT
  4. 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>
Enter fullscreen mode Exit fullscreen mode

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 401 and 403 responses
  • [ ] 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)