-
Notifications
You must be signed in to change notification settings - Fork 0
Authentication Module Documentation
- google_login.py - Google OAuth2 authentication management
- fernet_pubnew_class.py - Credential and API key encryption/decryption
Handles encryption and decryption of sensitive data (Google credentials and YouTube API keys) using Fernet symmetric encryption, with keys protected by Windows DPAPI (Data Protection API).
-
user_data_dir: str- Path to the user data directory where encrypted files are stored -
ctk_messagebox: ctk_messagebox- Instance of the custom messagebox for displaying errors/warnings
-
self.user_data_dir- Storage location for encrypted files -
self.ctk_messagebox- Messagebox instance for UI notifications -
self.Fernet_cred- Fernet cipher instance for credential encryption -
self.Fernet_API- Fernet cipher instance for API key encryption
The class manages four encrypted files:
-
fernet_cred_key.enc- Encrypted Fernet key for credential encryption (protected by Windows DPAPI) -
fernet_API_key.enc- Encrypted Fernet key for API encryption (protected by Windows DPAPI) -
cred.enc- Encrypted Google OAuth2 credentials -
API.enc- Encrypted YouTube API key
Purpose: Ensures encryption keys exist; creates them if missing.
Workflow:
- Check if
fernet_cred_key.encexists- If not: Create new key via
_create_cred_key() - Warn user if
cred.encexists (will be deleted) - Delete
cred.encto prevent decryption with wrong key
- If not: Create new key via
- Check if
fernet_API_key.encexists- If not: Create new key via
_create_API_key() - Warn user if
API.encexists (will be deleted) - Delete
API.encto prevent decryption with wrong key
- If not: Create new key via
- Load both Fernet instances
Security Note: Regenerating keys invalidates previously encrypted data.
Purpose: Generate and save a new Fernet key for credential encryption.
Workflow:
- Generate random Fernet key using
Fernet.generate_key() - Protect key using Windows DPAPI (
win32crypt.CryptProtectData()) - Save encrypted key blob to
fernet_cred_key.enc
Purpose: Generate and save a new Fernet key for API encryption.
Workflow:
- Generate random Fernet key
- Protect with Windows DPAPI
- Save to
fernet_API_key.enc
Purpose: Load and decrypt the credential encryption key.
Workflow:
- Read
fernet_cred_key.enc - Decrypt using Windows DPAPI (
win32crypt.CryptUnprotectData()) - Return Fernet cipher instance
Error Handling:
- On DPAPI error: Show fatal error messagebox and terminate app (
os._exit(1)) - Instructs user to delete
fernet_cred_key.encand restart
Purpose: Load and decrypt the API encryption key.
Workflow:
- Read
fernet_API_key.enc - Decrypt using Windows DPAPI
- Return Fernet cipher instance
Error Handling:
- On DPAPI error: Show fatal error and exit
- Instructs user to delete
fernet_API_key.encand restart
Purpose: Encrypt and save YouTube API key.
Workflow:
- Verify encryption keys exist (
check_and_create_sys_key()) - Encode API string to bytes
- Encrypt using
self.Fernet_API.encrypt() - Write encrypted data to
API.enc
Purpose: Decrypt and return YouTube API key.
Workflow:
- Read
API.enc - Decrypt using
self.Fernet_API.decrypt() - Decode bytes to string and return
Returns:
-
str- Decrypted API key -
None- If file not found or decryption fails
Error Handling:
-
FileNotFoundError: ReturnNone - Other exceptions: Show error messagebox and return
None
Purpose: Encrypt and save Google OAuth2 credentials.
Workflow:
- Verify encryption keys exist
- Convert credentials to JSON string (
cred.to_json()) - Encode to bytes
- Encrypt using
self.Fernet_cred.encrypt() - Write to
cred.enc
Error Handling:
- Show error messagebox on failure
Purpose: Decrypt and return Google OAuth2 credentials.
Workflow:
- Read
cred.enc - Decrypt using
self.Fernet_cred.decrypt() - Decode bytes to string
- Parse JSON and create Credentials object via
Credentials.from_authorized_user_info()
Returns:
-
Credentials- Google OAuth2 credentials object -
None- If file not found or decryption fails
Error Handling:
-
FileNotFoundError: ReturnNone - Other exceptions: Show error messagebox and return
None
Purpose: Delete all encryption-related files (reset encryption system).
Workflow: Attempts to delete all four files:
fernet_cred_key.encfernet_API_key.enccred.encAPI.enc
Sets Fernet instances to None.
Use Case: Complete reset of authentication/encryption system.
Manages Google OAuth2 authentication flow, credential storage, and user information retrieval for YouTube API access.
Custom browser handler to open OAuth2 flow in Chrome app mode (without browser UI chrome).
Workflow:
- Launch Chrome as a subprocess with
--appflag - Opens URL in borderless app window
- Stores process handle in global
chrome_process
Returns: True
Main authentication controller handling login, logout, credential management, and user info retrieval.
-
ver: str- Application version string -
current_dir: str- Application root directory -
ctk_messagebox: ctk_messagebox- Messagebox instance for UI notifications -
log_handle: Callable- Logging function -
youtubeAPI: str- YouTube API key (optional)
-
self.CONFIG- Loaded fromuser_data/config.json -
self.ver- Application version -
self.client_secret_path- Path to Google OAuth2 client secrets JSON -
self.youtubeAPI- YouTube API key -
self.log_handle- Logging function -
self.current_dir- App directory -
self.ctk_messagebox- Messagebox instance -
self.Fernet_encryptor- Instance ofFerner_encrptorfor credential encryption - Custom Chrome browser registered with webbrowser module
Purpose: Load saved credentials and refresh if expired (non-interactive).
Workflow:
- Decrypt credentials using
self.Fernet_encryptor.decrypte_cred() - If credentials don't exist: Return
None - If credentials expired but have refresh token:
- Attempt to refresh using
cred.refresh(Request()) - If successful: Re-encrypt and save updated credentials
- If failed: Return
None
- Attempt to refresh using
- If valid: Return credentials
Returns:
-
Credentials- Valid OAuth2 credentials -
None- If not found, expired without refresh token, or refresh failed
Error Handling:
-
FileNotFoundError: ReturnNone - Other exceptions: Show toast notification and return
None
Use Case: Called at app initialization to check for existing valid credentials.
Purpose: Retrieve Google user profile information.
Decorator: @check_internet_silent - Silently checks internet connection before execution.
Workflow:
- Check if credentials exist and are not expired
- Make API request to
https://www.googleapis.com/oauth2/v3/userinfo- Uses Bearer token authentication
- Parse JSON response
- Check for error_description in response
- If error: Show toast notification and return
None
- If error: Show toast notification and return
- Return user info dictionary
Returns:
-
dict- User information (email, name, picture, etc.) -
None- If credentials invalid or API error
Response Fields (typical):
-
sub- User ID -
name- Full name -
email- Email address -
picture- Profile picture URL
Error Handling:
- Exception: Show toast notification and return
None
Purpose: Logout user by deleting all stored authentication data.
Workflow: Attempts to delete three files:
-
user_data/cred.enc- Encrypted credentials -
user_data/liked.json- Cached liked videos -
user_data/sub.json- Cached subscriptions
Returns:
-
True- If logout successful -
Exception- If error occurs during file deletion
Error Handling:
- Silently ignores
FileNotFoundErrorfor each file
Purpose: Execute OAuth2 authentication flow and save credentials.
Decorator: @check_internet - Checks internet connection; shows error if offline.
Important Notes:
- Should run in separate thread (blocks until user completes auth)
- Requires modified
google_auth_oauthlib.flow.pyto support custom HTML success message
Workflow:
- Show toast notification about starting login process
- Verify
client_secret_pathexists- If not: Show error "no client secrets" and return
None
- If not: Show error "no client secrets" and return
- Verify YouTube API key exists
- If not: Show error "no API" and return
None
- If not: Show error "no API" and return
- Define OAuth2 scopes:
-
youtube.readonly- Read YouTube data -
userinfo.profile- Read user profile
-
- Create OAuth2 flow from client secrets
- Read custom success HTML from
_internal/google_login_suc_red_page.html - Run local server for OAuth2 callback:
- Port: 0 (random available port)
- Timeout: 120 seconds
- Browser:
chrome_app(custom Chrome handler) - Success message: Custom HTML page
- Encrypt and save credentials using
self.Fernet_encryptor.encrypt_cred() - Print success/failure message
- Return credentials
Returns:
-
Credentials- If authentication successful -
None- If error or user cancelled
Error Handling:
- Silent exception handling (bare
except: pass)
Purpose: Force Google login in separate thread and wait for completion.
Workflow:
- Create thread running
get_google_cred_and_save() - Start thread
- Wait for thread completion (
thread.join()) - Load saved credentials from environment
- Return credentials
Returns:
-
Credentials- Newly acquired credentials -
None- If login failed
Use Case: When user explicitly clicks "Login" button.
Purpose: Get valid credentials (load saved or force login if needed).
Workflow:
- Try to load credentials from environment (
load_token_from_env()) - If no valid credentials:
- Print "loaded cred from env"
- Force Google login (
get_google_cred())
- Return credentials
Returns:
-
Credentials- Valid credentials -
None- If all methods fail
Error Handling:
- Silent exception handling (bare
except: pass)
[App Start]
↓
[Load Config]
↓
[Initialize google_auth_control]
↓
[Initialize Ferner_encrptor]
↓
[Check/Create Encryption Keys]
↓
[load_token_from_env()]
↓
├─→ [Credentials Found & Valid] → [Load User Info] → [Continue]
├─→ [Credentials Expired] → [Attempt Refresh]
│ ↓
│ [Success] → [Save & Continue]
│ ↓
│ [Failed] → [Prompt Login]
└─→ [No Credentials] → [Prompt Login]
[User Clicks Login]
↓
[Verify Internet Connection]
↓
[Check Client Secrets File] ─[Missing]→ [Error: No Client Secrets]
↓ [Exists]
[Check API Key] ─[Missing]→ [Error: No API]
↓ [Exists]
[Start OAuth2 Flow]
↓
[Launch Chrome App Window]
↓
[User Logs In Google]
↓
[Google Redirects to Localhost]
↓
[Receive Authorization Code]
↓
[Exchange Code for Tokens]
↓
[Credentials Object Created]
↓
[Encrypt Credentials]
↓
[Save to cred.enc]
↓
[Success]
[Credential Object]
↓
[Convert to JSON String]
↓
[Encode to Bytes]
↓
[Fernet Encrypt]
↓
[Write to cred.enc]
[Read cred.enc]
↓
[Fernet Decrypt]
↓
[Decode to String]
↓
[Parse JSON]
↓
[Create Credentials Object]
[User Clicks Logout]
↓
[Delete cred.enc]
↓
[Delete liked.json]
↓
[Delete sub.json]
↓
[Clear UI Session]
↓
[Return to Login State]
-
Two-Layer Encryption:
- Layer 1: Fernet symmetric encryption for credentials/API
- Layer 2: Windows DPAPI for Fernet keys
-
Key Storage:
- Fernet keys never stored in plaintext
- Keys protected by Windows user account (DPAPI)
- Keys cannot be decrypted by different Windows user
-
Key Regeneration:
- If encryption keys are lost/corrupted, system auto-regenerates
- Old encrypted data becomes inaccessible (intentional security feature)
- User must re-authenticate
- Scopes: Minimal scopes requested (readonly + profile)
- Token Storage: Access/refresh tokens encrypted at rest
- Auto-Refresh: Expired tokens automatically refreshed without user interaction
- Timeout: 2-minute timeout for OAuth2 flow
- Fatal errors (DPAPI failure): Terminate app to prevent security bypass
- Non-fatal errors: Show user-friendly message and gracefully degrade
- Sensitive errors: Don't expose internal details to user
-
cryptography.fernet- Symmetric encryption -
google.oauth2.credentials- OAuth2 credential objects -
google_auth_oauthlib.flow- OAuth2 authentication flow -
google.auth.transport.requests- Token refresh -
win32crypt- Windows DPAPI -
pywintypes- Windows error types -
requests- HTTP client for API calls
-
notification.wintoast_notify.ToastNotification- Windows toast notifications -
notification.ctkmessagebox.ctk_messagebox- Custom messagebox -
utils.check_internet- Internet connectivity decorators
Located in user_data/config.json
Required Fields:
-
client_secret_path- Path to Google OAuth2 client secrets JSON file
Downloaded from Google Cloud Console
Contains:
- Client ID
- Client secret
- Redirect URIs
- Auth URIs
- Encryption keys bound to Windows user account
- Cannot be accessed by:
- Different Windows user on same machine
- Same username on different machine
- Administrator accounts (without user credentials)
- Encrypted data not portable between machines
- User must re-authenticate when:
- Switching Windows accounts
- Moving to new computer
- Reinstalling Windows
Cause: DPAPI cannot decrypt fernet_cred_key.enc
Reasons:
- File corrupted
- Created by different Windows user
- System integrity compromised
Solution: Delete fernet_cred_key.enc and restart app
Cause: DPAPI cannot decrypt fernet_API_key.enc
Solution: Delete fernet_API_key.enc and restart app
Cause: Fernet decryption failed on cred.enc
Possible Reasons:
- File corrupted
- Mismatched encryption key
- File modified externally
Result: Returns None, user must re-login
Cause: client_secret_path in config.json doesn't exist or is invalid
Solution: Download client secrets from Google Cloud Console and update config
Cause: YouTube API key not configured
Solution: Set YouTube API key in settings
-
Authorization:
https://accounts.google.com/o/oauth2/auth -
Token:
https://oauth2.googleapis.com/token -
User Info:
https://www.googleapis.com/oauth2/v3/userinfo
- Used by other modules (not directly in these files)
- Requires scopes:
youtube.readonly
Last Updated: February 4, 2026 Module Version: Compatible with JaTubePlayer 2.0