

Discover more from Securing Laravel
Security Tip: Protecting Production APIs
[Tip#29] Protecting the integrity of your data is just as important as stopping hackers.
Greetings everyone! Before we dive into our security tip for this week, I wanted to remind everyone that Laracon Online is on September 14th, streamed free on YouTube! Check out the website for the full speaker list, and stick around until the end when I’ll be talking about the strange, wonderful, majestic, and terrifying creatures that are web browsers. Specifically about the security features they come with and how to use them!
This week we’re covering a slightly different aspect of security than simply stopping hackers. We’re talking about protecting the integrity of your data by preventing accidental API key use in the wrong environments. Which, if you consider it, comes right back to stopping hackers: if you have production keys on staging and a hacker gets into staging through a bug, your production keys are exposed!
👉 Quick Update: Composer 2.4 is out, upgrade now to start using composer audit
.
👉 Security Audits: Want me to hack your app and help you improve your security? 🕵️
Protecting Production APIs
Firstly, what I mean by “production APIs” here are third-party APIs that your application connects to. Billing providers like Stripe immediately come to mind, as well as mail gateways like Postmark, and notification endpoints like Slack. These are the services your app communicates with as part of it’s normal operation, and should be considered just as important to secure as your application itself.
Your app will typically use API keys to connect to these services with, and you’ll often have at least two sets of keys: one for production use, and a second set for staging/testing/dev environments.
The production keys should only ever be used on production, and should only be known by whoever manages your production environment. While the testing keys should be used everywhere else… But how can you be sure?
Since security is all about sensible paranoia, it’s always worth taking extra steps to prevent security risks.
My solution is to prevent production API keys from being used in non-production environments at the Service Provider level. app()->isProduction()
is your friend when it comes to detecting production environments, and some APIs, such as Stripe, even generate keys with prefixes that identify the type of key they are, which is fantastic for blocking production keys outside of production.
Stripe production keys:
pk_live_*
sk_live_*
Stripe test keys:
pk_test_*
sk_test_*
Knowing this prefix, you can do something like this in your AppServiceProvider
:
protected function registerStripe()
{
$secret = config('services.stripe.secret');
if (! app()->isProduction() && ! Str::startsWith($secret, 'sk_test_')) {
throw new Exception('ERROR: Stripe secret for dev/testing key should start with: sk_test_*');
}
Stripe::setApiKey($secret);
}
If the API doesn’t distinguish between the different keys, you’ll have to get more creative though.
One idea is to hard-code the first 2-3 characters of your staging keys into the code and require the prefix when not in production. It won’t expose anything if the code is leaked, and if the staging key is changed, you can commit a fix pretty quickly. (Just make sure the prefix doesn’t also match the production key!)
I covered this a few weeks ago in our Composer Audit security tip.