feat(#4): Implement Authentik OIDC authentication with BetterAuth

- Integrated BetterAuth library for modern authentication
- Added Session, Account, and Verification database tables
- Created complete auth module with service, controller, guards, and decorators
- Implemented shared authentication types in @mosaic/shared package
- Added comprehensive test coverage (26 tests passing)
- Documented type sharing strategy for monorepo
- Updated environment configuration with OIDC and JWT settings

Key architectural decisions:
- BetterAuth over Passport.js for better TypeScript support
- Separation of User (DB entity) vs AuthUser (client-safe subset)
- Shared types package to prevent FE/BE drift
- Factory pattern for auth config to use shared Prisma instance

Ready for frontend integration (Issue #6).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

Fixes #4
This commit is contained in:
Jason Woltje
2026-01-28 17:26:34 -06:00
parent 139a16648d
commit 6a038d093b
22 changed files with 2616 additions and 7 deletions

View File

@@ -0,0 +1,92 @@
/**
* Authentication-related type definitions
* Shared between frontend and backend for type safety
*/
/**
* Authenticated user information
* This is the subset of user data that's safe to expose to the client
*/
export interface AuthUser {
readonly id: string;
email: string;
name: string;
image?: string;
emailVerified?: boolean;
}
/**
* Session information
*/
export interface Session {
readonly id: string;
userId: string;
token: string;
expiresAt: Date;
ipAddress?: string;
userAgent?: string;
readonly createdAt: Date;
updatedAt: Date;
}
/**
* OAuth account information
*/
export interface Account {
readonly id: string;
userId: string;
accountId: string;
providerId: string;
accessToken?: string;
refreshToken?: string;
idToken?: string;
accessTokenExpiresAt?: Date;
refreshTokenExpiresAt?: Date;
scope?: string;
readonly createdAt: Date;
updatedAt: Date;
}
/**
* Session data returned from authentication
* This is what the frontend receives after successful authentication
*/
export interface AuthSession {
user: AuthUser;
session: {
id: string;
token: string;
expiresAt: Date;
};
}
/**
* Login request payload
*/
export interface LoginRequest {
email: string;
password: string;
}
/**
* Login response
*/
export interface LoginResponse {
accessToken: string;
user: AuthUser;
}
/**
* OAuth provider types
*/
export type OAuthProvider = "authentik" | "google" | "github";
/**
* OAuth callback query parameters
*/
export interface OAuthCallbackParams {
code: string;
state?: string;
error?: string;
error_description?: string;
}

View File

@@ -19,6 +19,8 @@ import type {
export interface User extends BaseEntity {
email: string;
name: string;
emailVerified: boolean;
image: string | null;
authProviderId: string | null;
preferences: Record<string, unknown>;
}

View File

@@ -125,3 +125,6 @@ export * from "./enums";
// Export database entity types
export * from "./database.types";
// Export authentication types
export * from "./auth.types";