Skip to content

Commit 5bf5ee3

Browse files
Rodriguespngregnrhfclaude
authored
feature: auth agent references (#36)
* feat: auth agent references * Update skills/supabase/references/auth-core-sessions.md Co-authored-by: Stojan Dimitrovski <sdimitrovski@gmail.com> * refactor: improve auth state management and update session handling examples * docs: update performance note for asymmetric JWTs * fix: correct signOut() default scope to 'global' signOut() defaults to scope: 'global' (all sessions on all devices), not current session only. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: improve signOut() examples to show all three scope options Replace redundant explicit 'global' example with 'local' scope, making all three options (global, local, others) visible. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: flatten auth references to root references directory Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * correct auth hooks * correct auth server ssr * fix auth reference files * fix paths inside skill.md * update agents.md --------- Co-authored-by: Greg Richardson <greg.nmr@gmail.com> Co-authored-by: Stojan Dimitrovski <sdimitrovski@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 621ba8b commit 5bf5ee3

18 files changed

Lines changed: 3827 additions & 11 deletions

‎skills/supabase/AGENTS.md‎

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,34 @@ supabase/
2626

2727
| Priority | Category | Impact | Prefix |
2828
|----------|----------|--------|--------|
29-
| 1 | Database | CRITICAL | `db-` |
30-
| 2 | Edge Functions | HIGH | `edge-` |
31-
| 3 | SDK | HIGH | `sdk-` |
32-
| 4 | Realtime | MEDIUM-HIGH | `realtime-` |
33-
| 5 | Storage | HIGH | `storage-` |
29+
| 1 | Authentication | CRITICAL | `auth-` |
30+
| 2 | Database | CRITICAL | `db-` |
31+
| 3 | Edge Functions | HIGH | `edge-` |
32+
| 4 | SDK | HIGH | `sdk-` |
33+
| 5 | Realtime | MEDIUM-HIGH | `realtime-` |
34+
| 6 | Storage | HIGH | `storage-` |
3435

3536
Reference files are named `{prefix}-{topic}.md` (e.g., `query-missing-indexes.md`).
3637

3738
## Available References
3839

40+
**Authentication** (`auth-`):
41+
- `references/auth-core-sessions.md`
42+
- `references/auth-core-signin.md`
43+
- `references/auth-core-signup.md`
44+
- `references/auth-hooks-custom-claims.md`
45+
- `references/auth-hooks-send-email-http.md`
46+
- `references/auth-hooks-send-email-sql.md`
47+
- `references/auth-mfa-phone.md`
48+
- `references/auth-mfa-totp.md`
49+
- `references/auth-oauth-pkce.md`
50+
- `references/auth-oauth-providers.md`
51+
- `references/auth-passwordless-magic-links.md`
52+
- `references/auth-passwordless-otp.md`
53+
- `references/auth-server-admin-api.md`
54+
- `references/auth-server-ssr.md`
55+
- `references/auth-sso-saml.md`
56+
3957
**Database** (`db-`):
4058
- `references/db-conn-pooling.md`
4159
- `references/db-migrations-diff.md`
@@ -110,4 +128,4 @@ Reference files are named `{prefix}-{topic}.md` (e.g., `query-missing-indexes.md
110128

111129
---
112130

113-
*62 reference files across 5 categories*
131+
*77 reference files across 6 categories*

‎skills/supabase/SKILL.md‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@ Supabase is an open source Firebase alternative that provides a Postgres databas
1818

1919
Reference the appropriate resource file based on the user's needs:
2020

21+
### Authentication & Security
22+
23+
| Area | Resource | When to Use |
24+
| ------------------ | ----------------------------------- | -------------------------------------------------------- |
25+
| Auth Core | `references/auth-core-*.md` | Sign-up, sign-in, sessions, password reset |
26+
| OAuth/Social | `references/auth-oauth-*.md` | Google, GitHub, Apple login, PKCE flow |
27+
| Enterprise SSO | `references/auth-sso-*.md` | SAML 2.0, enterprise identity providers |
28+
| MFA | `references/auth-mfa-*.md` | TOTP authenticator apps, phone MFA, AAL levels |
29+
| Passwordless | `references/auth-passwordless-*.md`| Magic links, email OTP, phone OTP |
30+
| Auth Hooks | `references/auth-hooks-*.md` | Custom JWT claims, send email hooks (HTTP and SQL) |
31+
| Server-Side Auth | `references/auth-server-*.md` | Admin API, SSR with Next.js/SvelteKit, service role auth |
32+
2133
### Database
2234

2335
| Area | Resource | When to Use |

‎skills/supabase/references/_sections.md‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,32 @@ queries.
55

66
---
77

8-
## 1. Database (db)
8+
## 1. Authentication (auth)
9+
10+
**Impact:** CRITICAL
11+
**Description:** Sign-up, sign-in, sign-out, session management, OAuth/social login, SAML SSO, MFA, passwordless flows, auth hooks, and server-side auth patterns.
12+
13+
## 2. Database (db)
914

1015
**Impact:** CRITICAL
1116
**Description:** Row Level Security policies, connection pooling, schema design patterns, migrations, performance optimization, and security functions for Supabase Postgres.
1217

13-
## 2. Edge Functions (edge)
18+
## 3. Edge Functions (edge)
1419

1520
**Impact:** HIGH
1621
**Description:** Fundamentals, authentication, database access, CORS, routing, error handling, streaming, WebSockets, regional invocations, testing, and limits.
1722

18-
## 3. SDK (sdk)
23+
## 4. SDK (sdk)
1924

2025
**Impact:** HIGH
2126
**Description:** supabase-js client initialization, TypeScript generation, CRUD queries, filters, joins, RPC calls, error handling, performance, and Next.js integration.
2227

23-
## 4. Realtime (realtime)
28+
## 5. Realtime (realtime)
2429

2530
**Impact:** MEDIUM-HIGH
2631
**Description:** Channel setup, Broadcast messaging, Presence tracking, Postgres Changes listeners, cleanup patterns, error handling, and debugging.
2732

28-
## 5. Storage (storage)
33+
## 6. Storage (storage)
2934

3035
**Impact:** HIGH
3136
**Description:** File uploads (standard and resumable), downloads, signed URLs, image transformations, CDN caching, access control with RLS policies, and file management operations.
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
---
2+
title: Manage Auth Sessions Correctly
3+
impact: CRITICAL
4+
impactDescription: Session mismanagement causes auth failures, security issues, and poor UX
5+
tags: auth, sessions, tokens, refresh, onAuthStateChange, jwt
6+
---
7+
8+
## Manage Auth Sessions Correctly
9+
10+
Session lifecycle, token refresh, and auth state listeners.
11+
12+
## Session Structure
13+
14+
```typescript
15+
interface Session {
16+
access_token: string // JWT, expires in 1 hour (default)
17+
refresh_token: string // Single-use, used to get new access_token
18+
expires_at: number // Unix timestamp when access_token expires
19+
expires_in: number // Seconds until expiration
20+
user: User // User object with id, email, metadata
21+
}
22+
```
23+
24+
## Listen to Auth State Changes
25+
26+
`onAuthStateChange` is the single source of truth for auth state. In React, wrap it with `useSyncExternalStore` for safe, tear-free subscriptions:
27+
28+
```typescript
29+
import { useSyncExternalStore } from 'react'
30+
31+
let currentSession: Session | null = null
32+
33+
function subscribe(callback: () => void) {
34+
const { data: { subscription } } = supabase.auth.onAuthStateChange(
35+
(_event, session) => {
36+
currentSession = session
37+
callback()
38+
}
39+
)
40+
return () => subscription.unsubscribe()
41+
}
42+
43+
function getSnapshot() {
44+
return currentSession
45+
}
46+
47+
// In your component
48+
function useSession() {
49+
return useSyncExternalStore(subscribe, getSnapshot)
50+
}
51+
```
52+
53+
### Auth Events
54+
55+
| Event | When Fired |
56+
|-------|------------|
57+
| `INITIAL_SESSION` | Right after client is constructed and initial session from storage is loaded |
58+
| `SIGNED_IN` | User signed in successfully |
59+
| `SIGNED_OUT` | User signed out |
60+
| `TOKEN_REFRESHED` | Access token was refreshed |
61+
| `USER_UPDATED` | User profile was updated |
62+
| `PASSWORD_RECOVERY` | User clicked password reset link |
63+
64+
## Get Current Session
65+
66+
```typescript
67+
// From local storage (fast, but not validated)
68+
const { data: { session } } = await supabase.auth.getSession()
69+
70+
// Validate on server: getClaims() validates JWT locally (fast, preferred with asymmetric keys)
71+
const { data: claims } = await supabase.auth.getClaims()
72+
73+
// Or use getUser() which round-trips to Auth server (always accurate)
74+
const { data: { user } } = await supabase.auth.getUser()
75+
```
76+
77+
## Common Mistakes
78+
79+
### 1. Using getSession() for Server-Side Validation
80+
81+
**Incorrect:**
82+
83+
```typescript
84+
// Server-side code
85+
const { data: { session } } = await supabase.auth.getSession()
86+
// DANGER: getSession reads from storage, doesn't validate JWT
87+
const userId = session?.user.id
88+
```
89+
90+
**Correct:**
91+
92+
```typescript
93+
// Server-side code - always use getClaims() which validates the JWT
94+
const { data, error } = await supabase.auth.getClaims()
95+
if (error || !data) {
96+
return unauthorizedResponse()
97+
}
98+
const userId = data.claims.sub
99+
```
100+
101+
> **Asymmetric JWTs:** Asymmetric JWT signing keys are the recommended approach. Symmetric signing is not recommended for production. With asymmetric keys, `getClaims()` verifies tokens locally via WebCrypto with no network request, significantly faster than `getUser()` which always round-trips to the Auth server.
102+
103+
### 2. Calling Supabase in onAuthStateChange Without Deferring
104+
105+
**Incorrect:**
106+
107+
```typescript
108+
supabase.auth.onAuthStateChange(async (event, session) => {
109+
// This can cause deadlocks
110+
await supabase.from('profiles').select('*')
111+
})
112+
```
113+
114+
**Correct:**
115+
116+
```typescript
117+
supabase.auth.onAuthStateChange((event, session) => {
118+
// Defer Supabase calls with setTimeout
119+
setTimeout(async () => {
120+
await supabase.from('profiles').select('*')
121+
}, 0)
122+
})
123+
```
124+
125+
### 3. Not Unsubscribing from Auth Listener
126+
127+
**Incorrect:**
128+
129+
```typescript
130+
useEffect(() => {
131+
supabase.auth.onAuthStateChange((event, session) => {
132+
setUser(session?.user)
133+
})
134+
// Missing cleanup - causes memory leaks
135+
}, [])
136+
```
137+
138+
**Correct:**
139+
140+
```typescript
141+
useEffect(() => {
142+
const { data: { subscription } } = supabase.auth.onAuthStateChange(
143+
(event, session) => {
144+
setUser(session?.user ?? null)
145+
}
146+
)
147+
148+
return () => subscription.unsubscribe()
149+
}, [])
150+
```
151+
152+
## JWT Claims
153+
154+
Access user claims in RLS policies:
155+
156+
```sql
157+
-- Get user ID
158+
auth.uid() -- Returns UUID
159+
160+
-- Get full JWT
161+
auth.jwt() -- Returns JSONB
162+
163+
-- Get specific claims
164+
auth.jwt() ->> 'email' -- User email
165+
auth.jwt() -> 'app_metadata' ->> 'role' -- Custom role (admin-set)
166+
auth.jwt() ->> 'aal' -- Auth assurance level (aal1/aal2)
167+
```
168+
169+
## Related
170+
171+
- [core-signin.md](core-signin.md) - Sign-in flows
172+
- [server-ssr.md](server-ssr.md) - Server-side session handling
173+
- [Docs: Sessions](https://supabase.com/docs/guides/auth/sessions)
174+
- [Docs: onAuthStateChange](https://supabase.com/docs/reference/javascript/auth-onauthstatechange)

0 commit comments

Comments
 (0)