Commit graph

4 commits

Author SHA1 Message Date
Vadim Peretokin
b741663a1c
infrastructure: drop comments that restate the code beside them (#9681)
#### Brief overview of PR changes/additions
- Removed 8 comments that only repeated the statement or assertion
message next to them
- Kept 1 of the 16 identical copies of the `lua_next()` key-copy note in
`TLuaInterpreterMedia.cpp`
- Comment-only: zero code lines changed

#### Motivation for adding to Mudlet
Reading a comment and then the code that says the same thing is wasted
effort; the rationale comments that document real gotchas are all
untouched.

#### Other info (issues closed, discussion etc)
Result of a pass over the last month of commits on `development`. The
vast majority of comments added there explain *why* rather than restate
*what*, so this is deliberately a small diff.

**Test case:** `git diff development...HEAD` shows only comment lines
removed; build and test suites are unaffected.


Assisted-by: Claude:claude-opus-5
Signed-off-by: Vadim Peretokin <vadim.peretokin@mudlet.org>
2026-08-11 08:06:16 +02:00
Mike Conley
a97186ad5f
Add: sign in to supported games using your browser (e.g. Google, Discord, or the game's own account) (#9378)
#### Brief overview of PR changes/additions

Adds client-side support for the GMCP `Char.Login` v2 sign-in flow. When
a game offers it, Mudlet automates sign-in *around the game's own login
screen* — it renders no sign-in UI of its own:

- Hands off to the game's interactive screen with an empty
`Char.Login.Credentials {}` when nothing is stored, so the player picks
a provider (Google, Discord, GitHub, the game's own account, …) as text
on the game's own screen.
- Opens the sign-in URL the server pushes (`Char.Login.URL`) in the
system browser — but only after the player has acted on this connection,
never unprompted.
- Autofills a stored character name + password when the profile has
them.
- Persists and replays the server's reconnect token (`Char.Login.Token`
/ `Char.Login.Reconnect`) for instant, password-less reconnects, with a
"forget saved sign-in" control in Preferences → Connection.
- Resumes the *remembered* provider's browser sign-in without a menu
when a saved token has expired or been revoked (`Char.Login.Credentials
{account, provider}`), falling back to the interactive hand-off only
when no provider is remembered.
- Handles token rotation and multiple devices safely: overwrites the
saved token when the server rotates it, and if another running Mudlet
instance sharing the profile's keychain rotates the token mid-flight,
replays the fresh token instead of discarding it.
- For a game that is its own OpenID Provider over TLS, optionally runs
the client-driven PKCE flow end to end (`Char.Login.AuthCode`).

#### Motivation for adding to Mudlet

Modern games are moving to browser-based single sign-on; this lets
Mudlet players use those accounts directly, and reconnect without
re-entering anything — while classic character-name/password logins keep
working unchanged.

#### Other info (issues closed, discussion etc)

- Reworks the approach to resolve @vadi2's UX feedback
(https://github.com/Mudlet/Mudlet/pull/9373#issuecomment-4865669499):
there is **no client pop-up and no in-client chooser**. The game owns
the sign-in screen and offers the choice as text; Mudlet only automates
the mechanical hooks around it (autofill, open URL, save token, replay
token).
- Supersedes and closes #9373.
- Implements the revised v2 draft spec, inspired by #9354.
- Covered by new tests: `OAuthClientFlowTest` (OIDC discovery, PKCE,
loopback capture) and the `GMCPCharLoginTest` functional suite driving a
GMCP server stub through the full client flow.
- Try it out on StickMUD.



https://github.com/user-attachments/assets/566947f6-4f43-4bff-b98c-9328b7a40a2d

---------

Signed-off-by: Michael Conley <sousesider@gmail.com>
2026-07-14 12:20:02 +00:00
Mike Conley
9ce7f72e3d
Infrastructure: fix intermittent SecureStringUtilsTest failure in CI builds (#8194)
#### Brief overview of PR changes/additions

Fixes an intermittent test failure in the password security system that
was causing CI builds to randomly fail. The test now properly validates
that corrupted password data is correctly rejected by the security
mechanisms.

#### Motivation for adding to Mudlet

The `testCorruptedDataDecryption` test was occasionally failing in CI
builds, which could mask real security issues and create unreliable
build results. This fix ensures the test consistently validates that the
password encryption system properly detects and rejects corrupted data.

#### Other info (issues closed, discussion etc)

Requested by @vadi2. The intermittent failure was appearing in some
builds with this error:

```text
FAIL!  : SecureStringUtilsTest::testCorruptedDataDecryption() 'decrypted2.isEmpty() || decrypted2 != password' returned FALSE. ()
   Loc: [/Users/runner/work/Mudlet/Mudlet/test/SecureStringUtilsTest.cpp(264)]
2025-09-07 21:15:08 +02:00
Mike Conley
79ab7be4e2
Improve: Secure credential management with system keychain integration and legacy migration (#7956)
#### Brief overview of PR changes/additions

This pull request implements secure credential management for Mudlet
with system keychain integration and encrypted fallback storage:

**Core Components:**

- **CredentialManager**: High-level API for secure credential storage
with QtKeychain integration
- **SecureStringUtils**: Qt-based cryptographic utilities for encrypted
file storage
- **Legacy Migration**: Automatic detection and migration of existing
plaintext passwords

**Key Features:**

- **System Keychain Integration**: Primary storage in macOS Keychain,
Windows Credential Store, and Linux Secret Service via QtKeychain
- **Encrypted File Fallback**: Qt crypto-based AES encryption for
portable mode and keychain unavailability
- **Seamless Migration**: Automatic detection and upgrade of legacy
password storage formats
- **Profile Isolation**: Per-profile encryption keys prevent
cross-profile credential access
- **Portable Mode Support**: Automatic detection and secure file-based
storage for portable installations

#### Motivation for adding to Mudlet

**Security Enhancement:**

- Eliminates plaintext password storage in profile XML files
- Provides industry-standard system keychain integration for credential
security
- Implements authenticated encryption for fallback scenarios

**User Experience:**  

- Zero configuration required - works automatically across all platforms
- Seamless migration from existing plaintext passwords to secure storage
- Native system integration provides familiar credential management
experience

**Future-Proofing:**

- Extensible architecture supports additional credential types (API
keys, tokens, etc.)
- Robust fallback ensures functionality in all deployment scenarios
- Prepares foundation for OAuth and external service integrations

#### Other info (issues closed, discussion etc)

**Security Architecture:**

- **Keychain-First Strategy**: Prefers system keychain with automatic
encrypted file fallback
- **Legacy Format Detection**: Automatically migrates passwords from
development branch keychain format
- **Memory Security**: Secure string clearing and controlled credential
lifecycle management
- **Input Validation**: Path traversal protection and service name
sanitization

**Implementation Highlights:**

- **Async Operations**: Non-blocking keychain operations with timeout
protection
- **Thread Safety**: Event-driven architecture prevents UI blocking and
race conditions
- **Comprehensive Testing**: Full test coverage for encryption,
migration, and fallback scenarios
- **Cross-Platform**: Unified API across Windows, macOS, and Linux with
platform-specific optimizations

**Version Compatibility & Migration:**

- **Mudlet 4.19.x Compatibility**: Preserves existing plaintext password
storage to ensure compatibility when switching between 4.19.x stable and
development builds
- **Mudlet 4.20.x Migration**: Post-4.20.0 release, automatic migration
begins converting plaintext passwords to secure storage
- **Bidirectional Safety**: Users can safely run both 4.19.x and
development versions without losing access to their passwords during the
transition period
- **Legacy Format Support**: Automatically detects and migrates
passwords from the original development branch keychain format
(`service="Mudlet profile"`) to the new secure format

# Credential Management Workflows

## 1. Credential Storage Strategy

```mermaid
flowchart TD
    A[Store Password Request] --> B{Portable Mode?}
    B -->|Yes| C[Encrypt & Store in Profile File]
    B -->|No| D[Store in System Keychain]
    D --> E{Keychain Success?}
    E -->|Yes| F[Remove Encrypted Fallback File]
    E -->|No| G[Fallback to Encrypted File]
    F --> H[Success]
    G --> I{Encryption Success?}
    I -->|Yes| H
    I -->|No| J[Failure]
    C --> I
    
    classDef primary fill:#4CAF50,stroke:#2E7D32,stroke-width:2px,color:#000
    classDef fallback fill:#FF9800,stroke:#E65100,stroke-width:2px,color:#000
    classDef decision fill:#2196F3,stroke:#0D47A1,stroke-width:2px,color:#fff
    classDef result fill:#9C27B0,stroke:#4A148C,stroke-width:2px,color:#fff
    
    class D,F primary
    class C,G fallback
    class B,E,I decision
    class H,J result
```

## 2. Legacy Migration Workflow

```mermaid
flowchart TD
    A[Retrieve Password Request] --> B[Try New Keychain Format]
    B --> C{Password Found?}
    C -->|Yes| D[Return Password]
    C -->|No| E[Check Legacy Keychain Format]
    E --> F{Legacy Found?}
    F -->|Yes| G[Migrate to New Format]
    G --> H[Store in New Format]
    H --> I[Remove Legacy Entry]
    I --> J[Return Migrated Password]
    F -->|No| K[Try Encrypted File]
    K --> L{File Found?}
    L -->|Yes| M[Decrypt & Return]
    L -->|No| N[Return Empty - No Password Stored]
    
    classDef newformat fill:#4CAF50,stroke:#2E7D32,stroke-width:2px,color:#000
    classDef legacy fill:#FF9800,stroke:#E65100,stroke-width:2px,color:#000
    classDef migration fill:#9C27B0,stroke:#4A148C,stroke-width:2px,color:#fff
    classDef fallback fill:#607D8B,stroke:#263238,stroke-width:2px,color:#fff
    classDef result fill:#2196F3,stroke:#0D47A1,stroke-width:2px,color:#fff
    
    class B,H newformat
    class E,I legacy
    class G migration
    class K fallback
    class D,J,M,N result
```

## 3. Cross-Platform Keychain Integration

```mermaid
flowchart TD
    A[QtKeychain Request] --> B{Platform Detection}
    B -->|macOS| C[Access Keychain Services]
    B -->|Windows| D[Access Credential Store]
    B -->|Linux| E[Access Secret Service]
    C --> F[Store/Retrieve Credential]
    D --> F
    E --> F
    F --> G{Operation Success?}
    G -->|Yes| H[Return Result]
    G -->|No| I[Log Error & Fallback]
    I --> J[Use Encrypted File Storage]
    J --> K[AES Encryption with Profile Key]
    K --> L[Store in Profile Directory]
    
    classDef platform fill:#2196F3,stroke:#0D47A1,stroke-width:2px,color:#fff
    classDef keychain fill:#4CAF50,stroke:#2E7D32,stroke-width:2px,color:#000
    classDef fallback fill:#FF9800,stroke:#E65100,stroke-width:2px,color:#000
    classDef crypto fill:#9C27B0,stroke:#4A148C,stroke-width:2px,color:#fff
    
    class C,D,E platform
    class F,H keychain
    class I,J fallback
    class K,L crypto
```

This implementation provides a comprehensive, secure, and user-friendly
credential management system that seamlessly upgrades existing Mudlet
installations while providing robust security for future credential
storage needs.

---------

Co-authored-by: Vadim Peretokin <vperetokin@hey.com>
2025-08-17 12:44:38 +02:00