Appearance
Authentication
Authentication in this project is built on top of Better Auth, a flexible and secure authentication library. For more detailed information about the authentication concepts and implementation, please refer to the Better Auth documentation.
Why Better Auth?
Better Auth was chosen for this project due to its flexibility and unopinionated nature, which is a great fit for a custom microservices architecture. Here are a few key reasons for using it:
- Framework Agnostic: It is not tied to any specific framework like Next.js, making it ideal for use in any Node.js application, including our Express-based microservices.
- Database Agnostic: It supports multiple database adapters, including Prisma, which is used in this project. This allows for seamless integration with our existing database setup.
- Extensible: The library is designed to be highly extensible, allowing us to customize the authentication flow and add our own logic for things like permissions and roles.
- Secure by Default: It provides a solid foundation of security best practices, helping to protect against common vulnerabilities.
Authentication is handled by a dedicated service and a shared package.
Auth Service
The auth service is a microservice responsible for handling user registration, login, and other authentication-related tasks.
Core Responsibilities
- User Management: Handles user creation, and profile updates.
- Authentication: Manages the login process, including password verification and issuing session tokens.
- Session Management: Creates and validates user sessions.
- Two-Factor Authentication: Manages the setup and verification of two-factor authentication.
Structure
The auth service is located in the apps/auth directory.
apps/auth
├── src
│ ├── utils
│ │ └── logger.ts
│ ├── auth.ts
│ ├── index.ts
│ └── server.ts
├── package.json
├── tsconfig.json
└── turbo.jsonAuth Package
The auth package is a shared package that contains authentication-related utilities, permissions, and roles that can be used across different services.
Contents
- CLI: A command-line interface for auth-related tasks (
auth-cli.ts). - Email Services: Integration with Resend for sending authentication-related emails (
resend.ts). - Permissions & Roles: Logic for defining and checking user permissions and roles.
- Shared Utilities: Common utilities used by the auth service and other services.
Structure
The auth package is located in the packages/auth directory.
packages/auth
├── scripts
│ └── auth-cli.ts
├── src
│ ├── services
│ │ ├── index.ts
│ │ └── resend.ts
│ ├── client.ts
│ ├── emails.ts
│ ├── index.ts
│ ├── permissions.ts
│ ├── roles.ts
│ └── utils.ts
├── env.ts
├── eslint.config.js
├── package.json
└── tsconfig.jsonData Models
The authentication system uses the following data models. For more details, see the Database Schema documentation.
User: The core user model.Session: Stores user session information.Account: Represents user accounts from different providers (e.g., email/password, Google, etc.).Verification: Used for email verification and other verification flows.TwoFactor: Stores two-factor authentication settings.
Authentication Flow
The following diagram illustrates a simplified login flow:
Permissions and Roles
The project uses the admin plugin from better-auth to implement a role-based access control (RBAC) system. This allows for fine-grained control over what actions different users can perform.
Role Definitions
The available roles are defined in packages/auth/src/roles.ts:
typescript
export const UserRole = {
ADMIN: "ADMIN",
USER: "USER",
} as const;
export type UserRole = (typeof UserRole)[keyof typeof UserRole];This defines two roles: ADMIN and USER.
Permission Definitions
The permissions for each role are defined in packages/auth/src/permissions.ts. This file uses the default admin and user access control statements from better-auth.
typescript
import { createAccessControl } from "better-auth/plugins/access";
import {
adminAc,
defaultStatements,
userAc,
} from "better-auth/plugins/admin/access";
const statement = {
...defaultStatements,
} as const;
export const accessControl = createAccessControl(statement);
export const adminRole = accessControl.newRole({
...adminAc.statements,
});
export const userRole = accessControl.newRole({
...userAc.statements,
});This means that the project uses the standard permissions provided by the better-auth library for the ADMIN and USER roles. For a detailed list of these default permissions, please refer to the Better Auth documentation.
Configuration
The initAuth function configures the admin plugin as follows:
typescript
//...
plugins: [
admin({
defaultRole: UserRole.USER,
adminRole: UserRole.ADMIN,
roles: {
ADMIN: adminRole,
USER: userRole,
},
}),
//...This configuration sets the default role for new users to USER and defines the ADMIN role as the administrative role.
API Endpoints
This section will document the API endpoints for the Auth Service, including routes, request/response formats, and examples.