JWT Security Best Practices in Android

Jyotishgher Astrology
By -
0

 How to secure Token JWT Token in Android Studio

To make the saveJwtToken and getJwtToken methods reusable across different parts of your application, you can create a utility class. JSON Web Tokens (JWTs) are quite common in the OAuth and OpenID Connect world. We're so used to them that we often don't pay much attention to how they're actually used. The general opinion is that they're good for being used as ID tokens or access tokens and that they're secure — as the tokens are usually signed or even encrypted. You have to remember though, that JWT is not a protocol but merely a message format. Here's how to do it:

JWT Security Best Practices

Practice -1

Step 1: Create a Utility Class

Create a class, for example, SharedPreferencesUtils, to hold the methods for saving and retrieving the JWT token.

import android.content.Context;

import android.content.SharedPreferences;


public class SharedPreferencesUtils {


    private static final String PREF_NAME = "MyAppPrefs";

    private static final String JWT_KEY = "jwt_token";


    // Save JWT token

    public static void saveJwtToken(Context context, String token) {

        SharedPreferences sharedPreferences = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);

        SharedPreferences.Editor editor = sharedPreferences.edit();

        editor.putString(JWT_KEY, token);

        editor.apply();

    }


    // Get JWT token

    public static String getJwtToken(Context context) {

        SharedPreferences sharedPreferences = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);

        return sharedPreferences.getString(JWT_KEY, null); // Returns null if not found

    }

}

Advantages of This Approach:

  1. Centralized Code: The logic for saving and retrieving JWT tokens is encapsulated in one place, making it easier to maintain and modify.
  2. Reusability: You can use these utility methods across different activities, fragments, or services without rewriting code.
  3. Consistency: Ensures that the same preferences file and key are used throughout the app.

Practice - 2

To secure shared preferences and protect sensitive data like a JWT token from potential attackers, you can follow these best practices:

1. Encrypt the Data

Use encryption to store sensitive data securely in SharedPreferences. Android provides the EncryptedSharedPreferences class for this purpose.

Implementation with EncryptedSharedPreferences

import android.content.Context;
import android.content.SharedPreferences;
import androidx.security.crypto.EncryptedSharedPreferences;
import androidx.security.crypto.MasterKeys;

public class SecureSharedPreferencesUtils {

    private static final String PREF_NAME = "MyAppPrefs";
    private static final String JWT_KEY = "jwt_token";

    private static SharedPreferences getSecureSharedPreferences(Context context) {
        try {
            String masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);
            return EncryptedSharedPreferences.create(
                    PREF_NAME,
                    masterKeyAlias,
                    context,
                    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
                    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
            );
        } catch (Exception e) {
            throw new RuntimeException("Error creating encrypted shared preferences", e);
        }
    }

    public static void saveJwtToken(Context context, String token) {
        SharedPreferences sharedPreferences = getSecureSharedPreferences(context);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString(JWT_KEY, token);
        editor.apply();
    }

    public static String getJwtToken(Context context) {
        SharedPreferences sharedPreferences = getSecureSharedPreferences(context);
        return sharedPreferences.getString(JWT_KEY, null); // Returns null if not found
    }
}

Obfuscate the Code

  • Use ProGuard or R8 to obfuscate your code. This makes reverse-engineering your app more difficult.
  • Add rules to obfuscate your utility classes if they are not directly used via reflection.

Example: ProGuard Rules

-keepclassmembers class com.example.utils.SecureSharedPreferencesUtils {
    *;
}

Secure Backup Policies

  • Use the allowBackup flag in your app manifest to prevent your app’s data from being backed up and potentially exposed.
  • <application
  •     android:allowBackup="false"
  •     android:fullBackupContent="false">


Below is the final implementation that integrates all recommended security practices:

import android.content.Context;

import android.content.SharedPreferences;

import androidx.security.crypto.EncryptedSharedPreferences;

import androidx.security.crypto.MasterKeys;


public class SecurePreferencesManager {


    private static final String PREF_NAME = "SecureAppPrefs";

    private static final String JWT_KEY = "jwt_token";


    /**

     * Get EncryptedSharedPreferences instance

     *

     * @param context The application context

     * @return Encrypted SharedPreferences instance

     */

    private static SharedPreferences getSecureSharedPreferences(Context context) {

        try {

            // Generate or retrieve the master key for encryption

            String masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);


            return EncryptedSharedPreferences.create(

                    PREF_NAME,

                    masterKeyAlias,

                    context,

                    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,

                    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM

            );

        } catch (Exception e) {

            throw new RuntimeException("Error creating encrypted shared preferences", e);

        }

    }


    /**

     * Save JWT securely in EncryptedSharedPreferences

     *

     * @param context The application context

     * @param token   The JWT token to save

     */

    public static void saveJwtToken(Context context, String token) {

        SharedPreferences sharedPreferences = getSecureSharedPreferences(context);

        SharedPreferences.Editor editor = sharedPreferences.edit();

        editor.putString(JWT_KEY, token);

        editor.apply();

    }


    /**

     * Retrieve JWT securely from EncryptedSharedPreferences

     *

     * @param context The application context

     * @return The saved JWT token, or null if not found

     */

    public static String getJwtToken(Context context) {

        SharedPreferences sharedPreferences = getSecureSharedPreferences(context);

        return sharedPreferences.getString(JWT_KEY, null); // Returns null if not found

    }


    /**

     * Clear JWT token securely from EncryptedSharedPreferences

     *

     * @param context The application context

     */

    public static void clearJwtToken(Context context) {

        SharedPreferences sharedPreferences = getSecureSharedPreferences(context);

        SharedPreferences.Editor editor = sharedPreferences.edit();

        editor.remove(JWT_KEY);

        editor.apply();

    }

}


Usage Example

Save JWT Token

java
String token = "your_secure_jwt_token";
SecurePreferencesManager.saveJwtToken(context, token);

Retrieve JWT Token

java
String retrievedToken = SecurePreferencesManager.getJwtToken(context);
if (retrievedToken != null) { // Use the token System.out.println("Retrieved Token: " + retrievedToken); } else { // Handle missing token System.out.println("No token found."); }

Clear JWT Token

java
SecurePreferencesManager.clearJwtToken(context);
System.out.println("Token cleared from storage.");

Key Features of This Code

  1. Encryption:

    • Uses EncryptedSharedPreferences to encrypt both keys and values.
    • Ensures sensitive data is protected at rest.
  2. Key Management:

    • Leverages Android's MasterKeys to securely generate and manage the encryption key.
  3. Ease of Use:

    • Provides static methods to save, retrieve, and clear tokens.
  4. Security Considerations:

    • Data is encrypted using AES-256 encryption.
    • The EncryptedSharedPreferences API handles encryption and decryption seamlessly.
  5. Error Handling:

    • Wraps the encryption setup in a try-catch block to handle potential runtime issues securely.

Tags:

Post a Comment

0Comments

Post a Comment (0)