feat(auth): migrate authentication to better-auth#51
Merged
Conversation
Contributor
Reviewer's GuideMigrates authentication to Better Auth, replacing custom JWT/password flows, wiring Better Auth into the Express app and Prisma schema, and aligning models/DTOs/validators/tests with the new user/profile model while adding e2e coverage and tightening configuration validation and caching behavior. Sequence diagram for Better Auth–backed role-protected routesequenceDiagram
actor User
participant Browser
participant ExpressApp
participant AuthorizationMiddleware
participant BetterAuth as BetterAuth_auth.api
participant Prisma
User->>Browser: Clicks /api/admins/me
Browser->>ExpressApp: GET /api/admins/me (cookies)
ExpressApp->>AuthorizationMiddleware: isAuthorized(['admin'])
AuthorizationMiddleware->>BetterAuth: getSession(headers: fromNodeHeaders(req.headers))
BetterAuth->>Prisma: Load session and user via prismaAdapter
Prisma-->>BetterAuth: Session + user { role }
BetterAuth-->>AuthorizationMiddleware: session | null
alt session not found
AuthorizationMiddleware-->>ExpressApp: sendError(401, 'Authentication required')
ExpressApp-->>Browser: 401 Unauthorized
else session found
alt user.role not in allowedRoles
AuthorizationMiddleware-->>ExpressApp: sendError(403, 'Access denied: insufficient permissions')
ExpressApp-->>Browser: 403 Forbidden
else role allowed
AuthorizationMiddleware->>ExpressApp: set app.locals { userId, session, user }
ExpressApp-->>Browser: 200 OK (admin profile)
end
end
Entity relationship diagram for Better Auth migration in PrismaerDiagram
Users {
UUID id PK
TEXT name
TEXT email
BOOLEAN emailVerified
TEXT image
TEXT phone
TEXT password
TEXT role
BOOLEAN isVerified
BOOLEAN isActive
BOOLEAN isLocked
}
session {
TEXT id PK
TIMESTAMP expiresAt
TEXT token
TIMESTAMP createdAt
TIMESTAMP updatedAt
TEXT ipAddress
TEXT userAgent
UUID userId FK
}
account {
TEXT id PK
TEXT accountId
TEXT providerId
UUID userId FK
TEXT accessToken
TEXT refreshToken
TEXT idToken
TIMESTAMP accessTokenExpiresAt
TIMESTAMP refreshTokenExpiresAt
TEXT scope
TEXT password
TIMESTAMP createdAt
TIMESTAMP updatedAt
}
verification {
TEXT id PK
TEXT identifier
TEXT value
TIMESTAMP expiresAt
TIMESTAMP createdAt
TIMESTAMP updatedAt
}
Users ||--o{ session : "has sessions"
Users ||--o{ account : "has accounts"
verification }o--|| Users : "indirectly references via identifier (e.g. reset-password:, email)"
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Contributor
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- The
Usersmigration adds a non-nullnamecolumn without a default and notes that this is not possible on non-empty tables; consider either backfilling existing rows in the migration or introducing the column as nullable and tightening it in a follow-up step to avoid production deployment failures. - The new
requireEnv/parsePortusage inconfig.tsnow hard-requires values likeNODEMAILER_HOSTandNODEMAILER_PORT, which previously could be omitted; if email is optional in some environments, you may want to treat these as optional or gate their validation behind a feature flag to prevent the app from crashing when mail isn’t configured. - In
libs/auth.ts,createUserbyRolethrows whenrole === admin, while the README’s Auth API examples show an admin sign-up payload usingrole: "admin"; it would be good to align the runtime behavior and the documented API by either allowing controlled admin sign-up or clearly documenting that admins cannot be created via this endpoint.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The `Users` migration adds a non-null `name` column without a default and notes that this is not possible on non-empty tables; consider either backfilling existing rows in the migration or introducing the column as nullable and tightening it in a follow-up step to avoid production deployment failures.
- The new `requireEnv`/`parsePort` usage in `config.ts` now hard-requires values like `NODEMAILER_HOST` and `NODEMAILER_PORT`, which previously could be omitted; if email is optional in some environments, you may want to treat these as optional or gate their validation behind a feature flag to prevent the app from crashing when mail isn’t configured.
- In `libs/auth.ts`, `createUserbyRole` throws when `role === admin`, while the README’s Auth API examples show an admin sign-up payload using `role: "admin"`; it would be good to align the runtime behavior and the documented API by either allowing controlled admin sign-up or clearly documenting that admins cannot be created via this endpoint.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary by Sourcery
Migrate authentication to Better Auth with session-based authorization, update user and profile models to centralize identity data, and add end-to-end coverage for the new auth flows.
New Features:
Bug Fixes:
Enhancements:
Build:
CI:
Deployment:
Documentation:
Tests:
Chores: