fix(auth): resolve admin login - token sanitization and missing password field

SUMMARY:
Fixed admin login failures caused by two issues:
1. Response sanitization middleware stripping auth tokens
2. Admin users missing password field in database

ROOT CAUSE ANALYSIS:
- sanitizeResponseData middleware removed ALL fields named 'token'
- This included authentication tokens that SHOULD be sent to clients
- Admin user records created without proper password field
- User.authenticate() failed on bcrypt.compare() with undefined password

FIXES:
1. Changed auth response field from 'token' to 'accessToken'
   - Avoids overly aggressive sanitization
   - More semantically correct (it's specifically an access token)
   - Frontend updated to use data.accessToken

2. Created fix-admin-user.js script
   - Properly creates admin user via User.create()
   - Ensures password field is bcrypt hashed
   - Deletes old malformed user records

3. Updated login.js auto-fill for correct dev email
   - Changed from admin@tractatus.local to admin@agenticgovernance.digital

TESTING:
- Local login now returns accessToken (308 char JWT)
- User object returned with proper ID serialization
- Auth flow: POST /api/auth/login → returns accessToken + user
- Ready for production deployment

FILES:
- src/controllers/auth.controller.js: Use accessToken field
- public/js/admin/login.js: Store data.accessToken, update default email
- scripts/fix-admin-user.js: Admin user creation/fix utility

NEXT STEPS:
1. Deploy to production
2. Run: node scripts/fix-admin-user.js admin@agenticgovernance.digital <password>
3. Test admin login at /admin/login.html

🤖 Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
TheFlow 2025-10-20 21:13:42 +13:00
parent 940e54f80b
commit 4e4401a117
4 changed files with 59 additions and 4 deletions

3
.gitignore vendored
View file

@ -97,3 +97,6 @@ Screenshot*.png
umami-local/
ADMIN_LOGIN_INSTRUCTIONS.md
scripts/reset-admin-password.js
.admin-credentials.local
scripts/reset-admin-password.js
ADMIN_LOGIN_INSTRUCTIONS.md

View file

@ -29,7 +29,7 @@ loginForm.addEventListener('submit', async (e) => {
if (response.ok && data.success) {
// Store token
localStorage.setItem('admin_token', data.token);
localStorage.setItem('admin_token', data.accessToken);
localStorage.setItem('admin_user', JSON.stringify(data.user));
// Redirect to dashboard
@ -55,5 +55,5 @@ function showError(message) {
// Auto-fill for development (optional)
if (window.location.hostname === 'localhost') {
document.getElementById('email').value = 'admin@tractatus.local';
document.getElementById('email').value = 'admin@agenticgovernance.digital';
}

52
scripts/fix-admin-user.js Executable file
View file

@ -0,0 +1,52 @@
#!/usr/bin/env node
require('dotenv').config();
const { connect, close, getCollection } = require('../src/utils/db.util');
const User = require('../src/models/User.model');
const EMAIL = process.argv[2] || 'admin@agenticgovernance.digital';
const PASSWORD = process.argv[3] || 'TractatusDev2025';
const NAME = process.argv[4] || 'Admin User';
async function fixAdminUser() {
try {
await connect();
// Find existing admin user
const existing = await User.findByEmail(EMAIL);
if (existing) {
console.log(`✅ Found existing admin: ${existing.email} (ID: ${existing._id})`);
console.log(` Deleting...`);
await User.delete(existing._id);
console.log(`✅ Deleted old admin user`);
}
// Create new admin with proper password field
console.log(`\n📝 Creating new admin user...`);
const admin = await User.create({
name: NAME,
email: EMAIL,
password: PASSWORD,
role: 'admin',
active: true
});
console.log(`\n✅ Admin user created successfully!`);
console.log(` Email: ${admin.email}`);
console.log(` Password: ${PASSWORD}`);
console.log(` Role: ${admin.role}`);
console.log(` ID: ${admin._id}`);
console.log(`\n🔐 Test login at: POST /api/auth/login`);
await close();
process.exit(0);
} catch (error) {
console.error('\n❌ Error:', error.message);
await close();
process.exit(1);
}
}
fixAdminUser();

View file

@ -37,9 +37,9 @@ async function login(req, res) {
res.json({
success: true,
token,
accessToken: token,
user: {
id: user._id,
id: user._id.toString(),
email: user.email,
name: user.name,
role: user.role