[{"data":1,"prerenderedAt":689},["ShallowReactive",2],{"post-\u002Frest-api-security":3},{"page":4,"translation":574,"nav":576,"related":677,"random":682},{"id":5,"title":6,"body":7,"categories":558,"category":560,"date":561,"description":562,"draft":563,"extension":564,"image":565,"kind":560,"lang":566,"meta":567,"navigation":238,"path":531,"readingTime":242,"seo":568,"slug":569,"stem":569,"tags":570,"translationKey":569,"type":559,"updated":560,"__hash__":573},"posts\u002Frest-api-security.md","How to Secure a REST API?",{"type":8,"value":9,"toc":547},"minimark",[10,47,54,87,90,95,102,105,118,120,124,127,156,165,167,171,178,198,204,264,266,270,273,280,282,286,289,292,314,323,325,329,332,352,354,358,361,363,367,472,474,477,484,486,491,499,501,505,543],[11,12,13,21],"blockquote",{},[14,15,16,17],"p",{},"💡 ",[18,19,20],"strong",{},"Summary (TL;DR):",[22,23,24,31,37],"ul",{},[25,26,27,30],"li",{},[18,28,29],{},"Why it Matters:"," REST APIs are entry points to your application. A poorly configured API is an invitation for data breaches, unauthorized access, and DDoS attacks.",[25,32,33,36],{},[18,34,35],{},"Core Security Layers:"," HTTPS (encryption), authorization (OAuth2\u002FJWT), input validation (preventing XSS\u002FSQLi), CORS configuration, and Rate Limiting.",[25,38,39,42,43,46],{},[18,40,41],{},"Reference:"," You should align your security architecture with the ",[18,44,45],{},"OWASP API Security Top 10"," standards.",[14,48,49,50,53],{},"This article is part of the ",[18,51,52],{},"RESTful API Design"," series. If you haven't read the previous articles in the series, I highly recommend starting there:",[22,55,56,63,69,75,81],{},[25,57,58],{},[59,60,62],"a",{"href":61},"\u002Frest-api-design","REST Api Design: Principles and Output Format",[25,64,65],{},[59,66,68],{"href":67},"\u002Frest-api-uri-structure","What Should the REST API URI Structure Be?",[25,70,71],{},[59,72,74],{"href":73},"\u002Fwhat-is-hateoas","What is HATEOAS in REST API?",[25,76,77],{},[59,78,80],{"href":79},"\u002Frest-api-authentication","How to Perform REST API Authentication?",[25,82,83],{},[59,84,86],{"href":85},"\u002Frest-api-error-handling","How to Perform REST API Error Handling?",[88,89],"hr",{},[91,92,94],"h2",{"id":93},"_1-transport-layer-security-https-and-tls","1. Transport Layer Security: HTTPS and TLS",[14,96,97,98,101],{},"The first and most non-negotiable step in REST API security is utilizing the ",[18,99,100],{},"HTTPS"," protocol. A production-ready REST API must run exclusively over HTTPS.",[14,103,104],{},"Using HTTP is like locking your front door while leaving all your windows wide open. Unencrypted HTTP traffic can be intercepted by anyone on the network path (Man-in-the-Middle or MitM attacks). HTTPS encrypts all traffic between the client and server using TLS (Transport Layer Security).",[11,106,107],{},[14,108,109,110,113,114,117],{},"🔒 ",[18,111,112],{},"Extra Security:"," Simply using HTTPS is not enough. You should disable outdated SSL and weak TLS versions (TLS 1.0 and 1.1) on your API server and enforce modern, secure protocols like ",[18,115,116],{},"TLS 1.2 and TLS 1.3",".",[88,119],{},[91,121,123],{"id":122},"_2-authentication-and-authorization-authn-authz","2. Authentication and Authorization (AuthN & AuthZ)",[14,125,126],{},"If your API is not public, you must verify who is making each request (Authentication) and ensure they have permission to perform the requested action (Authorization).",[22,128,129,139,145],{},[25,130,131,134,135,138],{},[18,132,133],{},"JWT (JSON Web Token):"," Highly popular for stateless APIs. However, when using JWT, prefer secure asymmetric algorithms like ",[18,136,137],{},"RS256"," to sign tokens, and keep the expiration time short.",[25,140,141,144],{},[18,142,143],{},"OAuth 2.0:"," The industry standard for enabling secure, scoped access to user data by third-party applications.",[25,146,147,150,151,155],{},[18,148,149],{},"API Keys:"," Suitable for simple machine-to-machine communication. However, API keys must be passed in HTTP headers (e.g., ",[152,153,154],"code",{},"X-API-Key",") rather than URL query parameters.",[14,157,158,159,162,163],{},"For a deeper dive into authentication methods, see the dedicated article in this series:",[160,161],"br",{},"\n👉 ",[59,164,80],{"href":79},[88,166],{},[91,168,170],{"id":169},"_3-input-validation-and-sanitization","3. Input Validation and Sanitization",[14,172,173,174,177],{},"You should ",[18,175,176],{},"never trust"," data coming from the client. All inputs entering your API—including URL parameters, query strings, the HTTP request body, and headers—must undergo strict validation on the server.",[22,179,180,186,192],{},[25,181,182,185],{},[18,183,184],{},"SQL Injection (SQLi):"," Always use prepared statements or Object-Relational Mappers (ORMs) instead of executing raw, concatenated SQL strings.",[25,187,188,191],{},[18,189,190],{},"XSS (Cross-Site Scripting):"," Sanitize input to strip or escape HTML tags and Javascript scripts.",[25,193,194,197],{},[18,195,196],{},"Request Size Limiting:"," Enforce a maximum request size (e.g., 1MB or 10MB) to prevent attackers from exhausting server memory (RAM) by uploading massive payloads.",[14,199,200],{},[201,202,203],"em",{},"Example of Secure Database Querying in PHP using PDO:",[205,206,211],"pre",{"className":207,"code":208,"language":209,"meta":210,"style":210},"language-php shiki shiki-themes github-light github-dark","\u002F\u002F Bad & Vulnerable Method (Prone to SQL Injection)\n$input = $_GET['username'];\n$query = \"SELECT * FROM users WHERE username = '$input'\"; \n\n\u002F\u002F Correct & Secure Method (Prepared Statement)\n$statement = $pdo->prepare('SELECT * FROM users WHERE username = :username');\n$statement->execute(['username' => $_GET['username']]);\n$user = $statement->fetch();\n","php","",[152,212,213,221,227,233,240,246,252,258],{"__ignoreMap":210},[214,215,218],"span",{"class":216,"line":217},"line",1,[214,219,220],{},"\u002F\u002F Bad & Vulnerable Method (Prone to SQL Injection)\n",[214,222,224],{"class":216,"line":223},2,[214,225,226],{},"$input = $_GET['username'];\n",[214,228,230],{"class":216,"line":229},3,[214,231,232],{},"$query = \"SELECT * FROM users WHERE username = '$input'\"; \n",[214,234,236],{"class":216,"line":235},4,[214,237,239],{"emptyLinePlaceholder":238},true,"\n",[214,241,243],{"class":216,"line":242},5,[214,244,245],{},"\u002F\u002F Correct & Secure Method (Prepared Statement)\n",[214,247,249],{"class":216,"line":248},6,[214,250,251],{},"$statement = $pdo->prepare('SELECT * FROM users WHERE username = :username');\n",[214,253,255],{"class":216,"line":254},7,[214,256,257],{},"$statement->execute(['username' => $_GET['username']]);\n",[214,259,261],{"class":216,"line":260},8,[214,262,263],{},"$user = $statement->fetch();\n",[88,265],{},[91,267,269],{"id":268},"_4-cors-cross-origin-resource-sharing-configuration","4. CORS (Cross-Origin Resource Sharing) Configuration",[14,271,272],{},"CORS is a security mechanism enforced by web browsers that controls whether web apps hosted on other origins (domains) are allowed to make requests to your API.",[14,274,275,276,279],{},"Many developers use ",[152,277,278],{},"Access-Control-Allow-Origin: *"," to make things work quickly. However, for APIs containing sensitive data or requiring authentication, this wildcard is a major security vulnerability. You should explicitly define the allowed origin domains and properly configure the access parameters for credentials (cookies\u002FAuthorization headers).",[88,281],{},[91,283,285],{"id":284},"_5-rate-limiting","5. Rate Limiting",[14,287,288],{},"Limiting request volume at the server or application level protects your API from brute-force and DDoS attacks. It also prevents resource starvation caused by abusive clients.",[14,290,291],{},"To help client applications play nicely with these limits, include informative headers in your HTTP responses:",[205,293,297],{"className":294,"code":295,"language":296,"meta":210,"style":210},"language-http shiki shiki-themes github-light github-dark","X-Rate-Limit-Limit: 1000      # Max requests allowed in the current window\nX-Rate-Limit-Remaining: 985   # Remaining requests in the current window\nX-Rate-Limit-Reset: 16200000  # Unix timestamp when the limit resets\n","http",[152,298,299,304,309],{"__ignoreMap":210},[214,300,301],{"class":216,"line":217},[214,302,303],{},"X-Rate-Limit-Limit: 1000      # Max requests allowed in the current window\n",[214,305,306],{"class":216,"line":223},[214,307,308],{},"X-Rate-Limit-Remaining: 985   # Remaining requests in the current window\n",[214,310,311],{"class":216,"line":229},[214,312,313],{},"X-Rate-Limit-Reset: 16200000  # Unix timestamp when the limit resets\n",[14,315,316,317,322],{},"When a client exceeds the limit, the API should return a standard ",[18,318,319],{},[152,320,321],{},"429 Too Many Requests"," HTTP status code.",[88,324],{},[91,326,328],{"id":327},"_6-error-handling-and-information-disclosure","6. Error Handling and Information Disclosure",[14,330,331],{},"When managing errors, you must strike a balance between providing helpful details to developers and leaking sensitive system details to attackers. Never expose database schemas, stack traces, or server version strings in public error payloads.",[22,333,334,344],{},[25,335,336,337,340,341],{},"❌ ",[18,338,339],{},"Incorrect:"," ",[152,342,343],{},"Database Connection Error: Access denied for user 'admin'@'10.0.0.5' (using password: YES)",[25,345,346,340,349],{},[18,347,348],{},"Correct:",[152,350,351],{},"Internal Server Error. Please contact support with request ID: #98231",[88,353],{},[91,355,357],{"id":356},"_7-web-application-firewall-waf-usage","7. Web Application Firewall (WAF) Usage",[14,359,360],{},"While implementing security measures in your code is essential, filtering out attacks like SQL Injection, XSS, and DDoS before they reach your application server is much more efficient. Cloud-based WAFs (such as Cloudflare or AWS WAF) or server-level modules (like ModSecurity) analyze and filter malicious requests at the edge, reducing server load and preventing exploit attempts.",[88,362],{},[91,364,366],{"id":365},"security-methods-comparison","Security Methods Comparison",[368,369,370,390],"table",{},[371,372,373],"thead",{},[374,375,376,381,384,387],"tr",{},[377,378,380],"th",{"align":379},"left","Security Layer",[377,382,383],{"align":379},"Prevented Attack",[377,385,386],{"align":379},"Difficulty",[377,388,389],{"align":379},"Cost \u002F Performance Impact",[391,392,393,410,426,442,457],"tbody",{},[374,394,395,401,404,407],{},[396,397,398],"td",{"align":379},[18,399,400],{},"HTTPS (TLS 1.3)",[396,402,403],{"align":379},"MitM (Man-in-the-Middle), Eavesdropping",[396,405,406],{"align":379},"Low",[396,408,409],{"align":379},"Negligible (trivial for modern CPUs)",[374,411,412,417,420,423],{},[396,413,414],{"align":379},[18,415,416],{},"Rate Limiting",[396,418,419],{"align":379},"DDoS, Brute Force, Resource Exploitation",[396,421,422],{"align":379},"Medium",[396,424,425],{"align":379},"Low (easily handled with Redis\u002FMemcached)",[374,427,428,433,436,439],{},[396,429,430],{"align":379},[18,431,432],{},"Input Validation",[396,434,435],{"align":379},"SQL Injection, XSS, Buffer Overflow",[396,437,438],{"align":379},"High (requires ongoing maintenance)",[396,440,441],{"align":379},"None (minimal CPU processing)",[374,443,444,449,452,454],{},[396,445,446],{"align":379},[18,447,448],{},"CORS Config",[396,450,451],{"align":379},"CSRF, Unauthorized Browser Requests",[396,453,406],{"align":379},[396,455,456],{"align":379},"None",[374,458,459,464,467,469],{},[396,460,461],{"align":379},[18,462,463],{},"WAF",[396,465,466],{"align":379},"Broad web vulnerabilities and bots",[396,468,422],{"align":379},[396,470,471],{"align":379},"Variable (cloud provider costs)",[88,473],{},[14,475,476],{},"I'll keep adding new sections and details here as ideas come up or as new standards emerge. In the next section, we'll look at how to document an API.",[14,478,479,480],{},"👉 ",[59,481,483],{"href":482},"\u002Frest-api-documentation-and-testing","How to Document and Test a REST API?",[88,485],{},[487,488,490],"h5",{"id":489},"changelog","Changelog",[22,492,493,496],{},[25,494,495],{},"2026-06-20: Modernized article structure and updated language bindings.",[25,497,498],{},"2021-02-16: Original Turkish article published.",[88,500],{},[91,502,504],{"id":503},"rest-api-series","REST API Series",[22,506,507,511,515,519,523,527,533,537],{},[25,508,509],{},[59,510,62],{"href":61},[25,512,513],{},[59,514,68],{"href":67},[25,516,517],{},[59,518,74],{"href":73},[25,520,521],{},[59,522,80],{"href":79},[25,524,525],{},[59,526,86],{"href":85},[25,528,529],{},[59,530,532],{"href":531},"\u002Frest-api-security","How to Secure a REST API? (This article)",[25,534,535],{},[59,536,483],{"href":482},[25,538,539],{},[59,540,542],{"href":541},"\u002Ffull-stack-project-development","Sample REST API Project",[544,545,546],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":210,"searchDepth":223,"depth":223,"links":548},[549,550,551,552,553,554,555,556,557],{"id":93,"depth":223,"text":94},{"id":122,"depth":223,"text":123},{"id":169,"depth":223,"text":170},{"id":268,"depth":223,"text":269},{"id":284,"depth":223,"text":285},{"id":327,"depth":223,"text":328},{"id":356,"depth":223,"text":357},{"id":365,"depth":223,"text":366},{"id":503,"depth":223,"text":504},[559],"technical",null,"2026-06-20","Securing a REST API in practice — HTTPS\u002FTLS, authentication, input validation, CORS, rate limiting, and avoiding information disclosure.",false,"md","\u002Fimages\u002Fhero\u002Frest-api-security.avif","en",{},{"title":6,"description":562},"rest-api-security",[571,572],"api","rest","G9dVEAFjc0fyiXkygYJ-n5bVcOU5yBRVjYr3CoUmubs",{"path":575},"\u002Ftr\u002Frest-api-guvenligi-nasil-saglanir",{"prev":577,"next":578,"others":579,"lucky":676,"readingTime":242},{"path":85,"title":86},{"path":67,"title":68},[580,581,582,584,585,586,587,590,593,596,599,602,605,608,611,614,617,620,623,626,629,632,635,638,641,644,647,650,653,656,659,662,665,668,670,673],{"path":541,"title":542},{"path":79,"title":80},{"path":61,"title":583},"REST API Design: Principles and Output Format",{"path":482,"title":483},{"path":85,"title":86},{"path":67,"title":68},{"path":588,"title":589},"\u002Ftroubleshooting-cyberpanel-inaccessibility-after-ubuntu-release-upgrade","Troubleshooting CyberPanel Inaccessibility After Ubuntu Release Upgrade",{"path":591,"title":592},"\u002Freset-wordpress-admin-password-using-wp-cli","Reset WordPress Admin Password Using WP-CLI",{"path":594,"title":595},"\u002Fgraphql-vs-rest-api-which-is-the-best-choice-for-headless-wordpress","GraphQL vs REST API: Which is the Best Choice for Headless WordPress?",{"path":597,"title":598},"\u002Fgrow-your-business-in-turkey-with-expert-wordpress-plugin-and-theme-localization-and-support-services","Grow Your Business in Turkey with Expert WordPress Plugin and Theme Localization and Support Services",{"path":600,"title":601},"\u002Fgetting-started-with-devops-understanding-the-principles-and-adopting-the-tools","Getting Started with DevOps: Understanding the Principles and Adopting the Tools",{"path":603,"title":604},"\u002Fphp-graphql-development-advanced-techniques-for-optimizing-your-apis","PHP GraphQL Development: Advanced Techniques for Optimizing Your APIs",{"path":606,"title":607},"\u002Fadvanced-techniques-for-dependency-injection-in-php-tips-code-samples-and-faqs","Advanced Techniques for Dependency Injection in PHP: Tips, Code Samples, and FAQs",{"path":609,"title":610},"\u002Fmaximize-the-potential-of-headless-wordpress-with-graphql","Maximize the Potential of Headless WordPress with GraphQL",{"path":612,"title":613},"\u002Fwriting-clean-modular-and-reusable-code-in-php","Best Practices for Writing Clean, Modular, and Reusable Code in PHP",{"path":615,"title":616},"\u002Fheadless-cmss-an-overview-of-popular-alternatives-to-contentful-and-wordpress","Headless CMSs: An Overview of Popular Alternatives to Contentful and WordPress",{"path":618,"title":619},"\u002Fci-cd-for-php-a-comprehensive-guide","CI\u002FCD for PHP: A Comprehensive Guide",{"path":621,"title":622},"\u002Fintroduction-to-php-namespaces-a-beginners-guide-to-structuring-your-code","Introduction to PHP Namespaces: A Beginner's Guide to Structuring Your Code",{"path":624,"title":625},"\u002Fwhat-is-graylog-a-powerful-tool-for-collecting-indexing-and-analyzing-log-data","What is Graylog? A Powerful Tool for Collecting, Indexing, and Analyzing Log Data",{"path":627,"title":628},"\u002Felevate-your-turkish-audience-experience-with-professional-wordpress-plugin-and-theme-translation","Elevate Your Turkish Audience Experience with Professional WordPress Plugin and Theme Translation",{"path":630,"title":631},"\u002Fhow-to-set-up-a-self-hosted-api-gateway-a-comprehensive-guide","How to Set Up a Self-Hosted API Gateway: A Comprehensive Guide",{"path":633,"title":634},"\u002Fdifference-between-generators-and-iterators-in-php","The Key Differences Between PHP Generators and Iterators",{"path":636,"title":637},"\u002Fphp-and-machine-learning-a-winning-combination-with-php-ml","PHP and Machine Learning: A Winning Combination with PHP-ML",{"path":639,"title":640},"\u002Fphp-generators-a-beginners-guide-to-iteration","PHP Generators: A Beginner's Guide to Iteration",{"path":642,"title":643},"\u002Fmastering-closures-in-javascript-a-beginners-guide","Mastering Closures in JavaScript: A Beginner's Guide",{"path":645,"title":646},"\u002Fthe-top-php-certification-programs-for-developers","The Top PHP Certification Programs for Developers",{"path":648,"title":649},"\u002Fhow-to-revalidate-next-js-isr-cache-on-demand-cache-regeneration","How to Revalidate Next.js ISR Cache? On-Demand Cache Regeneration",{"path":651,"title":652},"\u002Ftips-for-translating-a-wordpress-plugin-wordpress-theme-to-turkish","Tips for Translating a WordPress Plugin \u002F WordPress Theme to Turkish",{"path":654,"title":655},"\u002Fall-about-headless-wordpress","All About Headless WordPress",{"path":657,"title":658},"\u002Finstall-composer-on-ubuntu","How to Install Composer on Ubuntu \u002F Linux",{"path":660,"title":661},"\u002Fwhat-is-an-api-gateway","What is an API Gateway? Should You Use It?",{"path":663,"title":664},"\u002Fis-jwt-safe-or-is-it-vulnerable","Is JWT Safe or Is It Vulnerable?",{"path":666,"title":667},"\u002Ftailwind-css-to-use-or-not-to-use-that-is-the-question","Tailwind CSS! To use? Or not to use? That is the question.",{"path":73,"title":669},"What is HATEOAS?",{"path":671,"title":672},"\u002Fhello-world","Hello World: A New Multilingual Journey",{"path":674,"title":675},"\u002Fwhat-is-ecmascript","What is ECMAScript? What is not?",{"path":606,"title":607},[678,679,680,681],{"path":541,"title":542,"date":561},{"path":79,"title":80,"date":561},{"path":61,"title":583,"date":561},{"path":482,"title":483,"date":561},[683,685,687],{"path":621,"title":622,"date":684},"2023-01-13",{"path":660,"title":661,"date":686},"2022-05-13",{"path":663,"title":664,"date":688},"2022-05-12",1782141978688]