netlify-access-control
Picks the right Netlify site-protection layer and disambiguates the three unrelated "auth" concepts users conflate — app-user…
Add user authentication to a Netlify site with @netlify/identity — signup/login/logout, Google/GitHub/GitLab/Bitbucket OAuth, server-side getUser() checks, role-based access control, and Identity event functions. Use it when a task involves adding a login or signup form, gating
Claude Code
$ npx -y skills add netlify/context-and-tools --skill netlify-identity --agent claude-code
Codex
$ npx skills add netlify/context-and-tools --skill netlify-identity -a codex -y
Cursor
$ npx skills add netlify/context-and-tools --skill netlify-identity -a cursor -y
Gemini CLI
$ npx skills add netlify/context-and-tools --skill netlify-identity -a gemini-cli -y
GitHub Copilot
$ npx skills add netlify/context-and-tools --skill netlify-identity -a github-copilot -y
OpenCode
$ npx skills add netlify/context-and-tools --skill netlify-identity -a opencode -y
Windsurf
$ npx skills add netlify/context-and-tools --skill netlify-identity -a windsurf -y
name: netlify-identity description: Add user authentication to a Netlify site with @netlify/identity, covering signup/login/logout, Google/GitHub/GitLab/Bitbucket OAuth, server-side getUser() checks, role-based access control, and Identity event functions. Use it when a task involves adding a login or signup form, gating content to members or roles, "auth middleware" or verifying users in Netlify Functions or Edge Functions, handling OAuth or email-confirmation callbacks, accepting user invites, assigning roles at signup, or customizing Identity emails. For locking a whole site to your company or employees-only access, use netlify-access-control instead.
Use `@netlify/identity` (npm). For new projects it replaces the legacy `netlify-identity-widget` and `gotrue-js`. Do not reach for those.
npm install @netlify/identity
Framework examples (Next.js/Astro/Remix/SvelteKit) and the full API reference are in the [`@netlify/identity` README on npm](https://www.npmjs.com/package/@netlify/identity).
> **Identity does not run under `netlify dev`.** Test all auth flows on a deploy. Deploy Previews work. Local dev will not complete signup/login/OAuth.
> **Identity config is dashboard-only. There is no public API.** Never curl `api.netlify.com` to flip or read Identity settings, never read tokens from local Netlify config, and never probe undocumented endpoints. Enable and configure Identity at `https://app.netlify.com/projects/{site_name}/identity`.
> **Never build a from-scratch OAuth flow alongside Identity.** No provider app registration in code, no `client_id`/`secret` in source, and no custom callback token exchange. Use `oauthLogin()` + `handleAuthCallback()`. Raw OAuth beside Identity is the most common source of rework.
import { signup, login, logout, getUser, oauthLogin, handleAuthCallback } from '@netlify/identity'
// Register — confirmation email sent by default (unless autoconfirm is on)
const user = await signup('jane@example.com', 'securepassword', { full_name: 'Jane Doe' })
// Log in / out
await login('jane@example.com', 'securepassword')
await logout()
// Current user or null
const current = await getUser()
if (current) console.log(`Logged in as ${current.email}`)
// External provider — redirects the browser; provider is one of
// 'google' | 'github' | 'gitlab' | 'bitbucket'
oauthLogin('github')> **`handleAuthCallback()` is mandatory on your landing page.** Without it, OAuth redirects, email-confirmation links, password-recovery links, and invite links never complete. Call it on page load.
> **Invites are NOT logged in by `handleAuthCallback()`.** For an invite it returns `type === 'invite'` with the token in `result.token` and `result.user === null`. The account does not exist yet. You must collect a password and call `acceptInvite(result.token, password)`. If you skip this step, invited users never get an account.
import { handleAuthCallback, acceptInvite } from '@netlify/identity'
const result = await handleAuthCallback() // falsy if no token in URL hash
if (result?.type === 'invite' && result.token) {
// Invited user has no account yet. Ask them to choose a password first.
const password = (document.getElementById('password') as HTMLInputElement).value
const user = await acceptInvite(result.token, password)
console.log('Account created:', user.email)
} else if (result) {
// OAuth, email confirmation, recovery, or email change
console.log(result.type, result.user?.email)
}For recovery tokens you can call `recoverPassword()` directly instead. Refresh a session with `refreshSession()`.
Don't hard-code which providers exist. Call `getSettings()` at startup and render the signup form and OAuth buttons from what it returns.
Server-side `getUser()`/`login()`/`admin.*` require modern **v2 functions** (`export default`). The v1 `export { handler }` form is not supported.
`getUser()` works in both runtimes. **`admin.*` runs ONLY in Netlify Functions. It does not run in the browser or in Edge Functions.**
// netlify/functions/me.ts — verify user
import { getUser } from '@netlify/identity'
import type { Context } from '@netlify/functions'
export default async (req: Request, context: Context) => {
const user = await getUser()
if (!user) return new Response('Unauthorized', { status: 401 })
return Response.json({ id: user.id, email: user.email })
}The Edge Function form is identical but imports `Context` from `@netlify/edge-functions`.
// netlify/functions/admin-users.ts
import { getUser, admin } from '@netlify/identity'
import type { Context } from '@netlify/functions'
export default async (req: Request, context: Context) => {
const user = await getUser()
if (!user) return new Response('Unauthorized', { status: 401 })
if (!user.roles.includes('admin')) return new Response('Forbidden', { status: 403 })
const users = await admin.listUsers()
return Response.json({ users })
}> Any endpoint that runs `login()`, `signup()`, or `logout()` server-side **must** call `verifyRequestOrigin(req)` at the top of the handler. It throws a 403 on origin mismatch.
// netlify/functions/login.ts
import { login, verifyRequestOrigin } from '@netlify/identity'
import type { Context } from '@netlify/functions'
export default async (req: Request, context: Context) => {
verifyRequestOrigin(req)
const { email, password } = await req.json()
await login(email, password)
return new Response(null, { status: 302, headers: { Location: '/dashboard' } })
}The platform calls your handler when an Identity event occurs. Export a default object with a method per event. File: `netlify/functions/identity.mts`.
> Typed handlers (`UserSignupEvent`, `event.deny()`) require `@netlify/functions` ≥ 5.2.0.
Public Netlify skills for AI coding agents. Each skill is a focused, factual reference for a Netlify platform primitive — designed to help agents build correctly on Netlify without needing to search docs.
Picks the right Netlify site-protection layer and disambiguates the three unrelated "auth" concepts users conflate — app-user…
Run AI agent tasks remotely on Netlify using Claude, Codex, or Gemini. Use when the user wants to run an AI agent on their site,…
Use Netlify AI Gateway to call OpenAI, Anthropic Claude, Google Gemini, TypeSafe (Jev), or OpenRouter-hosted models…
Store and retrieve unstructured objects, files, and cache-like state on Netlify with the @netlify/blobs module. Use when…
Cache dynamic and static responses on Netlify's CDN from Functions, Edge Functions, and proxies. Use when you add caching or…
Configure Netlify builds and routing via netlify.toml, _redirects, and _headers. Use when setting a build command or publish…
Use this skill whenever the user mentions Horizon by name in a Laravel context. Covers the full Horizon lifecycle: installing…
Use when launching cloud VMs, Kubernetes pods, or Slurm jobs for GPU/TPU/CPU workloads, training or fine-tuning models on cloud…
Use this skill when the user mentions "pinme", or needs to upload files, store to IPFS, create/publish/deploy websites or…