REST API Design and Security: Architecture-Level Best Practices and Standards


REST API Design and Security: Architecture-Level Best Practices and Standards

Designing a robust, platform-neutral REST API requires mastery of two interlocking disciplines: standards-based HTTP semantics (when, why, and where to use each HTTP method) and a comprehensive security architecture covering both user-facing and machine-to-machine access. This report consolidates guidance from IETF RFCs, the OWASP API Security project, and official documentation from Microsoft Azure, AWS, and Google Cloud.

Adhere to HTTP Semantics & Idempotency

GET is safe and cacheable — use it exclusively for read-only retrieval. POST creates resources or triggers processing — it is neither safe nor idempotent. PUT performs idempotent full-resource updates; PATCH applies partial updates (not guaranteed idempotent); DELETE removes resources idempotently.

Secure by Design — Zero Trust & Least Privilege

Mandate TLS for all API traffic, authenticate every request, and enforce token scopes/claims at the endpoint level. Design against the OWASP API Security Top 10 (2023 edition) threat categories, and implement rate limiting to counter unrestricted resource consumption.

Modern Auth: OAuth 2.0 / OIDC over SAML

OAuth 2.0 handles authorization via lightweight JSON tokens; OpenID Connect adds authentication on top. SAML 2.0 remains relevant for legacy enterprise SSO but is XML-heavy and browser-bound. The Microsoft identity platform uses OAuth for authorization and OIDC for authentication, while SAML is commonly used with identity providers such as AD FS federated to Microsoft Entra ID.


1. RESTful API Design Principles and HTTP Methods

1.1 Resource-Oriented Design and the Uniform Interface

A RESTful web API is built around resources — any object, data, or service the client can access — each uniquely identified by a URI. Two foundational principles govern design:

  • Platform independence: clients call the API regardless of internal implementation, using HTTP as the standard protocol and a familiar format such as JSON or XML.
  • Loose coupling: client and service evolve independently; only standard protocols and agreed-upon data formats bind them.

The uniform interface is realized through standard HTTP verbs — GETPOSTPUTPATCH, and DELETE — applied to resources. Resource URIs should be modelled as nouns (e.g. /orders/customers/1) rather than verbs (e.g. /createOrder). The HTTP method already implies the action. For example, creating a new order for customer 1 is expressed as POST /customers/1/orders with the order data in the body; retrieving all orders for that customer uses GET /customers/1/orders.

The Google Cloud API design guide, used internally at Google since 2014, reinforces resource-oriented design and recommends choosing methods in this priority order: (1) standard methods on collections/resources, (2) standard batch or aggregate methods, (3) custom methods, (4) streaming methods. Standard methods offer the greatest uniformity: they are automatable across declarative clients, CLIs, UIs, and SDKs.

RESTful APIs also use a stateless request model: each HTTP request is independent and self-contained, meaning the server retains no session state between requests. This supports high scalability because it removes any affinity between a client and a specific server.

1.2 GET vs POST — Safety, Idempotency, and Caching

The distinction between GET and POST is rooted in three formal properties defined in RFC 7231 (now obsoleted by RFC 9110, published in 2022):

ropertyDefinitionGETPOSTPUTPATCHDELETEHEADOPTIONS
SafeRead-only; no state change requested by the client???????
IdempotentRepeating N times ? doing it once (same state change)???????
CacheableResponses may be stored and reused by intermediaries???????
REST CRUD Operations

Safe methods (GET, HEAD, OPTIONS, TRACE) are essentially read-only — the client does not request or expect any state change on the server, though incidental side effects such as logging may occur. Safety matters because browsers can prefetch safe requests, web crawlers can follow safe links automatically, users can bookmark and re-request safe URLs, and caches can serve responses without forwarding to the origin server.

Idempotent methods guarantee that executing the same request N times produces the same state change as executing it once (though the response body may differ between calls, e.g. different timestamps). All safe methods are idempotent, but not all idempotent methods are safe — DELETE and PUT change state but are idempotent.

GET should be used exclusively for retrieving a representation of a resource. A successful GET returns 200 OK with the resource in the body, 204 No Content when a search returns no matches, or 404 Not Found when the resource does not exist.

POST should be used to create a new resource or to submit data for processing to an existing resource without necessarily creating anything new. The server assigns the URI for a newly created resource and returns it in the Locationheader with a 201 Created status. Other valid POST responses include 200 OK (processing done, no new resource), 204 No Content, 400 Bad Request, and 405 Method Not Allowed. POST is neither safe nor idempotent — repeating a POST may create duplicate resources or repeat an action (e.g. charging a payment twice).

