When developing applications that consume internal web services, the requirement for HTTPS connections often creates a dilemma. Our team recently faced this exact scenario where our application needed to communicate with an intranet-hosted web service using HTTPS.
For internal services, we essentially have two options:
- Self-signed certificates: Generated internally without CA validation
- Purchased certificates: Issued by a trusted Certificate Authority (CA)
Here's how each approach looks in code when making HTTPS requests:
// Using self-signed certificate (Node.js example)
const https = require('https');
const fs = require('fs');
const options = {
hostname: 'internal-service.company.local',
port: 443,
path: '/api',
method: 'GET',
ca: fs.readFileSync('self-signed-cert.pem'), // Must specify CA
rejectUnauthorized: true // Important for security
};
const req = https.request(options, (res) => {
// Handle response
});
// Using purchased certificate (standard HTTPS)
const https = require('https');
const options = {
hostname: 'internal-service.company.local',
port: 443,
path: '/api',
method: 'GET'
};
const req = https.request(options, (res) => {
// Handle response
});
For self-signed certificates:
- No cost involved
- Requires manual certificate distribution to all clients
- Needs additional code to handle certificate verification
- Potential security risks if not implemented properly
For purchased certificates:
- Minimal client-side configuration needed
- Works seamlessly with most HTTP clients/libraries
- Comes with automatic trust from all major operating systems
- Involves annual costs
If you opt for self-signed certificates:
# Generate self-signed certificate (OpenSSL)
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
For purchased certificates, consider these options:
- Standard DV certificates (cheapest option)
- Wildcard certificates if you have multiple subdomains
- Private PKI if you have many internal services
Choose self-signed when:
- You have complete control over all client machines
- Certificate management infrastructure exists
- Budget constraints prevent purchasing certificates
Choose purchased certificates when:
- You need to support various client devices/platforms
- Your development team prefers standard HTTPS behavior
- You want to minimize maintenance overhead
Both approaches can be secure if implemented correctly. The main differences:
Factor | Self-Signed | Purchased |
---|---|---|
Encryption Strength | Equal | Equal |
Trust Verification | Manual | Automatic |
Revocation Handling | Manual | OCSP/CRL |
For most internal web services that need to support various applications and developers, purchased SSL certificates provide the best balance between security and convenience. The cost is relatively low compared to the development time saved from not having to handle certificate distribution and verification in code.
However, if you have a controlled environment where you can manage certificate distribution effectively, self-signed certificates remain a viable option.
When developing applications that consume internal web services, the HTTPS requirement often comes up - even for services that never face the public internet. Here's why developers insist on HTTPS:
// Modern browsers block mixed content
fetch('http://internal-api.company.local/data') // Blocked in Chrome
.then(response => response.json())
.catch(err => console.error('Failed:', err));
// While HTTPS connections work normally
fetch('https://internal-api.company.local/data')
.then(response => response.json());
For internal services, you essentially have three approaches:
Option | Cost | Setup Complexity | Maintenance | Browser Trust |
---|---|---|---|---|
Commercial SSL | $50-$500/yr | Low | Annual renewal | Full |
Self-Signed | Free | Medium | Manual updates | Warnings |
Internal CA | Free | High | Centralized | Full (when configured) |
Self-signed certificates are perfectly viable for:
- Development environments
- Testing clusters
- Temporary services
- Prototyping phases
Here's how to generate one with OpenSSL:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/CN=internal-service.local"
Purchased certificates become necessary when:
- Multiple teams consume the API
- You need to automate certificate distribution
- Service availability is critical
- You want to avoid certificate warnings
For enterprises, setting up an internal CA provides the best balance:
# Example of importing CA cert on Windows
Import-Certificate -FilePath "C:\certs\company-ca.crt" -CertStoreLocation Cert:\LocalMachine\Root
# On Linux (Debian/Ubuntu):
sudo cp company-ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
When deciding, consider these technical factors:
- Certificate revocation requirements
- Support for modern cipher suites
- SAN (Subject Alternative Name) requirements
- Certificate transparency logging
For Node.js services, here's how to use a self-signed cert:
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
};
https.createServer(options, (req, res) => {
res.writeHead(200);
res.end('Secure internal service\n');
}).listen(8443);