mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-27 21:08:00 +00:00
Update deep link authentication scheme from outsourced:// to alphahuman://
- Changed all references in documentation and code to reflect the new `alphahuman://` URL scheme for web-to-desktop handoff. - Updated deep link handling in Tauri configuration, utility functions, and authentication flow to ensure compatibility with the new scheme. - Enhanced documentation to guide users on the updated authentication process. This update improves the clarity and functionality of the authentication flow for the desktop application.
This commit is contained in:
@@ -75,7 +75,7 @@ src/
|
||||
- **165+ TypeScript files**: Comprehensive component library with settings modal system
|
||||
- **Provider chain**: Redux → PersistGate → Socket → Telegram → HashRouter → Routes
|
||||
- **MCP Integration**: 99 Telegram tools for AI-driven interactions
|
||||
- **Deep Link Auth**: Web-to-desktop handoff using `outsourced://` scheme
|
||||
- **Deep Link Auth**: Web-to-desktop handoff using `alphahuman://` scheme
|
||||
|
||||
## React with Tauri
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ Web Browser Backend Server Desktop App (Tauri
|
||||
│<─────────────────────────────│ │
|
||||
│ │ │
|
||||
│ 5. Redirect to │ │
|
||||
│ outsourced://auth?token= │ │
|
||||
│ alphahuman://auth?token= │ │
|
||||
│─────────────────────────────────────────────────────────────>│
|
||||
│ │ │
|
||||
│ │ 6. Rust invoke │
|
||||
@@ -56,7 +56,7 @@ Initiates Telegram OAuth. The frontend opens this URL in the system browser.
|
||||
2. On callback, validate Telegram user data
|
||||
3. Create or find user in database
|
||||
4. Generate a short-lived `loginToken` (single-use, 5-minute TTL)
|
||||
5. Redirect to `outsourced://auth?token=<loginToken>`
|
||||
5. Redirect to `alphahuman://auth?token=<loginToken>`
|
||||
|
||||
### 2. `POST /api/auth/web-complete`
|
||||
|
||||
@@ -180,7 +180,7 @@ Called by the Tauri Rust command `exchange_token` (NOT browser fetch). Exchanges
|
||||
3. **HTTPS only** in production — tokens travel as URL parameters and POST bodies
|
||||
4. **Rate limiting** — on `/api/auth/web-complete` and `/auth/desktop-exchange`
|
||||
5. **Token entropy** — minimum 256 bits of randomness
|
||||
6. **Deep link validation** — the desktop app only processes `outsourced://auth` paths; ignore unknown paths
|
||||
6. **Deep link validation** — the desktop app only processes `alphahuman://auth` paths; ignore unknown paths
|
||||
7. **Telegram data verification** — validate the `hash` field using your bot token per Telegram docs
|
||||
|
||||
## Implementation Details
|
||||
@@ -226,7 +226,7 @@ Set `VITE_BACKEND_URL` environment variable for different environments.
|
||||
|------|------|
|
||||
| `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 `outsourced://auth?token=...` URL |
|
||||
| `src/utils/deeplink.ts` | Web-side: calls `/api/auth/web-complete` and builds `alphahuman://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) |
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Overview
|
||||
|
||||
The `outsourced://` custom URL scheme is used to hand off authentication from a web browser to the Tauri desktop app. This document covers platform-specific behavior, gotchas, and build requirements discovered during development.
|
||||
The `alphahuman://` custom URL scheme is used to hand off authentication from a web browser to the Tauri desktop app. This document covers platform-specific behavior, gotchas, and build requirements discovered during development.
|
||||
|
||||
## Scheme Registration
|
||||
|
||||
@@ -12,7 +12,7 @@ Configured in `src-tauri/tauri.conf.json`:
|
||||
"plugins": {
|
||||
"deep-link": {
|
||||
"desktop": {
|
||||
"schemes": ["outsourced"]
|
||||
"schemes": ["alphahuman"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ cp -R src-tauri/target/debug/bundle/macos/tauri-app.app /Applications/
|
||||
open /Applications/tauri-app.app
|
||||
|
||||
# Test deep link
|
||||
open "outsourced://auth?token=YOUR_TOKEN"
|
||||
open "alphahuman://auth?token=YOUR_TOKEN"
|
||||
```
|
||||
|
||||
### Cargo Caching Gotcha
|
||||
|
||||
@@ -116,9 +116,9 @@ Model Context Protocol implementation for AI tool execution over Socket.io:
|
||||
|
||||
### Deep Link Auth Flow
|
||||
|
||||
Web-to-desktop handoff using `outsourced://` URL scheme:
|
||||
Web-to-desktop handoff using `alphahuman://` URL scheme:
|
||||
1. User authenticates in browser
|
||||
2. Browser redirects to `outsourced://auth?token=<loginToken>`
|
||||
2. Browser redirects to `alphahuman://auth?token=<loginToken>`
|
||||
3. Tauri catches the deep link, Rust `exchange_token` command calls backend via `reqwest` (bypasses CORS)
|
||||
4. Backend returns `sessionToken` + user object
|
||||
5. App stores session in Redux, navigates to onboarding/home
|
||||
@@ -182,7 +182,7 @@ Key updates from recent commits:
|
||||
- ConnectionsPanel.tsx - Connection management with status indicators
|
||||
- Hooks: useSettingsNavigation.ts, useSettingsAnimation.ts
|
||||
- **Onboarding Flow**: Multi-step process with privacy, analytics, and connection steps
|
||||
- **Authentication**: Web-to-desktop handoff using `outsourced://` scheme
|
||||
- **Authentication**: Web-to-desktop handoff using `alphahuman://` scheme
|
||||
- **Connection Management**: Telegram MTProto and Socket.io integration
|
||||
|
||||
## Key Patterns
|
||||
|
||||
@@ -108,7 +108,7 @@ listen("socket:should_connect", (event) => {
|
||||
| Plugin | Version | Purpose |
|
||||
|--------|---------|---------|
|
||||
| `tauri-plugin-opener` | 2 | Open URLs in browser |
|
||||
| `tauri-plugin-deep-link` | 2.0.0 | Handle `outsourced://` URLs |
|
||||
| `tauri-plugin-deep-link` | 2.0.0 | Handle `alphahuman://` URLs |
|
||||
| `tauri-plugin-autostart` | 2 | Launch at login |
|
||||
| `tauri-plugin-notification` | 2 | Native notifications |
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ Open Telegram login widget in browser.
|
||||
|
||||
```typescript
|
||||
await invoke('start_telegram_login');
|
||||
// Opens ${DEFAULT_BACKEND_URL}/auth/telegram-widget?redirect=outsourced://auth
|
||||
// Opens ${DEFAULT_BACKEND_URL}/auth/telegram-widget?redirect=alphahuman://auth
|
||||
```
|
||||
|
||||
### `start_telegram_login_with_url`
|
||||
|
||||
@@ -25,7 +25,7 @@ This documentation covers the Tauri Rust backend for the AlphaHuman desktop appl
|
||||
|
||||
### Existing Implementation (`lib.rs`)
|
||||
- ✅ System tray with show/hide/quit
|
||||
- ✅ Deep link handling (`outsourced://` scheme)
|
||||
- ✅ Deep link handling (`alphahuman://` scheme)
|
||||
- ✅ Token exchange command (CORS bypass)
|
||||
- ✅ Autostart plugin (macOS LaunchAgent)
|
||||
- ✅ Window minimize-to-tray on close (macOS)
|
||||
@@ -114,7 +114,7 @@ impl SocketService {
|
||||
1. User clicks "Login with Telegram" in desktop app
|
||||
↓
|
||||
2. App opens system browser to:
|
||||
${BACKEND_URL}/auth/telegram-widget?redirect=outsourced://auth
|
||||
${BACKEND_URL}/auth/telegram-widget?redirect=alphahuman://auth
|
||||
↓
|
||||
3. Backend serves Telegram Login Widget HTML page
|
||||
↓
|
||||
@@ -122,7 +122,7 @@ impl SocketService {
|
||||
↓
|
||||
5. Telegram callback → Backend validates → Creates loginToken
|
||||
↓
|
||||
6. Backend redirects to: outsourced://auth?token={loginToken}
|
||||
6. Backend redirects to: alphahuman://auth?token={loginToken}
|
||||
↓
|
||||
7. Desktop app catches deep link
|
||||
↓
|
||||
@@ -144,7 +144,7 @@ Returns HTML page with Telegram Login Widget that redirects to the specified sch
|
||||
#[tauri::command]
|
||||
async fn start_telegram_login(app: AppHandle) -> Result<(), String> {
|
||||
// Open browser to Telegram widget page
|
||||
let url = format!("{}/auth/telegram-widget?redirect=outsourced://auth", BACKEND_URL);
|
||||
let url = format!("{}/auth/telegram-widget?redirect=alphahuman://auth", BACKEND_URL);
|
||||
opener::open(&url)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ MCP System:
|
||||
|
||||
### Authentication Flow (Deep Link)
|
||||
1. User authenticates in browser → receives `loginToken`
|
||||
2. Browser redirects to `outsourced://auth?token=<loginToken>`
|
||||
2. Browser redirects to `alphahuman://auth?token=<loginToken>`
|
||||
3. Desktop app catches deep link via Tauri plugin
|
||||
4. `desktopDeepLinkListener` invokes Rust `exchange_token` command
|
||||
5. Rust calls backend `POST /auth/desktop-exchange` (CORS-free)
|
||||
|
||||
@@ -358,7 +358,7 @@ import('./utils/desktopDeepLinkListener').then((m) => {
|
||||
});
|
||||
```
|
||||
|
||||
The listener intercepts `outsourced://auth?token=...` and:
|
||||
The listener intercepts `alphahuman://auth?token=...` and:
|
||||
1. Exchanges token via Rust command
|
||||
2. Stores session in Redux
|
||||
3. Navigates to `/onboarding` or `/home`
|
||||
|
||||
@@ -221,7 +221,7 @@ import { buildAuthDeepLink } from '../utils/deeplink';
|
||||
|
||||
// Build URL for browser redirect
|
||||
const deepLink = buildAuthDeepLink(loginToken);
|
||||
// → "outsourced://auth?token=abc123"
|
||||
// → "alphahuman://auth?token=abc123"
|
||||
|
||||
// In web frontend after auth:
|
||||
window.location.href = deepLink;
|
||||
@@ -247,7 +247,7 @@ import('./utils/desktopDeepLinkListener').then((m) => {
|
||||
|
||||
**What it does:**
|
||||
1. Listens for `onOpenUrl` events from Tauri deep-link plugin
|
||||
2. Parses `outsourced://auth?token=...` URLs
|
||||
2. Parses `alphahuman://auth?token=...` URLs
|
||||
3. Calls Rust `exchange_token` command (bypasses CORS)
|
||||
4. Stores session in Redux
|
||||
5. Navigates to `/onboarding` or `/home`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Telegram Login (Web → Desktop Handoff)
|
||||
|
||||
This app implements **Telegram login for the desktop (Tauri) client** using a **system-browser auth flow** plus a **custom URL scheme deep link** (`outsourced://`) to return control back to the desktop app.
|
||||
This app implements **Telegram login for the desktop (Tauri) client** using a **system-browser auth flow** plus a **custom URL scheme deep link** (`alphahuman://`) to return control back to the desktop app.
|
||||
|
||||
---
|
||||
|
||||
@@ -8,10 +8,10 @@ This app implements **Telegram login for the desktop (Tauri) client** using a **
|
||||
|
||||
1. **User clicks “Continue with Telegram”** inside the desktop app.
|
||||
2. The app opens the system browser to the backend:
|
||||
- `GET ${BACKEND_URL}/auth/telegram-widget?redirect=outsourced://auth`
|
||||
- `GET ${BACKEND_URL}/auth/telegram-widget?redirect=alphahuman://auth`
|
||||
3. The backend performs Telegram authentication (bot-based login / OAuth-like flow).
|
||||
4. On success, the backend generates a **short-lived single-use `loginToken`** and redirects the browser to:
|
||||
- `outsourced://auth?token=<loginToken>`
|
||||
- `alphahuman://auth?token=<loginToken>`
|
||||
5. The OS routes that deep link to the installed desktop app.
|
||||
6. The desktop app extracts the `token` from the deep link and exchanges it for a **long-lived `sessionToken`** by calling a Rust Tauri command (bypassing CORS):
|
||||
- `POST ${BACKEND_URL}/auth/desktop-exchange` with `{ token }`
|
||||
@@ -45,7 +45,7 @@ The URL scheme is declared in `src-tauri/tauri.conf.json`:
|
||||
"plugins": {
|
||||
"deep-link": {
|
||||
"desktop": {
|
||||
"schemes": ["outsourced"]
|
||||
"schemes": ["alphahuman"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,8 +85,8 @@ import('./utils/desktopDeepLinkListener').then(m => {
|
||||
```
|
||||
|
||||
The deep link handler:
|
||||
- Accepts only the `outsourced:` scheme
|
||||
- Requires `outsourced://auth?token=...`
|
||||
- Accepts only the `alphahuman:` scheme
|
||||
- Requires `alphahuman://auth?token=...`
|
||||
- Calls the Rust command `exchange_token`
|
||||
- Stores `sessionToken` in Redux auth state
|
||||
- Redirects to `#/onboarding` (HashRouter)
|
||||
@@ -98,7 +98,7 @@ const handleDeepLinkUrls = async (urls: string[] | null | undefined) => {
|
||||
|
||||
try {
|
||||
const parsed = new URL(url);
|
||||
if (parsed.protocol !== 'outsourced:') return;
|
||||
if (parsed.protocol !== 'alphahuman:') return;
|
||||
if (parsed.hostname !== 'auth') return;
|
||||
|
||||
const token = parsed.searchParams.get('token');
|
||||
@@ -140,13 +140,13 @@ async fn exchange_token(backend_url: String, token: String) -> Result<serde_json
|
||||
|
||||
Your backend must implement **both**:
|
||||
|
||||
### A) `GET /auth/telegram-widget?redirect=outsourced://auth`
|
||||
### A) `GET /auth/telegram-widget?redirect=alphahuman://auth`
|
||||
|
||||
- **Purpose**: start Telegram auth in the user’s browser.
|
||||
- **On success**:
|
||||
- create/find user
|
||||
- mint a **short-lived** `loginToken` (single-use, recommended TTL \(\le 5\) minutes)
|
||||
- redirect to: `outsourced://auth?token=<loginToken>`
|
||||
- redirect to: `alphahuman://auth?token=<loginToken>`
|
||||
|
||||
### B) `POST /auth/desktop-exchange`
|
||||
|
||||
@@ -179,7 +179,7 @@ Your backend must implement **both**:
|
||||
|
||||
### Backend (required)
|
||||
|
||||
- **Implement `GET /auth/telegram?platform=desktop`** and ensure it redirects to `outsourced://auth?token=...` on success.
|
||||
- **Implement `GET /auth/telegram?platform=desktop`** and ensure it redirects to `alphahuman://auth?token=...` on success.
|
||||
- **Implement `POST /auth/desktop-exchange`** to exchange the login token for a session token.
|
||||
- **Enforce security**:
|
||||
- `loginToken` is **single-use**
|
||||
@@ -189,7 +189,7 @@ Your backend must implement **both**:
|
||||
### Desktop app (required for reliable behavior)
|
||||
|
||||
- **Ensure the deep-link plugin is configured and permitted**:
|
||||
- `src-tauri/tauri.conf.json` includes `"schemes": ["outsourced"]`
|
||||
- `src-tauri/tauri.conf.json` includes `"schemes": ["alphahuman"]`
|
||||
- `src-tauri/capabilities/default.json` includes `"deep-link:default"`
|
||||
- **Use a real backend URL**:
|
||||
- set `VITE_BACKEND_URL` for dev/prod so `Login.tsx` opens the correct domain
|
||||
@@ -197,7 +197,7 @@ Your backend must implement **both**:
|
||||
### Desktop app (recommended hardening / cleanup)
|
||||
|
||||
- **Validate the deep link target more strictly** in `src/utils/desktopDeepLinkListener.ts`:
|
||||
- today it checks only `parsed.protocol === 'outsourced:'`
|
||||
- today it checks only `parsed.protocol === 'alphahuman:'`
|
||||
- recommended: also require `parsed.hostname === 'auth'` (and optionally a known path)
|
||||
- **Don’t skip Telegram auth in onboarding**:
|
||||
- `src/pages/onboarding/Step1Phone.tsx` currently has a “Continue with Telegram” button that *only navigates* and does not authenticate.
|
||||
|
||||
@@ -23,7 +23,7 @@ pub async fn start_telegram_login_with_url(
|
||||
backend_url: String,
|
||||
) -> Result<(), String> {
|
||||
let url = format!(
|
||||
"{}/auth/telegram-widget?redirect=outsourced://auth",
|
||||
"{}/auth/telegram-widget?redirect=alphahuman://auth",
|
||||
backend_url
|
||||
);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ pub const APP_IDENTIFIER: &str = "com.megamind.tauri-app";
|
||||
pub const KEYCHAIN_SERVICE: &str = "AlphaHuman";
|
||||
|
||||
/// Deep link scheme
|
||||
pub const DEEP_LINK_SCHEME: &str = "outsourced";
|
||||
pub const DEEP_LINK_SCHEME: &str = "alphahuman";
|
||||
|
||||
/// Socket.io reconnection settings
|
||||
pub const SOCKET_RECONNECT_ATTEMPTS: u32 = 5;
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"plugins": {
|
||||
"deep-link": {
|
||||
"desktop": {
|
||||
"schemes": ["outsourced"]
|
||||
"schemes": ["alphahuman"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export interface TelegramLoginContext {
|
||||
|
||||
export type WebLoginContext = PhoneLoginContext | TelegramLoginContext;
|
||||
|
||||
const DESKTOP_SCHEME = "outsourced";
|
||||
const DESKTOP_SCHEME = "alphahuman";
|
||||
|
||||
export const buildDesktopDeeplink = (token: string): string => {
|
||||
const encoded = encodeURIComponent(token);
|
||||
|
||||
@@ -6,7 +6,7 @@ import { setToken } from "../store/authSlice";
|
||||
|
||||
/**
|
||||
* Handle a list of deep link URLs delivered by the Tauri deep-link plugin.
|
||||
* Parses `outsourced://auth?token=...` URLs and exchanges the token for a
|
||||
* Parses `alphahuman://auth?token=...` URLs and exchanges the token for a
|
||||
* desktop session via the backend.
|
||||
*/
|
||||
const handleDeepLinkUrls = async (urls: string[] | null | undefined) => {
|
||||
@@ -18,7 +18,7 @@ const handleDeepLinkUrls = async (urls: string[] | null | undefined) => {
|
||||
|
||||
try {
|
||||
const parsed = new URL(url);
|
||||
if (parsed.protocol !== "outsourced:") {
|
||||
if (parsed.protocol !== "alphahuman:") {
|
||||
return;
|
||||
}
|
||||
// Harden: ensure this deep link is intended for auth handoff
|
||||
@@ -66,7 +66,7 @@ const handleDeepLinkUrls = async (urls: string[] | null | undefined) => {
|
||||
|
||||
/**
|
||||
* Set up listeners for deep links so that when the desktop app is opened
|
||||
* via a URL like `outsourced://auth?token=...`, we can react to it.
|
||||
* via a URL like `alphahuman://auth?token=...`, we can react to it.
|
||||
* Only works in Tauri desktop app environment.
|
||||
*/
|
||||
export const setupDesktopDeepLinkListener = async () => {
|
||||
|
||||
Reference in New Issue
Block a user