SSL/TLS for Mobile Apps: Security Guide 2025
Mobile apps require robust SSL/TLS implementation to protect user data and API communications. This guide covers mobile-specific security considerations and implementation best practices.
iOS App Transport Security (ATS)
NSAppTransportSecurity
NSAllowsArbitraryLoads
NSExceptionDomains
api.example.com
NSIncludesSubdomains
NSExceptionMinimumTLSVersion
TLSv1.2
NSExceptionRequiresForwardSecrecy
Certificate Pinning - iOS
// Swift
let pinnedHash = "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
guard let serverTrust = challenge.protectionSpace.serverTrust,
let certificate = SecTrustGetCertificateAtIndex(serverTrust, 0) else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
let serverPublicKey = SecCertificateCopyKey(certificate)
let serverPublicKeyData = SecKeyCopyExternalRepresentation(serverPublicKey!, nil)! as Data
let serverHash = sha256(data: serverPublicKeyData)
if serverHash == pinnedHash {
completionHandler(.useCredential, URLCredential(trust: serverTrust))
} else {
completionHandler(.cancelAuthenticationChallenge, nil)
}
}
Certificate Pinning - Android
// Kotlin with OkHttp
val certificatePinner = CertificatePinner.Builder()
.add("api.example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.add("api.example.com", "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=")
.build()
val client = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build()
Android Network Security Config
api.example.com
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=
API Security Best Practices
- Always use HTTPS for API calls
- Implement certificate pinning for production
- Use token-based authentication (OAuth 2.0, JWT)
- Validate SSL certificates properly
- Never disable SSL verification in production
- Implement request signing
- Use API rate limiting
Testing SSL in Mobile Apps
# Test with Charles Proxy
# 1. Install Charles certificate on device
# 2. Configure proxy settings
# 3. Monitor SSL traffic
# 4. Verify pinning blocks MITM
# Test with mitmproxy
mitmproxy --mode transparent --showhost
Common Mistakes
⚠️ Never Do This
- Disable SSL verification in production
- Accept all certificates
- Use single pin without backup
- Store API keys in app code
- Allow cleartext traffic
Mobile SSL Challenges
Mobile applications face unique SSL/TLS challenges including certificate pinning implementation, handling certificate validation errors, managing network transitions, and dealing with corporate proxies. Mobile platforms (iOS and Android) provide built-in SSL/TLS support, but proper implementation requires understanding platform-specific APIs and security best practices.
Certificate Pinning Implementation
Why Certificate Pinning
Certificate pinning protects against man-in-the-middle attacks by validating that the server's certificate matches a known, trusted certificate or public key. This prevents attacks using compromised or fraudulent certificates, even if they're signed by trusted CAs. Pinning is essential for mobile apps handling sensitive data like financial transactions or personal information.
iOS Certificate Pinning
// iOS Certificate Pinning with URLSession
import Foundation
import Security
class PinningDelegate: NSObject, URLSessionDelegate {
let pinnedCertificates: [Data]
init(certificates: [Data]) {
self.pinnedCertificates = certificates
}
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
guard let serverTrust = challenge.protectionSpace.serverTrust,
let certificate = SecTrustGetCertificateAtIndex(serverTrust, 0) else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
let serverCertificateData = SecCertificateCopyData(certificate) as Data
if pinnedCertificates.contains(serverCertificateData) {
let credential = URLCredential(trust: serverTrust)
completionHandler(.useCredential, credential)
} else {
completionHandler(.cancelAuthenticationChallenge, nil)
}
}
}
Android Certificate Pinning
// Android Certificate Pinning with OkHttp
import okhttp3.CertificatePinner;
import okhttp3.OkHttpClient;
OkHttpClient client = new OkHttpClient.Builder()
.certificatePinner(new CertificatePinner.Builder()
.add("api.example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.add("api.example.com", "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=")
.build())
.build();
// Network Security Configuration (Android 7.0+)
// res/xml/network_security_config.xml
api.example.com
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=
Backup Pins and Pin Rotation
Always implement backup pins to prevent app lockout if primary certificate changes. Include pins for both current and future certificates. Plan pin rotation strategy before certificate renewal. Test pin updates thoroughly in staging environments before production deployment.
Pin Rotation Strategy
Implement dynamic pin updates through app configuration APIs. Include multiple pins (current + backup) in initial app release. Update pins through app updates well before certificate expiration. Monitor pin validation failures to detect issues early.
Handling Certificate Validation
Custom Trust Managers
Implement custom trust managers for special cases like development environments or corporate proxies. Never disable certificate validation in production apps. Use separate build configurations for development and production with different validation logic.
Network Security Best Practices
Cleartext Traffic Prevention
Disable cleartext (HTTP) traffic in mobile apps. Use App Transport Security (ATS) on iOS and Network Security Configuration on Android to enforce HTTPS. Configure exceptions only for specific domains when absolutely necessary.
// iOS App Transport Security (Info.plist)
NSAppTransportSecurity
NSAllowsArbitraryLoads
NSExceptionDomains
example.com
NSIncludesSubdomains
NSRequiresCertificateTransparency
Performance Optimization
Connection Pooling
Reuse SSL/TLS connections to reduce handshake overhead. Configure appropriate connection pool sizes and timeouts. Implement connection keep-alive for long-lived connections.
Session Resumption
Enable TLS session resumption to reduce handshake latency for subsequent connections. Mobile platforms handle session caching automatically, but ensure server-side session cache is properly configured.
Testing and Debugging
SSL Proxy Testing
Test SSL implementation using proxy tools like Charles Proxy or mitmproxy. Verify certificate pinning prevents proxy interception. Test error handling for various SSL failure scenarios.
Certificate Expiration Testing
Test app behavior when certificates expire or are revoked. Implement graceful error handling and user-friendly error messages. Provide clear guidance for users experiencing SSL errors.
Compliance and Security
Ensure mobile SSL implementation meets compliance requirements (PCI DSS, HIPAA, GDPR). Implement certificate transparency checking where required. Maintain audit logs of SSL/TLS connections for security monitoring.
Third-Party Libraries
Use well-maintained SSL libraries like Alamofire (iOS) or OkHttp (Android). Keep libraries updated to patch security vulnerabilities. Review library SSL configuration and customize as needed for security requirements.