electric-proxy-auth

Set up a server-side proxy to forward Electric shape requests securely. Covers ELECTRIC_PROTOCOL_QUERY_PARAMS forwarding, server-side shape definition (table, where, params), content-encoding/content-length header cleanup, CORS configuration for electric-offset/electric-handle/ electric-schema/electric-cursor headers, auth token injection, ELECTRIC_SECRET/SOURCE_SECRET server-side only, tenant isolation via WHERE positional params, onError 401 token refresh, and subset security (AND semantics). Load when creating proxy routes, adding auth, or configuring CORS for Electric.

25 stars

Best use case

electric-proxy-auth is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Set up a server-side proxy to forward Electric shape requests securely. Covers ELECTRIC_PROTOCOL_QUERY_PARAMS forwarding, server-side shape definition (table, where, params), content-encoding/content-length header cleanup, CORS configuration for electric-offset/electric-handle/ electric-schema/electric-cursor headers, auth token injection, ELECTRIC_SECRET/SOURCE_SECRET server-side only, tenant isolation via WHERE positional params, onError 401 token refresh, and subset security (AND semantics). Load when creating proxy routes, adding auth, or configuring CORS for Electric.

Teams using electric-proxy-auth should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/electric-proxy-auth/SKILL.md --create-dirs "https://raw.githubusercontent.com/ComeOnOliver/skillshub/main/skills/electric-sql/electric/electric-proxy-auth/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/electric-proxy-auth/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How electric-proxy-auth Compares

Feature / Agentelectric-proxy-authStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Set up a server-side proxy to forward Electric shape requests securely. Covers ELECTRIC_PROTOCOL_QUERY_PARAMS forwarding, server-side shape definition (table, where, params), content-encoding/content-length header cleanup, CORS configuration for electric-offset/electric-handle/ electric-schema/electric-cursor headers, auth token injection, ELECTRIC_SECRET/SOURCE_SECRET server-side only, tenant isolation via WHERE positional params, onError 401 token refresh, and subset security (AND semantics). Load when creating proxy routes, adding auth, or configuring CORS for Electric.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

This skill builds on electric-shapes. Read it first for ShapeStream configuration.

# Electric — Proxy and Auth

## Setup

```ts
import { ELECTRIC_PROTOCOL_QUERY_PARAMS } from '@electric-sql/client'

// Server route (Next.js App Router example)
export async function GET(request: Request) {
  const url = new URL(request.url)
  const originUrl = new URL('/v1/shape', process.env.ELECTRIC_URL)

  // Only forward Electric protocol params — never table/where from client
  url.searchParams.forEach((value, key) => {
    if (ELECTRIC_PROTOCOL_QUERY_PARAMS.includes(key)) {
      originUrl.searchParams.set(key, value)
    }
  })

  // Server decides shape definition
  originUrl.searchParams.set('table', 'todos')
  originUrl.searchParams.set('secret', process.env.ELECTRIC_SOURCE_SECRET!)

  const response = await fetch(originUrl)
  const headers = new Headers(response.headers)
  headers.delete('content-encoding')
  headers.delete('content-length')

  return new Response(response.body, {
    status: response.status,
    statusText: response.statusText,
    headers,
  })
}
```

Client usage:

```ts
import { ShapeStream } from '@electric-sql/client'

const stream = new ShapeStream({
  url: '/api/todos', // Points to your proxy, not Electric directly
})
```

## Core Patterns

### Tenant isolation with WHERE params

```ts
// In proxy route — inject user context server-side
const user = await getAuthUser(request)
originUrl.searchParams.set('table', 'todos')
originUrl.searchParams.set('where', 'org_id = $1')
originUrl.searchParams.set('params[1]', user.orgId)
```

### Auth token refresh on 401

```ts
const stream = new ShapeStream({
  url: '/api/todos',
  headers: {
    Authorization: async () => `Bearer ${await getToken()}`,
  },
  onError: async (error) => {
    if (error instanceof FetchError && error.status === 401) {
      const newToken = await refreshToken()
      return { headers: { Authorization: `Bearer ${newToken}` } }
    }
    return {}
  },
})
```

