TL;DR
Basic authentication on mobile devices is risky because credentials can be easily compromised if stored insecurely. This guide shows how to identify and mitigate those risks, focusing on secure storage options and avoiding unnecessary use of basic auth.
Identifying the Problem
- App Storage: Most apps store usernames and passwords somewhere on the device. Common locations include shared preferences (Android) or Keychains (iOS). These are often not adequately protected by default.
- Network Traffic: Basic authentication sends credentials in plain text (Base64 encoded, but easily decoded) over the network if HTTPS isn’t used. Even with HTTPS, compromised devices can intercept traffic.
- Third-Party Libraries: Some older or poorly maintained libraries might use insecure storage methods for basic auth details.
Solution Steps
- Avoid Basic Auth Where Possible: The best solution is to avoid using basic authentication altogether. Consider these alternatives:
- OAuth 2.0 / OpenID Connect: Use industry-standard protocols for secure delegation of access.
- API Keys: For machine-to-machine communication, API keys are often a better choice than usernames and passwords.
- Token-Based Authentication (JWT): Use JSON Web Tokens to represent authenticated sessions.
- Secure Storage (If Basic Auth is Unavoidable): If you absolutely must use basic authentication, store the credentials securely:
- Android: Use the EncryptedSharedPreferences class from Jetpack Security. This encrypts shared preferences using your app’s key.
// Example (Kotlin) - requires adding dependencies in build.gradle val masterKeyAlias = "my_app_key" val encryptedPreferences = EncryptedSharedPreferences.create("auth_prefs", masterKeyAlias, ContextCompat.getMainExecutor(context)) encryptedPreferences.edit().putString("username", "your_username").apply() encryptedPreferences.edit().putString("password", "your_password").apply() - iOS: Use the Keychain Services API to store credentials securely. The Keychain provides hardware-backed encryption on many devices.
// Example (Swift) let keychainItem = SecItem(service: "my_app_auth", accessControl: .userAuthentication, data: Data("your_username".utf8), label: "Username") SecItem.saveItem(&keychainItem) // Requires error handling and proper security considerations.
- Android: Use the EncryptedSharedPreferences class from Jetpack Security. This encrypts shared preferences using your app’s key.
- HTTPS Enforcement: Always use HTTPS for all network communication. This encrypts the data in transit, protecting credentials from interception.
- Configure your server to redirect HTTP requests to HTTPS.
- Use a valid SSL/TLS certificate.
- Regular Security Audits: Regularly review your app’s code and dependencies for potential security vulnerabilities, especially related to credential storage.
- Use static analysis tools to identify insecure coding practices.
- Perform penetration testing to simulate real-world attacks.
- Device Security Checks: Implement checks to detect if the device is rooted or jailbroken, as this indicates a higher risk of compromise.
- Consider limiting functionality or requiring additional authentication on compromised devices.
- Credential Rotation: Encourage users to change their passwords regularly. Implement features like password reset and two-factor authentication (2FA) for added security.
Further Considerations
- Biometric Authentication: Integrate biometric authentication (fingerprint, face ID) as an alternative to traditional passwords.
- Data Minimization: Only store the necessary credentials. Avoid storing sensitive information that isn’t required.

