Skip to main content

robel-auth

Integrate and maintain Robelest Convex Auth in apps by always checking upstream before implementation. Use when adding auth setup, updating auth wiring, migrating between upstream patterns, or troubleshooting @robelest/convex-auth behavior across projects.

설치로 이동

소스 정보

저장소
waynesutton/markdown-site
최근 소스 활동
2026년 4월 26일 22:59
감지된 SKILL.md 언어
영어
스타
630
포크
91

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
2 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
robel-auth
description
Integrate and maintain Robelest Convex Auth in apps by always checking upstream before implementation. Use when adding auth setup, updating auth wiring, migrating between upstream patterns, or troubleshooting @robelest/convex-auth behavior across projects.
# Robel auth skill Use this skill when a user asks to implement, update, or debug auth based on `robelest/convex-auth`. This skill is designed to be copied into other repos. ## Non negotiable upstream check before any auth change Run this every time before proposing code or commands. Preferred command: ```bash bash .cursor/skills/robel-auth/scripts/check-upstream.sh ``` Manual checklist if script is unavailable: 1. Read official docs: `https://auth.estifanos.com/getting-started/installation/` 2. Read latest `main` README: `https://raw.githubusercontent.com/robelest/convex-auth/main/README.md` 3. Read latest `release` README: `https://raw.githubusercontent.com/robelest/convex-auth/release/README.md` 4. Check branch level differences: `https://github.com/robelest/convex-auth/compare/release...main` 5. Read current self hosting docs if portal or static hosting is involved: - `https://raw.githubusercontent.com/get-convex/self-hosting/main/INTEGRATION.md` - `https://github.com/get-convex/self-hosting` If `main` and `release` conflict, prefer the branch requested by the user. If unspecified, use `release` for stability and explain that choice. ## Important assumptions for this skill - Treat the official docs site (`auth.estifanos.com`) and GitHub as sources of truth every time. - Do not assume npm package availability. - Validate package availability at execution time. - If npm is unavailable, use a GitHub source install pinned to a branch or commit. - Keep all Convex code type safe and validator complete. ## Published package reality check (critical) The docs site (`auth.estifanos.com`) and `main` branch sometimes describe APIs ahead of the latest preview release on npm. Before writing imports, always inspect what the installed version actually exports: ```bash ls node_modules/@robelest/convex-auth/dist/providers/ cat node_modules/@robelest/convex-auth/dist/providers/index.js cat node_modules/@robelest/convex-auth/dist/component/index.d.ts ``` ### As of `0.0.4-preview.30` The published package now matches the docs site for the common cases: - Lowercase factory exports from `@robelest/convex-auth/providers`: `github`, `google`, `apple`, `microsoft`, `password`, `passkey`, `credentials`, `anonymous`, `device`, `email`, `phone`, `sso`, `totp`, `custom`. - `github`, `google`, `apple`, `microsoft` are first-party factories with built-in profile fetch. No `arctic` wrapping required. - `password` is a factory function. Call it as `password()`, not `new Password()`. - `createAuth` is exported from `@robelest/convex-auth/component`. - Client factory: `import { client } from "@robelest/convex-auth/client"` (or `/browser` for the browser-tuned variant). Both require `api` in SPA mode: `client({ convex, api: api.auth })`. Omitting `api` throws `"The \`api\` option is required when \`proxyPath\` is not set. Pass { api: api.auth }."` at first `signIn`/`signOut`/`verifyCode` call. Only `proxyPath` mode can skip it. ### Older releases (legacy notes) - `0.0.4-preview.25` and earlier shipped PascalCase classes (`Password`, `OAuth`, etc.) and required `arctic` for OAuth providers. - If you find code on the older API, the upgrade path is: bump to `^0.0.4-preview.30`, remove `arctic`, switch `OAuth(new GitHub(...), { profile })` to `github({ clientId, clientSecret })`, and switch `new Password()` to `password()`. If the installed version drifts from the docs site, follow the installed exports and note the drift to the user. Do not blindly copy doc examples. ## Clarifying questions to ask first Ask these before editing: 1. Which branch is source of truth for this task, `release` or `main`. 2. Is this a new integration or an update to an existing auth setup. 3. Which framework is used: Vite, Next.js, SvelteKit, TanStack Start, Expo web, or other. 4. Is self hosted portal/static delivery needed now. 5. Are they okay pinning dependency to a specific Git commit for reproducibility. ## Install and dependency strategy Never assume one install path. 1. Try package registry lookup: - `npm view @robelest/convex-auth version` 2. If package is unavailable or blocked, install from GitHub: - `npm install github:robelest/convex-auth#release` 3. For deterministic builds, pin a commit SHA: - `npm install github:robelest/convex-auth#<commit-sha>` If the project uses pnpm or bun, translate the same GitHub dependency pinning pattern. ## Quick setup (CLI wizard) The recommended setup flow: 1. Install `@robelest/convex-auth` 2. Start a Convex deployment with `convex dev` 3. Run the auth setup wizard The wizard handles key generation, `convex.config.ts`, `auth.ts`, and `http.ts` automatically. ## Core wiring (3 files) ### 1. Register the component ```typescript // convex/convex.config.ts import { defineApp } from "convex/server"; import auth from "@robelest/convex-auth/convex.config"; const app = defineApp(); app.use(auth); export default app; ``` ### 2. Configure auth ```typescript // convex/auth.ts import { createAuth } from "@robelest/convex-auth/component"; import { components } from "./_generated/api"; import { github } from "@robelest/convex-auth/providers/github"; const auth = createAuth(components.auth, { providers: [ github({ clientId: process.env.AUTH_GITHUB_ID!, clientSecret: process.env.AUTH_GITHUB_SECRET!, }), ], }); export { auth }; export const { signIn, signOut, store } = auth; ``` ### 3. Wire up HTTP routes ```typescript // convex/http.ts import { httpRouter } from "convex/server"; import { auth } from "./auth"; const http = httpRouter(); auth.http.add(http); export default http; ``` `auth.http.add` registers OAuth callbacks and JWKS endpoints in one call. ## API layers Client auth flow: `signIn`, `signOut`, and `store` are the only required client-callable auth functions. Frontends use them through `client({ convex, api: api.auth })`. Server helpers: `auth.user.*`, `auth.session.*`, `auth.account.*`, `auth.group.*`, `auth.member.*`, `auth.invite.*`, `auth.key.*`, `auth.http.*`, `auth.group.sso.*`, and `auth.group.sso.scim.*` are server-side helpers for Convex code. They are not automatically public RPC. Optional group SSO RPC: If your app wants client-callable group SSO admin APIs, expose app-owned wrappers such as `convex/auth/group.ts`. ## Available providers All providers import from `@robelest/convex-auth/providers`: ```typescript import { anonymous, apple, custom, email, github, google, microsoft, passkey, password, phone, sso, totp, } from "@robelest/convex-auth/providers"; ``` ### OAuth providers | Provider | Factory | Required env vars | |----------|---------|-------------------| | GitHub | `github({ clientId, clientSecret })` | `AUTH_GITHUB_ID`, `AUTH_GITHUB_SECRET` | | Google | `google({ clientId, clientSecret })` | `AUTH_GOOGLE_ID`, `AUTH_GOOGLE_SECRET` | | Apple | `apple({ clientId, teamId, keyId, privateKey })` | `AUTH_APPLE_ID`, `AUTH_APPLE_TEAM_ID`, `AUTH_APPLE_KEY_ID`, `AUTH_APPLE_PRIVATE_KEY` | | Microsoft | `microsoft({ tenant, clientId, clientSecret? })` | `AUTH_MICROSOFT_TENANT_ID`, `AUTH_MICROSOFT_ID` | All OAuth wrappers derive callback URL from `CONVEX_SITE_URL` automatically. ### Custom OAuth Use `custom()` for providers without a first-party wrapper: ```typescript custom({ id: "discord", clientId: process.env.AUTH_DISCORD_ID!, clientSecret: process.env.AUTH_DISCORD_SECRET!, scopes: ["identify", "email"], authorization: { url: "https://discord.com/oauth2/authorize", pkce: "optional" }, token: { url: "https://discord.com/api/oauth2/token", authMethod: "body" }, profile: async ({ accessToken }) => { const res = await fetch("https://discord.com/api/users/@me", { headers: { Authorization: `Bearer ${accessToken}` }, }); const user = await res.json(); return { id: String(user.id), email: user.email, name: user.username }; }, }) ``` ### Non-OAuth providers | Provider | Factory | Notes | |----------|---------|-------| | Password | `password()` | Built-in password auth | | Magic links | `email({ from, send })` | Requires email transport (e.g. Resend) | | Passkeys | `passkey()` | WebAuthn based | | TOTP | `totp({ issuer })` | Authenticator app codes | | Anonymous | `anonymous()` | Guest sessions | | Phone/SMS | `phone({ send })` | Requires SMS transport (e.g. Twilio) | | Group SSO | `sso()` | Enables OIDC, SAML 2.0, SCIM 2.0 | ## Configuration options ```typescript const auth = createAuth(components.auth, { providers: [/* ... */], session: { totalDurationMs: 30 * 24 * 60 * 60 * 1000, // 30 days inactiveDurationMs: 7 * 24 * 60 * 60 * 1000, // 7 days }, jwt: { durationMs: 60 * 1000, // 1 minute }, signIn: { max_failed_attempts_per_hour: 10, }, callbacks: { afterUserCreatedOrUpdated: async (ctx, { userId, existingUser }) => { /* ... */ }, }, authorization: { roles, // from defineRoles() }, }); ``` | Option | Type | Default | Description | |--------|------|---------|-------------| | `providers` | `AuthProviderConfig[]` | required | Auth methods to enable | | `session.totalDurationMs` | `number` | 30 days | Maximum session lifetime | | `session.inactiveDurationMs` | `number` | varies | Inactive session timeout | | `jwt.durationMs` | `number` | 60s | JWT token lifetime | | `signIn.max_failed_attempts_per_hour` | `number` | 10 | Rate limit for failed sign-in attempts | | `callbacks.afterUserCreatedOrUpdated` | `function` | none | Post sign-in hook | | `authorization.roles` | `Record` | `{}` | App-defined role definitions and grants | ## Multi-access patterns Every auth path resolves to the same `userId`. Three access patterns: | Pattern | Context | How userId is available | |---------|---------|------------------------| | App code (query/mutation/action) | `auth.ctx()` | `ctx.auth.userId` and `ctx.auth.user` | | Raw HTTP (session or API key) | `auth.http.context(ctx, request)` | `authContext.userId` | | API key HTTP | `auth.http.action(...)` | `ctx.key.userId` | ### Auth-aware custom functions ```typescript // convex/functions.ts import { customMutation, customQuery } from "convex-helpers/server/customFunctions"; import { mutation, query } from "./_generated/server"; import { auth } from "./auth"; export const authQuery = customQuery(query, auth.ctx()); export const authMutation = customMutation(mutation, auth.ctx()); ``` Use `auth.ctx({ optional: true })` when the same handler should work for both guests and signed-in users. ### Raw HTTP mixed auth ```typescript http.route({ path: "/api/data", method: "GET", handler: httpAction(async (ctx, request) => { const authContext = await auth.http.context(ctx, request, { optional: true }); if (authContext.userId === null) { return new Response(JSON.stringify({ error: "Unauthorized" }), { status: 401 }); } const data = await ctx.runQuery(internal.data.forUser, { userId: authContext.userId }); return Response.json(data);
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기