Claude-skill-registry auth-bootstrapper
Adds BetterAuth authentication to Apso backends. Handles entity setup, code generation, auto-fixes, and verification. Triggers when user needs to add authentication, setup auth, or integrate BetterAuth.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/auth-bootstrapper" ~/.claude/skills/majiayu000-claude-skill-registry-auth-bootstrapper && rm -rf "$T"
skills/data/auth-bootstrapper/SKILL.mdAuth Bootstrapper
I add production-ready BetterAuth authentication to Apso backends, giving you a fully functional authenticated REST API in under 5 minutes with zero manual steps.
Core Capabilities
1. setup-backend-with-auth
Complete backend setup from scratch with authentication
What I automate:
- Create Apso backend project structure
- Generate .apsorc with BetterAuth entities
- Run
code generationapso server - Fix known integration issues automatically
- Set up environment variables
- Initialize database
- Verify all endpoints work
- Test authentication flows
Usage: "Setup backend with auth" or "Create new backend with authentication"
2. add-auth-to-existing
Add BetterAuth to existing Apso backend
What I automate:
- Analyze current .apsorc schema
- Detect and resolve entity naming conflicts
- Add BetterAuth entities (User, account, session, verification)
- Regenerate code with
apso server - Fix DTO and entity issues
- Update database schema
- Configure auth endpoints
- Test integration
Usage: "Add auth to my backend" or "Integrate BetterAuth"
3. fix-auth-issues
Auto-fix common BetterAuth integration problems
Issues I fix automatically:
- Missing
field in DTOsid - Nullable field constraints
- Entity naming conflicts
- AppModule wiring issues
- Database NOT NULL constraint errors
- CORS configuration
- Session cookie settings
Usage: "Fix auth issues" or "My auth isn't working"
4. verify-auth-setup
Run comprehensive verification checks
What I verify:
- Database tables exist and are correct
- All CRUD endpoints respond
- User signup flow works
- User signin flow works
- Session creation works
- Token validation works
- Multi-tenancy isolation works
- Organization auto-creation works
Usage: "Verify auth setup" or "Test the backend"
The 5-Minute Setup Process
When you say "setup backend with auth", I execute this fully automated workflow:
Phase 1: Project Initialization (30 seconds)
# 1. Create backend directory mkdir backend && cd backend # 2. Initialize Apso project npx apso init # 3. Install dependencies npm install
Phase 2: Schema Configuration (1 minute)
I create
.apsorc with:
BetterAuth Required Entities:
(PascalCase) - Authentication user entityUser
(lowercase) - OAuth/credential providersaccount
(lowercase) - Active user sessionssession
(lowercase) - Email verification tokensverification
Business Entities (renamed to avoid conflicts):
(NOT "Account") - Multi-tenant rootOrganization
(NOT "Session") - Your business sessionsDiscoverySession- Junction tables for relationships
Critical Configuration Points:
{ "service": "your-backend", "database": { "provider": "postgresql", "multiTenant": true, "tenantKey": "account_id" }, "entities": { "User": { "fields": { "avatar_url": { "nullable": true }, // ← MUST be nullable "password_hash": { "nullable": true }, // ← MUST be nullable "oauth_provider": { "nullable": true }, // ← MUST be nullable "oauth_id": { "nullable": true } // ← MUST be nullable } } } }
See
references/apsorc-templates/ for complete examples.
Phase 3: Code Generation (30 seconds)
# Generate NestJS backend apso server # This creates: # - REST API controllers # - TypeORM entities # - DTOs with validation # - Service layer # - OpenAPI docs
Phase 4: Automatic Fixes (1 minute)
I apply these fixes automatically (no manual intervention):
Fix 1: Add
to Create DTOsid
// backend/src/autogen/User/dtos/User.dto.ts export class UserCreate { @ApiProperty() @IsUUID() id: string; // ← I add this automatically // ... rest of fields }
Fix 2: Verify Nullable Fields
// backend/src/autogen/User/User.entity.ts @Column({ nullable: true }) // ← I verify this is set avatar_url: string; @Column({ nullable: true }) // ← I verify this is set password_hash: string;
Fix 3: AppModule Wiring
// backend/src/app.module.ts // I ensure all auth modules are imported imports: [ UserModule, AccountModule, SessionModule, VerificationModule, OrganizationModule, // ... ]
Phase 5: Environment Setup (30 seconds)
I create
.env files:
# .env.development NODE_ENV=development PORT=3001 # Database DATABASE_URL=postgresql://postgres:postgres@localhost:5433/backend_dev # BetterAuth (I generate secure secrets) BETTER_AUTH_SECRET=generated-32-char-secret BETTER_AUTH_URL=http://localhost:3001 # CORS ALLOWED_ORIGINS=http://localhost:3000,http://localhost:3003
Phase 6: Database Initialization (1 minute)
# Start PostgreSQL via Docker docker-compose up -d # Run migrations (TypeORM sync) npm run start:dev # Verify tables created psql -U postgres -d backend_dev -c "\dt"
Expected tables:
useraccountsessionverificationorganizationaccount_user
Phase 7: Verification & Testing (1 minute)
I run these tests automatically:
Test 1: Server Health
curl http://localhost:3001/health # Expected: {"status": "ok"}
Test 2: User Signup
curl -X POST http://localhost:3001/Users \ -H "Content-Type: application/json" \ -d '{ "id": "generated-uuid", "email": "test@example.com", "name": "Test User", "email_verified": false }' # Expected: User object with ID
Test 3: Database Verification
SELECT id, email, name, email_verified FROM "user"; SELECT id, "userId", "providerId" FROM account; SELECT COUNT(*) FROM organization;
Test 4: CRUD Operations
# GET all users curl http://localhost:3001/Users # GET user by ID curl http://localhost:3001/Users/{id} # UPDATE user curl -X PATCH http://localhost:3001/Users/{id} \ -d '{"name": "Updated Name"}' # DELETE user curl -X DELETE http://localhost:3001/Users/{id}
Complete .apsorc Templates
I provide ready-to-use templates in
references/apsorc-templates/:
1. minimal-auth.json
Use for: Simple apps with just authentication Includes: User, account, session, verification, Organization
2. saas-platform.json
Use for: Full SaaS with multi-tenancy Includes: Auth + Organization + Projects + Billing + Audit logs
3. marketplace.json
Use for: Multi-vendor platforms Includes: Auth + Vendors + Products + Orders + Reviews
4. collaboration-tool.json
Use for: Team collaboration apps Includes: Auth + Workspaces + Channels + Messages + Files
Common Issues I Auto-Fix
Issue 1: "null value in column 'avatar_url' violates not-null constraint"
What I do:
- Check
for nullable settingsUser.entity.ts - Update to
@Column({ nullable: true }) - Drop and recreate database schema
- Verify with test insert
Script:
references/fix-scripts/fix-nullable-fields.sh
Issue 2: "null value in column 'id' of relation 'account'"
What I do:
- Add
field toid
DTOaccountCreate - Add
field toid
DTOUserCreate - Add
validator@IsUUID() - Regenerate OpenAPI docs
Script:
references/fix-scripts/fix-dto-id-fields.sh
Issue 3: "Entity 'Account' conflicts with Better Auth"
What I do:
- Detect conflict in .apsorc parsing
- Rename
→AccountOrganization - Update all foreign key references
- Update entity descriptions
- Regenerate code
Script:
references/fix-scripts/fix-entity-conflicts.sh
Issue 4: "AppModule doesn't import auth entities"
What I do:
- Parse AppModule imports
- Add missing module imports
- Verify module wiring
- Test module loading
Script:
references/fix-scripts/fix-app-module.sh
Environment Variables Management
I manage these environment files:
.env.development
.env.developmentNODE_ENV=development PORT=3001 DATABASE_URL=postgresql://postgres:postgres@localhost:5433/backend_dev BETTER_AUTH_SECRET=dev-secret-min-32-chars BETTER_AUTH_URL=http://localhost:3001 ALLOWED_ORIGINS=http://localhost:3000,http://localhost:3003 LOG_LEVEL=debug
.env.test
.env.testNODE_ENV=test PORT=3002 DATABASE_URL=postgresql://postgres:postgres@localhost:5433/backend_test BETTER_AUTH_SECRET=test-secret-min-32-chars LOG_LEVEL=error
.env.production
(template)
.env.productionNODE_ENV=production PORT=3001 DATABASE_URL=${DATABASE_URL} # From AWS RDS BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET} # From AWS Secrets Manager BETTER_AUTH_URL=https://api.yourdomain.com ALLOWED_ORIGINS=https://yourdomain.com LOG_LEVEL=info
Verification Checklist
Before marking setup as complete, I verify:
Backend Services:
- Server starts without errors (port 3001)
- Database connection successful
- All tables created in database
- OpenAPI docs accessible at /api/docs
- Health endpoint returns 200
Entity Endpoints:
- GET /Users returns 200
- POST /Users creates user
- GET /accounts returns 200
- GET /sessions returns 200
- GET /verifications returns 200
- GET /Organizations returns 200
Authentication Flow:
- User signup creates user + account
- User signin validates credentials
- Session creation works
- Token validation works
- Password hashing works
Multi-Tenancy (via scopeBy):
- Organization auto-created on signup
- User-Organization link created
- Queries scoped to organizationId via ScopeGuard
- Cross-tenant access blocked by scope verification
Data Integrity:
- Foreign keys enforced
- Unique constraints work
- Nullable fields accept null
- Required fields reject null
- Enums validate values
Generated API Documentation
After setup, you get interactive docs at
http://localhost:3001/api/docs
Endpoints per entity:
- List all (paginated, filtered)GET /{entity}
- Get by IDGET /{entity}/{id}
- Create newPOST /{entity}
- Full updatePUT /{entity}/{id}
- Partial updatePATCH /{entity}/{id}
- DeleteDELETE /{entity}/{id}
Built-in features:
- Pagination:
?page=1&limit=10 - Sorting:
?sort=created_at&order=desc - Filtering:
?status=active - Search:
?search=keyword - Relations:
?include=organization,user
File Structure Created
backend/ ├── src/ │ ├── autogen/ # ⚠️ NEVER MODIFY - Auto-generated by Apso │ │ ├── User/ │ │ │ ├── User.entity.ts │ │ │ ├── User.controller.ts │ │ │ ├── User.service.ts │ │ │ └── dtos/User.dto.ts │ │ ├── account/ │ │ ├── session/ │ │ ├── verification/ │ │ ├── Organization/ │ │ └── guards/ # ⚠️ AUTO-GENERATED - Auth & scope guards │ │ ├── auth.guard.ts # AuthGuard for session validation │ │ ├── scope.guard.ts # ScopeGuard for multi-tenant data isolation │ │ ├── guards.module.ts # NestJS module for guards │ │ └── index.ts # Barrel exports │ │ │ ├── extensions/ # ✅ Your custom code (safe to modify) │ │ ├── auth/ │ │ │ ├── auth.decorator.ts │ │ │ └── auth.service.ts │ │ └── organization/ │ │ └── organization.hooks.ts │ │ │ ├── common/ │ │ ├── filters/ │ │ ├── interceptors/ │ │ └── pipes/ │ │ │ ├── app.module.ts │ └── main.ts │ ├── test/ │ ├── e2e/ │ │ ├── auth.e2e-spec.ts │ │ └── users.e2e-spec.ts │ └── unit/ │ ├── .apsorc # Schema definition ├── .env.development ├── .env.test ├── docker-compose.yml ├── package.json └── README.md
Important: Guards are now generated inside
src/autogen/guards/ to clearly indicate they are auto-generated and should not be manually edited. All files in autogen/ are overwritten on every apso server scaffold run.
Troubleshooting Commands
I provide these commands for debugging:
# Check database connection npm run db:ping # View all tables npm run db:tables # Run migrations npm run db:migrate # Seed test data npm run db:seed # Reset database npm run db:reset # View logs npm run logs # Test all endpoints npm run test:e2e # Generate new migration npm run migration:generate -- -n AddAuthTables
CRITICAL: Better Auth Architecture
Understanding how Better Auth stores credentials is essential for debugging!
┌──────────────────────────────────────────────────────────────────────────┐ │ Better Auth Data Model │ ├──────────────────────────────────────────────────────────────────────────┤ │ │ │ User table: account table: │ │ ┌────────────────┐ ┌─────────────────────────────┐ │ │ │ id │ │ id │ │ │ │ email │───────│ userId │ │ │ │ name │ 1:N │ providerId = "credential" │ ← CRITICAL! │ │ │ email_verified │ │ password (bcrypt hash) │ ← Password! │ │ │ avatar_url │ │ accountId │ │ │ └────────────────┘ └─────────────────────────────┘ │ │ │ │ KEY INSIGHT: Passwords are in the ACCOUNT table, NOT the User table! │ │ │ │ Sign-in flow: │ │ 1. Better Auth calls: findUserByEmail(email, { includeAccounts: true }) │ │ 2. Adapter returns user WITH accounts array populated │ │ 3. Better Auth finds: user.accounts.find(a => a.providerId === "credential") │ 4. Password verified against account.password (bcrypt) │ │ │ │ If providerId is undefined/null → Login ALWAYS fails! │ │ │ └──────────────────────────────────────────────────────────────────────────┘
Why Signup Works But Login Fails
The most common issue is: signup succeeds but login fails with "Invalid email or password".
Root Cause: The
account.providerId field is not being set to "credential" during account creation, OR the adapter isn't returning it correctly during user lookup.
Solution:
- Use
or higher@apso/better-auth-adapter@2.0.2 - Ensure
has.apsorc
field in account entityproviderId - Verify database:
should showSELECT "providerId" FROM account;"credential"
Integration with Frontend
After backend setup, I guide you to:
-
Install BetterAuth adapter in frontend (CRITICAL: use v2.0.2+):
cd frontend npm install better-auth @apso/better-auth-adapter@latest -
Configure auth client:
// frontend/lib/auth.ts import { betterAuth } from 'better-auth'; import { createApsoAdapter } from '@apso/better-auth-adapter'; export const auth = betterAuth({ database: createApsoAdapter({ baseUrl: process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:3001', }), emailAndPassword: { enabled: true }, }); -
Test end-to-end flow (BOTH signup AND login!):
- Frontend signup → Backend creates user + account with providerId="credential"
- Frontend signin → Backend validates via account.password (NOT user.password_hash!)
- Frontend protected route → Backend validates token
Reference Documentation
All in
references/:
- Complete .apsorc examplesapsorc-templates/
- Automated fix scriptsfix-scripts/
- Test commandsverification-commands/
- Common issues & solutionstroubleshooting/
- Complete auth guidebetter-auth-integration.md
Success Metrics
Setup time: < 5 minutes from start to working API Manual steps: 0 (fully automated) Error rate: < 5% (auto-fixes handle most issues) Test coverage: 100% of CRUD endpoints verified
Ready to Start?
Just say:
- "Setup backend with auth" - Complete new backend
- "Add auth to backend" - Add to existing backend
- "Fix auth issues" - Debug current setup
- "Verify backend" - Run all checks
I'll handle everything automatically and show you exactly what's happening at each step.