Skip to content

Align authentication endpoints with better-auth protocol - #590

Merged
hotlong merged 6 commits into
mainfrom
copilot/evaluate-plugin-auth-compliance
Feb 10, 2026
Merged

Align authentication endpoints with better-auth protocol#590
hotlong merged 6 commits into
mainfrom
copilot/evaluate-plugin-auth-compliance

Conversation

CopilotAI commented Feb 10, 2026

Copy link
Copy Markdown
Contributor

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

  • Addedauth-endpoints.zod.ts defining canonical better-auth endpoints as the API contract
  • Includes HTTP methods, endpoint aliases, and legacy path mappings
  • 17 new tests validating endpoint definitions

Client SDK Updates

  • Updatedclient.auth.* methods to use correct better-auth paths:
    // Before → Afterlogin() : POST/loginPOST/sign-in/emailregister() : POST/registerPOST/sign-up/emaillogout() : POST/logoutPOST/sign-outme() : GET/meGET/get-sessionrefreshToken(): POST/refreshGET/get-session
  • No changes to method signatures or public API

Documentation

  • Updatedauth.mdx with complete endpoint reference table
  • Added usage examples for both client SDK and direct API calls
  • Created evaluation report documenting adapter issues for future work

Migration Impact

Zero breaking changes. Public SDK methods unchanged. Only internal HTTP paths updated:

// Application code remains identicalconstclient=newObjectStackClient({baseUrl: 'http://localhost:3000'});awaitclient.auth.register({ email, password, name });// Still worksawaitclient.auth.login({type: 'email', email, password });

Direct API consumers must update paths (e.g., /api/v1/auth/register/api/v1/auth/sign-up/email).

Test Results

  • Spec tests: 4213/4213 passing
  • Auth endpoint tests: 17/17 passing
  • Client auth tests: passing

Known Issues

Adapters (Hono/Next.js/NestJS) use deprecated HttpDispatcher.handleAuth() instead of kernel.getService('auth'). Functional but should be updated in future PR. Documented in evaluation report.

Original prompt

评估目前 plugin-auth 是否符合 spec API 协议,是否 所有 adaptor hono nextjs nestjs 都已按协议规范接入,评估 @objectstack/client 是否按协议接入。按照最新的代码更新测试用例,更新官网文档

The user has attached the following file paths as relevant context:

  • .github/copilot-instructions.md

Created from VS Code.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@vercel

vercelBot commented Feb 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
objectstack-playCanceledCanceledFeb 10, 2026 2:38pm
specCanceledCanceledFeb 10, 2026 2:38pm

Request Review

CopilotAIand others added 5 commits February 10, 2026 14:08
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>
CopilotAI changed the title [WIP] Evaluate plugin-auth for spec API complianceAlign authentication endpoints with better-auth protocolFeb 10, 2026
CopilotAI requested a review from hotlongFebruary 10, 2026 14:20
@hotlong
hotlong marked this pull request as ready for review February 10, 2026 14:21
CopilotAI review requested due to automatic review settings February 10, 2026 14:21
@hotlong
hotlong merged commit 4f54fbe into mainFeb 10, 2026
4 of 5 checks passed

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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/client auth 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
FileDescription
packages/spec/src/api/index.tsRe-exports the new auth endpoints spec module.
packages/spec/src/api/auth-endpoints.zod.tsDefines canonical better-auth endpoint paths, aliases, and mappings.
packages/spec/src/api/auth-endpoints.test.tsAdds vitest coverage for endpoint path/constants and helper behavior.
packages/client/src/index.tsUpdates client auth HTTP paths to better-auth endpoints.
packages/client/src/client.test.tsUpdates client tests to assert the new auth endpoint paths/methods.
docs/AUTH_PROTOCOL_EVALUATION.mdAdds a detailed compliance evaluation document (currently includes pre-fix findings).
docs/AUTH_IMPLEMENTATION_SUMMARY.mdAdds a migration/implementation summary for the endpoint alignment.
docs/AUTH_EVALUATION_FINAL_REPORT.mdAdds a final evaluation report capturing the post-change status.
content/docs/references/api/auth.mdxDocuments the canonical endpoints and provides usage examples.

Comment on lines +146 to +158
/**
* 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;

CopilotAIFeb 10, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +60 to +82
### 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

CopilotAIFeb 10, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
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();

CopilotAIFeb 10, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
returnres.json();
constdata=awaitres.json();
if(data.data?.token){
this.token=data.data.token;
}
returndata;

Copilot uses AI. Check for mistakes.
method: z.literal('GET'),
path: z.literal(AuthEndpointPaths.verifyEmail),
description: z.literal('Verify email with token'),
}),

CopilotAIFeb 10, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Suggested change
}),
}),
// ------------------------------------------
// 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'),
}),

Copilot uses AI. Check for mistakes.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@hotlong