API & Web Architecture - Security Best Practices
An API that is well-designed and built for performance behaves and functions well in response to evolving customer and business requirements. However, security must also be a key forerunner when building APIs.
Security misconfigurations pose tremendous risks to all businesses and enterprises, especially as the world continues the overdrive into digital and public/hybrid cloud adoption.
Inadequate security measures can cause (and have caused) irreparable damages to a company’s reputation, customers, employees, and both financial & non-financial assets.
Real-World Examples of Misconfigured API Security
Venmo had an API misconfiguration in 2019 which made payment transaction descriptions available publicly. The connection was unsecured, allowing for the mass scraping of 200 million payment transactions.
The YouTube API had broken object security access in 2020, which allowed users to upload their videos to different YouTube channels (apart from their own), by referencing the channel ID. Since the channel ID was the only key differentiator for successfully uploading to a YouTube channel/account, this helped enable users to upload their videos to other YouTube channels just by swapping out various channel IDs. YouTube at the time was not verifying additional permissions, and allowed users to upload videos to whatever specified channel ID.
Just imagine your private code being able to be scanned, or detected by an external party (or worse, a malicious actor) who should not have access… 😱
The Reality 🥽
Every day, new types of security vulnerabilities and attack vectors get uncovered. Some are detected by development teams early during development, and some unfortunately go undetected until they are reported in production.
No matter how well-experienced any team is in building APIs, there will always be some knowledge gaps about API Security.
This is simply because the subject is extremely vast, and evergrowing as technologies continue to advance, and application connections continue to exponentially grow across the digital and cloud landscape.
I personally do not claim to be an expert on API Security. However, having built numerous APIs in the last five and a half years (both internal and external-facing) in highly-regulated industries has taught me some best practices on what to do and not do.
So, I put together a 🧾 checklist of security practices that I prefer to follow when building APIs in any professional setting, securely.
Security Checklist 🧾
1) Identify your Customers (Before doing any development)
- 1a) If you have various classes/groupings of customers (ex: Basic, Premium, Platinum) for your API & application, you should first identify the authenticated and authorized data & views for all of them.
- 1b) By first deciding what data & views you will share with every type of customer, you will avoid scenarios where: Basic-plan customers are able to view application features for Platinum-plan, and avoid sharing more data than what is needed.
- Bottom line: You want to avoid a customer potentially accessing subscription-only content for which they have not paid for; and, a customer not having access to their subscription-only content when they have already paid for it. Both scenarios lead to a horrible user experience, along with reputational and revenue loss for the company.
2) The Basics
- 2a) Store all of your credentials (i.e. username & password, application IDs, database IDs, API Keys) in some type of Secrets Manager. 🤐
- DO NOT under ANY CIRCUMSTANCES store your credentials in plain-text, accessible via the code, deployment scripts, or version control (Git).
.envfile to point to the location of your credentials in a Secrets Manager.
- These are some well-known Secrets Managers/Engines: HashiCorp Vault, AWS Secrets Manager, Google Cloud Secret Manager
- 💡Pro-Tip: Avoid having different APIs share the same passwords. Use separate credentials for separate APIs. This a huge mistake teams make for the sake of delivering stuff faster. Let’s say you have to debug some error, and you’re analyzing error logs/stack traces. API A and API B are both using the same username_bob to call API C. How will you know from the logs whether the issue while calling API C originated from API A or API B? Or worse, what happens when username_bob is leaked somewhere? Now you have two resources (APIs) negatively impacted, and your world is on 🔥🔥🔥fire trying to figure out what the hell is going on.
3) Secure the Data Transfer between API and Customer(s)
- 3a) Validate everything that you receive and/or send (ex: Request Body, Content, Request Headers, Input Parameters, Character length). These are the values that malicious actors most frequently try to manipulate, in order to see if they can elicit a different type of response from an API.
- 3b) Use HTTPS for your API, and TLS for your application. HTTP traffic is readable by any entity with access to the internet. HTTPS traffic on the other hand can only be decrypted by the owner of the HTTPS certificate.
- 3c) TLS can be enabled on an application site by installing a tiny data file that authenticates your API server’s identity, and encrypts data that is sent back to the server from the customer-facing application.
- 💡Pro-Tip: Make sure to remember to verify your TLS certificate files for all requests. Just because you believe that the exchange/communication is occurring between your application and the API, the exchange can be hijacked by man-in-the-middle attacks.
4) Properly handle Authentication and Authorization
- 4a) You need some sort of mechanism to identify who is the customer that is making a request, and whether they are allowed to make that request.
- 4b) Use a protocol such as OAuth 2.0 to enable authorization flows for your customers.
- 4c) If your customer is supplying SSO Tokens, you will need to determine the LOA (Level of Assurance) of their token, and whether their token has the proper LOA to access the data they are requesting.
- 4d) You should also decide on a SSO Token Refresh/Expire Policy; a token that never expires poses a huge security risk, especially if the customer is using a shared device. On the other hand, if your SSO Token expires faster than the amount of time it takes for a customer to complete a flow in your application, you will need to find a way to refresh that token or create a new one for them.
- 💡Pro-Tip: For customer-facing applications, create an alert modal that notifies the customer something like: “Hello! Your session will timeout in X number of seconds/minutes. Please press “Extend” to continue, or “Home” to end your session securely. Thank you!” This way, you empower your customers, and inform them to make a choice. And their session does not abruptly timeout, and break their flow, and give them a nasty experience.
5) Traffic Management — Request and Network Security
- 5a) Protect your services from being accessed by known belligirent IPs through using WAF (Web Application Firewalls). You can include specific IPs or IP ranges to blacklists/whitelists, and effectively block or allow traffic from anywhere.
- 5b) WAFs also protect applications from other OWASP Top-10 Vulnerabilities such as: XSS Cross-Site Scripting, Cookie Poisoning, SQL Injections, Sensitive Data Exposure, and more.
- 5c) Use API Gateways to gatekeep and manage traffic. API Gateways enforce security policies that guard access to the underlying API and data. The security policies determine the behavior of the API, in response to the request that comes through.
- 5d) API Gateway policies can be implemented at various levels such as: 1) Method (policy applying to calling method like getBook), 2) Resource (policy applying to access a specific resource, and its underlying methods), and 3) API (policy that applies to the entire API itself).
- 5e) Use Rate-Limiting to limit the number of API calls the customer or application can make within a specified period of time. This will protect the API from intended and unintended excessive use, thereby maintaining API service availability.
- 💡Pro-Tip: Also be sure to track your various users with API Keys and/or Custom Request Headers. This will give you visibility into who is calling your API, and for what various API calls. Which will also position you to better monitor and audit your API usage, and take corrective measures if necessary.
6) Practice Secure Coding
- 6b) Use some sort of utility to convert and map externally-displayed identifiers to your internal identifiers. NEVER display the internal identifiers (ex: database ID, customer ID, etc.) to clients. Convert them to external identifiers (preferably in GUID/UUID formats) first, and display those. Otherwise, you run the risk of exposing your internal API data to the outside world.
- 6c) Be extremely thorough with your customer matching logic; Does the customer have a valid SSO Token? Cool. Make sure they also have a valid AND active subscription. This way, you are ensuring that only the customers with current and valid subscriptions are entering your application, not just anybody with a valid SSO Token. Remember what happened with YouTube’s channel ID blunder…🔥
- 6d) Build a strong Automated Test Suite which thoroughly tests all of your various customer views; Include Unit and End-to-End tests that can assume all classes/groupings of your customers, and ensure that the appropriate view is rendered for each customer type. So that you are confident of your application behavior, and ensuring that a Platinum-subscription customer is in fact seeing their subscriptions.
7) Scan and Analyze your APIs and Applications
- 7a) Utilize any of the static code scanning tools to preemptively catch and refactor any vulnerable methods in your code before deploying to production.
- 7b) Use dependency scans to scan and make sure that you are not using any compromised tools, libraries, or frameworks in your code that can end up being used as backdoors or attack vectors.
- 💡Pro-Tip: When using dependencies (utilities, libraries, etc.) in your code, always aim to use the most current, and long-term-supported version of the dependency. But, make sure that the latest version does not have any problems associated with it. Check and verify! It happens rarely, but does happen.
- 7c) You have a web application? Use SHAPE Security to scan and collect fingerprint and telemetry data. This will help collect and identify any automated bots or malicious users trying to abuse or access your application.
8) Talk with your Internal Security Team(s)!
- 8a) Make sure your design is PCI/DSS Compliant, or compliant with the jurisdictional laws of whichever region(s) your application is hosted. If it is not, make it compliant before your production deployment.
- 8b) Conduct Penetration tests and resolve any findings.
- 8c) Perform Threat modeling to identify, establish, and understand threats and mitigation measures to protect the value of something.
9) Educate yourself, your teams, and Champion Security! 🙌
- 9a) Participate in gamified security challenges hosted by the Secure Code Warrior. Fun and interactive way to learn about fixing numerous types of code vulnerabilities. Highly-customizable, and lots of fun!
- 9b) Check-in with the OWASP Top-10 to learn about the latest code vulnerabilities, and how to avoid and/or fix them.
- 9c) Take Inventory of your APIs; Catalog and mark your internal-only APIs, external/customer-facing APIs, and establish an API Governance Strategy to share with all stakeholders in your organization for building awareness, education, alignment, and standards around what different APIs can be used for, and how.
Closing Thoughts 📕
This is by no means a final exhuastive list of what engineers should or should not do when building secure APIs. Your experience may differ from mine based on what I’ve shared above.
APIs are super valuable, and security misconfigurations can be extremely costly from both financial, reputation, and branding standpoints.
Please share your thoughts, I would love to learn from you. 💬
Thank you for reading! 🙂👋
Want to learn more about API Architecture? Secure Coding?📝
Check out my series linked below! 🙂
API Architecture: 👇
🛡️Secure Coding🔒 & Engineering: 👇