[{"data":1,"prerenderedAt":265},["ShallowReactive",2],{"blog-checklists/api-security-checklist":3},{"id":4,"title":5,"body":6,"category":240,"date":241,"dateModified":241,"description":242,"draft":243,"extension":244,"faq":245,"featured":243,"headerVariant":250,"image":251,"keywords":251,"meta":252,"navigation":253,"ogDescription":254,"ogTitle":251,"path":255,"readTime":251,"schemaOrg":256,"schemaType":257,"seo":258,"sitemap":259,"stem":260,"tags":261,"twitterCard":263,"__hash__":264},"blog/blog/checklists/api-security-checklist.md","API Security Checklist: 26-Item Guide for REST & GraphQL",{"type":7,"value":8,"toc":234},"minimark",[9,16,19,22,47,67,85,109,125,140,154,173,178,181,203,222],[10,11,12],"tldr",{},[13,14,15],"p",{},"This 26-item checklist covers the most critical security issues in REST and GraphQL APIs: authentication, authorization, input validation, rate limiting, and CORS configuration. 8 critical items must be fixed before launch, 15 important items within the first week, and 3 recommended items when you can.",[13,17,18],{},"Your API is the front door to your data, and attackers love finding unlocked doors. Whether you are building a REST API or a GraphQL endpoint, the security fundamentals are the same -- authenticate every request, validate every input, and never trust the client. Here is everything you need to check.",[20,21],"print-button",{},[23,24,26,31,35,39,43],"checklist-section",{"title":25},"Quick Checklist (5 Critical Items)",[27,28],"checklist-item",{"description":29,"label":30},"Every protected endpoint must check JWT, session, or API key","Verify tokens on all protected endpoints",[27,32],{"description":33,"label":34},"Verify signature, expiration, and issuer on backend","Validate tokens server-side",[27,36],{"description":37,"label":38},"Users can only access/modify their own resources","Verify resource ownership",[27,40],{"description":41,"label":42},"Changing IDs in requests should not expose other users' data","No IDOR vulnerabilities",[27,44],{"description":45,"label":46},"Never trust client-side validation alone","Validate all input server-side",[23,48,51,55,59,63],{"title":49,"count":50},"Authentication","4",[27,52],{"description":53,"label":54},"Check JWT, session cookie, or API key on every request. How to verify API tokens","All protected endpoints verify tokens",[27,56],{"description":57,"label":58},"Verify signature, expiration, and issuer on backend. How to validate JWT tokens","Tokens validated server-side",[27,60],{"description":61,"label":62},"Use Authorization header, not URL parameters. How to send tokens securely","Tokens sent securely",[27,64],{"description":65,"label":66},"Short-lived access tokens with refresh token rotation. How to configure token expiration","Token expiration appropriate",[23,68,70,74,78,81],{"title":69,"count":50},"Authorization",[27,71],{"description":72,"label":73},"Users can only access/modify their own resources. How to verify resource ownership","Resource ownership verified",[27,75],{"description":76,"label":77},"Admin endpoints check for admin role, etc. How to implement RBAC","Role-based access control",[27,79],{"description":80,"label":42},"Changing IDs in requests shouldn't give access to other users' data. How to prevent IDOR",[27,82],{"description":83,"label":84},"Check permissions on GET, POST, PUT, DELETE - not just one. How to check operation permissions","Permission checks on every operation",[23,86,89,93,97,101,105],{"title":87,"count":88},"Input Validation","5",[27,90],{"description":91,"label":92},"Never trust client-side validation. How to validate on server","All input validated server-side",[27,94],{"description":95,"label":96},"Use Zod, Yup, or similar for schema validation. How to implement schema validation","Type checking enforced",[27,98],{"description":99,"label":100},"Prevent DoS via oversized inputs. How to limit input sizes","String lengths limited",[27,102],{"description":103,"label":104},"Sanitize or escape as needed for context (SQL, HTML, etc.). How to sanitize input","Special characters handled",[27,106],{"description":107,"label":108},"Set max payload size to prevent large payload attacks. How to limit payload size","Request body size limited",[23,110,113,117,121],{"title":111,"count":112},"Rate Limiting","3",[27,114],{"description":115,"label":116},"Login, signup, password reset must be rate limited. How to rate limit auth endpoints","Rate limiting on authentication endpoints",[27,118],{"description":119,"label":120},"Limit requests per user/IP to prevent abuse. How to implement rate limiting","General API rate limiting",[27,122],{"description":123,"label":124},"X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. How to add rate limit headers","Rate limit headers returned",[23,126,128,132,136],{"title":127,"count":112},"CORS Configuration",[27,129],{"description":130,"label":131},"Specify exact allowed origins. How to configure CORS","No wildcard (*) in production",[27,133],{"description":134,"label":135},"If using cookies, set credentials: true and specific origins. How to configure CORS with credentials","Credentials mode configured correctly",[27,137],{"description":138,"label":139},"Only allow methods your API actually uses. How to restrict CORS methods","Allowed methods restricted",[23,141,143,146,150],{"title":142,"count":112},"Error Handling",[13,144,145],{},"::checklist-item{label=\"Generic error messages for auth failures\" description=\"\"Invalid credentials\" not \"User not found\" or \"Wrong password\". How to secure error messages\"}\n::",[27,147],{"description":148,"label":149},"Return friendly errors to users, log details server-side. How to hide stack traces","No stack traces in production errors",[27,151],{"description":152,"label":153},"Use standard format like { error: { code, message } }. How to standardize API errors","Consistent error format",[23,155,157,161,165,169],{"title":156,"count":50},"GraphQL Specific",[27,158],{"description":159,"label":160},"Prevent deeply nested queries that cause DoS. How to limit GraphQL depth","Query depth limiting",[27,162],{"description":163,"label":164},"Limit total query cost/complexity. How to analyze query complexity","Query complexity analysis",[27,166],{"description":167,"label":168},"Disable schema introspection to hide API structure. How to disable introspection","Introspection disabled in production",[27,170],{"description":171,"label":172},"Check permissions on sensitive fields, not just types. How to implement field-level auth","Field-level authorization",[174,175,177],"h2",{"id":176},"api-security-fundamentals","API Security Fundamentals",[13,179,180],{},"Every API endpoint should answer four questions: Who is making this request (authentication)? Are they allowed to do this (authorization)? Is the data they sent safe (validation)? Are they making too many requests (rate limiting)?",[182,183,184,191,197],"faq-section",{},[185,186,188],"faq-item",{"question":187},"What is IDOR and how do I prevent it?",[13,189,190],{},"IDOR (Insecure Direct Object Reference) occurs when users can access other users' data by changing IDs in requests. Prevent it by always verifying that the authenticated user owns or has permission to access the requested resource before returning or modifying it.",[185,192,194],{"question":193},"Should I use wildcard CORS in production?",[13,195,196],{},"Never use wildcard (*) CORS in production for APIs that handle sensitive data. Specify exact allowed origins. If using cookies for authentication, you must specify origins anyway since credentials mode doesn't work with wildcards.",[185,198,200],{"question":199},"Why validate input on the server if I validate on the client?",[13,201,202],{},"Client-side validation can be bypassed by anyone with browser DevTools or API tools like Postman. It's for user experience, not security. Always validate on the server - that's where security decisions must be made.",[204,205,206,212,217],"related-articles",{},[207,208],"related-card",{"description":209,"href":210,"title":211},"Complete guide to API security","/blog/best-practices/api-design","API Security Guide",[207,213],{"description":214,"href":215,"title":216},"Secure your auth implementation","/blog/checklists/authentication-security-checklist","Authentication Checklist",[207,218],{"description":219,"href":220,"title":221},"Understanding authorization flaws","/blog/vulnerabilities/idor","IDOR Explained",[223,224,227,231],"cta-box",{"href":225,"label":226},"/","Start Free Scan",[174,228,230],{"id":229},"scan-your-api","Scan Your API",[13,232,233],{},"Our scanner checks for authentication issues, authorization flaws, and common API vulnerabilities.",{"title":235,"searchDepth":236,"depth":236,"links":237},"",2,[238,239],{"id":176,"depth":236,"text":177},{"id":229,"depth":236,"text":230},"checklists","2026-01-23","Printable 26-item API security checklist for REST and GraphQL APIs. Authentication, authorization, input validation, rate limiting, and CORS configuration.",false,"md",[246,248],{"question":187,"answer":247},"IDOR (Insecure Direct Object Reference) occurs when users can access other users' data by changing IDs in requests. Prevent it by always verifying that the authenticated user owns or has permission to access the requested resource.",{"question":193,"answer":249},"Never use wildcard (*) CORS in production for APIs that handle sensitive data. Specify exact allowed origins. If using cookies, you must specify origins anyway since credentials mode doesn't work with wildcards.","green",null,{},true,"Printable 26-item API security checklist. Auth, validation, rate limiting, CORS.","/blog/checklists/api-security-checklist","[object Object]","HowTo",{"title":5,"description":242},{"loc":255},"blog/checklists/api-security-checklist",[262],"Security Checklist","summary_large_image","1kNh29wqD-Com6PkMSe3NCD9maGYdjnTBa5ZJkcy7Nc",1775843918547]