# Bookhoard Device Authentication & Sync Implementation Plan ## Executive Summary **Current Problem:** - OPDS routes are publicly accessible (security vulnerability) - Kobo sync uses Bearer tokens but Kobo firmware can't send them (broken) - KOReader documentation is incorrect about Basic Auth - No clear authentication strategy for different device types - Sidecar implementation exists but isn't integrated **Vision:** Transform Bookhoard into a comprehensive Kindle-replacement ecosystem with seamless device sync, supporting both Kobo (native) and KOReader (via plugin) with full functionality including progress, highlights, notes, and bookmarks. --- ## 1. Current State Analysis ### 1.1 Authentication Landscape **Existing Infrastructure:** ```go // DeviceAuthMiddleware - Currently only supports Bearer tokens // File: internal/middleware/device_auth.go:37-108 func (m *DeviceAuthMiddleware) Authenticate(next echo.HandlerFunc) echo.HandlerFunc { // Only checks Authorization: Bearer {token} // Validates against devices.auth_token } ``` **Routes Using Device Auth:** - `/api/sync/kobo/*` - Kobo sync endpoints - `/api/sync/koreader/*` - KOReader sync endpoints - `/opds/devices/*` - OPDS catalog (currently NOT protected, needs auth) **Database Schema:** ```sql -- devices table already has device_identifier field -- Can store serial numbers for Kobo devices ``` ### 1.2 Kobo Integration Status **What's Broken:** - Kobo sends `Authorization: Bearer {kobo-store-token}` (wrong token) - Kobo sends `x-kobo-device: {"SerialNumber":"N123..."}` (what we need to use) - Current middleware rejects Kobo requests because token doesn't match **What's Working:** - Kobo sync handler implementation exists - Endpoints registered: `/api/sync/kobo/markup`, `/bookmark`, `/v1/initialization`, etc. - Can sync progress, highlights, notes, bookmarks once auth works ### 1.3 KOReader Integration Status **What's Broken:** - Documentation says use "Basic Auth" - this is WRONG - KOReader doesn't support custom headers natively for sync - Bearer token can't be sent via standard KOReader settings **What's Working:** - KOReader sync handler supports full feature set - Can sync: progress, bookmarks, highlights, notes, library metadata - Plugin architecture exists but no Bookhoard plugin yet ### 1.4 OPDS Status **Current:** - Routes registered in `internal/router/opds.go:11-12` - **NOT using DeviceAuthMiddleware** (security hole) - Publicly accessible - anyone can enumerate device UUIDs **Required:** - Must require authentication - Needs to work with both Kobo (serial) and KOReader (Bearer token) --- ## 2. User Priorities (Ranked) ### Priority 1: Functionality First **User Quote:** "I want a Kindle system replacement, otherwise I could just use Booklore or KOReader" **Requirements:** - ✅ Full sync: progress, highlights, notes, bookmarks - ✅ Works on both Kobo and KOReader - ✅ Seamless user experience - ✅ OPDS for wireless book delivery - ✅ Two-way sync (device ↔ server) ### Priority 2: Security Second (with documentation) **User Quote:** "This is a self-hosted app so as long as the user is aware of the security implications in the documentation it should be fine" **Acceptable Trade-offs:** - Serial-based auth for Kobo (less secure but easier) - Security risks documented clearly - Token-based for KOReader (more secure) - Users responsible for network security (VPN, etc.) ### Priority 3: Simple Setup **Goal:** Minimal friction for users **Kobo Experience:** - Enter serial number during registration - One line in `Kobo eReader.conf` - No token management - Works immediately **KOReader Experience:** - Copy plugin files - Enter server URL and token - One-time setup - Background sync works automatically --- ## 3. Target State ### 3.1 Unified Authentication Architecture ``` ┌─────────────────────────────────────────────────────────────┐ │ DeviceAuthMiddleware │ │ Enhanced to support multiple auth methods: │ │ │ │ 1. Authorization: Bearer {token} │ │ → Lookup device by auth_token │ │ → Used by: KOReader, OPDS apps │ │ │ │ 2. X-Kobo-Device: {"SerialNumber":"N123..."} │ │ → Extract serial from JSON │ │ → Lookup device by device_identifier │ │ → Used by: Kobo e-readers │ │ │ │ Both paths result in: device context set in echo.Context │ └─────────────────────────────────────────────────────────────┘ ``` ### 3.2 Feature Matrix | Feature | Kobo (Native) | KOReader (Plugin) | |---------|---------------|-------------------| | **Progress Sync** | ✅ Automatic | ✅ Automatic | | **Highlights** | ✅ Native support | ✅ Via plugin API | | **Bookmarks** | ✅ Native support | ✅ Via plugin API | | **Notes** | ✅ Native support | ✅ Via plugin API | | **OPDS** | ✅ Via NickelMenu | ✅ Native OPDS support | | **Setup Complexity** | Low (1 config line) | Medium (plugin install) | | **Auth Method** | Serial number | Bearer token | | **Security** | Medium (documented) | High | ### 3.3 User Flows **Kobo User Journey:** 1. Install NickelMenu (one-time, jailbreak) 2. Open Bookhoard web UI 3. Register device → enter serial number (from Settings) 4. Approve device 5. Edit `Kobo eReader.conf` → add sync URL 6. Read books → automatic sync 7. Access OPDS via NickelMenu **KOReader User Journey:** 1. Install KOReader on device 2. Open Bookhoard web UI 3. Register device → copy auth token 4. Approve device 5. Install Bookhoard plugin → paste token 6. Configure sync settings 7. Read books → automatic sync 8. Add OPDS catalog → browse library --- ## 4. Implementation Plan ### Phase 1: Enhanced Authentication (Week 1) **Goal:** Make auth work for both Kobo and KOReader **Tasks:** 1. **Update DeviceAuthMiddleware** (`internal/middleware/device_auth.go`) - [ ] Try Bearer token lookup first (existing behavior) - [ ] If no Bearer token, check for `x-kobo-device` header - [ ] Parse JSON to extract `SerialNumber` field - [ ] Query database: `GetDeviceByDeviceIdentifier(serial)` - [ ] Set device context on successful auth - [ ] Return 401 if both methods fail 2. **Add Database Query** (`internal/database/queries/devices.sql`) - [ ] Add query: `GetDeviceByDeviceIdentifier` - [ ] Ensure index exists on `device_identifier` column 3. **Update Device Registration UI** (`templates/devices.templ`) - [ ] Add device type selector (Kobo/KOReader) - [ ] Show serial number field for Kobo (required) - [ ] Show serial number field for KOReader (optional, for fallback) - [ ] Generate/display auth token after approval (for KOReader) 4. **Apply Middleware to OPDS** (`internal/router/opds.go`) - [ ] Add `DeviceAuthMiddleware` to all `/opds/devices/*` routes - [ ] Update comments to reflect auth requirements **Testing:** - Kobo device sync with serial auth - KOReader sync with Bearer token auth - OPDS access with both auth methods --- ### Phase 2: Kobo Integration (Week 1-2) **Goal:** Seamless Kobo experience with serial-based auth **Tasks:** 1. **Kobo Setup Documentation** (`docs/user/devices/kobo-setup.md`) - [ ] Revise to reflect serial-based auth (not username/password) - [ ] Step-by-step guide for finding serial number - [ ] NickelMenu configuration for sync - [ ] Security warning about serial-based auth - [ ] Network security recommendations (VPN, local network) 2. **Kobo Sync Validation** (`cmd/server/tests/kobo_test.go`) - [ ] Update tests to use serial auth - [ ] Test sync endpoints with `x-kobo-device` header - [ ] Verify all features work: progress, highlights, bookmarks, notes 3. **Kobo OPDS Integration** - [ ] Document OPDS URL format - [ ] Test OPDS browsing with serial auth - [ ] Test book downloads **Success Criteria:** - New Kobo device registered and syncing within 5 minutes - All sync features working without token management - Security implications clearly documented --- ### Phase 3: KOReader Plugin Development (Week 2-4) **Goal:** Full-featured KOReader plugin with Bearer token auth **Tasks:** 1. **Plugin Architecture** - [ ] Create `koreader-plugin/bookhoard.koplugin/` directory - [ ] Implement `_meta.lua` (plugin metadata) - [ ] Implement `main.lua` (entry point) 2. **Core Plugin Features** - [ ] Settings UI: server URL, auth token, sync options - [ ] HTTP client with Bearer token authentication - [ ] Auto-sync on events: - Page turn (configurable: every N pages) - Bookmark added/deleted - Highlight created/deleted - Note added/edited - [ ] Manual sync button in KOReader menu - [ ] Sync status indicator - [ ] Error handling and retry logic 3. **Plugin API Integration** - [ ] Call `/api/sync/koreader/progress` with reading position - [ ] Call `/api/sync/koreader/bookmarks` with annotations - [ ] Call `/api/sync/koreader/metadata` to get server-side progress - [ ] Handle conflicts (server vs local progress) 4. **Plugin Documentation** - [ ] Installation guide (copy files, restart KOReader) - [ ] Configuration guide (get token from Bookhoard UI) - [ ] Usage instructions - [ ] Troubleshooting guide **Success Criteria:** - Plugin installed and configured in under 10 minutes - Background sync works transparently - All annotation types sync properly - No Lua errors or crashes --- ### Phase 4: OPDS Security & Integration (Week 2-3) **Goal:** Secure OPDS with unified device authentication **Tasks:** 1. **Secure OPDS Routes** (`internal/router/opds.go`) - [ ] Apply `DeviceAuthMiddleware` to all OPDS endpoints - [ ] Ensure auth works with both serial and Bearer methods - [ ] Update router comments 2. **Kobo OPDS Access** - [ ] Document OPDS URL with device ID - [ ] Test with NickelMenu OPDS browser - [ ] Test book downloads 3. **KOReader OPDS Access** - [ ] Works natively via KOReader's OPDS support - [ ] Uses Bearer token in header - [ ] Document catalog URL format 4. **Test Coverage** (`cmd/server/tests/opds_test.go`) - [ ] Test unauthenticated access → expect 401 - [ ] Test with valid Bearer token → expect 200 - [ ] Test with valid serial header → expect 200 - [ ] Test book download with auth --- ### Phase 5: Testing & Documentation (Week 4) **Goal:** Production-ready release with comprehensive docs **Tasks:** 1. **End-to-End Testing** - [ ] Fresh Kobo setup: register → sync → highlights → OPDS - [ ] Fresh KOReader setup: install plugin → sync → highlights → OPDS - [ ] Cross-device sync: Kobo ↔ KOReader same book - [ ] Offline scenarios and conflict resolution - [ ] Error handling and recovery 2. **Security Documentation** - [ ] Security implications page - [ ] Network security recommendations - [ ] Comparison: Bearer vs Serial auth - [ ] Threat model for self-hosted users 3. **User Documentation** - [ ] Quick start guide (Kobo) - [ ] Quick start guide (KOReader) - [ ] Feature comparison table - [ ] FAQ and troubleshooting 4. **Release Preparation** - [ ] Version bump - [ ] Changelog - [ ] Migration guide (if needed) --- ## 5. Technical Decisions ### 5.1 Why Serial-Based Auth for Kobo? **Pros:** - No token management required - Works with unmodified Kobo firmware - Single configuration line - User can't lose/forget credentials **Cons:** - Serial numbers are somewhat predictable - No token rotation possible - If leaked, can't be revoked (must delete device) **Mitigations:** - Document security risks - Recommend VPN for remote access - Use HTTPS (reverse proxy) - Acceptable for self-hosted personal use ### 5.2 Why Bearer Token for KOReader? **Pros:** - Cryptographically secure - Can be revoked/regenerated - Standard authentication method - Works with KOReader plugin architecture **Cons:** - Requires plugin (can't use native settings) - Token must be copy-pasted during setup - User must manage token **Trade-off Accepted:** More secure but requires plugin installation. Justified because KOReader users are typically more technical and willing to install plugins. ### 5.3 Why Not Use Kobo's Token? Kobo sends `Authorization: Bearer {kobo-store-token}` which is: - Managed by Kobo (not under our control) - May rotate/expire without warning - Only valid for Kobo's servers - Doesn't identify the device in our system **Decision:** Parse the `x-kobo-device` header for serial number instead. --- ## 6. Files to Modify ### Core Authentication - `internal/middleware/device_auth.go` - Enhance with serial support - `internal/database/queries/devices.sql` - Add serial lookup query - `internal/router/opds.go` - Apply middleware ### Device Management - `templates/devices.templ` - Update registration form - `internal/handlers/devices.go` - Handle serial input ### Testing - `cmd/server/tests/kobo_test.go` - Update for serial auth - `cmd/server/tests/opds_test.go` - Add auth tests - `cmd/server/tests/test_helpers.go` - Add serial auth helpers ### Documentation - `docs/user/devices/kobo-setup.md` - Rewrite for serial auth - `docs/user/devices/koreader-setup.md` - Update for Bearer token - `docs/user/security.md` - New security implications doc - `koreader-plugin/README.md` - Plugin documentation ### New Files - `koreader-plugin/bookhoard.koplugin/_meta.lua` - Plugin metadata - `koreader-plugin/bookhoard.koplugin/main.lua` - Plugin implementation - `docs/user/quickstart-kobo.md` - Quick start guide - `docs/user/quickstart-koreader.md` - Quick start guide --- ## 7. Success Metrics **Functionality:** - ✅ Kobo syncs progress, highlights, notes, bookmarks automatically - ✅ KOReader syncs same features via plugin - ✅ OPDS works on both platforms - ✅ Cross-device sync works (read on Kobo, continue on KOReader) **Usability:** - ✅ Kobo setup time: < 5 minutes - ✅ KOReader setup time: < 10 minutes - ✅ No token management for Kobo users - ✅ Clear documentation with security warnings **Security:** - ✅ OPDS no longer publicly accessible - ✅ Auth required for all sync endpoints - ✅ Security implications documented - ✅ Network security recommendations provided --- ## 8. Future Enhancements (Out of Scope) - Auto-discovery of devices on network - QR code setup for mobile devices - Background sync service (no plugin needed) - Readwise/Joplin integration - Calibre integration - Mobile apps (iOS/Android) --- ## 9. Decisions Made (User Input) Based on user feedback, the following decisions have been finalized: ### 9.1 KOReader Sync Trigger **Decision:** Configurable with multiple options - **Auto-sync**: Every N pages (configurable, default every 10 pages) - **Auto-sync**: Every N minutes (configurable, default every 5 minutes) - **Manual sync**: Always available via menu - **Event-triggered**: On bookmark/highlight/note creation (immediate) **Rationale:** User wants automatic sync for convenience but manual fallback for control. ### 9.2 Plugin Distribution **Decision:** Separate repository under Bookhoard organization - Repository: `github.com/bookhoard/koreader-plugin` - Licensed under same terms as Bookhoard - Versioned independently - Referenced in main Bookhoard documentation **Rationale:** Clean separation of concerns, easier plugin-specific issues/PRs. ### 9.3 Kobo Authentication **Decision:** Serial number ONLY - No Bearer token fallback for Kobo - Serial entered during device registration - Stored in `devices.device_identifier` **Rationale:** Simplest user experience, one auth method per platform. ### 9.4 Conflict Resolution **Decision:** Use existing codebase strategy - Already implemented in `internal/handlers/koreader.go` - Uses timestamp-based last-write-wins - Device priority can be configured per-device **Rationale:** Don't reinvent the wheel, existing implementation is sufficient. ### 9.5 Implementation Order **Decision:** Parallel implementation with separate sections - Phase 2a: Kobo Integration - Phase 2b: KOReader Plugin (runs concurrently) - Separate milestones and deliverables - Can ship Kobo support before plugin is ready **Rationale:** Faster time-to-market for Kobo users, plugin can follow. --- ## 10. Historical Context & Conversation Summary ### Why This Plan Exists This implementation plan emerged from a detailed analysis of the current authentication and sync architecture. Key discoveries from codebase review: #### The Authentication Problem **Original Issue:** The plan started with `@fix-opds-device-authentication.md` which identified: - OPDS routes were publicly accessible (security vulnerability) - Test `GetDeviceCatalog_WithoutDeviceAuth` expected 401 but got 404 - DeviceAuthMiddleware was already applied to OPDS routes, but tests were failing **Root Cause Discovery:** - Kobo devices send `Authorization: Bearer {kobo-store-token}` (Kobo's store token, not Bookhoard's) - Kobo also sends `x-kobo-device: {"SerialNumber":"N123..."}` header - The middleware was rejecting requests because the Bearer token didn't match `devices.auth_token` - Kobo cannot send custom Bearer tokens through `eReader.conf` #### The Sidecar File Red Herring **Initial Thought:** Use `.bookhoard.json` sidecar file to pass device tokens to Kobo **Problem Discovered:** - Sidecar handler exists (`internal/handlers/sidecar.go`) but routes are NOT registered - Kobo firmware is locked down - cannot read custom config files - No plugin architecture on Kobo (unlike KOReader) - Would require Kobo firmware modification (impossible for most users) **Decision:** Abandon sidecar approach, use serial-based auth instead #### KOReader Documentation Bug **Original Documentation:** Claimed KOReader uses "Basic Auth" with username/password **Reality:** - KOReader sync sends `Authorization: Bearer {token}` to sync servers - The official KOReader sync protocol uses MD5 hashed passwords - Bookhoard's implementation expects Bearer tokens in `DeviceAuthMiddleware` - KOReader cannot send custom headers through native settings **Solution:** Create KOReader plugin that can send proper Bearer tokens #### Booklore Analysis **Investigation:** Analyzed how Booklore handles Kobo authentication **Booklore Approach:** - Token embedded in URL path: `/api/kobo/{token}/...` - Works but token appears in logs - One token per user (not per device) - OPDS uses separate Basic Auth **Decision:** Don't copy Booklore - less secure. Use device-specific auth with proper tokens for KOReader. #### Plugin Feasibility Research **Concern:** Is KOReader a "moving target" for plugin development? **Findings:** - UI plugins are unstable (Issue #13942) - frequent breaking changes - Backend/sync plugins (like Wallabag) are stable - Wallabag2 plugin has minimal updates over years - HTTP client APIs don't change often **Decision:** Proceed with plugin - sync plugins are low-risk ### Technical Constraints Discovered 1. **Kobo Firmware Limitations:** - Cannot send custom HTTP headers (except `x-kobo-device`) - Cannot install plugins - Settings in `eReader.conf` are limited - NickelMenu required for OPDS access (jailbreak) 2. **KOReader Capabilities:** - Can install plugins (copy files to `/koreader/plugins/`) - Lua-based plugin architecture - Can send custom HTTP requests - Can access device serial for identification - Native OPDS client support 3. **Security Trade-offs:** - Serial numbers: Somewhat predictable, easy for users - Bearer tokens: Cryptographically secure, requires setup - User accepted security/usability trade-off for self-hosted use ### Why Functionality Trumps Security **User Quote:** "I want a Kindle system replacement, otherwise I could just use booklore or KOReader. My biggest concern is do any of these limit any of the syncing/downloading implementation I already have. Functionality and features are more important than anything else. Although security does come in at a close second." **Translation:** - Self-hosted = trusted network environment - User understands and accepts risks - Willing to document security implications - Prioritizes working features over perfect security **Resulting Architecture:** - Kobo: Serial auth (medium security, zero friction) - KOReader: Bearer token (high security, requires plugin setup) - Both get full feature parity - Security implications clearly documented --- ## 11. Updated Implementation Timeline ### Parallel Track Structure **Track A: Kobo Integration** - Phase 1: Enhanced Auth (Week 1) - Phase 2a: Kobo Implementation (Week 1-2) - Phase 4: Kobo Testing (Week 3) **Track B: KOReader Plugin** - Phase 1: Enhanced Auth (Week 1) [shared] - Phase 2b: Plugin Development (Week 2-4) - Phase 4: Plugin Testing (Week 4) **Track C: OPDS Security** - Phase 3: OPDS Integration (Week 2-3) **Track D: Documentation** - Phase 5: Final Docs & Release (Week 4) ### Milestones **Milestone 1 (End of Week 2):** Kobo Fully Functional - Serial auth working - All sync features operational - OPDS access secured - Can ship to Kobo users **Milestone 2 (End of Week 4):** KOReader Plugin Ready - Plugin released in separate repo - Full feature parity with Kobo - Documentation complete - Production release --- ## 12. Files & Components Reference ### Critical Files for Implementation **Authentication Core:** - `internal/middleware/device_auth.go:37-108` - Main auth middleware - `internal/database/queries/devices.sql` - Device queries - `internal/database/models.go` - Device model (has device_identifier) **Routing:** - `internal/router/opds.go:11-12` - OPDS routes (need middleware) - `internal/router/sync.go:17-50` - Sync routes - `internal/router/device.go` - Device management routes **Handlers:** - `internal/handlers/kobo.go:26-679` - Kobo sync implementation - `internal/handlers/koreader.go:23-897` - KOReader sync implementation - `internal/handlers/opds.go` - OPDS handler **Tests:** - `cmd/server/tests/kobo_test.go` - Kobo tests - `cmd/server/tests/opds_test.go` - OPDS tests - `cmd/server/tests/test_helpers.go` - Test utilities **Documentation (to update):** - `docs/user/devices/kobo-setup.md` - Currently has wrong info - `docs/user/devices/koreader-setup.md` - Needs Bearer token info **Sidecar (reference only, not implementing):** - `internal/handlers/sidecar.go` - Exists but not wired up - Routes not registered in router --- ## 13. Next Steps ### Immediate Actions (When Ready to Proceed) 1. **Review this plan** - Ensure all decisions and context are captured 2. **Create KOReader plugin repo** - Set up `github.com/bookhoard/koreader-plugin` 3. **Begin Phase 1** - Enhanced DeviceAuthMiddleware 4. **Parallel development** - Kobo and KOReader tracks ### Success Criteria (Reiterated) **Functional:** - ✅ Kobo: Enter serial → register → sync works immediately - ✅ KOReader: Install plugin → enter token → sync works - ✅ Both: Full sync (progress, highlights, notes, bookmarks) - ✅ OPDS: Authenticated access on both platforms - ✅ Cross-device: Read on one, continue on another **Security:** - ✅ OPDS no longer public - ✅ All sync endpoints require auth - ✅ Security implications documented - ✅ Network security recommendations provided **User Experience:** - ✅ Kobo setup: < 5 minutes - ✅ KOReader setup: < 10 minutes - ✅ Clear documentation - ✅ Working examples --- **Plan Status:** Ready for implementation **Last Updated:** Based on conversation ending with user decisions **Note:** User indicated it's late and not proceeding tonight **Ready to implement when you are. This plan captures all our discussion and decisions.** --- ## 10. Risk Assessment **Low Risk:** - Serial auth implementation (well-understood pattern) - OPDS security (straightforward middleware application) - Kobo sync (already implemented, just fixing auth) **Medium Risk:** - KOReader plugin development (Lua learning curve, potential API changes) - Cross-device sync conflicts (need clear resolution strategy) **High Risk:** - KOReader API instability (if they change plugin APIs frequently) - User adoption (may resist plugin installation) **Mitigations:** - Start with Kobo to prove concept - Simple plugin architecture (minimize breaking changes impact) - Excellent documentation to reduce friction - Community feedback loop --- ## 11. Timeline Summary | Phase | Duration | Key Deliverable | |-------|----------|----------------| | Phase 1 | Week 1 | Enhanced auth middleware working | | Phase 2 | Week 1-2 | Kobo fully functional | | Phase 3 | Week 2-4 | KOReader plugin complete | | Phase 4 | Week 2-3 | OPDS secured | | Phase 5 | Week 4 | Testing & docs complete | **Total Duration: 4 weeks** --- **Next Steps:** 1. User reviews and approves plan 2. Answer open questions (Section 9) 3. Begin Phase 1 implementation 4. Weekly check-ins on progress **Ready to proceed?** --- ## 14. Critical Modifications Required ### Issues Discovered During Review The following issues were identified during codebase analysis and must be addressed before or during implementation: ### 14.1 Missing Database Query **Issue**: Phase 1 references `GetDeviceByDeviceIdentifier` query but it doesn't exist in queries.sql **Location**: `internal/database/queries/queries.sql` **Required Addition**: ```sql -- name: GetDeviceByDeviceIdentifier :one SELECT * FROM devices WHERE device_identifier = $1; ``` **Impact**: Blocker - cannot implement serial-based auth without this query --- ### 14.2 Incorrect Documentation **Issue**: Current `docs/user/devices/kobo-setup.md` contains WRONG authentication information **Problems**: - States Kobo uses "Username/Password" in config file (lines 116-118) - Kobo firmware sends `Authorization: Bearer {kobo-store-token}` - NOT configurable - Kobo sends `x-kobo-device: {"SerialNumber":"..."}` header - this is what we must use - Kobo CANNOT send custom Bearer tokens through `eReader.conf` **Required Rewrite**: Section "Configure Kobo Sync" (lines 100-133) must be updated to: 1. Remove Username/Password references 2. Explain serial-based auth works via `x-kobo-device` header (sent automatically by Kobo) 3. Clarify that NO manual token configuration is needed for Kobo 4. Update troubleshooting section to reflect serial auth approach --- ### 14.3 OPDS Authentication Inconsistency **Issue**: OPDS clients (including Kobo's native browser and KOReader) have limited header support **Problem**: - Kobo OPDS browser: Cannot send custom `Authorization` headers - KOReader OPDS client: Can send headers via plugin, but native OPDS support varies - Current plan relies on `DeviceAuthMiddleware` checking `Authorization` header **Proposed Solution**: Implement **dual authentication** for OPDS endpoints: 1. **Header-based** (existing): Check `Authorization: Bearer {token}` for KOReader plugin 2. **URL-based** (new): Check `?token=...` query parameter for Kobo and other clients **Implementation**: ```go // In internal/middleware/device_auth.go func (m *DeviceAuthMiddleware) authenticateWithFallback(c echo.Context) error { // Try Bearer token first authHeader := c.Request().Header.Get("Authorization") if authHeader != "" { token := strings.TrimPrefix(authHeader, "Bearer ") device, err := m.db.GetDeviceByAuthToken(c.Request().Context(), token) if err == nil { return m.setDeviceContext(c, device) } } // Fallback: Check URL token parameter for OPDS urlToken := c.QueryParam("token") if urlToken != "" { device, err := m.db.GetDeviceByAuthToken(c.Request().Context(), urlToken) if err == nil { return m.setDeviceContext(c, device) } } return c.JSON(http.StatusUnauthorized, map[string]string{"error": "authentication required"}) } ``` **Why This Matters**: Without URL-based fallback, Kobo devices cannot access OPDS catalogs regardless of authentication method. --- ### 14.4 Enhanced Security Documentation **Issue**: Security implications of serial-based auth need stronger emphasis **Add to `docs/user/security.md`** (new file): ```markdown ## Serial-Based Authentication Security Considerations ### Risks - **Predictable Identifiers**: Kobo serial numbers follow known patterns (N + 12 digits) - **No Rotation**: Unlike Bearer tokens, serial numbers cannot be changed - **Device Theft**: Physical access to device grants permanent access until manually revoked - **Network Exposure**: On public networks, serial could be intercepted ### Recommended Mitigations 1. **Network Security** (REQUIRED for serial auth) - Use VPN for remote access - Restrict Bookhoard to local network only - Use reverse proxy with SSL/TLS termination - Implement firewall rules limiting access by IP 2. **Monitor Access Logs** - Review device sync logs regularly - Set up alerts for: - Unknown serial numbers - Sync attempts from unusual locations - Rapid sync failures (possible brute force) 3. **Device Management** - Revoke unrecognized devices immediately - Use device approval workflow (already implemented) - Regular audit of registered devices 4. **HTTPS is Mandatory for Remote Access** - Never expose Bookhoard over plain HTTP publicly - Use valid SSL/TLS certificates - Consider client certificate authentication for high-security deployments ### Comparison | Method | Security | Usability | Revocable | Rotation | |---------|-----------|-------------|------------|----------| | Serial Number | ⭐⭐ Medium | ⭐⭐⭐⭐⭐ Excellent | No | No | | Bearer Token | ⭐⭐⭐⭐ High | ⭐⭐⭐ Good | Yes | Yes | **Recommendation**: For self-hosted personal use with trusted local network, serial auth provides acceptable security/usability trade-off. ``` --- ### 14.5 Implementation Order Adjustment **Modified Phase 1 Tasks**: 1. **[CRITICAL]** Add `GetDeviceByDeviceIdentifier` to queries.sql 2. **[CRITICAL]** Update kobo-setup.md documentation with correct auth flow 3. Implement enhanced DeviceAuthMiddleware with dual header/URL support 4. Add device_identifier index if not exists 5. Update tests to verify both auth methods work **Why This Order**: Database query must exist BEFORE middleware can use it. Documentation must be correct BEFORE users attempt setup. --- ## 15. Updated Success Criteria Add to Section 7: **Authentication**: - ✅ Kobo serial-based auth working via `x-kobo-device` header - ✅ KOReader Bearer token auth working via `Authorization` header - ✅ OPDS accessible via BOTH header and URL token fallback - ✅ Security implications documented with mitigation strategies **Database**: - ✅ `GetDeviceByDeviceIdentifier` query implemented and indexed - ✅ `device_identifier` column has UNIQUE constraint (already exists in schema) **Documentation**: - ✅ kobo-setup.md reflects actual auth mechanism (no username/password) - ✅ security.md created with serial auth considerations - ✅ OPDS dual-auth documented in troubleshooting --- **Modified Plan Status**: Critical issues identified and resolved. Ready for implementation. **Last Updated**: Based on codebase review - added Section 14 modifications