Anti-pattern alert: Using GET for operations that modify state — such as GET /blog/1234/delete — violates HTTP semantics. Because GET is safe and cacheable, middleware proxies may cache the response, meaning a subsequent client requesting the same URL could receive the cached response without the server ever being contacted again, and a web crawler could inadvertently trigger the destructive action.

1.3 PUT, PATCH, and DELETE

PUT replaces or creates a resource at a client-specified URI. The client must supply a complete representation of the resource in the request body. PUT is idempotent: submitting the same request multiple times always results in the same resource state. Use PUT when the client can meaningfully assign the resource URI before it exists; otherwise, use POST for creation and PUT (or PATCH) for updates. Valid responses: 200 OK, 201 Created, 204 No Content, 409 Conflict.

PATCH performs a partial update to an existing resource, sending only the changed fields. Two common formats are JSON merge patch (RFC 7396, media type application/merge-patch+json) and JSON patch (RFC 6902, media type application/json-patch+json), the latter specifying changes as a sequence of operations (add, remove, replace, copy, test). PATCH is not guaranteed idempotent. Valid responses: 200 OK, 400 Bad Request, 409 Conflict, 415 Unsupported Media Type.

DELETE removes the resource at the specified URI and is idempotent: deleting the same resource twice yields the same end state (resource gone). Responses: 204 No Content (success) or 404 Not Found (resource already absent).

1.4 Pagination, Filtering, Sorting, and Field Selection

For large collections, the Azure Architecture Center recommends implementing pagination using limit and offset query parameters with meaningful defaults such as limit=25 and offset=0. Example: GET /orders?limit=25&offset=50.

To help prevent denial-of-service attacks, impose an upper bound on the number of items returned. If a service sets max-limit=25 and a client requests limit=1000, the service can either return 25 items or an HTTP Bad Request error, depending on documented policy.

Filtering allows clients to refine results by applying conditions via query parameters: GET /orders?minCost=100&status=shipped.

Sorting can be supported via a sort parameter (e.g. sort=price), with the caveat that different sort values alter the cache key and can negatively affect caching effectiveness.

Field selection (client-defined projections) lets clients request only needed fields using a parameter like fields=id,name, reducing payload size. The API must validate that the client is allowed to access the requested fields and must not expose fields that are not normally available.

The Google Cloud blog additionally cautions against “chatty” APIs that force many sequential calls: consider providing coarser-grained “experience APIs” that compose multiple domains into a single endpoint for common use cases, reducing network overhead. Observation studies cited by Google suggest that developers spend more than 51% of their time in editor and client environments versus approximately 18% on reference documentation, underscoring the importance of self-explanatory payload design.

1.5 Asynchronous Operations

When a POST, PUT, PATCH, or DELETE requires lengthy processing, return HTTP 202 (Accepted) with a Locationheader pointing to a status-polling endpoint. The status endpoint returns 200 OK with current progress and, optionally, a cancel link. When the asynchronous operation creates a new resource, the status endpoint returns 303 (See Other) with a Location header pointing to the new resource URI (e.g. /api/orders/12345).

1.6 Content Negotiation and Partial Responses

Clients indicate acceptable response formats via the Accept header (e.g. Accept: application/json, application/xml). If the server cannot match any listed media type, it returns 406 (Not Acceptable). When sending data, the Content-Type header specifies the format; if the server does not support it, it returns 415 (Unsupported Media Type).

For large binary resources (files, images), support partial retrieval via the Accept-Ranges header on GET responses and Range requests from clients. A HEAD request lets the client inspect the Content-Length and Accept-Ranges headers before deciding whether to fetch the resource in chunks.

1.7 Common Design Anti-Patterns

Anti-PatternWhy It FailsCorrect Approach
Verbs in URIs (/createUser)HTTP method already implies the actionUse nouns: POST /users to create, GET /users to list
GET with side effects (GET /blog/1234/delete)Violates safety; caches and crawlers may trigger itUse DELETE /blogs/1234
Tunneling everything through POSTClients and caches cannot infer intent; no caching benefitUse the semantically correct verb for each operation
Designing “inside-out” instead of “outside-in”Exposes internal structure rather than consumer needsStart from consumer use cases and work inward
Chatty APIs (many sequential calls)Multiple network calls increase latency and operational costOffer experience APIs or batch endpoints
Missing pagination/filteringOverwhelming payloads; potential DoS vectorImplement limit/offset with enforced upper bounds

1.8 HATEOAS and Hypermedia

