API Keys Hardcoded in Apex: Now in Version Control Forever
“Hardcoded an API key in an Apex class. Committed to Git. Deployed to prod. Key visible to every developer.”
What Happened
Integrating with a third-party payment API for a client. I hardcoded the API key directly in the Apex callout class. Pushed to Git. Deployed to production. The API key was now visible to every developer with repo access, every admin who could view Apex classes in Setup, and anyone who pulled the metadata. When we rotated the key, I had to update the code, run tests, and deploy again. Meanwhile the old key was still in Git history forever.
The Wrong Way
public class PaymentService {
private static final String API_KEY =
'sk_live_4eC39HqLyjWDarjtT1zdp7dc'; // EXPOSED
private static final String ENDPOINT =
'https://api.payment.com/v1/charges';
public static HttpResponse charge(Decimal amount) {
HttpRequest req = new HttpRequest();
req.setEndpoint(ENDPOINT);
req.setHeader('Authorization',
'Bearer ' + API_KEY); // In version control
req.setMethod('POST');
// ...
}
}The Right Way
// Use Named Credentials (best) or Custom Metadata
//
// Setup → Named Credentials:
// Label: Payment API
// URL: https://api.payment.com/v1
// Authentication: Per User or Named Principal
// Auth Protocol: Custom Header
// Header: Authorization
// Value: Bearer {api_key_stored_securely}
public class PaymentService {
public static HttpResponse charge(Decimal amount) {
HttpRequest req = new HttpRequest();
// Named Credential handles auth automatically
req.setEndpoint(
'callout:Payment_API/charges');
req.setMethod('POST');
// No API key in code. Not in Git.
// Not visible in Apex class viewer.
// Rotatable without deployment.
}
}The Lesson
Never put secrets in code. Use Named Credentials for API authentication. They're secure, rotatable without deployment, and invisible in version control. Custom Metadata or Custom Settings (protected) work for other config secrets.
Enjoyed this? Get more like it.
Glen's Musings — AI, investing, and building things. Occasional. Free.
More Security Mistakes
Forgot 'with sharing': Every User Could See Everything
Wrote an Apex class without the sharing keyword. Every user bypassed all sharing rules. Full org access.
Read moreCareer-EndingString Concatenation in SOQL: Hello, Injection
Built a dynamic SOQL query with string concatenation from user input. Textbook injection vulnerability.
Read morePainfulGave Everyone 'Modify All' Because It Fixed the Bug
Users couldn't edit records. I gave the profile 'Modify All Data' instead of fixing the actual sharing rules.
Read more