### CORS configuration for cross-origin proxies

```ts
// In proxy response headers
headers.set(
  'Access-Control-Expose-Headers',
  'electric-offset, electric-handle, electric-schema, electric-cursor'
)
```

### Subset security (AND semantics)

Electric combines the main shape WHERE (set in proxy) with subset WHERE (from POST body) using AND. Subsets can only narrow results, never widen them:

```sql
-- Main shape: WHERE org_id = $1 (set by proxy)
-- Subset: WHERE status = 'active' (from client POST)
-- Effective: WHERE org_id = $1 AND status = 'active'
```

Even `WHERE 1=1` in the subset cannot bypass the main shape's WHERE.

## Common Mistakes

### CRITICAL Forwarding all client params to Electric

Wrong:

```ts
url.searchParams.forEach((value, key) => {
  originUrl.searchParams.set(key, value)
})
```

Correct:

```ts
import { ELECTRIC_PROTOCOL_QUERY_PARAMS } from '@electric-sql/client'

url.searchParams.forEach((value, key) => {
  if (ELECTRIC_PROTOCOL_QUERY_PARAMS.includes(key)) {
    originUrl.searchParams.set(key, value)
  }
})
originUrl.searchParams.set('table', 'todos')
```

Forwarding all params lets the client control `table`, `where`, and `columns`, accessing any Postgres table. Only forward `ELECTRIC_PROTOCOL_QUERY_PARAMS`.

Source: `examples/proxy-auth/app/shape-proxy/route.ts`

### CRITICAL Not deleting content-encoding and content-length headers

Wrong:

```ts
return new Response(response.body, {
  status: response.status,
  headers: response.headers,
})
```

Correct:

```ts
const headers = new Headers(response.headers)
headers.delete('content-encoding')
headers.delete('content-length')
return new Response(response.body, { status: response.status, headers })
```

`fetch()` decompresses the response body but keeps the original `content-encoding` and `content-length` headers, causing browser decoding failures.

Source: `examples/proxy-auth/app/shape-proxy/route.ts:49-56`

### CRITICAL Exposing ELECTRIC_SECRET or SOURCE_SECRET to browser

Wrong:

```ts
// Client-side code
const url = `/v1/shape?table=todos&secret=${import.meta.env.VITE_ELECTRIC_SOURCE_SECRET}`
```

Correct:

```ts
// Server proxy only
originUrl.searchParams.set('secret', process.env.ELECTRIC_SOURCE_SECRET!)
```

Bundlers like Vite expose `VITE_*` env vars to client code. The secret must only be injected server-side in the proxy.

Source: `AGENTS.md:17-20`

### CRITICAL SQL injection in WHERE clause via string interpolation

Wrong:

```ts
originUrl.searchParams.set('where', `org_id = '${user.orgId}'`)
```

Correct:

```ts
originUrl.searchParams.set('where', 'org_id = $1')
originUrl.searchParams.set('params[1]', user.orgId)
```

String interpolation in WHERE clauses enables SQL injection. Use positional params (`$1`, `$2`).

Source: `website/docs/guides/auth.md`

### HIGH Not exposing Electric response headers via CORS

Wrong:

```ts
// No CORS header configuration — browser strips custom headers
return new Response(response.body, { headers })
```

Correct:

```ts
headers.set(
  'Access-Control-Expose-Headers',
  'electric-offset, electric-handle, electric-schema, electric-cursor'
)
return new Response(response.body, { headers })
```

The client throws `MissingHeadersError` if Electric response headers are stripped by CORS. Expose `electric-offset`, `electric-handle`, `electric-schema`, and `electric-cursor`.

Source: `packages/typescript-client/src/error.ts:109-118`

### CRITICAL Calling Electric directly from production client

Wrong:

```ts
new ShapeStream({
  url: 'https://my-electric.example.com/v1/shape',
  params: { table: 'todos' },
})
```

Correct:

```ts
new ShapeStream({
  url: '/api/todos', // Your proxy route
})
```