REST APIs can be driven by hypermedia links embedded in resource representations, a principle known as HATEOAS(Hypertext as the Engine of Application State). Each response contains links describing valid next actions, making the API self-documenting and enabling clients to discover capabilities dynamically. While not all APIs implement HATEOAS fully, embedding navigation links in responses (e.g. links to related resources, pagination cursors) improves discoverability and reduces hard-coded assumptions in client code.


2. API Security Architecture

2.1 Transport Security — HTTPS Is Non-Negotiable

Secure REST services must only provide HTTPS endpoints. TLS protects authentication credentials in transit (passwords, API keys, JWTs), allows clients to authenticate the service, and guarantees data integrity. For highly privileged web services, consider mutually authenticated client-side certificates (mutual TLS) to provide additional protection.

2.2 Authentication vs Authorization

Authentication (AuthN) is the process of proving that a caller is who they claim to be. The Microsoft identity platform uses the OpenID Connect protocol for handling authentication.

Authorization (AuthZ) is the act of granting an authenticated party permission to perform specific actions or access specific data. The Microsoft identity platform uses the OAuth 2.0 protocol for handling authorization.

Both must be enforced on every API endpoint. Without authentication, the API cannot identify the caller; without authorization, even a valid caller may exceed permitted access. Non-public REST services must perform access control at each API endpoint; user authentication should be centralized in an Identity Provider (IdP) that issues access tokens.

2.3 Token-Based Security — JWTs, Access Tokens, and Refresh Tokens

There is a convergence toward using JSON Web Tokens (JWT) as the format for security tokens in REST APIs. JWTs are JSON data structures containing a set of claims that can be used for access control decisions. A cryptographic signature or message authentication code (MAC) protects integrity.

The Microsoft identity platform defines three primary token types:

Token TypePurposeIssued Via
Access tokenGrants access to a protected resource; contains user/resource infoOAuth 2.0 flow
Refresh tokenExchanged for a new access token when the current one expiresIssued alongside access token (short-lived access tokens paired with longer-lived refresh tokens)
ID tokenAuthenticates the user; conveys identity claimsOpenID Connect flow

Access tokens are passed as the bearer token in the Authorization header. The resource server validates the token by verifying the signature using the authorization server’s published public key.

Critical JWT validation rules from the OWASP REST Security Cheat Sheet:

  • Never allow unsecured JWTs ({"alg":"none"}).
  • Prefer signatures over MACs for integrity protection; with MACs, all services sharing the same key can forge new tokens, meaning a compromise of any one service compromises all others using that key.
  • The relying party must verify integrity based on its own configuration, not the JWT header’s algorithm claim, to prevent algorithm-substitution attacks.
  • At minimum, validate the following standard claims: iss (issuer — is this a trusted issuer?), aud (audience — is this token intended for this service?), exp (expiration time — has the token expired?), and nbf (not-before time — is the token valid yet?).

2.4 Scopes and Claims for Least Privilege

Claims are name-value pairs that relay facts about the token subject: the security token server that generated it, generation date, subject identity, audience (the app the token was generated for), and the requesting client app. Applications use claims to validate the token, identify the subject’s tenant, display user information, and determine authorization.

Scopes define the permitted access for a service within an OAuth 2.0 flow. They are a way for the resource server to group permissions related to actions and resources, and they specify the coarse-grained operations OAuth 2.0 clients can request. Scopes are defined per section 3.3 of OAuth 2.0 (RFC 6749). AWS IAM Identity Center enforces a maximum of 25 scopes per access token request.

Design your token issuance to grant only the minimum scopes and claims necessary for the client’s function — this is the principle of least privilege, aligned with the Zero Trust tenet of “use least privilege access”.

2.5 API Keys — Supplementary, Not Sole Protection

Public REST services without access control risk excessive bandwidth or compute costs. API keys can mitigate this risk and are often used to monetize APIs via purchased access plans. However:

  • Require API keys for every request to protected endpoints.
  • Return 429 Too Many Requests if requests arrive too quickly.
  • Revoke the API key if the client violates the usage agreement.
  • Do not rely exclusively on API keys to protect sensitive, critical, or high-value resources — they are relatively easy to compromise when issued to third-party clients.

2.6 OWASP API Security Top 10 (2023 Edition)

The following table captures the ten most critical API security risks identified by OWASP in 2023:

