Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .vitepress/sidebars/concepts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,37 @@ export const conceptsSidebar: DefaultTheme.SidebarItem[] = [
},
],
},
{
text: "Client",
items: [
{
text: "Authentication",
items: [
{
text: "Methods",
link: "/concepts/client/auth_methods",
},
{
text: "Caching of Tokens",
link: "/concepts/client/auth_caching",
},
],
},
{
text: "Community implementations",
items: [
{
text: "Golang SDK",
link: "/concepts/client/community_golang",
},
{
text: "Python SDK",
link: "/concepts/client/community_python",
},
],
},
],
},
{
text: "Essentials",
items: [
Expand Down
64 changes: 64 additions & 0 deletions .vitepress/sidebars/guides.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,4 +247,68 @@ export const guidesSidebar: DefaultTheme.SidebarItem[] = [
},
],
},
{
text: "Client Guides",
items: [
{
text: "Install the SDK",
link: "/guides/client/install",
},
Comment on lines +250 to +256
{
text: "Base Setup",
link: "/guides/client/base_setup",
},
{
text: "Core Features",
items: [
{
text: "Extract Requests",
link: "/guides/client/extract_requests",
},
{
text: "Manage Findings",
link: "/guides/client/manage_findings",
},
{
text: "Environments and Variables",
link: "/guides/client/environments",
},
],
},
{
text: "Plugins",
items: [
{
text: "Install a Plugin",
link: "/guides/client/install_plugin",
},
{
text: "Call a Plugin Function",
link: "/guides/client/call_function",
},
{
text: "Receive Plugin Events",
link: "/guides/client/receive_events",
},
{
text: "Use a Plugin's NPM Spec Package",
link: "/guides/client/spec_typing",
},
],
},
{
text: "Advanced",
items: [
{
text: "Call GraphQL Directly",
link: "/guides/client/graphql_direct",
},
{
text: "Custom Cache Implementation",
link: "/guides/client/custom_cache",
},
],
},
],
},
];
9 changes: 9 additions & 0 deletions .vitepress/sidebars/tutorials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,13 @@ export const tutorialsSidebar: DefaultTheme.SidebarItem[] = [
},
],
},
{
text: "Client SDK",
items: [
{
text: "Using the Scanner API",
link: "/tutorials/client/scanner",
},
],
},
];
38 changes: 38 additions & 0 deletions src/concepts/client/auth_caching.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Caching of Tokens

After a script authenticates against a Caido instance, the SDK keeps the resulting access token in memory for the rest of the process. To preserve that state across script runs without repeating the [authentication flow](./auth_methods.md) every time, the SDK can serialize it to a cache and reload it on the next connection.

The SDK ships with two built-in caches (file-based for Node and localStorage-based for browsers) and accepts a custom implementation for everything else.

## File

The file cache writes the token state to a JSON file on disk. It is the natural choice for Node.js scripts and CI/CD environments where local disk is available and acceptable.

The file is written with `0o600` permissions (read and write for the owner only) to limit accidental exposure to other users on the same machine. Beyond that, the file content is plain JSON: anyone with file system access can read the tokens.