Electric's HTTP API is public by default with no auth. Always proxy through your server so the server controls shape definitions and injects secrets.

Source: `AGENTS.md:19-20`

See also: electric-shapes/SKILL.md — Shape URLs must point to proxy routes, not directly to Electric.
See also: electric-deployment/SKILL.md — Production requires ELECTRIC_SECRET and proxy; dev uses ELECTRIC_INSECURE=true.
See also: electric-postgres-security/SKILL.md — Proxy injects secrets that Postgres security enforces.

## Version

Targets @electric-sql/client v1.5.10.

Related Skills

oauth2-flow-helper

25
from ComeOnOliver/skillshub

Oauth2 Flow Helper - Auto-activating skill for Security Fundamentals. Triggers on: oauth2 flow helper, oauth2 flow helper Part of the Security Fundamentals skill category.

oauth-client-setup

25
from ComeOnOliver/skillshub

Oauth Client Setup - Auto-activating skill for API Integration. Triggers on: oauth client setup, oauth client setup Part of the API Integration skill category.

oauth-callback-handler

25
from ComeOnOliver/skillshub

Oauth Callback Handler - Auto-activating skill for API Integration. Triggers on: oauth callback handler, oauth callback handler Part of the API Integration skill category.

exa-install-auth

25
from ComeOnOliver/skillshub

Install the exa-js SDK and configure API key authentication. Use when setting up a new Exa integration, configuring API keys, or initializing Exa in a Node.js/Python project. Trigger with phrases like "install exa", "setup exa", "exa auth", "configure exa API key", "exa-js".

evernote-install-auth

25
from ComeOnOliver/skillshub

Install and configure Evernote SDK and OAuth authentication. Use when setting up a new Evernote integration, configuring API keys, or initializing Evernote in your project. Trigger with phrases like "install evernote", "setup evernote", "evernote auth", "configure evernote API", "evernote oauth".

envoy-proxy-config

25
from ComeOnOliver/skillshub

Envoy Proxy Config - Auto-activating skill for DevOps Advanced. Triggers on: envoy proxy config, envoy proxy config Part of the DevOps Advanced skill category.

elevenlabs-install-auth

25
from ComeOnOliver/skillshub

Install and configure ElevenLabs SDK authentication for Node.js or Python. Use when setting up a new ElevenLabs project, configuring API keys, or initializing the elevenlabs npm/pip package. Trigger: "install elevenlabs", "setup elevenlabs", "elevenlabs auth", "configure elevenlabs API key", "elevenlabs credentials".

documenso-install-auth

25
from ComeOnOliver/skillshub

Install and configure Documenso SDK/API authentication. Use when setting up a new Documenso integration, configuring API keys, or initializing Documenso in your project. Trigger with phrases like "install documenso", "setup documenso", "documenso auth", "configure documenso API key".

deepgram-install-auth

25
from ComeOnOliver/skillshub

Install and configure Deepgram SDK authentication. Use when setting up a new Deepgram integration, configuring API keys, or initializing Deepgram in your project. Trigger: "install deepgram", "setup deepgram", "deepgram auth", "configure deepgram API key", "deepgram credentials".

databricks-install-auth

25
from ComeOnOliver/skillshub

Install and configure Databricks CLI and SDK authentication. Use when setting up a new Databricks integration, configuring tokens, or initializing Databricks in your project. Trigger with phrases like "install databricks", "setup databricks", "databricks auth", "configure databricks token", "databricks CLI".

customerio-install-auth

25
from ComeOnOliver/skillshub

Install and configure Customer.io SDK/CLI authentication. Use when setting up a new Customer.io integration, configuring API keys, or initializing Customer.io in your project. Trigger: "install customer.io", "setup customer.io", "customer.io auth", "configure customer.io API key", "customer.io credentials".

cursor-install-auth

25
from ComeOnOliver/skillshub

Install Cursor IDE and configure authentication across macOS, Linux, and Windows. Triggers on "install cursor", "setup cursor", "cursor authentication", "cursor login", "cursor license", "cursor download".