* chore: update AlphaHuman version to 0.49.3 and configure updater plugin in tauri.conf.json - Bumped the AlphaHuman package version in Cargo.lock to 0.49.3. - Added updater configuration in tauri.conf.json to enable automatic updates with specified endpoints. * refactor: rename AlphaHuman to OpenHuman across the codebase - Updated all instances of "AlphaHuman" to "OpenHuman" in comments, tooltips, and constants to reflect the new branding. - Adjusted relevant documentation and prompts to ensure consistency with the new name. * refactor: update documentation and configurations to reflect OpenHuman branding - Replaced all instances of "AlphaHuman" with "OpenHuman" in documentation, comments, and configuration files to ensure consistency with the new branding. - Updated deep link URLs and related authentication flows to use the new "openhuman://" scheme. - Adjusted paths and references in the skills system and other related files to align with the new project name.te * refactor: standardize OpenHuman references and update configurations - Replaced all instances of "AlphaHuman" with "OpenHuman" across documentation, comments, and configuration files to maintain branding consistency. - Updated URLs and paths to reflect the new "openhuman://" scheme. - Adjusted environment variable names and related settings to align with the new project identity. - Enhanced documentation for clarity and accuracy regarding the OpenHuman framework.r * chore: update subproject commit reference in skills directory * refactor: update backend URL to reflect new service domain - Changed default backend URL from "https://api.openhuman.xyz" to "https://api.tinyhumans.ai" in both JavaScript and Rust configuration files. - Ensured consistency across the codebase regarding the new backend service endpoint. * feat: introduce identity and migration modules for OpenHuman - Added a new identity module to support AIEOS v1.1 JSON format, including structures for identity, psychology, linguistics, motivations, capabilities, physicality, history, and interests. - Implemented a migration module to facilitate data migration from OpenClaw memory, including SQLite and Markdown sources, with detailed reporting on migration statistics and warnings. - Established utility functions for handling multimodal content and image processing within the OpenHuman framework. - Enhanced the agent system with new dispatcher and classifier functionalities to improve tool management and message classification. * chore: remove Android project files and configurations - Deleted various Android project files including .editorconfig, .gitignore, build.gradle.kts, gradle.properties, and others to clean up the project structure. - Removed all related resources, layouts, and source files from the Android app directory to streamline the codebase. - This cleanup is part of a larger effort to refactor and simplify the project structure. * refactor: update login flow and remove Telegram integration - Removed the TelegramLoginButton component and its references from the OAuthLoginSection, streamlining the login options. - Updated the AppRoutes to remove the login route, reflecting changes in the authentication flow. - Enhanced the RotatingTetrahedronCanvas component with improved geometry and lighting effects for better visual presentation. - Adjusted the TypewriterGreeting component's styling for consistency. - Cleaned up the Welcome page to integrate the OAuthLoginSection directly, improving user experience. * chore: update subproject commit reference in skills directory * chore: update test configurations and improve test assertions - Modified test scripts in package.json to use a specific Vitest configuration file for consistency. - Updated assertions in loader tests to ensure loading durations are non-negative. - Enhanced tool loading tests to clarify expected behavior regarding localStorage and cache management. - Adjusted agent tool registry tests to improve error handling and ensure accurate statistics. - Refined device detection tests to reflect updated fallback URLs. * fix: enhance parameter formatting and remove unused components - Updated the `formatParameters` function to handle cases where schema properties are empty, returning a more informative response. - Deleted the `DownloadScreen` component and associated device detection utilities to streamline the codebase and remove unused functionality. - Adjusted tests to reflect changes in the tool loading and agent tool registry, ensuring accuracy in assertions. * chore: simplify Vitest configuration by removing unused include patterns - Updated the Vitest configuration to remove unnecessary test file patterns, streamlining the test setup for better clarity and maintainability. * refactor: update paths and comments for AI configuration and file watching - Modified Vite configuration to ignore only the `src-tauri` directory. - Updated logging messages to reflect the correct path for writing AI configuration files. - Adjusted fetch calls in the file watcher to use the new path for `TOOLS.md`. - Revised comments and logic in Rust code to clarify the handling of AI configuration file paths, including legacy fallback options. * chore: remove unused updater secrets from GitHub Actions workflow - Deleted UPDATER_GIST_URL and UPDATER_GIST_ID environment variables from the package-and-publish workflow, streamlining the configuration. * chore: comment out Vitest thresholds for clarity - Commented out the thresholds section in the Vitest configuration to improve clarity and maintainability, as it is currently not in use. * ran formatter * chore: update updater public key in tauri configuration - Replaced the existing public key in the updater plugin configuration with a new value to ensure proper functionality and security. * chore: update ESLint configuration and refactor components - Added `localStorage` and `sessionStorage` as readonly globals in ESLint configuration for better linting support. - Removed unused imports from `SkillsPanel.tsx` to clean up the code. - Changed the type of `watcherInterval` in `file-watcher.ts` for improved type safety. - Refactored toast management logic in `Intelligence.tsx` to enhance clarity and maintainability. - Simplified import statements in `IntelligenceProvider.tsx` for consistency. - Streamlined object property shorthand in `agentToolRegistry.ts` for cleaner code. * refactor: improve error handling and type safety in Intelligence component - Enhanced toast notification logic to defer state updates, preventing potential issues with setState in effects. - Updated the source filter dispatch to use a more specific type for improved type safety. * refactor: enhance type safety across various components and services - Updated type definitions from `any` to `unknown` in multiple files to improve type safety and prevent potential runtime errors. - Refactored state management in `TauriCommandsPanel` to use more specific types. - Adjusted context and parameters in several interfaces to ensure consistent typing. - Added ESLint directive to `polyfills.ts` for intentional global assignments. - Streamlined type handling in utility functions and API responses for better clarity and maintainability. * refactor: streamline import statements and improve code clarity - Consolidated import statements in `agentToolRegistry.ts` and `intelligenceSlice.ts` for better readability. - Simplified the `createTestStore` function in `test-utils.tsx` to enhance code conciseness. - Cleaned up the `isExecutionStepProgressEvent` function in `intelligence-chat-api.ts` for improved clarity and maintainability.
11 KiB
Backend Authentication Implementation Guide
Overview
The login web-to-desktop flow uses deep links to hand off authentication from a web browser to the Tauri desktop app. The frontend and Rust-side token exchange are implemented. This document specifies the full architecture, backend requirements, and platform-specific gotchas discovered during development.
Architecture
Web Browser Backend Server Desktop App (Tauri)
│ │ │
│ 1. User clicks login │ │
│─────────────────────────────>│ │
│ │ │
│ 2. Auth flow (Telegram/ │ │
│ Phone OTP) │ │
│<────────────────────────────>│ │
│ │ │
│ 3. POST /api/auth/ │ │
│ web-complete │ │
│─────────────────────────────>│ │
│ │ │
│ 4. Returns loginToken │ │
│<─────────────────────────────│ │
│ │ │
│ 5. Redirect to │ │
│ openhuman://auth?token= │ │
│─────────────────────────────────────────────────────────────>│
│ │ │
│ │ 6. Rust invoke │
│ │ exchange_token │
│ │ (POST /auth/desktop-exchange) │
│ │<─────────────────────────────│
│ │ │
│ │ 7. Returns sessionToken │
│ │ + user object │
│ │─────────────────────────────>│
│ │ │
│ │ 8. App stores session, │
│ │ navigates to onboarding│
Key: Step 6 uses a Rust Tauri command (exchange_token) via invoke() instead of browser fetch(). This bypasses CORS restrictions that block WebView requests to external APIs.
Required Endpoints
1. GET /auth/telegram
Initiates Telegram OAuth. The frontend opens this URL in the system browser.
Query params:
platform=desktop— indicates the callback should produce a deep link handoff
Behavior:
- Redirect user to Telegram OAuth authorization URL
- On callback, validate Telegram user data
- Create or find user in database
- Generate a short-lived
loginToken(single-use, 5-minute TTL) - Redirect to
openhuman://auth?token=<loginToken>
2. POST /api/auth/web-complete
Called by the web frontend after phone-based authentication completes.
Request body:
{ "method": "phone", "phoneNumber": "+1234567890", "countryCode": "+1" }
or
{
"method": "telegram",
"telegramUser": {
/* Telegram user object */
}
}
Response (200):
{ "loginToken": "short-lived-opaque-token" }
Behavior:
- Validate the authentication data (verify OTP for phone, verify Telegram hash)
- Create or find user in database
- Generate a short-lived
loginToken- Store in database with: token value, user ID, created_at, expires_at, used (boolean)
- TTL: 5 minutes
- Single-use: invalidate after first exchange
- Return the token
3. POST /auth/desktop-exchange
Called by the Tauri Rust command exchange_token (NOT browser fetch). Exchanges the short-lived handoff token for a long-lived session.
Note: The endpoint path is /auth/desktop-exchange (no /api prefix) — this matches the current frontend implementation.
Request body:
{ "token": "loginToken-from-web" }
Response (200):
{
"sessionToken": "long-lived-session-token",
"user": { "id": "uuid", "username": "string", "firstName": "string" }
}
Error response (401):
{ "success": false, "error": "Token expired or invalid" }
Behavior:
- Look up the
loginTokenin the database - Validate: not expired, not already used
- Mark token as used (single-use enforcement)
- Generate a long-lived
sessionToken(e.g., 30-day TTL) - Return session token and user profile
Database Schema
users table
| Column | Type | Description |
|---|---|---|
| id | UUID (PK) | User ID |
| username | TEXT | Display name |
| first_name | TEXT (nullable) | First name |
| phone_number | TEXT (nullable) | Phone number |
| telegram_id | TEXT (nullable) | Telegram user ID |
| created_at | TIMESTAMP | Account creation |
| updated_at | TIMESTAMP | Last update |
login_tokens table (handoff tokens)
| Column | Type | Description |
|---|---|---|
| id | UUID (PK) | Token record ID |
| token | TEXT (unique, indexed) | The opaque token string |
| user_id | UUID (FK -> users) | Associated user |
| created_at | TIMESTAMP | When issued |
| expires_at | TIMESTAMP | Expiration (created_at + 5min) |
| used | BOOLEAN | Whether already exchanged |
sessions table
| Column | Type | Description |
|---|---|---|
| id | UUID (PK) | Session ID |
| token | TEXT (unique, indexed) | Session token |
| user_id | UUID (FK -> users) | Associated user |
| created_at | TIMESTAMP | When issued |
| expires_at | TIMESTAMP | Expiration (created_at + 30 days) |
| revoked | BOOLEAN | Whether revoked |
Token Generation
- Use cryptographically secure random bytes (32+ bytes, base64url-encoded)
loginToken: short-lived (5 min), single-use, opaquesessionToken: long-lived (30 days), opaque, revocable
Security Requirements
- Single-use handoff tokens — Mark as used immediately on exchange; reject reuse
- Short TTL on handoff tokens — 5 minutes maximum
- HTTPS only in production — tokens travel as URL parameters and POST bodies
- Rate limiting — on
/api/auth/web-completeand/auth/desktop-exchange - Token entropy — minimum 256 bits of randomness
- Deep link validation — the desktop app only processes
openhuman://authpaths; ignore unknown paths - Telegram data verification — validate the
hashfield using your bot token per Telegram docs
Implementation Details
Rust Token Exchange Command
The desktop app calls the backend via a Rust Tauri command (exchange_token in src-tauri/src/lib.rs) using reqwest. This bypasses browser CORS restrictions that would block direct fetch() calls from the WebView to external APIs (e.g., ngrok tunnels).
#[tauri::command]
async fn exchange_token(backend_url: String, token: String) -> Result<serde_json::Value, String>
Frontend invocation:
const data = await invoke<{ sessionToken?: string; user?: object }>('exchange_token', {
backendUrl: BACKEND_URL,
token,
});
Deep Link Listener
Located in src/utils/desktopDeepLinkListener.ts. Key behaviors:
- Uses lazy dynamic import in
main.tsxto avoid loading before Tauri IPC is ready - No
window.__TAURI__guard — the try/catch handles non-Tauri environments - Uses
localStorage.setItem('deepLinkHandled', 'true')to prevent infinite reload loops (sincegetCurrent()returns the same URL afterwindow.location.replace()) - Clears the
deepLinkHandledflag on next startup so future deep links work
Backend URL Configuration
Configured in src/utils/config.ts:
export const BACKEND_URL =
import.meta.env.VITE_BACKEND_URL || 'https://2937933edf8a.ngrok-free.app';
Set VITE_BACKEND_URL environment variable for different environments.
Frontend Integration Points
| File | Role |
|---|---|
src/main.tsx |
Lazy-imports and starts the deep link listener |
src/utils/desktopDeepLinkListener.ts |
Parses deep link -> invokes Rust exchange_token -> stores session -> navigates |
src/utils/deeplink.ts |
Web-side: calls /api/auth/web-complete and builds openhuman://auth?token=... URL |
src/utils/config.ts |
Backend URL configuration |
src/pages/Login.tsx |
Opens GET /auth/telegram?platform=desktop in browser |
src-tauri/src/lib.rs |
Rust exchange_token command using reqwest (CORS-free) |
Phone OTP Flow (Future)
The frontend has a phone input UI but the OTP verification flow needs:
POST /api/auth/send-otp— sends SMS to phone numberPOST /api/auth/verify-otp— verifies code, returns success- Then
POST /api/auth/web-completewithmethod: "phone"to get the handoff token
Platform-Specific Notes
See 14-deep-link-platform-guide.md for detailed platform gotchas.
Last updated: 2026-01-28