Authentication System
Relevant source files
The following files were used as context for generating this wiki page:
The Authentication System in Easy Asphalt (Driveway Estimator Pro) provides a secure, type-safe mechanism for managing user identities and sessions. It leverages an external OAuth provider (Manus) to handle primary authentication, which is then synchronized with a local MySQL database via Drizzle ORM to maintain project ownership and user roles. Sources: README.md:52-60, server/_core/sdk.ts:1-20
The system follows a modern web architecture using JWT (JSON Web Tokens) for session persistence and tRPC for secure backend communication. Users can sign in via multiple platforms including Email, Google, Apple, Microsoft, and GitHub, with their profile data automatically synced to the local users table upon successful login. Sources: server/_core/sdk.ts:110-120, drizzle/schema.ts:13-30
Architecture and Components
The system is divided into a core SDK for external communication, a database layer for persistence, and a frontend layer for user interaction. Sources: server/_core/sdk.ts:77-80, server/db.ts:1-10
Core SDK (SDKServer)
The SDKServer class acts as the primary orchestrator for authentication logic. It handles the exchange of OAuth codes for access tokens, retrieves user information, and manages the signing and verification of session JWTs. Sources: server/_core/sdk.ts:77-248
Key methods include:
exchangeCodeForToken: Exchanges a one-time code from the OAuth provider for a persistent access token.getUserInfoWithJwt: Fetches user profile details using a valid JWT.verifySession: Decodes and validates the session cookie.authenticateRequest: A high-level middleware-style function that validates a request's cookies and returns a localUserobject. Sources: server/_core/sdk.ts:128-132, server/_core/sdk.ts:192-205, server/_core/sdk.ts:211-247
Database Layer
User profiles are persisted in the users table. This table stores the openId (the unique identifier from Manus), along with the user's name, email, and assigned role. Sources: drizzle/schema.ts:13-30
The relationship between users and projects is strictly enforced, ensuring that a project cannot exist without a valid owner reference (userId). Sources: drizzle/schema.ts:37-40
Data Flow: Login and Synchronization
When a user authenticates, the system performs an "upsert" operation. If the user does not exist in the local database, a new record is created; otherwise, the lastSignedIn timestamp and profile details are updated. Sources: server/db.ts:30-80
Authentication Sequence
The following diagram illustrates the flow from the initial OAuth callback to session establishment.
API and Data Structures
User Roles and Constraints
The system supports a basic Role-Based Access Control (RBAC) model defined in the schema. Sources: drizzle/schema.ts:25-26
| Field | Type | Description |
|---|---|---|
id | int | Internal auto-incrementing ID. |
openId | varchar(64) | Unique ID from OAuth provider. |
role | enum | Either 'user' or 'admin'. Defaults to 'user'. |
loginMethod | varchar(64) | Tracks if the user used Google, GitHub, etc. |
Configuration and Environment
The authentication behavior is governed by specific environment variables. Sources: README.md:154-165
JWT_SECRET: Used to sign the session cookies.OAUTH_SERVER_URL: The endpoint for the Manus Auth service.OWNER_OPEN_ID: A specific ID that is automatically granted 'admin' status upon login. Sources: server/db.ts:65-68
Session Management
Sessions are managed using signed JWTs stored in cookies. These cookies have a default lifespan of one year. Sources: server/_core/sdk.ts:1-5, server/_core/sdk.ts:167-175
// server/_core/sdk.ts:175-190
async signSession(
payload: SessionPayload,
options: { expiresInMs?: number } = {}
): Promise<string> {
const issuedAt = Date.now();
const expiresInMs = options.expiresInMs ?? ONE_YEAR_MS;
const expirationSeconds = Math.floor((issuedAt + expiresInMs) / 1000);
const secretKey = this.getSessionSecret();
return new SignJWT({
openId: payload.openId,
appId: payload.appId,
name: payload.name,
})
.setProtectedHeader({ alg: "HS256", typ: "JWT" })
.setExpirationTime(expirationSeconds)
.sign(secretKey);
}
Security and Testing
The system enforces authentication on sensitive API routes. For instance, the projects.list and projects.delete procedures in the tRPC router throw an UNAUTHORIZED error if the session is invalid or missing. Sources: server/routers/projects.test.ts:35-50
Security Policies
- Vulnerability Reporting: Security issues are tracked via the project's security policy. Sources: SECURITY.md:1-25
- Request Sanitization: The
debug-collector.jsscript explicitly redacts sensitive fields likepassword,token, andcookiebefore logging interaction data. Sources: client/public/manus/debug-collector.js:33-45
Conclusion
The Easy Asphalt Authentication System provides a robust foundation for user management by delegating identity verification to a trusted OAuth provider while maintaining local control over application roles and project ownership. The use of JWTs and type-safe SDKs ensures that user sessions are both secure and easy to manage across the React frontend and Express backend. Sources: README.md:52-70, server/_core/sdk.ts:211-248