fix(db): support verification operations with secondary storage#8247
fix(db): support verification operations with secondary storage#8247
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
@better-auth/api-key
better-auth
auth
@better-auth/core
@better-auth/drizzle-adapter
@better-auth/electron
@better-auth/expo
@better-auth/i18n
@better-auth/kysely-adapter
@better-auth/memory-adapter
@better-auth/mongo-adapter
@better-auth/oauth-provider
@better-auth/passkey
@better-auth/prisma-adapter
@better-auth/redis-storage
@better-auth/scim
@better-auth/sso
@better-auth/stripe
@better-auth/telemetry
@better-auth/test-utils
commit: |
When secondaryStorage is enabled without verification.storeInDatabase, updateVerificationValue and deleteVerificationValue would fail with "Model verification not found in schema" because they always tried to hit the database directly. - Generate an id for verifications stored in secondary storage only - Store a reverse id-to-identifier mapping in secondary storage - Add secondary storage support to updateVerificationValue - Add secondary storage cleanup to deleteVerificationValue and deleteVerificationByIdentifier - Add regression tests for magic link with secondary storage
61b35ea to
466f876
Compare
There was a problem hiding this comment.
Pull request overview
This PR fixes verification CRUD behavior when secondaryStorage is enabled but verification.storeInDatabase is disabled, so verification updates/deletes no longer fail due to missing DB schema. It extends the internal adapter to support updating verifications by identifier and adds secondary-storage bookkeeping to support update/delete flows.
Changes:
- Add
updateVerificationByIdentifierto the internal adapter interface and implement it in the Better Auth internal adapter. - Introduce a secondary-storage reverse mapping (
verification-id:<id>→<storedIdentifier>) and use it to support update/delete by id in secondary-only mode. - Update Magic Link verification to update/delete by identifier and add regression tests for Magic Link with secondary storage.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| packages/core/src/types/context.ts | Extends InternalAdapter with updateVerificationByIdentifier. |
| packages/better-auth/src/db/internal-adapter.ts | Adds secondary-storage reverse mapping + secondary-only update/delete support; adds updateVerificationByIdentifier. |
| packages/better-auth/src/plugins/magic-link/index.ts | Switches Magic Link attempt tracking/cleanup to identifier-based update/delete. |
| packages/better-auth/src/plugins/magic-link/magic-link.test.ts | Adds regression tests covering Magic Link flows with secondary storage enabled. |
Comments suppressed due to low confidence (1)
packages/better-auth/src/db/internal-adapter.ts:1277
updateVerificationByIdentifierupdates the cached JSON under the key derived from the input identifier. Ifdata.identifieris being updated (some flows update a verification row to a new identifier), the secondary-storage entry should be migrated to the newverification:${newStoredIdentifier}key (and anyverification-id:${id}reverse mapping updated) so future lookups by the new identifier work in secondary-only mode.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } | ||
|
|
||
| if (!secondaryStorage || options.verification?.storeInDatabase) { | ||
| const verification = await updateWithHooks<Verification>( | ||
| data, | ||
| [{ field: "identifier", value: storedIdentifier }], | ||
| "verification", | ||
| undefined, | ||
| ); |
There was a problem hiding this comment.
In the secondary-storage update path, updates that change identifier will leave the cached entry under the old verification:${storedIdentifier} key and keep verification-id:${id} pointing at the old identifier. This makes the verification unreachable via findVerificationValue(newIdentifier) in secondary-only mode (and can also cause later updates/deletes by id to target the wrong key). Consider detecting updateData.identifier changes and, if present, recomputing the new stored identifier, moving the cache entry to the new key, and updating the reverse mapping accordingly (including deleting the old key/mapping).
Move magic link secondary storage tests from the plugin test file to test/unit/ for better organization and real-world integration testing. Adds coverage for pre-parsed object storage (e.g., Redis wrappers).
83812ad to
102f6c3
Compare
…sed only Migrate all callers of deleteVerificationValue(id) and updateVerificationValue(id, data) to use deleteVerificationByIdentifier and updateVerificationByIdentifier. This ensures all verification operations work correctly with both secondary storage and database storage, fixing the root cause of #8228 across all plugins.
102f6c3 to
1aafea2
Compare
1aafea2 to
d574d18
Compare
Summary
Fixes #8228
When
secondaryStorageis configured withoutverification.storeInDatabase, the verification table is excluded from the DB schema bygetAuthTables(). This causeddeleteVerificationValue(id)andupdateVerificationValue(id)to fail withModel "verification" not found in schemabecause they operate by DB id, which doesn't exist in secondary-only mode.updateVerificationByIdentifierto the internal adapter, following the existingdeleteVerificationByIdentifierpatterndeleteVerificationValue/updateVerificationValue) to identifier-based (deleteVerificationByIdentifier/updateVerificationByIdentifier) methodsexpiresAtas string when secondary storage returns pre-parsed objects (fixesexpiresAt.getTime is not a function)Affected plugins/modules
magic-link,email-otp,two-factor,phone-number,one-time-token,oidc-provider,mcp,siwe,oauth-provider,electron,sso,state,password,update-userTest plan
test/unit/magic-link-secondary-storage.test.tscovering: