Installs into .claude/skills of the current project.
Are you the author of Gotrue?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/dev-toolbelt-gotrue)
---
name: gotrue
description: GoTrue auth — user management, JWT, refresh tokens, custom claims.
---
# GoTrue
GoTrue is a stateless authentication microservice. It issues JWTs, manages user sessions, and handles OAuth flows. Supabase embeds it as the `auth` service; it can also run standalone.
---
## Detection Signals
Load this skill when any of the following are present:
| Signal | Location |
|---|---|
| `GOTRUE_*` env vars | `.env`, `.env.example`, deploy config |
| `SUPABASE_JWT_SECRET`, `SUPABASE_SERVICE_ROLE_KEY` | `.env`, `.env.example` |
| `@supabase/supabase-js`, `@supabase/auth-js`, `@supabase/ssr` | `package.json` |
| `supabase.auth.*` calls | application source |
| `[auth]` or `[auth.hook.*]` section | `supabase/config.toml` |
| `auth.users` table or `auth` schema | database schema / migrations |
| `supabase/auth` or `gotrue` image | `docker-compose.yml` |
---
## Auth Methods
| Method | API call (supabase-js) |
|---|---|
| Email + password | `supabase.auth.signInWithPassword({ email, password })` |
| Magic link | `supabase.auth.signInWithOtp({ email })` |
| Phone OTP | `supabase.auth.signInWithOtp({ phone })` |
| OAuth (Google, GitHub, etc.) | `supabase.auth.signInWithOAuth({ provider: 'google' })` |
| Anonymous | `supabase.auth.signInAnonymously()` |
| SSO / SAML | `supabase.auth.signInWithSSO({ domain })` |
---
## Core Rules
These decide the shape of the work. Code-level detail lives in the references below.
| Area | Rule |
|---|---|
| Authorization source | Read roles and permissions from `app_metadata` only — it is server-controlled |
| `user_metadata` | User-writable. Never an authorization input, under any circumstance |
| Server-side trust | `getSession()` does not verify — always follow with `getUser()` before trusting an identity on the server |
| Service-role key | Server-side only. Reaching it from client code grants full auth admin access |
| Token lifetime | Access tokens are short-lived (1h default); the client must handle refresh via `onAuthStateChange` |
| Claim changes | Custom claims are frozen into an issued JWT — a role change only applies after a token refresh |
| Environment parity | Confirm email-confirmation and expiry settings match between environments; GoTrue defaults differ |
---
## References
| File | Load when |
|---|---|
| `references/client-and-admin-api.md` | Implementing sign-in, sessions, refresh, the Admin API, or server-side JWT verification |
| `references/claims-and-hooks.md` | Adding custom claims, writing RLS against them, or configuring GoTrue hooks |
---
## Common Pitfalls
- Reading `user_metadata` for authorization — users control it, never trust it for permissions
- Not calling `onAuthStateChange` on the client — sessions expire silently
- Using `getSession()` on the server without re-verification — the session in the cookie may be stale; always call `getUser()` to verify server-side
- Exposing the service-role key in client code — gives full auth admin access
- Not enabling email confirmations in production — GoTrue defaults may differ between environments
- Assuming a revoked role takes effect immediately — the old JWT stays valid until it expires or is refreshed