Encrypted SharedPreferences for secure storage

Alex Chen Jan 2026
1 tab
package com.example.myapp.data.local

import android.content.Context
import android.content.SharedPreferences
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class SecurePreferencesManager @Inject constructor(
    context: Context
) {
    private val masterKey = MasterKey.Builder(context)
        .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
        .build()

    private val sharedPreferences: SharedPreferences =
        EncryptedSharedPreferences.create(
            context,
            "secure_prefs",
            masterKey,
            EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
            EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
        )

    companion object {
        private const val KEY_AUTH_TOKEN = "auth_token"
        private const val KEY_REFRESH_TOKEN = "refresh_token"
        private const val KEY_USER_ID = "user_id"
        private const val KEY_IS_LOGGED_IN = "is_logged_in"
    }

    var authToken: String?
        get() = sharedPreferences.getString(KEY_AUTH_TOKEN, null)
        set(value) {
            sharedPreferences.edit().putString(KEY_AUTH_TOKEN, value).apply()
        }

    var refreshToken: String?
        get() = sharedPreferences.getString(KEY_REFRESH_TOKEN, null)
        set(value) {
            sharedPreferences.edit().putString(KEY_REFRESH_TOKEN, value).apply()
        }

    var userId: Int
        get() = sharedPreferences.getInt(KEY_USER_ID, -1)
        set(value) {
            sharedPreferences.edit().putInt(KEY_USER_ID, value).apply()
        }

    var isLoggedIn: Boolean
        get() = sharedPreferences.getBoolean(KEY_IS_LOGGED_IN, false)
        set(value) {
            sharedPreferences.edit().putBoolean(KEY_IS_LOGGED_IN, value).apply()
        }

    fun saveTokens(authToken: String, refreshToken: String) {
        sharedPreferences.edit()
            .putString(KEY_AUTH_TOKEN, authToken)
            .putString(KEY_REFRESH_TOKEN, refreshToken)
            .putBoolean(KEY_IS_LOGGED_IN, true)
            .apply()
    }

    fun clearAll() {
        sharedPreferences.edit().clear().apply()
    }

    fun logout() {
        sharedPreferences.edit()
            .remove(KEY_AUTH_TOKEN)
            .remove(KEY_REFRESH_TOKEN)
            .putBoolean(KEY_IS_LOGGED_IN, false)
            .apply()
    }
}
1 file · kotlin Explain with highlit

EncryptedSharedPreferences secures simple key-value data using Android Keystore. I create instances with EncryptedSharedPreferences.create() specifying encryption schemes. The master key uses MasterKeys or MasterKey.Builder for automatic key generation and storage. Data is encrypted at rest using AES256-GCM for values and AES256-SIV for keys. The API matches standard SharedPreferences—putString(), getString(), etc. Security supports API 23+. For older devices, fallback to unencrypted or custom encryption. Use for auth tokens, API keys, user preferences—not large files. EncryptedSharedPreferences handles encryption transparently, providing security without complexity.