The file cache is not suitable for shared, networked, or untrusted storage. For those scenarios, see [Custom Implementation](#custom-implementation).

## Local Storage

The localStorage cache writes the token state to the browser's `localStorage` under a key. It is the built-in choice for SDK use inside a browser environment.

Like the file cache, the stored value is plain JSON. Browser sandboxing scopes the storage to the origin, but anything running in the same origin (including third-party scripts loaded into the page) can read it.

## Custom Implementation

For everything that does not fit the file or localStorage models, scripts can implement the `TokenCache` interface (`load`, `save`, `clear`) and pass an instance to the `Client` constructor. Common motivations include:

- Encrypted storage on disk
- Tokens stored in a remote secret manager (Vault, AWS Secrets Manager, etc.)
- Shared cache across multiple workers (Redis, database)
- In-memory cache for tests

A custom cache is opaque to the SDK: it only calls the three interface methods, and the implementation owns where and how the tokens are stored.

## Refresh

Access tokens have a limited lifetime. When an authenticated request fails because the access token has expired or been revoked, the SDK uses the cached refresh token to mint a new access token through the instance's `refreshAuthenticationToken` mutation. The new tokens replace the old ones in memory and are written back to the cache.

The renewal happens reactively rather than on a timer: the SDK does not consult the cached `expiresAt` to refresh proactively. It waits until the server rejects a request, then refreshes and retries. From the script's point of view, the failure is invisible.

A cache holding only an access token (no refresh token) can serve a single short run but cannot recover when the access token expires. Pairing access tokens with refresh tokens is what keeps cached state usable over time.
29 changes: 29 additions & 0 deletions src/concepts/client/auth_methods.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Authentication Methods

The Client SDK supports three methods for authenticating a script against a Caido instance: Personal Access Token, Browser Login, and Direct Token. They all produce the same kind of access token, but they differ in how that token is obtained.

Two of them use the same <a href="https://www.rfc-editor.org/rfc/rfc8628.html" target="_blank">OAuth 2.0 Device Authorization</a> grant that the Caido desktop and web applications use, described in [Instance Authentication](https://docs.caido.io/app/concepts/instance_authentication.html). The third skips the flow entirely.

## Personal Access Token

A Personal Access Token (PAT) is a long-lived credential created in the Caido Dashboard. When the SDK authenticates with a PAT, it starts the device authorization flow on the instance and then automatically approves it by calling the Caido Cloud API with the PAT as a Bearer credential. No human interaction is required.

This is the natural choice for headless environments: scripts, CI/CD pipelines, scheduled jobs, and anything that runs without a person nearby. A PAT is tied to the user that created it and inherits that user's permissions on the resources it targets, whether that's a personal account or a Team.

The PAT itself is not used as the credential for API calls. Once the Cloud approves the device flow, the instance delivers an access token and a refresh token to the script, and those are what subsequent API calls carry as Bearer tokens.

The full mechanics of PATs as a credential, where to create one, and how they relate to accounts and Teams are covered in [Personal Access Token](https://docs.caido.io/app/concepts/pat.html) in the user docs.

## Browser Login

Browser Login uses the same device authorization flow as PAT, but with a person in the loop instead of the Cloud. The SDK starts the flow on the instance, receives a verification URL and a short user code, and surfaces them to the script through an `onRequest` callback. A person opens the URL in a browser, enters the code, and approves the request on the [Caido Dashboard](https://dashboard.caido.io). The SDK waits on a WebSocket subscription until the instance delivers the resulting token pair.

This suits interactive scripts, developer tools, and one-off automations where the person running the script can complete the approval step at the time of authentication. Outside of who approves the request, the resulting token pair is identical to one obtained through a PAT.

## Direct Token

Direct Token skips the device authorization flow entirely. Instead of negotiating with the instance and the Cloud, the script provides an access token, and optionally a refresh token, that it has already obtained through some other channel. The SDK uses the token as-is on every authenticated request.

This pattern fits when the surrounding system already manages tokens for the script. Examples include a parent process that ran the device flow itself and passed the result down, a service that mints tokens out-of-band, or tests that need deterministic credentials.

If only an access token is provided, the SDK has no way to obtain a new one when it expires. The script must rotate the token externally or switch to one of the other two methods. Providing both an access token and a refresh token restores the automatic renewal behavior covered in [Caching of Tokens](./auth_caching.md).
22 changes: 22 additions & 0 deletions src/concepts/client/community_golang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Golang SDK

A community-maintained Go port of the official [JavaScript Client SDK](https://github.com/caido/sdk-js), hosted at [`caido-community/sdk-go`](https://github.com/caido-community/sdk-go) under the MIT license. It mirrors the API surface of `@caido/sdk-client` and uses [`genqlient`](https://github.com/Khan/genqlient) for type-safe GraphQL code generation, tracking the same schema the official SDK consumes.

The Go SDK exposes the same domain-specific clients as the JavaScript SDK (requests, intercept, replay, findings, scopes, projects, environments, hosted files, workflows, tasks, filters, plugins, and more), plus low-level GraphQL access for operations not covered by domain methods.

Initialization mirrors the JavaScript SDK's `Client` constructor:

```go
client, _ := caido.NewClient(caido.Options{
URL: "http://localhost:8080",
Auth: caido.PATAuth("caido_xxxxx"),
})
client.Connect(context.Background())
```

## Differences from the JavaScript SDK

Coverage of the authentication model is intentional rather than exhaustive:

- **Browser Login** is not exposed in the public API. Only [Personal Access Token](./auth_methods.md#personal-access-token) (`caido.PATAuth`) and [Direct Token](./auth_methods.md#direct-token) (`caido.TokenAuth(accessToken, refreshToken)`) are supported.
- **[Token caching](./auth_caching.md)** is not built in. Tokens are held in memory for the lifetime of the `Client`, and refresh is driven by an optional `TokenRefreshFunc` callback that the script provides. Persisting tokens across runs is the script's responsibility.
27 changes: 27 additions & 0 deletions src/concepts/client/community_python.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Python SDK

A community-maintained Python port of the official [JavaScript Client SDK](https://github.com/caido/sdk-js), hosted at [`caido-community/sdk-py`](https://github.com/caido-community/sdk-py) under the MIT license. The client is published to PyPI as [`caido-sdk-client`](https://pypi.org/project/caido-sdk-client/).

The repository is a monorepo with two packages that mirror the JavaScript split:

- `caido-sdk-client` is the high-level client that scripts use to interact with a Caido instance.
- `caido-server-auth` is the lower-level authentication library that the client builds on.

The Python SDK is `asyncio`-based, and its type names match the JavaScript SDK closely (`Client`, `PATAuthOptions`, `AuthCacheFile`, and so on).

A minimal usage looks like:

```python
client = Client(
"http://localhost:8080",
auth=PATAuthOptions(
pat="caido_xxxxxx",
cache=AuthCacheFile(file=".secrets.json"),
),
)
await client.connect()
```

## Differences from the JavaScript SDK

The Python SDK supports all three [authentication methods](./auth_methods.md) and the file and custom variants of [token caching](./auth_caching.md). The `localStorage` cache variant has no equivalent in Python, since the language does not have a browser storage model.
Loading
Loading