Blog | G5 Cyber Security

Offline C# App Security: User Authorization

TL;DR

This guide shows how to add user authorization to a Windows C# application that doesn’t connect to the internet. We’ll store user details locally (encrypted) and check credentials before allowing access to sensitive features.

Setting up User Storage

  1. Choose a storage method: For simplicity, we’ll use an encrypted file. More robust options include using the Windows Data Protection API or a lightweight database like SQLite with encryption.
  2. Create a User class: Define a class to represent user information.
    public class User
    {
        public string Username { get; set; }
        public string PasswordHash { get; set; }
        public string Salt { get; set; }
    }
    
  3. Implement Encryption: Use a strong encryption algorithm (e.g., AES) to protect user credentials.
    using System.Security.Cryptography;
    ...
    private static byte[] Encrypt(string plainText, byte[] key)
    {
        byte[] iv = GenerateIV();
        AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
        aes.Key = key;
        aes.IV = iv;
        ICryptoTransform encryptor = aes.CreateEncryptor();
        using (MemoryStream ms = new MemoryStream())
        {
            using (CryptoStream cs = new CryptoStream(ms, encryptor))
            {
                using (StreamWriter sw = new StreamWriter(cs))
                {
                    sw.Write(plainText);
                }
            }
            return ms.ToArray();
        }
    }
    
  4. Store Users: When a user registers, hash the password (using PBKDF2 or Argon2), generate a salt, and encrypt both the hash and salt before saving them to the file.
    // Example of hashing with PBKDF2
    using System.Security.Cryptography;
    ...
    byte[] salt = GenerateSalt();
    string passwordHash = HashPassword(password, salt);
    User newUser = new User { Username = username, PasswordHash = passwordHash, Salt = Convert.ToBase64String(salt) };
    // Encrypt the user object to a byte array before saving.
    

Authentication Process

  1. Load Users: When the application starts, decrypt the user file and load the users into memory.
  2. Login Form: Create a login form with username and password fields.
  3. Verify Credentials: On login attempt:
    • Retrieve the stored user from memory based on the entered username.
    • Hash the entered password using the stored salt.
    • Compare the hashed entered password with the stored password hash.

Authorization Controls

  1. Define Roles/Permissions: Determine what access levels your application needs (e.g., Admin, Standard User). You can add a ‘Role’ property to the User class.
    public enum Role { Admin, StandardUser } 
    
    public class User
    {
      // ... other properties...
      public Role Role { get; set; }
    }
    
  2. Check Permissions: Before allowing access to sensitive features, check the current user’s role.
    if (currentUser.Role == Role.Admin)
    {
        // Allow access to admin feature
    } else {
        // Deny access and show an error message
    }
    
  3. UI Control Enablement: Disable or hide UI elements based on the user’s role.
    if (currentUser.Role == Role.Admin)
    {
        adminButton.Enabled = true;
    } else {
        adminButton.Enabled = false;
    }
    

Important Considerations

Exit mobile version