Skip to main content

auth

Authentication integration guidance — Clerk (native Vercel Marketplace), Better Auth, Descope, and Auth0 setup for Next.js applications, plus Sign in with Vercel, Vercel Passport, and Vercel KMS. Covers server config, route handlers, proxy.ts auth patterns, sign-in/sign-up flows, and Marketplace provisioning. Use when implementing user authentication, sessions, protected routes, or protecting deployments.

소스 정보

저장소
vercel/vercel-plugin
최근 소스 활동
2026년 10월 5일 12:40
감지된 SKILL.md 언어
영어
스타
308
포크
68

설치 방법

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

소스 파일 검토

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

파일 탐색기
2 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
auth
description
Authentication integration guidance — Clerk (native Vercel Marketplace), Better Auth, Descope, and Auth0 setup for Next.js applications, plus Sign in with Vercel, Vercel Passport, and Vercel KMS. Covers server config, route handlers, proxy.ts auth patterns, sign-in/sign-up flows, and Marketplace provisioning. Use when implementing user authentication, sessions, protected routes, or protecting deployments.
metadata
{"priority":6,"docs":["https://authjs.dev/getting-started","https://nextjs.org/docs/app/guides/authentication","https://better-auth.com/llms.txt"],"sitemap":"https://authjs.dev/sitemap.xml","pathPatterns":["proxy.ts","proxy.js","src/proxy.ts","src/proxy.js","middleware.ts","middleware.js","src/middleware.ts","src/middleware.js","clerk.config.*","app/sign-in/**","app/sign-up/**","src/app/sign-in/**","src/app/sign-up/**","app/(auth)/**","src/app/(auth)/**","auth.config.*","auth.ts","auth.js","lib/auth.ts","src/lib/auth.ts","lib/auth-client.ts","src/lib/auth-client.ts","app/api/auth/[...all]/**","src/app/api/auth/[...all]/**"],"bashPatterns":["\\bnpm\\s+(install|i|add)\\s+[^\\n]*@clerk/nextjs\\b","\\bpnpm\\s+(install|i|add)\\s+[^\\n]*@clerk/nextjs\\b","\\bbun\\s+(install|i|add)\\s+[^\\n]*@clerk/nextjs\\b","\\byarn\\s+add\\s+[^\\n]*@clerk/nextjs\\b","\\bnpm\\s+(install|i|add)\\s+[^\\n]*@descope/nextjs-sdk\\b","\\bpnpm\\s+(install|i|add)\\s+[^\\n]*@descope/nextjs-sdk\\b","\\bbun\\s+(install|i|add)\\s+[^\\n]*@descope/nextjs-sdk\\b","\\byarn\\s+add\\s+[^\\n]*@descope/nextjs-sdk\\b","\\bnpm\\s+(install|i|add)\\s+[^\\n]*@auth0/nextjs-auth0\\b","\\bpnpm\\s+(install|i|add)\\s+[^\\n]*@auth0/nextjs-auth0\\b","\\bbun\\s+(install|i|add)\\s+[^\\n]*@auth0/nextjs-auth0\\b","\\byarn\\s+add\\s+[^\\n]*@auth0/nextjs-auth0\\b","\\bnpm\\s+(install|i|add)\\s+[^\\n]*@vercel/kms\\b","\\bpnpm\\s+(install|i|add)\\s+[^\\n]*@vercel/kms\\b","\\bbun\\s+(install|i|add)\\s+[^\\n]*@vercel/kms\\b","\\byarn\\s+add\\s+[^\\n]*@vercel/kms\\b","\\bnpm\\s+(install|i|add)\\s+[^\\n]*\\bbetter-auth\\b","\\bpnpm\\s+(install|i|add)\\s+[^\\n]*\\bbetter-auth\\b","\\bbun\\s+(install|i|add)\\s+[^\\n]*\\bbetter-auth\\b","\\byarn\\s+add\\s+[^\\n]*\\bbetter-auth\\b","\\b(npx|bunx|pnpm\\s+dlx)\\s+(auth@latest|@better-auth/cli)\\b"],"importPatterns":["@vercel/kms","better-auth"]}
validate
[{"pattern":"VERCEL_CLIENT_(ID|SECRET)|vercel\\.com/oauth/(authorize|access_token|token)","message":"Hand-rolled Vercel OAuth detected. Use the Sign in with Vercel OIDC provider (or the built-in `vercel` social provider in Better Auth) instead of manual token exchange.","severity":"recommended","skipIfFileContains":"signInWithVercel|@vercel/auth|better-auth|socialProviders"}]
retrieval
{"aliases":["authentication","login system","sign in","auth flow","sign in with vercel","passport","kms"],"intents":["add auth","protect routes","manage sessions","implement login","secure api endpoints"],"entities":["NextAuth","Auth.js","Better Auth","betterAuth","authClient","JWT","OAuth","session","middleware","getServerSession","Vercel Passport","Okta","Microsoft Entra ID","Vercel KMS","signToken"],"examples":["add login to my app","protect this route with auth","set up NextAuth","set up Better Auth","add better auth to my next app"]}
chainTo
[{"pattern":"export\\s+(default\\s+)?function\\s+middleware","targetSkill":"routing-middleware","message":"Auth logic in a middleware() export — Next.js 16 uses proxy.ts with a proxy() export. Loading Routing Middleware guidance for the migration."},{"pattern":"from\\s+['\\\"](jsonwebtoken)['\"]|require\\s*\\(\\s*['\\\"](jsonwebtoken)['\"]|jwt\\.sign\\s*\\(","targetSkill":"auth","message":"Manual JWT handling with jsonwebtoken detected — use Clerk, Better Auth, or Auth.js for built-in session handling, CSRF protection, and token rotation.","skipIfFileContains":"better-auth|@clerk|next-auth"},{"pattern":"from\\s+['\\\"](next-auth)['\"]|NextAuthOptions|authOptions\\s*:","targetSkill":"auth","message":"Legacy next-auth (v4) pattern detected — loading auth guidance for Auth.js v5 migration with the new universal auth() helper."},{"pattern":"from\\s+['\"]@clerk/nextjs['\"]","targetSkill":"auth","message":"Clerk import detected — loading Auth guidance for Clerk v7 patterns, middleware setup, organization handling, and Vercel Marketplace integration.","skipIfFileContains":"clerkMiddleware|ClerkProvider"},{"pattern":"bcrypt|argon2","targetSkill":"auth","message":"Manual password hashing detected (bcrypt/argon2) — use Clerk, Better Auth, or Auth0 for authentication with built-in password hashing and rate limiting.","skipIfFileContains":"@clerk|@auth0|better-auth"},{"pattern":"from\\s+['\"]better-auth['\"]|betterAuth\\s*\\(","targetSkill":"auth","message":"Better Auth config detected — loading Auth guidance for the Next.js route handler, nextCookies plugin, cookie-only middleware checks, cookie cache, and Marketplace Postgres/Redis wiring.","skipIfFileContains":"nextCookies|toNextJsHandler"}]
# Authentication Integrations You are an expert in authentication for Vercel-deployed applications — covering Clerk (native Vercel Marketplace integration), Better Auth (self-hosted, with data in your own database), Descope, and Auth0 for application sign-in, plus Vercel's own primitives: Sign in with Vercel (OAuth/OIDC provider), Passport (deployment protection with your identity provider), and KMS (managed signing keys). All Next.js examples target Next.js 16, where the request-interception file is `proxy.ts` (exporting `proxy`). On Next.js 15 or earlier the same code lives in `middleware.ts` (exporting `middleware`). ## Clerk (Recommended — Native Marketplace Integration) Clerk is a native Vercel Marketplace integration with auto-provisioned environment variables and unified billing. Current SDK: `@clerk/nextjs` v7 (Core 3, March 2026). ### Install via Marketplace ```bash # Install Clerk from Vercel Marketplace (auto-provisions env vars) vercel integration add clerk ``` Auto-provisioned environment variables: - `CLERK_SECRET_KEY` — server-side API key - `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY` — client-side publishable key ### SDK Setup ```bash # Install the Clerk Next.js SDK npm install @clerk/nextjs ``` ### Proxy Configuration ```ts // proxy.ts (Next.js 16; middleware.ts on Next.js 15 and earlier) import { clerkMiddleware } from "@clerk/nextjs/server"; export default clerkMiddleware(); export const config = { matcher: [ // Skip Next.js internals and static files "/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)", // Always run for API routes "/(api|trpc)(.*)", ], }; ``` ### Protect Routes ```ts // proxy.ts — protect specific routes import { clerkMiddleware, createRouteMatcher } from "@clerk/nextjs/server"; const isProtectedRoute = createRouteMatcher(["/dashboard(.*)", "/api(.*)"]); export default clerkMiddleware(async (auth, req) => { if (isProtectedRoute(req)) { await auth.protect(); } }); ``` ### Frontend API Proxy (Core 3) Proxy Clerk's Frontend API through your own domain to avoid third-party requests: ```ts // proxy.ts export default clerkMiddleware({ frontendApiProxy: { enabled: true }, }); ``` ### Provider Setup ```tsx // app/layout.tsx import { ClerkProvider } from "@clerk/nextjs"; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="en"> <body> <ClerkProvider>{children}</ClerkProvider> </body> </html> ); } ``` ### Sign-In and Sign-Up Pages ```tsx // app/sign-in/[[...sign-in]]/page.tsx import { SignIn } from "@clerk/nextjs"; export default function Page() { return <SignIn />; } ``` ```tsx // app/sign-up/[[...sign-up]]/page.tsx import { SignUp } from "@clerk/nextjs"; export default function Page() { return <SignUp />; } ``` Add routing env vars to `.env.local`: ```env NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up ``` ### Access User Data ```tsx // Server component import { currentUser } from "@clerk/nextjs/server"; export default async function Page() { const user = await currentUser(); return <p>Hello, {user?.firstName}</p>; } ``` ```tsx // Client component "use client"; import { useUser } from "@clerk/nextjs"; export default function UserGreeting() { const { user, isLoaded } = useUser(); if (!isLoaded) return null; return <p>Hello, {user?.firstName}</p>; } ``` ### API Route Protection ```ts // app/api/protected/route.ts import { auth } from "@clerk/nextjs/server"; export async function GET() { const { userId } = await auth(); if (!userId) { return Response.json({ error: "Unauthorized" }, { status: 401 }); } return Response.json({ userId }); } ``` ## Better Auth (Self-Hosted) Better Auth is a framework-agnostic TypeScript auth library that runs inside your app. Users, sessions, and accounts live in your own database, so the only external dependency is the database itself. Choose it when the user wants auth inside their app with data in their own database, or is building on a framework other than Next.js. Current release line: v1.7. ### Agent Workflow 1. **Detect** framework (Next.js App/Pages Router, SvelteKit, Nuxt, Hono…), database/ORM (`prisma/schema.prisma`, `drizzle.config.ts`, `pg`, `@neondatabase/serverless`), and package manager from the lockfile. 2. **Install** `better-auth` plus the DB driver. Provision Postgres from the Marketplace if the project has no database. 3. **Create** `lib/auth.ts` (server) and `lib/auth-client.ts` (client). 4. **Mount** the route handler at `app/api/auth/[...all]/route.ts`. 5. **Migrate** with `npx auth@latest migrate` (built-in adapter) or `generate` + the ORM's migrate (Prisma/Drizzle). 6. **Protect** routes: cookie check in `proxy.ts`, real `getSession()` in pages/route handlers. 7. **Verify** `GET /api/auth/ok` returns `{ "status": "ok" }`, then run a sign-up → sign-in → `getSession()` pass. 8. **Re-run migrate** after every plugin change. ### Install ```bash npm install better-auth pg # Postgres from the Marketplace (auto-provisions DATABASE_URL) vercel integration add neon ``` ### Environment Variables ```env BETTER_AUTH_SECRET=<openssl rand -base64 32> BETTER_AUTH_URL=http://localhost:3000 ``` - **Production:** set `BETTER_AUTH_URL` to your production domain. - **Preview:** leave `BETTER_AUTH_URL` unset for the Preview environment. Better Auth infers the base URL from the incoming request, so every preview URL works without config. `VERCEL_URL` is **not** read automatically. - OAuth providers need registered redirect URIs (`<base>/api/auth/callback/<provider>`), so social login on previews needs a stable branch alias. ### Server Config ```ts // lib/auth.ts import { betterAuth } from "better-auth"; import { nextCookies } from "better-auth/next-js"; import { Pool } from "pg"; export const auth = betterAuth({ database: new Pool({ connectionString: process.env.DATABASE_URL }), emailAndPassword: { enabled: true }, socialProviders: { github: { clientId: process.env.GITHUB_CLIENT_ID!, clientSecret: process.env.GITHUB_CLIENT_SECRET!, }, // Sign in with Vercel — create a Vercel App in the dashboard for credentials vercel: { clientId: process.env.VERCEL_CLIENT_ID!, clientSecret: process.env.VERCEL_CLIENT_SECRET!, }, }, session: { // Signed cookie cache: most getSession() calls skip the database cookieCache: { enabled: true, maxAge: 5 * 60 }, }, plugins: [nextCookies()], // keep last — sets cookies from Server Actions }); ``` Prisma / Drizzle / MongoDB users pass an adapter instead of a pool: `prismaAdapter(prisma, { provider: "postgresql" })` from `better-auth/adapters/prisma`, `drizzleAdapter(db, { provider: "pg" })` from `better-auth/adapters/drizzle`. ### Route Handler ```ts // app/api/auth/[...all]/route.ts import { auth } from "@/lib/auth"; import { toNextJsHandler } from "better-auth/next-js"; export const { GET, POST } = toNextJsHandler(auth); ``` ### Database Schema ```bash npx auth@latest migrate # built-in adapter (pg / mysql / sqlite): applies directly npx auth@latest generate # Prisma / Drizzle: writes the schema, then run your ORM's migrate ``` Re-run after adding or removing plugins. Verify with `GET /api/auth/ok` → `{ "status": "ok" }`. ### Client ```ts // lib/auth-client.ts import { createAuthClient } from "better-auth/react"; export const authClient = createAuthClient(); ``` ```tsx "use client"; import { authClient } from "@/lib/auth-client"; // Sign in await authClient.signIn.email({ email, password, callbackURL: "/dashboard" }); await authClient.signIn.social({ provider: "github", callbackURL: "/dashboard" }); await authClient.signUp.email({ email, password, name }); await authClient.signOut(); // Reactive session const { data: session, isPending } = authClient.useSession(); ``` ### Access Session Data (Server) ```tsx // Server Component, Server Action, or Route Handler import { auth } from "@/lib/auth"; import { headers } from "next/headers"; import { redirect } from "next/navigation"; export default async function Page() { const session = await auth.api.getSession({ headers: await headers() }); if (!session) redirect("/sign-in"); return <p>Hello, {session.user.name}</p>; } ``` Every endpoint (including plugin endpoints) is callable server-side via `auth.api.*` — no HTTP round-trip. ### Protect Routes Only check for the session **cookie** in middleware/proxy — never call the database there. Do the real check in the page or route handler. ```ts // proxy.ts (Next.js 16) — rename to middleware.ts on Next.js 15 import { NextRequest, NextResponse } from "next/server"; import { getSessionCookie } from "better-auth/cookies"; export function proxy(request: NextRequest) { if (!getSessionCookie(request)) { return NextResponse.redirect(new URL("/sign-in", request.url)); } return NextResponse.next(); } export const config = { matcher: ["/dashboard/:path*"] }; ``` ### Keep It Fast on Vercel - **Cookie cache on** (`session.cookieCache`) — avoids a DB read per request in Fluid Compute functions. - **Redis for shared state** — `vercel integration add upstash`, then pass a `secondaryStorage` adapter. Sessions and rate-limit counters move to Redis; the default in-memory rate limiter does not share state across function instances. Set `rateLimit.storage: "secondary-storage"`. - **Import plugins from subpaths** for tree-shaking: `import { twoFactor } from "better-auth/plugins/two-factor"`, not `"better-auth/plugins"`. - **Cookie check only in middleware** — `getSessionCookie()` is synchronous and works on the Edge runtime; `auth.api.getSession()` in middleware requires the Node.js runtime and costs a DB hit per request. - **Separate frontend origin?** Add it to `trustedOrigins` (wildcards allowed: `"https://*.vercel.app"`). Same-origin apps need nothing. ### Common Mistakes | Symptom | Cause | Fix | |---------|-------|-----| | Cookies not set from a Server Action | `nextCookies()` missing or not last in `plugins` | Add it as the last plugin | | Middleware slow or fails on Edge | `auth.api.getSession()` in middleware | Use `getSessionCookie()`; verify in the page | | "Invalid origin" on a separate frontend | Origin not trusted | Add it to `trustedOrigins` | | Type errors or missing tables after adding a plugin | Schema not regenerated | Re-run `npx auth@latest migrate` / `generate` | | Adapter can't find a model | Config uses the DB table name | Use the ORM **model** name (`modelName: "user"`, not `"users"`) | | Rate limits reset per request in production | Default in-memory rate-limit storage | Use `secondaryStorage` (Redis) or `rateLimit.storage: "database"` | | Callback URL wrong on Vercel | `BETTER_AUTH_URL` points at localhost or a preview | Set the production domain in Production; leave unset for Preview | ### Plugins Server plugin + matching client plugin + re-run migrations. | Feature | Server import | Client plugin | |---------|--------------|---------------| | Two-factor (TOTP/OTP) | `twoFactor` from `better-auth/plugins/two-factor` | `twoFactorClient` | | Organizations / teams | `organization` from `better-auth/plugins/organization` | `organizationClient` |
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기