agents
Use when designing, deploying, or debugging a Butterbase Agent (declarative LLM/tool graph), registering an MCP server for tool use, or wiring access controls…
Use when configuring OAuth providers (Google/GitHub/Apple/X/etc.), setting up post-login auth hooks, tuning JWT lifetimes, or generating service API keys
$ npx -y skills add butterbase-ai/butterbase-skills --skill auth-setup --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/auth-setupContext preview
The summary Claude sees to decide when to auto-load this skill.
Use when configuring OAuth providers (Google/GitHub/Apple/X/etc.), setting up post-login auth hooks, tuning JWT lifetimes, or generating service API keys
name: auth-setup description: Use when configuring OAuth providers (Google/GitHub/Apple/X/etc.), setting up post-login auth hooks, tuning JWT lifetimes, or generating service API keys
Two umbrella tools cover end-user authentication:
For broad app build-out, see also `butterbase-skills:build-app`. This skill is the deep dive.
---
Every request runs under one of three database roles:
| Auth header | Role | `current_user_id()` | RLS | |-------------|------|---------------------|-----| | _none_ | `butterbase_anon` | NULL | enforced; default deny | | End-user JWT (issued by `manage_oauth` or email login) | `butterbase_user` | user UUID | enforced | | Service key (`bb_sk_*`) | `butterbase_service` | NULL | bypassed |
Auth is what transforms a request into the right role. RLS is what filters the data. Both must be configured.
---
manage_oauth({
app_id: "app_abc123",
action: "configure",
provider: "google",
client_id: "123456789.apps.googleusercontent.com",
client_secret: "GOCSPX-...",
redirect_uris: ["https://api.butterbase.ai/auth/app_abc123/oauth/google/callback"]
// scopes / authorization_url / token_url / userinfo_url / provider_metadata are auto-filled for built-in providers
})**Built-in providers (URLs and scopes pre-filled):** `google`, `github`, `discord`, `facebook`, `linkedin`, `microsoft`, `apple`, `x`.
**Custom providers:** pass `authorization_url`, `token_url`, `userinfo_url`, and `scopes` explicitly.
https://api.butterbase.ai/auth/{app_id}/oauth/{provider}/callbackRegister **this exact URI** in the provider's developer console. Mismatch is the most common reason OAuth flows fail.
| Provider | Quirk | |----------|-------| | `apple` | Requires `provider_metadata: { teamId, keyId, privateKey }`. Apple only returns the user's name on **first** auth and uses POST callback (handled automatically). | | `x` | Does not return email. Butterbase synthesises `{username}@users.noreply.x.local` for the user record. | | `facebook` | Default scopes `email`, `public_profile`. | | `google` | Standard. | | `github` | Standard. |
manage_oauth({ app_id, action: "get" }) // list all providers (secrets redacted)
manage_oauth({ app_id, action: "get", provider: "google" }) // single provider
manage_oauth({ app_id, action: "update", provider: "google", client_secret: "new-secret" })
manage_oauth({ app_id, action: "delete", provider: "google" }) // disables future logins; existing sessions valid until expiryGET https://api.butterbase.ai/auth/{app_id}/oauth/{provider}?redirect_to=https://yourapp.com/auth/callbackUser signs in at the provider, gets bounced back to `redirect_to` with `access_token` and `refresh_token` as query params. The Butterbase SDK wraps this:
await client.auth.signInWithOAuth({ provider: "google" });
const { user, accessToken } = await client.auth.getSession();---
manage_auth_config({
app_id: "app_abc123",
action: "update_jwt",
accessTokenTtl: "15m", // formats: "15m", "1h", "2h", "1d"
refreshTokenTtlDays: 30 // integer days
})Defaults: 15-minute access tokens, 7-day refresh tokens.
| Use case | `accessTokenTtl` | `refreshTokenTtlDays` | |----------|------------------|------------------------| | High-security (banking, admin) | `5m`–`15m` | `1`–`7` | | Standard SaaS | `15m` (default) | `30` | | Low-friction consumer apps | `1h` | `90` |
**Important:** changes apply only to **new** tokens. Active tokens keep their original expiration — there is no global revoke. Treat TTL changes as forward-looking only.
---
A post-auth function is a deployed Butterbase function invoked **fire-and-forget** after every successful auth event (OAuth login, email login, email signup).
// 1. Deploy the function first (see butterbase-skills:function-dev)
deploy_function({
app_id: "app_abc123",
name: "after-auth",
code: postAuthHandlerCode,
trigger: { type: "http", config: { auth: "none" } }
})
// 2. Register it as the auth hook
manage_auth_config({
app_id: "app_abc123",
action: "configure_auth_hook",
post_auth_function: "after-auth"
})
// To remove the hook later: pass post_auth_function: nullThe function **must already exist** when you configure the hook.
The function receives a POST with this body:
{
"event": "oauth_login | login | signup",
"user": {
"id": "uuid",
"email": "...",
"provider": "google | github | email | ...",
"display_name": "...",
"avatar_url": "..."
},
"isNewUser": true,
"provider": "google"
}The function runs as `butterbase_service` (RLS bypassed, `ctx.user` is `null`). Use `body.user.id` to know who just logged in.
// after-auth/index.ts
export async function handler(req, ctx) {
const { user, isNewUser, event } = await req.json();
if (isNewUser) {
// 1. Create profile row
await ctx.db.query(
"INSERT INTO profiles (user_id, display_name) VALUES ($1, $2) ON CONFLICT DO NOTHING",
[user.id, user.display_name]
);
// 2. Send welcome email (via env-stored API key)
ctx.waitUntil(sendWelcomeEmail(ctx.env.RESEND_API_KEY, user.email));
}
// 3. Audit log on every login
await ctx.db.query(
"INSERT INTO login_log (user_id, event, provider) VALUES ($1, $2, $3)",
[user.id, event, ctx.user ?? null]
);
return new Response("ok", { status: 200 });
}> Auth hooks are fire-and-forget. Don't return data the user needs — they won't see it. Use them for side effects
Claude Code plugin for Butterbase — the AI-Native Backend-as-a-Service. This plugin gives Claude deep knowledge of Butterbase's 42+ MCP tools, guides you through common workflows, and auto-configures the MCP server connection.
Repo: butterbase-ai/butterbase-skills
Use when designing, deploying, or debugging a Butterbase Agent (declarative LLM/tool graph), registering an MCP server for tool use, or wiring access controls…
Use when calling the app's AI gateway from agent tools — chat completions, embeddings, listing models, configuring defaults or BYOK, reading token/cost usage
Use when building a new Butterbase app from scratch, creating a full-stack application, or when the user asks to set up a complete backend with database, auth,…
Use when contributing to the Butterbase codebase, adding new MCP tools, creating API routes, writing migrations, or understanding the monorepo architecture
Use when users report access denied errors, see wrong data, RLS policies are not working, or when troubleshooting Row-Level Security issues in Butterbase
Use when deploying a frontend (React, Next.js, or static HTML) to a live URL on Butterbase, or when troubleshooting deployment issues like MIME type errors or…