feat: SaaS onboarding, Stripe billing, MFA, SSO, passkeys, refresh tokens

Complete SaaS self-service onboarding sprint:

- Stripe-powered signup flow: pricing page → checkout → provisioning → activation
- Refresh token infrastructure: 1h access tokens + 30-day httpOnly cookie refresh
- TOTP MFA with QR setup, recovery codes, and login challenge flow
- Google + Azure AD SSO (conditional on env vars) with account linking
- WebAuthn passkey registration and passwordless login
- Guided onboarding checklist with server-side progress tracking
- Stubbed email service (console + DB logging, ready for real provider)
- Settings page with tabbed security settings (MFA, passkeys, linked accounts)
- Login page enhanced with MFA verification, SSO buttons, passkey login
- Database migration 015 with all new tables and columns
- Version bump to 2026.03.17

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-16 21:12:35 -04:00
parent 17bdebfb52
commit dfcd172ef3
39 changed files with 4673 additions and 82 deletions

View File

@@ -4,8 +4,15 @@ import { PassportModule } from '@nestjs/passport';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { AuthController } from './auth.controller';
import { AdminController } from './admin.controller';
import { MfaController } from './mfa.controller';
import { SsoController } from './sso.controller';
import { PasskeyController } from './passkey.controller';
import { AuthService } from './auth.service';
import { AdminAnalyticsService } from './admin-analytics.service';
import { RefreshTokenService } from './refresh-token.service';
import { MfaService } from './mfa.service';
import { SsoService } from './sso.service';
import { PasskeyService } from './passkey.service';
import { JwtStrategy } from './strategies/jwt.strategy';
import { LocalStrategy } from './strategies/local.strategy';
import { UsersModule } from '../users/users.module';
@@ -21,12 +28,27 @@ import { OrganizationsModule } from '../organizations/organizations.module';
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
secret: configService.get<string>('JWT_SECRET'),
signOptions: { expiresIn: '24h' },
signOptions: { expiresIn: '1h' },
}),
}),
],
controllers: [AuthController, AdminController],
providers: [AuthService, AdminAnalyticsService, JwtStrategy, LocalStrategy],
exports: [AuthService],
controllers: [
AuthController,
AdminController,
MfaController,
SsoController,
PasskeyController,
],
providers: [
AuthService,
AdminAnalyticsService,
RefreshTokenService,
MfaService,
SsoService,
PasskeyService,
JwtStrategy,
LocalStrategy,
],
exports: [AuthService, RefreshTokenService, JwtModule],
})
export class AuthModule {}