Files
markmywords/PASSWORD_PROTECTION.md
T

6.8 KiB

Password Protection for markmywords

This document describes the password protection feature for encrypted markdown files in markmywords.

Overview

When you encrypt a file with a password, it is automatically password-protected. Users must authenticate with the password before viewing the content in a browser.

Important: Only encrypted files (.md.enc) support password protection. Regular markdown files (.md) are always publicly viewable.

Security Features

  • Bcrypt Hashing: Passwords are hashed using bcrypt, a secure password hashing algorithm
  • Session Management: Once authenticated, users remain authenticated for that file in their session
  • File Permissions: Password database is stored with restricted file permissions (0600)
  • No Plain Text: Passwords are never stored in plain text
  • HTTPS Ready: Works seamlessly with HTTPS/SSL
  • Encryption Compatible: Works with encrypted files for defense-in-depth security

Configuration

Environment Variables

# Set a strong secret key for Flask sessions (REQUIRED for production)
export FLASK_SECRET_KEY="your-very-secure-random-key"

# Optional: Set master admin password for programmatic file operations
export MARKMYWORDS_ADMIN_PASSWORD="your-admin-password"

Using the CLI Tool

The manage_content.py script provides encryption and password protection management.

Encrypt a File (Automatically Protected)

python manage_content.py encrypt <filepath> <password>

# Example:
python manage_content.py encrypt content/docs/secret-guide.md "mypassword123"

This encrypts the file and automatically sets password protection. The same password is used for both encryption and browser authentication.

Remove Password Requirement (Keep Encryption)

python manage_content.py unprotect <filepath>

# Example:
python manage_content.py unprotect content/docs/secret-guide.md.enc

# File stays encrypted but no password prompt in browser

List Protected Files

# List all encrypted/protected files
python manage_content.py list

# List encrypted files in a directory
python manage_content.py list content/docs/

Check Protection Status

python manage_content.py status <filepath>

# Example:
python manage_content.py status content/docs/secret-guide.md.enc

# Output shows: Encrypted: Yes, Protected: Yes

Encrypted Files with Automatic Protection

When you encrypt a file, password protection is automatic:

# Encrypt a file - automatically sets password protection
python manage_content.py encrypt content/secret.md "mypassword"

# In browser:
# 1. User navigates to file
# 2. User sees password prompt (same password as encryption)
# 3. User enters password
# 4. File is decrypted and displayed with full markdown support

The same password is used for both encryption and browser authentication.

Using the API

Authenticate for an Encrypted File

curl -X POST http://localhost:5000/api/auth/docs/secret-guide.md.enc \
  -d "password=mypassword123"

# Response:
# {"success": true, "redirect": "/view/docs/secret-guide.md.enc"}

After successful authentication, the password is stored in the session and used to decrypt the file for display.

Password Database

Passwords are stored in /config/page_passwords.json with the following structure:

{
  "content/path/to/file.md": {
    "protected": true,
    "password_hash": "$2b$12$...",
    "created_at": "2024-01-15T10:30:00.000000"
  },
  "content/path/to/encrypted.md.enc": {
    "encrypted": true,
    "protected": true,
    "password_hash": "$2b$12$...",
    "encrypted_at": "2024-01-15T10:30:00.000000",
    "created_at": "2024-01-15T10:30:00.000000"
  }
}

Important: This file should be backed up and kept secure. The password hashes cannot be reversed, but the file itself should have restricted access.

How It Works

  1. User Requests File: User navigates to a protected file
  2. Protection Check: Application checks if file is password protected
  3. Password Prompt: If protected and user not authenticated, show password form
  4. Authentication: User enters password
  5. Verification: Password is checked against the stored bcrypt hash
  6. Session Storage: On success, file authentication is stored in user's session
  7. Content Display: Protected file content is displayed
  8. Session Expiry: Authentication expires when user's session expires (typically when browser is closed)

Use Cases

  • Sensitive Documentation: Encrypt internal documentation
  • Private Notes: Keep personal notes encrypted and password-protected
  • Confidential Information: Encrypt security guidelines, API keys, or business secrets
  • Draft Content: Encrypt unfinished or embargoed content with password protection
  • Temporary Public Access: Use unprotect to share encrypted content without password requirement

Best Practices

  1. Strong Passwords: Use passwords with at least 8 characters including mixed case and numbers
  2. Unique Passwords: Use different passwords for different files
  3. Regular Backups: Backup the password database
  4. Secure Secret Key: Set a strong FLASK_SECRET_KEY environment variable
  5. HTTPS: Always use HTTPS in production
  6. Share Carefully: Share passwords through secure channels only
  7. Monitor Access: Check logs for authentication attempts

Troubleshooting

"Invalid password" error repeatedly

  • Check that the password is exactly correct (case-sensitive)
  • Verify the file is actually protected: python manage_content.py status content/path/to/file.md

Session expires too quickly

  • The session expires based on Flask's session cookie settings
  • For persistent authentication longer than the browser session, consider implementing "Remember Me" functionality

Lost access to protected file

  • If you lose the password, you must unprotect the file using the CLI:
    python manage_content.py unprotect content/path/to/file.md
    
  • Then set a new password if desired

Password database corruption

  • If /config/page_passwords.json becomes corrupted, delete it and recreate protections:
    rm /config/page_passwords.json
    python manage_content.py protect content/path/to/file.md <password>
    

Security Considerations

  • Never share passwords via email or unencrypted channels
  • Always use HTTPS in production
  • Regularly audit which files are protected
  • Securely delete the password database when no longer needed
  • Use strong, random passwords generated by a password manager
  • Backup the password database in a secure location

Future Enhancements

Potential future features:

  • Per-user authentication and roles
  • IP whitelisting for protected files
  • Audit logging of access attempts
  • Time-limited access links
  • Integration with external authentication systems (LDAP, OAuth, SAML)