How the In-Process Core Communicates with the Tauri Frontend Using JSON-RPC and Bearer Token Authentication in OpenHuman
OpenHuman uses an in-process Rust core that exposes an HTTP JSON-RPC endpoint on a local port, secured by an ephemeral bearer token stored in the OPENHUMAN_CORE_TOKEN environment variable, which the Tauri frontend retrieves via invoke commands and injects into every request header.
OpenHuman is a desktop AI application built with Tauri that keeps its Rust-based core logic running inside the same process as the UI shell. Rather than using standard Tauri commands for all operations, the core launches an embedded HTTP server that accepts JSON-RPC 2.0 requests. The frontend communicates with this server through a secure, token-authenticated relay system that prevents unauthorized local access.
Core Initialization and Token Generation
When the application starts, app/src-tauri/src/core_process.rs spawns the core as a Tokio task using run_server_embedded_with_ready. During startup, the core generates a cryptographically random bearer token and binds it to the process environment.
let token = generate_random_token();
std::env::set_var("OPENHUMAN_CORE_TOKEN", &token);
let (addr, handle) = CoreBuilder::new()
.provider(...)
.access(...)
.backend_url(...)
.build()
.await?
.run_server_embedded_with_ready(rpc_token: Some(token))
.await?;
The rpc_token parameter ensures the HTTP server validates this specific token on every incoming request. Because the token lives only in memory and never touches disk, it is ephemeral per session.
Tauri Command Layer
The Tauri backend exposes three distinct commands in app/src-tauri/src/core_rpc.rs that allow the renderer to discover the core's endpoint and authenticate itself:
core_rpc_url– Returns the full HTTP URL (e.g.,http://127.0.0.1:7788/rpc) where the JSON-RPC server is listening.core_rpc_token– Returns the raw bearer token string stored inOPENHUMAN_CORE_TOKEN.core_rpc_endpoint– Returns both values in a single atomic payload, ensuring the URL and token remain consistent even if the core restarts between calls.
These functions are annotated with #[tauri::command] and registered in the Tauri application builder, making them accessible to the frontend via the invoke API.
Relaying Authenticated Requests
For operations that must forward raw JSON-RPC calls, the backend provides relay_http_rpc. This command constructs a reqwest::Client request and passes it through the apply_auth helper before dispatching:
#[tauri::command]
async fn relay_http_rpc(
method: String,
params: serde_json::Value,
) -> Result<serde_json::Value, String> {
let client = http_client();
let url = core_rpc_url_value();
let req = client
.post(&url)
.json(&json!({ "jsonrpc": "2.0", "id": 1, "method": method, "params": params }))
.await
.map_err(|e| e.to_string())?;
let req = apply_auth(req)?; // Inject Authorization header
let resp = req.send().await.map_err(|e| e.to_string())?;
let json = resp.json().await.map_err(|e| e.to_string())?;
Ok(json)
}
The apply_auth function retrieves the token from the environment and attaches an Authorization: Bearer <token> header to the outgoing request.
Frontend Implementation
The TypeScript client in app/src/lib/services/coreRpcClient.ts bridges the Tauri invoke layer with standard web fetch logic. It first obtains the endpoint credentials, then constructs a compliant JSON-RPC 2.0 payload:
import { invoke } from '@tauri-apps/api/tauri';
async function getCoreEndpoint() {
const { url, token } = await invoke('core_rpc_endpoint');
return { url, token };
}
async function callCore(method: string, params: any) {
const { url, token } = await getCoreEndpoint();
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify({
jsonrpc: '2.0',
id: Date.now(),
method,
params
}),
});
return response.json();
}
This pattern keeps the frontend agnostic of the underlying port allocation while enforcing the bearer token on every call.
Complete Request Lifecycle
The full communication flow follows these steps:
- Renderer initiates – The frontend calls
invoke('core_rpc_endpoint')to retrieve the current URL and token. - Tauri bridges – The Rust command layer reads
OPENHUMAN_CORE_TOKENand the bound socket address, returning them as a JSON object. - Frontend authenticates – The TypeScript client sets
Authorization: Bearer <token>and POSTs to the local HTTP endpoint. - Core validates – The server in
src/openhuman/api/rest.rsextracts the header, compares it against the startup token, and rejects mismatches with a 401 Unauthorized error. - RPC execution – Upon validation, the core deserializes the JSON-RPC body, routes the method call (e.g.,
openhuman.chat_sendoropenhuman.memory_query), serializes the result, and returns it via HTTP. - Response delivery – The fetch promise resolves in the frontend, delivering the JSON-RPC response object containing the result or error.
Security Model
OpenHuman's architecture provides multiple isolation guarantees:
- Ephemeral credentials – The bearer token is generated per-process launch and exists only in the
OPENHUMAN_CORE_TOKENenvironment variable, preventing persistence attacks. - Localhost binding – The HTTP server binds strictly to
127.0.0.1, rejecting external network interfaces. - Token validation – Every request to
src/openhuman/api/rest.rsmust present the exact token provided at startup; missing or incorrect tokens terminate the connection immediately. - In-process isolation – Because the core runs as a Tokio task within the Tauri process, there is no IPC overhead or socket exposure to other applications.
Summary
- The Rust core initializes in
core_process.rswithrun_server_embedded_with_ready, storing a random token inOPENHUMAN_CORE_TOKEN. - Tauri commands in
core_rpc.rsexposecore_rpc_endpointandrelay_http_rpcto ferry the URL, token, and JSON-RPC payloads between frontend and core. - The
apply_authhelper injects theAuthorization: Bearerheader usingreqwest. - The TypeScript client in
coreRpcClient.tsretrieves credentials viainvoke, then performs authenticated HTTP POSTs following JSON-RPC 2.0 specification. - The core validates every request against the startup token in
src/openhuman/api/rest.rs, ensuring only the same process can execute RPC methods.
Frequently Asked Questions
How does the frontend discover the core's JSON-RPC port?
The frontend calls the Tauri command core_rpc_endpoint defined in app/src-tauri/src/core_rpc.rs. This command returns both the dynamically allocated localhost URL and the bearer token, ensuring the frontend always targets the correct server instance even after restarts.
What prevents other applications from calling the core's HTTP endpoint?
The core validates a bearer token on every request. This token is generated at startup in core_process.rs, stored in the OPENHUMAN_CORE_TOKEN environment variable, and never written to disk. Because the token is unpredictable and ephemeral per session, external processes cannot authenticate even if they detect the open port.
Why use HTTP JSON-RPC instead of standard Tauri commands?
HTTP JSON-RPC allows the core to expose a standardized API surface that can be consumed by both the Tauri frontend and potential future local clients, while maintaining strict authentication via bearer tokens. The in-process Tokio task architecture keeps latency minimal compared to external process communication.
Where is the bearer token actually validated?
The validation logic resides in src/openhuman/api/rest.rs, where incoming HTTP requests are inspected for the Authorization: Bearer header. The server compares the provided token against the value passed to run_server_embedded_with_ready during initialization, rejecting any mismatches before routing to the JSON-RPC handler.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →