Uh oh!
There was an error while loading. Please reload this page.
Align authentication endpoints with better-auth protocol - #590
Conversation
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
…paths Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Pull request overview
Aligns ObjectStack authentication contract and client SDK behavior with the canonical better-auth endpoint protocol to eliminate client↔plugin route mismatches.
Changes:
- Added spec-level canonical auth endpoint definitions + tests.
- Updated
@objectstack/clientauth methods/tests to call better-auth paths (/sign-in/email,/sign-up/email,/sign-out,/get-session). - Updated documentation and added evaluation/summary reports describing the protocol alignment and remaining adapter gaps.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/spec/src/api/index.ts | Re-exports the new auth endpoints spec module. |
| packages/spec/src/api/auth-endpoints.zod.ts | Defines canonical better-auth endpoint paths, aliases, and mappings. |
| packages/spec/src/api/auth-endpoints.test.ts | Adds vitest coverage for endpoint path/constants and helper behavior. |
| packages/client/src/index.ts | Updates client auth HTTP paths to better-auth endpoints. |
| packages/client/src/client.test.ts | Updates client tests to assert the new auth endpoint paths/methods. |
| docs/AUTH_PROTOCOL_EVALUATION.md | Adds a detailed compliance evaluation document (currently includes pre-fix findings). |
| docs/AUTH_IMPLEMENTATION_SUMMARY.md | Adds a migration/implementation summary for the endpoint alignment. |
| docs/AUTH_EVALUATION_FINAL_REPORT.md | Adds a final evaluation report capturing the post-change status. |
| content/docs/references/api/auth.mdx | Documents the canonical endpoints and provides usage examples. |
| /** | ||
| * Endpoint Mapping | ||
| * | ||
| * Maps common/legacy endpoint names to canonical better-auth paths. | ||
| * This allows clients to use simpler names while maintaining compatibility. | ||
| */ | ||
| export const EndpointMapping = { | ||
| '/login': AuthEndpointPaths.signInEmail, | ||
| '/register': AuthEndpointPaths.signUpEmail, | ||
| '/logout': AuthEndpointPaths.signOut, | ||
| '/me': AuthEndpointPaths.getSession, | ||
| '/refresh': AuthEndpointPaths.getSession, // Session refresh handled by better-auth automatically | ||
| } as const; |
There was a problem hiding this comment.
EndpointMapping currently isn't referenced anywhere outside the spec test, and it may imply that the server supports legacy routes like /login or /refresh (it doesn’t, since plugin-auth forwards directly to better-auth). Consider removing it, renaming it to something explicitly client-side (e.g., LegacyPathToCanonicalPath), or adding clear documentation that it’s only a reference mapping and not a supported API surface.
| ### Issues Identified | ||
| #### 1. Missing Endpoint Specification 🔴 CRITICAL | ||
| **Finding:** The spec defines request/response schemas but does NOT define explicit HTTP endpoints. | ||
| **Expected (not defined):** | ||
| ```typescript | ||
| export const AuthEndpointsSchema = z.object({ | ||
| login: z.literal('POST /api/v1/auth/login'), | ||
| register: z.literal('POST /api/v1/auth/register'), | ||
| logout: z.literal('POST /api/v1/auth/logout'), | ||
| me: z.literal('GET /api/v1/auth/me'), | ||
| refreshToken: z.literal('POST /api/v1/auth/refresh'), | ||
| }); | ||
| ``` | ||
| **Impact:** Clients and plugin implementations use different endpoint paths: | ||
| - Client expects: `/login`, `/register`, `/logout`, `/me`, `/refresh` | ||
| - Plugin provides (better-auth): `/sign-in/email`, `/sign-up/email`, `/sign-out`, `/get-session` | ||
| **Recommendation:** Create `auth-endpoints.zod.ts` defining explicit endpoint contracts. | ||
| #### 2. No HTTP Method Specifications 🟡 HIGH |
There was a problem hiding this comment.
The report still calls out “Missing Endpoint Specification” and recommends creating auth-endpoints.zod.ts, but this PR already adds that file and exports it. To keep the evaluation doc accurate for readers, update these sections to reflect the current state (e.g., mark as resolved and focus remaining gaps like adapter integration), or clearly label this document as a pre-fix snapshot and link to the final report as the authoritative status.
| const route = this.getRoute('auth'); | ||
| const res = await this.fetch(`${this.baseUrl}${route}/me`); | ||
| const res = await this.fetch(`${this.baseUrl}${route}/get-session`); | ||
| return res.json(); |
There was a problem hiding this comment.
auth.me() calls /get-session but (unlike login(), register(), and refreshToken()) it does not update this.token when the response includes data.token. Since SessionResponseSchema allows an updated bearer token from get-session, consider applying the same auto-token update logic here for consistency and to avoid the client keeping a stale token.
| returnres.json(); | |
| constdata=awaitres.json(); | |
| if(data.data?.token){ | |
| this.token=data.data.token; | |
| } | |
| returndata; |
| method: z.literal('GET'), | ||
| path: z.literal(AuthEndpointPaths.verifyEmail), | ||
| description: z.literal('Verify email with token'), | ||
| }), |
There was a problem hiding this comment.
AuthEndpointPaths includes 2FA/passkey/magic-link endpoints, but AuthEndpointSchema only defines a subset (up through verifyEmail). This makes the schema name/intent misleading and prevents validation for the additional paths that are documented elsewhere. Either extend AuthEndpointSchema to cover the remaining entries in AuthEndpointPaths (and add corresponding tests), or narrow AuthEndpointPaths/AuthEndpointSchema to the same surface area (e.g., core endpoints only).
| }), | |
| }), | |
| // ------------------------------------------ | |
| // 2FA Endpoints | |
| // ------------------------------------------ | |
| /** Enable two-factor authentication */ | |
| twoFactorEnable: z.object({ | |
| method: z.literal('POST'), | |
| path: z.literal(AuthEndpointPaths.twoFactorEnable), | |
| description: z.literal('Enable two-factor authentication'), | |
| }), | |
| /** Verify two-factor authentication code */ | |
| twoFactorVerify: z.object({ | |
| method: z.literal('POST'), | |
| path: z.literal(AuthEndpointPaths.twoFactorVerify), | |
| description: z.literal('Verify two-factor authentication code'), | |
| }), | |
| // ------------------------------------------ | |
| // Passkey Endpoints | |
| // ------------------------------------------ | |
| /** Register a new passkey credential */ | |
| passkeyRegister: z.object({ | |
| method: z.literal('POST'), | |
| path: z.literal(AuthEndpointPaths.passkeyRegister), | |
| description: z.literal('Register a new passkey credential'), | |
| }), | |
| /** Authenticate using a passkey credential */ | |
| passkeyAuthenticate: z.object({ | |
| method: z.literal('POST'), | |
| path: z.literal(AuthEndpointPaths.passkeyAuthenticate), | |
| description: z.literal('Authenticate using a passkey credential'), | |
| }), | |
| // ------------------------------------------ | |
| // Magic Link Endpoints | |
| // ------------------------------------------ | |
| /** Send a magic link for passwordless authentication */ | |
| magicLinkSend: z.object({ | |
| method: z.literal('POST'), | |
| path: z.literal(AuthEndpointPaths.magicLinkSend), | |
| description: z.literal('Send a magic link for passwordless authentication'), | |
| }), | |
| /** Verify a magic link token */ | |
| magicLinkVerify: z.object({ | |
| method: z.literal('GET'), | |
| path: z.literal(AuthEndpointPaths.magicLinkVerify), | |
| description: z.literal('Verify a magic link token'), | |
| }), |
Client SDK was using incorrect endpoint paths (
/login,/register,/logout,/me) while plugin-auth implements better-auth endpoints (/sign-in/email,/sign-up/email,/sign-out,/get-session). This mismatch would cause authentication failures.Changes
Protocol Specification
auth-endpoints.zod.tsdefining canonical better-auth endpoints as the API contractClient SDK Updates
client.auth.*methods to use correct better-auth paths:Documentation
auth.mdxwith complete endpoint reference tableMigration Impact
Zero breaking changes. Public SDK methods unchanged. Only internal HTTP paths updated:
Direct API consumers must update paths (e.g.,
/api/v1/auth/register→/api/v1/auth/sign-up/email).Test Results
Known Issues
Adapters (Hono/Next.js/NestJS) use deprecated
HttpDispatcher.handleAuth()instead ofkernel.getService('auth'). Functional but should be updated in future PR. Documented in evaluation report.Original prompt
Created from VS Code.
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.