#RiskDescription
API1Broken Object Level AuthorizationAPIs expose endpoints handling object identifiers, creating a wide attack surface; object-level authorization checks should occur in every function accessing a data source using a user-supplied ID
API2Broken AuthenticationIncorrectly implemented auth mechanisms allow attackers to compromise tokens or assume other users’ identities, compromising API security overall
API3Broken Object Property Level AuthorizationCombines excessive data exposure and mass assignment — improper validation at the object property level leads to information exposure or manipulation
API4Unrestricted Resource ConsumptionAPI requests consume network bandwidth, CPU, memory, and storage; successful attacks cause denial of service or cost escalation
API5Broken Function Level AuthorizationComplex access policies with unclear separation between admin and regular functions lead to authorization flaws, allowing access to others’ resources or admin functions
API6Unrestricted Access to Sensitive Business FlowsBusiness flows (buying a ticket, posting a comment) exposed without compensating for automated excessive use
API7Server-Side Request Forgery (SSRF)API fetches a remote resource without validating the user-supplied URI, enabling crafted requests to unexpected destinations even behind firewalls
API8Security MisconfigurationComplex configurations are missed or don’t follow security best practices, opening the door for attacks
API9Improper Inventory ManagementAPIs expose more endpoints than traditional web apps; proper inventory of hosts and deployed API versions is critical to mitigate issues like deprecated API versions and exposed debug endpoints
API10Unsafe Consumption of APIsDevelopers trust third-party API data more than user input and adopt weaker standards; attackers target integrated third-party services instead of the API directly

2.7 Zero Trust Considerations for APIs

The Zero Trust security model assumes breach and verifies each request as though it originated from an uncontrolled network, regardless of where it actually originates or what resource it accesses. Microsoft’s developer guidance distills this into three guiding principles:

  1. Verify explicitly — authenticate and authorize based on all available data points on every request.
  2. Use least privilege access — limit user and service access with just-in-time and just-enough-access policies.
  3. Assume breach — minimize blast radius by segmenting access, verifying end-to-end encryption, and using analytics to detect and respond to threats.

For API developers, this means: do not bypass security checks for internal calls. Instead of believing everything behind the corporate firewall is safe, verify identity and permissions on every request — “never trust, always verify”. Compromised applications can affect the entire organization; the work-from-anywhere workforce and hybrid cloud environments have redefined the security perimeter such that data is accessed outside the corporate network and shared with external collaborators.

Microsoft’s guidance recommends using Zero Trust identity and access management best practices throughout the application development lifecycle, protecting APIs through registration, defining permissions and consent, and enforcing access to achieve Zero Trust goals.


3. OAuth 2.0 / OpenID Connect vs SAML 2.0

3.1 OAuth 2.0 — Delegated Authorization

OAuth 2.0 is a protocol that allows applications to access and share user data securely without sharing passwords. It provides a secure and standardized way for users to allow applications access to their resources, facilitated by different grant flows.

Key architectural roles:

  • Resource Owner — the user who owns the data.
  • Client — the application requesting access.
  • Authorization Server — the identity provider that authenticates the user and issues tokens.
  • Resource Server — the API that validates tokens and serves protected resources.

Standardized grant flows supported by modern identity services (per AWS IAM Identity Center):

Grant FlowRFCUse Case
Authorization Code Grant with PKCERFC 6749 + RFC 7636Web and mobile apps running on devices with a browser
Device Authorization GrantRFC 8628Devices with or without a browser (e.g. CLI tools, IoT)
Client CredentialsRFC 6749Machine-to-machine (M2M) / server-to-server, no human user involved

The Microsoft identity platform lists six supported authorization flows, each producing different token combinations:

FlowID TokenAccess TokenRefresh TokenAuthorization Code
Authorization code flow????
Implicit flow??
Hybrid OIDC flow??
Refresh token redemption???
On-behalf-of flow???
Client credentials?(App only)

Source: [learn.microsoft.com]

The Authorization Code flow with PKCE proceeds as follows: a browser opens, the user authenticates (if not already), a consent screen displays the application name and the access scopes being requested, and after consent is granted the application proceeds with access based on the user’s permissions.

3.2 OpenID Connect (OIDC) — Authentication Layer over OAuth

OIDC is an authentication protocol built on top of the OAuth 2.0 framework. While OAuth alone provides authorization(granting token-based access to APIs), OIDC adds authentication — confirming the user’s identity — by introducing the ID token, a JWT containing identity claims (subject, name, email, etc.).

The Microsoft identity platform clarifies the relationship: “The platform uses OAuth for authorization and OpenID Connect (OIDC) for authentication. OpenID Connect is built on top of OAuth 2.0, so the terminology and flow are similar between the two. You can even both authenticate a user (through OpenID Connect) and get authorization to access a protected resource that the user owns (through OAuth 2.0) in one request”.

OIDC is commonly used for apps that are purely in the cloud, such as mobile apps, websites, and web APIs.

3.3 SAML 2.0 — XML-Based Enterprise SSO

SAML 2.0 is an industry standard used for securely exchanging SAML assertions that pass information about a user between a SAML authority (called an Identity Provider or IdP) and a SAML consumer (called a Service Provider or SP). This information is used to provide federated single sign-on access for authorized users.

SAML operates via browser redirects and XML-based signed assertions: the user attempts to access an SP, is redirected to the IdP for authentication, and upon success the IdP posts a signed XML assertion back to the SP through the user’s browser. The SP validates the assertion and establishes a session.

Enterprise applications that use SAML authentication are commonly integrated with identity providers such as Active Directory Federation Services (AD FS) federated to Microsoft Entra ID. Many enterprise apps also use SAML assertions, as referenced by the Microsoft Tokens and Claims documentation.

3.4 Comparative Analysis — When to Use Which

DimensionOAuth 2.0 / OIDCSAML 2.0
Primary purposeOAuth: authorization; OIDC: authentication + authorizationAuthentication and SSO
Token/assertion formatJSON (JWT) — compact, web-friendlyXML — verbose, requires signature validation
TransportHTTP/REST, JSON payloadsBrowser POST of XML assertions
Client typesMobile, SPA, web, server, IoT, CLIBrowser-based web applications primarily
Enterprise SSOSupported (especially OIDC); preferred for cloud-native appsWidely deployed; commonly used with ADFS + Microsoft Entra ID
API authorizationNative capability (access tokens with scopes)Not designed for API authorization; requires translation layer
Token validationFast local validation via JWT signature + public keyRequires XML signature validation and certificate trust chain
Specification lineageIETF RFC 6749 (OAuth 2.0), OpenID Foundation (OIDC)OASIS standard (2005)

When to prefer OAuth 2.0 / OIDC:

  • Any new REST API — user-facing or M2M.
  • Mobile or single-page applications where lightweight JSON tokens and HTTP-based flows are essential.
  • Scenarios requiring fine-grained API access control through scopes and claims.
  • Multi-platform environments (Azure, AWS, GCP all standardize on OAuth2/OIDC).

When SAML remains relevant:

  • Legacy enterprise applications that only support SAML-based SSO.
  • B2B federation with partners whose identity infrastructure is SAML-based.
  • Environments where AD FS is the primary federation service and OIDC migration is not yet complete.

Tradeoff: SAML’s maturity and XML extensibility allow it to carry rich attribute statements, which can be useful for complex enterprise authorization decisions in legacy systems. However, this comes at the cost of complexity, payload size, and incompatibility with non-browser clients (mobile, CLI, IoT). OAuth 2.0/OIDC trades some of that extensibility for simplicity, speed, and broad client support — which is why the industry has converged on it for modern API architectures.

3.5 Hybrid Environments

In practice, organizations frequently combine both protocols. The Microsoft identity platform explicitly supports this: “The platform uses OAuth 2.0 for authorization and SAML for authentication” and documents a SAML bearer assertion flow where SAML-based authentication can be exchanged for OAuth tokens to call protected APIs. This allows an enterprise user to authenticate via SAML with a corporate IdP and then receive OAuth-based access tokens for API consumption — bridging legacy SSO infrastructure with modern API security.

3.6 Implementation Guidance

For OAuth 2.0 / OIDC:

  • Use the Authorization Code Grant with PKCE for public clients (mobile, SPA); the implicit flow is deprecated in favor of this approach.
  • Use Client Credentials for M2M communication where no user is present.
  • Validate tokens rigorously: check issaudexpnbf claims; verify the cryptographic signature using the authorization server’s public key; never rely on the JWT header’s alg claim to select the verification algorithm.
  • Each Microsoft Entra tenant publishes a standards-compliant well-known metadata document containing information about the issuer name, authentication and authorization endpoints, supported scopes, and claims.
  • Use established libraries such as the Microsoft Authentication Libraries (MSAL), which implement token acquisition, refresh, and validation, and support standards-compliant discovery of tenant settings and keys using the OpenID well-known discovery document.

For SAML 2.0:

  • Rely on vetted SAML libraries for XML parsing, signature validation, and assertion handling — avoid custom implementations.
  • Note that AWS IAM Identity Center does not support validating signatures of incoming SAML authentication requests from SAML applications; the assertion from the IdP is validated, but the SP-initiated AuthN request signature is not checked at the AWS end.
  • If you need to translate SAML-authenticated sessions into API access tokens, use an intermediary (identity broker) that can exchange SAML assertions for OAuth tokens.

Key Authoritative References

All guidance in this report is grounded in the following official and standards-body sources: