API Security, Authentication and Authorization Questions
Controlling who can call an API, what they may do, and defending it against abuse. Covers the access-control mechanics: API keys, OAuth 2.0 flows, OpenID Connect, JWT issuance/validation, session vs. token auth, scopes/roles for fine-grained authorization, token lifetime and refresh, mutual TLS, and machine-to-machine vs. user-delegated access. Also covers the adversarial hardening view: input validation, injection and deserialization risks, broken object-level authorization (BOLA), mass assignment, secrets handling, and the OWASP API Security Top 10, plus securing data in transit, preventing enumeration/scraping, and testing APIs for vulnerabilities.
Explain OAuth 2.0 concepts relevant to APIs: scope-driven authorization, access tokens (JWT vs opaque), refresh tokens, and token revocation. Compare the trade-offs of short-lived JWTs with no introspection versus opaque tokens with centralized introspection for internal and external APIs.
Sample Answer
OAuth 2.0 access tokens carry scopes that declare exactly what the token is allowed to do, and whether the token itself is a self-contained JSON Web Token (JWT) or an opaque reference determines how fast you can shut it down early. For high-throughput internal services, prefer short-lived JWTs validated locally; for external clients or anything needing instant revocation, prefer opaque tokens backed by a centralized introspection endpoint.
Scopes: least-privilege authorization
A scope is a string like orders:read or orders:write that the client requests, the resource owner (or an admin, for machine clients) grants, and the resource server checks on every call. Keep scopes small and specific rather than one broad full_access scope, this is what limits the damage if a token leaks.
Access tokens: JWT vs opaque
| JWT (self-contained) | Opaque token | |
|---|---|---|
| Validation | Local signature check, no network call | Requires an introspection call to the authorization server |
| Revocation | Hard, the server can't unsign a token others still hold | Immediate, the authorization server just marks it invalid |
| Latency | Fast, no round trip | Adds one round trip (mitigated with a short-TTL local cache) |
| Best fit | Internal, high-throughput, latency-sensitive calls | External clients, anything needing fast, auditable revocation |
Refresh tokens
A refresh token is a longer-lived credential used to obtain a new access token without forcing the user to log in again. Issue it only to clients that can store it securely, and rotate it on every use: each refresh call returns a brand-new refresh token and invalidates the one just used. If that now-invalid refresh token is ever presented again, treat it as evidence of theft and revoke the whole token family, not just the one request.
Revocation
Two standard endpoints matter here: a revocation endpoint (RFC 7009) that lets a client or admin explicitly kill a token, and an introspection endpoint (RFC 7662) that lets a resource server ask "is this token still valid?" For self-contained JWTs, since you can't recall a token that's already out in the world, revocation in practice means short lifetimes plus an optional deny-list check for high-risk operations.
Worked example
Access token TTL is 600 seconds (10 minutes). Suppose it leaks at the 120-second mark. For a bare JWT with no introspection, there is no revocation path, so the exposure window is bounded only by the remaining lifetime: 600 - 120 = 480 seconds. For an opaque token with introspection, an admin can call the revocation endpoint the moment theft is confirmed, so the exposure window is however long detection and response take, which can be far shorter than 480 seconds, or, if detection is slow, could exceed it. The trade-off is not "which is always safer" but "which failure mode you're designing for": a bounded-but-fixed window (JWT) versus a variable-but-potentially-instant one (opaque + introspection).
Trade-offs and pitfalls
For internal microservices, short-lived signed JWTs with automated key rotation avoid the fan-out load that calling introspection on every internal request would create. For external or regulated APIs, opaque tokens with a scalable, cached introspection layer buy immediate revocation and centralized auditing. A caching layer in front of introspection helps performance but reintroduces a small revocation-lag window of its own, so keep that cache's TTL well under the access token's TTL, not equal to it. A common wrong turn is assuming "JWTs are stateless, so we don't need any server-side state", that's true for routine reads, but you still need somewhere to record and check revocation for anything sensitive enough to outlive its own trust.
You operate a mixed monolith + microservices environment. For security controls (authentication, authorization, rate limiting, input/schema validation, transport security), decide which responsibilities should be enforced at the API gateway/proxy and which should remain inside services. Justify choices with availability, security, and performance trade-offs and propose testing and observability to validate enforcement.
Sample Answer
Direct answer
Push the checks that are cheap, universal, and identity-only to the gateway (authentication verification, transport security, coarse rate limiting, structural request validation), and keep the checks that need business or ownership context inside the service (fine-grained authorization, business-aware rate limiting, semantic validation). Never treat the gateway's decision as the only check: services should still re-verify authorization even for traffic they assume already passed the gateway, because a bypass or misconfiguration at the gateway should not be the single point of failure for data access.
Structured elaboration
| Control | At the gateway | Inside the service | Why the split |
|---|---|---|---|
| Authentication | Verify token signature and expiry once, forward a verified identity to downstream services | Trust the forwarded identity, do not re-parse raw credentials | Cheap and identical for every route; centralizing it avoids every service wiring its own token validation |
| Authorization | Coarse: is this identity allowed to call this route at all | Fine-grained: does this specific caller own this specific resource | The gateway has no idea which record ID belongs to which user; that context lives only in the service |
| Rate limiting | Global/per-key throttling to protect the whole platform from volume abuse | Business-aware limiting (e.g. failed login attempts per account) that needs domain state | The gateway can count requests; it cannot reason about "too many wrong passwords for this specific account" |
| Input/schema validation | Structural: does the payload match the declared shape, reject malformed junk early | Semantic: is this SKU real, is there enough stock, do these fields make business sense together | Structural checks are cheap and universal; semantic checks require the service's own data |
| Transport security | TLS termination for client-to-gateway traffic | Mutual TLS or a service mesh for gateway-to-service and service-to-service hops | Encrypting only the outer hop leaves the internal network unauthenticated between services |
Worked example
A checkout request hits the gateway without a valid token: the gateway rejects with 401 before the order service, inventory service, or payment service ever see it, saving three services from processing traffic that was never going to be allowed. A validly authenticated request for PATCH /orders/482 is forwarded with a verified user-id header; the order service still checks that the caller actually owns order 482 before applying the patch, because the gateway only confirmed "this is a real, authenticated user," not "this user owns this specific order." If that service-side ownership check were removed on the assumption the gateway already handled it, any authenticated user could edit any order by changing the ID in the URL, which is exactly the Broken Object Level Authorization pattern, one of the most reliably tested authorization failures in API interviews at any level.
Trade-offs & pitfalls
Availability: a gateway that is horizontally scaled and stateless is not a bigger single point of failure than any other tier, but a gateway that grows to hold business logic becomes a deploy bottleneck for every service behind it, so keep it thin on purpose.
Performance: the extra hop at the gateway adds latency, but it is repaid by filtering malformed or unauthenticated traffic before it costs any downstream service compute, which is a net win under load.
Security: defense in depth means the service re-checks authorization even though the gateway already made a coarse allow decision. A common pitfall is deleting service-side authorization checks because "the gateway already checks it," which turns a misrouted internal call, a compromised adjacent service, or a gateway misconfiguration into a full authorization bypass.
Testing and observability: run contract tests that assert the gateway's allowed routes and the service's own authorization rules agree, so they cannot silently drift apart. Run synthetic BOLA probes directly against services in a staging environment, bypassing the gateway entirely, to confirm services do not rely on the gateway as their only defense. Correlate logs across the gateway and every service hop with a shared request ID, track 401/403 rates and rate-limit rejections per route as standing metrics, and alert when the gateway's allow decision and a service's deny decision disagree for the same request, since that disagreement is itself a signal of policy drift between the two layers.
Propose detection and mitigation strategies for abusive API usage and credential theft at scale. Cover techniques such as per-key behavioral baselines, anomaly detection, per-key throttling and freezing, ephemeral credential issuance, credential rotation, fingerprinting, and forensics-ready logging while balancing privacy and performance.
Sample Answer
Build a per-key behavioral baseline, normal request rate, endpoints touched, geography, for every API key, score each new burst of activity against its own history rather than a single global threshold, and respond with graduated actions, soft throttle, then freeze, then full revoke, so a false positive costs a legitimate client a slowdown, not a hard outage.
Per-key behavioral baselines
Track, per key, over a rolling window (for example, 7 days): request rate, endpoint mix, typical payload size, source IP or geography, and time-of-day pattern. Use a decaying window, weighting recent activity more, so a key's baseline adapts as legitimate usage genuinely changes, without being so reactive that an attacker can slowly retrain the baseline toward their own behavior, cap how fast the baseline itself is allowed to shift per day.
Anomaly detection
Combine simple rules, an absolute rate ceiling, or a geographically impossible gap between two consecutive requests, with a statistical or machine-learning layer, unsupervised outlier detection (flagging unusual activity by comparing it to the shape of normal data, with no need for pre-labeled examples of "bad") over the same behavioral features, so you catch both obvious abuse and subtler drift. Score risk as a combination of signals rather than one metric alone, as shown in the worked example below.
Per-key throttling and freezing
Use a graduated response: soft throttle (a reduced rate limit) at a moderate anomaly score, freeze (block new requests, let existing sessions time out) at a high score, and full revoke only after freeze plus either automated corroboration or human review, so a single noisy signal doesn't take down a legitimate integration outright.
Ephemeral credential issuance and rotation
For high-privilege operations, issue short-lived, single-purpose credentials, minutes rather than months, rather than relying solely on the long-lived key. Rotate long-lived keys on a fixed cadence automatically, with a grace overlap so rotation itself never causes an outage.
Fingerprinting
Collect signals that aren't tied to a person's identity. A TLS client fingerprint is the common starting point, since it's cheap to capture at the TLS layer with no application changes; an HTTP header ordering fingerprint and a hashed device signal are rarer, higher-effort additions worth reaching for only once TLS fingerprinting alone isn't separating attackers from genuine clients. The goal is to distinguish "the same script hitting us from many rotated IPs" from genuinely independent clients, without needing to know who the human behind it is.
Forensics-ready logging, balancing privacy and performance
Keep an append-only, tamper-evident log of every mitigation decision, the score, the signals that fired, the action taken, so an incident can be reconstructed after the fact. Store raw request bodies only when a risk threshold is crossed, sampled or fully captured once triggered rather than captured for every request by default, so both storage cost and privacy exposure scale with actual risk.
Worked example
Key partner-key-77 has a 7-day baseline of 150 requests/hour, 95% from a stable IP range, touching a consistent mix of 4 endpoints. In one hour it makes 900 requests (6 times baseline), from a new IP range, hitting a 5th endpoint it has never called before. Define a risk score:
score = rate_ratio + new_ip_flag + new_endpoint_flag
rate_ratio = 900 / 150 = 6
new_ip_flag = 2 (a range never seen before)
new_endpoint_flag = 1 (one never-seen endpoint)
score = 6 + 2 + 1 = 9
Thresholds: score >= 4 triggers a soft throttle (halve this key's rate limit); score >= 8 triggers a freeze (block new requests, page security on-call); score >= 15 triggers auto-revoke pending review. At a score of 9, the key is frozen and a human is paged, but not auto-revoked, since a new endpoint plus an IP change could still reflect a legitimate deployment change on the partner's side. The human reviewer's job is to distinguish that from theft within the freeze window before deciding whether to restore or revoke.
Trade-offs and pitfalls
Graduated response reduces false-positive damage but adds an operational cost, someone has to staff the review queue between freeze and revoke, size that team for your expected alert volume before relying on it. Behavioral baselines that adapt too quickly can be gamed by an attacker who ramps up slowly, capping the daily rate of baseline drift bounds this risk. Full-fidelity request logging aids forensics but raises both storage cost and privacy exposure if applied to every request, trigger deeper capture only once risk crosses a threshold, and document the retention window for that captured data separately from normal logs.
A B2B customer integration needs strong authentication, auditability, and occasional offline batch transfers. Compare OAuth2 (confidential clients), mutual TLS, API keys, and JWT-based approaches for this scenario. Outline token lifecycle, rotation, scopes/least-privilege, revocation strategies, and developer ergonomics for each approach.
Sample Answer
No single mechanism wins outright here: use mutual TLS (mTLS) for strong machine identity at the transport layer, layered with OAuth 2.0 confidential-client tokens (JWTs, issued to a "confidential client": a client, like a backend server, that can securely hold a secret, unlike a mobile app or single-page app that can't) for fine-grained, auditable scopes, and treat plain API keys as the fallback for only the lowest-risk pieces of the integration.
Comparison across the four approaches
| Approach | Token lifecycle | Rotation | Scopes / least privilege | Revocation | Developer ergonomics |
|---|---|---|---|---|---|
| OAuth 2.0 (confidential client) | short-lived JWT access token plus a longer refresh token | rotate client secret periodically; rotate refresh token on use | scopes embedded in token, enforced by resource server | revoke refresh token, short access-token TTL bounds exposure | standard libraries, works for both online calls and scheduled batch renewal |
| Mutual TLS (mTLS) | a certificate presented per TLS connection, no separate token | certificate rotation via public key infrastructure (PKI), often automated | authenticates identity only; combine with a policy layer for fine-grained scopes | a certificate revocation list (CRL, a periodically-published list of revoked certificate serial numbers) or the Online Certificate Status Protocol (OCSP, a live per-certificate revocation check against the issuer) | strong security, heavier certificate-management burden on both sides |
| API keys | static, often long-lived | manual or scheduled | coarse; can map a key to a role but not fine-grained by default | immediate server-side disable, but no standard introspection protocol (a live network check with the issuer asking "is this credential still valid right now") | easiest to implement, weakest security, acceptable only for low-risk pieces with extra controls |
| JWT-based (self-contained) | short-lived recommended, verified locally via signature | rotate signing keys via published key IDs | scopes and roles embedded as claims, fine-grained and auditable | hard to revoke a stateless token early, mitigate with short TTL plus a revocation list for exceptions | very usable, especially for offline batch, since verification needs no live network call |
Why layer mTLS with OAuth for this scenario
mTLS answers "is this really the partner's server calling me" at the network layer, independent of any application-level credential, which matters for occasional offline batch transfers where a job might run without a live interactive session to refresh a token against. OAuth 2.0 confidential-client JWTs answer "what is this specific call allowed to do" with fine-grained, auditable scopes, something mTLS alone doesn't express. Plain API keys are kept only for the lowest-risk pieces (for example a status-check endpoint with no sensitive data) because they lack native scoping and revocation tooling.
Worked example
A partner runs a nightly batch job, no interactive user, sometimes running from a machine with intermittent connectivity, that uploads a settlement file. The batch job authenticates via mTLS using a certificate valid for 90 days, auto-renewed by an internal PKI service 30 days before expiry, so a job running mid-renewal still has a valid certificate. At call time it also presents a Client Credentials-issued JWT access token, TTL 15 minutes, scope settlements:write only. Because the JWT is self-contained and locally verifiable, the batch job can check its own token's expiry before starting an upload and pre-fetch a fresh one if needed, without a live back-and-forth handshake beyond the initial token request. That's the property that makes JWTs a good fit for the "occasional offline batch" requirement, compared with an opaque token that would need a live introspection call on every use.
Trade-offs and pitfalls
Requiring mTLS for every integration adds real onboarding cost, certificate issuance, renewal automation, partner-side competence, so reserve it for partners handling sensitive data or high transaction value rather than every low-risk integration. JWTs are convenient for offline batch specifically because they don't need a live call to verify, but that same property makes early revocation hard, keep the TTL short enough that a compromised token has a small blast radius even without a live revoke path. API keys are tempting for their simplicity but the weakest option across every dimension in the table above; if you must use them, add compensating controls (IP allowlisting, mandatory rotation, no export of cleartext after creation).
Build a secure, auditable data-sharing API for content partners (studios) to receive usage reports and aggregated metrics. Define authentication, authorization, data transformations/aggregation to protect PII and trade secrets, rate limits, schema versioning, and logging/auditing for access and changes.
Sample Answer
Give each studio partner an authenticated, scoped channel to pre-aggregated data only, never raw per-user records, so the privacy control is architectural, the API literally cannot return an individual's data, rather than something enforced purely by policy or trust.
Authentication and authorization
Mutual TLS (mTLS) for partner identity plus OAuth 2.0 Client Credentials tokens carrying resource-scoped claims (for example reports:monthly_views, reports:ad_breaks), so a studio can only request the report types their contract covers. Per-partner entitlements (which titles, which geographies) are stored centrally and checked on every request, not baked into the token at issuance, so a contract change takes effect without reissuing credentials.
Protecting PII and trade secrets through transformation
No raw per-user rows ever leave the aggregation boundary. Techniques, applied per field based on sensitivity:
- k-anonymity: suppress any aggregate group smaller than k rows (for example, "views by city" for a city with 3 viewers gets dropped or merged into a broader region), so no aggregate can be reverse-engineered to a single person.
- Bucketing and time-windowing: report "views per day," never a per-minute, per-user timeline.
- Differential privacy (calibrated random noise added to a released statistic): applied to the most sensitive aggregates, tunable per contract.
Rate limits and quotas
A per-partner token bucket, tiered by contract, with both daily and per-minute caps, since a partner running an automated nightly pull has very different burst needs than a live dashboard.
Schema versioning
Explicit versioned endpoints (/v1/reports, /v2/reports) or an Accept-Version header, with deprecation announced well ahead, for example 90/30/7-day notices, and both old and new versions live during the overlap.
Logging and auditing
Log every access: partner id, report type, filters requested, and the aggregation level actually returned, not the underlying raw data. Also log every change to a transformation policy, who changed the k-anonymity threshold and when, since a mis-set threshold is itself a privacy incident waiting to happen.
Worked example
A studio requests "daily views by city" for a title. Raw data: city "Elm Creek" had 3 viewers that day. With a k-anonymity threshold of k=10, any city-day group with fewer than 10 viewers is suppressed from the individual breakdown and rolled into an "other cities" bucket instead, Elm Creek's 3 viewers get folded in, so the partner never sees a number small enough to plausibly identify a single household. A city with 400 viewers that day passes through untouched, since 400 is well above the threshold of 10. If the studio's contract adds differential privacy on top for the top-line national number, calibrated random noise is added to the final published aggregate so even that released figure carries some irreducible uncertainty about any single viewer's contribution, rather than being an exact count.
Trade-offs and pitfalls
k-anonymity thresholds and differential-privacy noise reduce accuracy, too aggressive and the partner's report becomes useless (everything suppressed), too weak and it doesn't actually protect anyone, this threshold should be a documented, per-contract decision, not a guess. Logging the aggregation level actually returned, not just what was requested, matters because a transformation bug that accidentally returns finer-grained data than intended is itself the incident you most need to detect quickly. A common pitfall is applying privacy transformations only at the external API response layer while an internal analyst tool bypasses them to query the same underlying data directly, the enforcement boundary has to be the actual data access path, not just the partner-facing endpoint.
Unlock Full Question Bank
Get access to all 24 API Security, Authentication and Authorization interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.