Skip to content

Commit fee94a6

Browse files
authored
fix(auth): pin OAuth state + sessions to Postgres regardless of Redis (#85)
When secondaryStorage is configured Better Auth routes verification (OAuth state, magic-link tokens, email-verify tokens) and sessions through it by default. When Redis hiccups — even briefly — those disappear and OAuth callbacks fail with 'State mismatch: verification not found'. Pin both to the DB: - verification.storeInDatabase: true - session.storeSessionInDatabase: true Redis remains the secondaryStorage backend for rate-limit counters (rateLimit.storage = 'secondary-storage'), which is the original intent of #34. Rate-limit is best-effort cache, OAuth state is not.
1 parent 2b89217 commit fee94a6

1 file changed

Lines changed: 9 additions & 4 deletions

File tree

packages/auth/src/index.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,16 @@ export function createAuth() {
2929
provider: "pg",
3030
schema,
3131
}),
32-
// When REDIS_URL is set, Better Auth uses Redis for sessions
33-
// (optional) and rate-limit counters (see `rateLimit.storage` below).
34-
// When unset, falls back to the in-memory store — fine for dev,
35-
// not safe across multiple replicas in prod.
32+
// When REDIS_URL is set, Better Auth uses Redis as secondaryStorage
33+
// for rate-limit counters (see `rateLimit.storage` below).
34+
//
35+
// We pin OAuth state + verification rows + sessions to Postgres
36+
// regardless of Redis state — losing them when Redis hiccups is
37+
// catastrophic (OAuth callbacks fail with "state mismatch", users
38+
// get signed out). Redis is a cache for rate-limit only.
3639
...(secondaryStorage ? { secondaryStorage } : {}),
40+
verification: { storeInDatabase: true },
41+
session: { storeSessionInDatabase: true },
3742
appName: "starter-saas",
3843
trustedOrigins: [env.CORS_ORIGIN, env.APP_URL],
3944
secret: env.BETTER_AUTH_SECRET,

0 commit comments

Comments
 (0)