---
title: "sdk/linux"
description: "Rust SDK for Linux desktop using xdg-open for browser launch, loopback TCP for the authorization callback, PKCE S256, and freedesktop.org Secret Service token storage."
locale: "en"
---

> Documentation Index
> Fetch the relevant documentation index at: https://vonvon.id/sdks/llms.txt
> Use this file to discover all available pages before exploring further.

# sdk/linux

## Status

Package status is **Implemented and verified locally**. The Rust unit-test suite passes. Secret Service D-Bus storage, xdg-open, the complete loopback callback, and a real IdP round-trip still require a desktop Linux integration environment. This page documents implemented behavior; it is not a production-readiness claim.

Registry status: UNPUBLISHED. Install this SDK only from the repository source checkout; do not use an external package registry.

## Requirements

- Rust (stable, 2021 edition)
- tokio async runtime
- Desktop Linux with xdg-open (xdg-utils) for system browser launch and a running D-Bus session with gnome-keyring or kwallet for Secret Service storage
- Headless / CI environments: use the in-memory-storage feature or inject InMemoryStorage directly

## Installation

Add vonvon-linux to Cargo.toml:

```toml
[dependencies]
vonvon-linux = { path = "../vonvon/sdk/linux" }
tokio = { version = "1", features = ["full"] }
```

## Quick start

```rust
use vonvon_linux::{VonvonClient, VonvonConfigBuilder};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
// 1. Build config. offline_access is rejected until DPoP is implemented.
let config = VonvonConfigBuilder::new()
    .issuer("https://vonvon.id")
    .client_id("your_client_id")
    .redirect_uri("http://127.0.0.1:51234/callback")
    .redirect_port(51234)
    .build()?;

// 2. Create client (default: Secret Service storage)
let client = VonvonClient::configure(config)?;

// 3. Sign in. xdg-open launches the browser and loopback TCP receives the callback.
let session = client.sign_in(None).await?;
println!("user: {}", session.user.sub);

// 4. Get the current unexpired access token. Expiry returns SessionExpired.
let token = client.get_access_token(None).await?;

// 5. Clear local token and guest state. No revoke request is sent.
client.sign_out().await?;
Ok(())
}
```

## Headless / CI usage

When no D-Bus Secret Service daemon is available, pass InMemoryStorage to avoid a runtime error:

```rust
use vonvon_linux::{VonvonClient, VonvonConfigBuilder};
use vonvon_linux::storage::InMemoryStorage;
use std::sync::Arc;

let config = VonvonConfigBuilder::new()
.issuer("https://vonvon.id")
.client_id("your_client_id")
.redirect_uri("http://127.0.0.1:51234/callback")
.build()?;

let client = VonvonClient::configure_with_storage(config, Arc::new(InMemoryStorage::new()))?;
```

## Core API

| Method | Description |
| --- | --- |
| `VonvonConfigBuilder::new()` | Builder for VonvonConfig. Required fields: issuer, client\_id, redirect\_uri. Optional: scopes, redirect\_port (default 51234), http\_timeout\_secs (default 30). |
| `VonvonClient::configure(config)` | Create client with default SecretServiceStorage. |
| `VonvonClient::configure_with_storage(config, adapter)` | Create client with a custom StorageAdapter (e.g. InMemoryStorage). |
| `sign_in(options) async` | Open xdg-open browser, start loopback TCP listener on redirect\_port, wait for the authorization code callback, exchange it, store tokens, and return a Session. |
| `get_session() async` | Return the current unexpired stored session; expiry clears local token state and returns SessionExpired. |
| `get_access_token(options) async` | Return the current unexpired access token; expiry or force\_refresh clears local token state and returns SessionExpired. |
| `sign_out() async` | Clear local token and guest session storage; no revoke request is sent. |
| `set_token_storage(adapter)` | Replace the storage adapter after construction. |

## Storage adapters

| Adapter | Description |
| --- | --- |
| `SecretServiceStorage` | Default. Stores tokens in the freedesktop.org Secret Service (gnome-keyring or kwallet) via D-Bus. Requires a running desktop session. |
| `InMemoryStorage` | In-process memory only. Tokens are lost on process exit. Use for testing or CI environments without a Secret Service. |

## Security

- Public client — no client secret stored or transmitted.
- PKCE S256 only. Server rejects plain challenge method.
- OAuth state validated on the loopback callback to prevent CSRF (RFC 8252 loopback redirect).
- Secret Service encrypts tokens at rest via the desktop keyring daemon — the app does not manage encryption keys directly.
- The SDK rejects offline\_access until DPoP is implemented; unexpected refresh\_token response fields are not persisted.

## Known limitations

- JWKS-backed ID token verification, nonce validation, and JWKS cache renewal are implemented and locally tested. A desktop Secret Service and real IdP round-trip are still required before L4 support.
- The redirect port is fixed and must match the redirect\_uri registered in the Vonvon console. Dynamic port randomization (RFC 8252) requires dynamic client registration support.
- System browser redirect and Secret Service storage require desktop environment evidence.

Source: https://vonvon.id/sdks/linux/index.mdx
