FitAiid provides a secure authentication system with multiple registration and login options, including traditional email/password authentication and Google OAuth integration.
Authentication Methods
FitAiid supports two primary authentication methods:
Email/Password Traditional registration with email verification code
Google OAuth One-click authentication with Google account
User Registration
Registration with Email
The email registration flow uses a two-step verification process to ensure account security.
Submit Registration Form
Users fill out the registration form with their personal information: frontend/scripts/register.js
const userData = {
firstName: 'John' ,
lastName: 'Doe' ,
email: '[email protected] ' ,
password: 'SecurePass123!' ,
phone: '1234567890'
};
const response = await fetch ( ` ${ API_URL } /api/auth/register-with-code` , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ( userData )
});
The frontend validates:
Name fields (letters only, 2-50 characters)
Phone number (exactly 10 digits)
Email format
Password strength (minimum 6 characters)
Receive Verification Code
The backend sends a 6-digit verification code to the user’s email: backend/src/controllers/authController.js
const verificationCode = Math . floor ( 100000 + Math . random () * 900000 ). toString ();
await savePendingVerification ( email , verificationCode , userData );
await sendVerificationCodeEmail ( email , firstName , verificationCode );
The user data is stored temporarily and NOT saved to MongoDB until the code is verified. The verification code expires in 15 minutes.
Verify Code and Create Account
Users enter the 6-digit code to complete registration: backend/src/controllers/authController.js
const verification = await getPendingVerification ( email );
if ( verification . code === code ) {
const user = new User ({
... verification . userData ,
isEmailVerified: true ,
isActive: true
});
await user . save ();
const token = user . generateAuthToken ();
// Return JWT token and user profile
}
Store Authentication Token
The client stores the JWT token and user information: localStorage . setItem ( 'token' , data . token );
localStorage . setItem ( 'userId' , data . user . _id );
localStorage . setItem ( 'user' , JSON . stringify ( data . user ));
Registration with Google
Google OAuth provides a streamlined registration experience.
Initialize Firebase Authentication
The frontend initializes Firebase with Google provider: frontend/pages/register.html
import { initializeApp } from 'firebase/app' ;
import { getAuth , GoogleAuthProvider , signInWithPopup } from 'firebase/auth' ;
const app = initializeApp ( firebaseConfig );
const auth = getAuth ( app );
const provider = new GoogleAuthProvider ();
Authenticate with Google
User clicks “Continue with Google” button: const result = await signInWithPopup ( auth , provider );
const { displayName , email , uid } = result . user ;
Register in Backend
The frontend sends Google user data to create MongoDB account: const response = await fetch ( ` ${ API_URL } /api/auth/google-register` , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ({
firstName: displayName . split ( ' ' )[ 0 ],
lastName: displayName . split ( ' ' ). slice ( 1 ). join ( ' ' ),
email: email ,
uid: uid
})
});
Google users are automatically marked as email verified and receive a temporary password GoogleTemp123.
User Login
Login with Email/Password
Standard authentication flow with rate limiting and account lockout protection.
Frontend Request
Backend Controller
const credentials = {
email: '[email protected] ' ,
password: 'myPassword123'
};
const response = await fetch ( ` ${ API_URL } /api/auth/login` , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ( credentials )
});
const data = await response . json ();
if ( data . success ) {
localStorage . setItem ( 'token' , data . data . token );
localStorage . setItem ( 'user' , JSON . stringify ( data . data . user ));
window . location . href = 'home.html' ;
}
After 5 failed login attempts, the account is locked for 30 minutes to prevent brute force attacks.
Login with Google
Google login requires the user to already have an account registered.
backend/src/controllers/authController.js
const googleLogin = async ( req , res ) => {
const { email , uid } = req . body ;
// Search for existing user in MongoDB
let user = await User . findOne ({ email: email . toLowerCase () });
// Reject if user not registered
if ( ! user ) {
throw new AppError ( 'Este correo no está registrado. Por favor regístrate primero.' , 404 );
}
// Verify account is active
if ( ! user . isActive ) {
throw new AppError ( 'Tu cuenta ha sido desactivada' , 401 );
}
// Generate JWT and return user data
const token = user . generateAuthToken ();
const publicProfile = user . getPublicProfile ();
res . status ( 200 ). json ({
success: true ,
message: 'Inicio de sesión con Google exitoso' ,
token ,
user: publicProfile
});
};
Password Recovery
FitAiid provides a secure password recovery system using verification codes.
Request Reset Code
User enters their email address: const response = await fetch ( ` ${ API_URL } /api/auth/forgot-password` , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ({ email: '[email protected] ' })
});
The backend generates a 6-digit code and hashes it before saving: backend/src/controllers/authController.js
const resetCode = Math . floor ( 100000 + Math . random () * 900000 ). toString ();
const resetCodeHash = crypto
. createHash ( 'sha256' )
. update ( resetCode )
. digest ( 'hex' );
user . resetPasswordCode = resetCodeHash ;
user . resetPasswordExpire = Date . now () + 15 * 60 * 1000 ; // 15 minutes
await user . save ();
Verify Reset Code
User enters the 6-digit code received via email: await fetch ( ` ${ API_URL } /api/auth/verify-code` , {
method: 'POST' ,
body: JSON . stringify ({ email , code })
});
Set New Password
User submits new password (minimum 8 characters): backend/src/controllers/authController.js
const resetPassword = async ( req , res ) => {
const { email , code , password } = req . body ;
if ( password . length < 8 ) {
throw new AppError ( 'La contraseña debe tener al menos 8 caracteres' , 400 );
}
const codeHash = crypto . createHash ( 'sha256' ). update ( code ). digest ( 'hex' );
const user = await User . findOne ({
email: email . toLowerCase (),
resetPasswordCode: codeHash ,
resetPasswordExpire: { $gt: Date . now () }
});
if ( ! user ) {
throw new AppError ( 'Código inválido o expirado' , 400 );
}
// Update password (automatically hashed by User model)
user . password = password ;
user . resetPasswordCode = undefined ;
user . resetPasswordExpire = undefined ;
await user . save ();
};
Authentication Middleware
All protected routes use JWT authentication middleware:
backend/src/middleware/auth.js
const protect = async ( req , res , next ) => {
let token ;
if ( req . headers . authorization ?. startsWith ( 'Bearer' )) {
token = req . headers . authorization . split ( ' ' )[ 1 ];
}
if ( ! token ) {
throw new AppError ( 'No autorizado. Token requerido' , 401 );
}
try {
const decoded = jwt . verify ( token , process . env . JWT_SECRET );
req . user = await User . findById ( decoded . id ). select ( '-password' );
next ();
} catch ( error ) {
throw new AppError ( 'Token inválido o expirado' , 401 );
}
};
UI Components
The login page features a split-screen design with:
Left Panel
Animated gym background image with zoom effect
FitAiid logo with gradient styling
Motivational hero text with gradient effects
Red accent stripes and grid overlay
Right Panel
Login form with email and password fields
Password visibility toggle
Forgot password link
Google sign-in button with hover effects
Link to registration page
Security Features
Rate Limiting API requests are rate-limited to prevent abuse
Account Lockout After 5 failed attempts, accounts lock for 30 minutes
Password Hashing Passwords are hashed using bcrypt before storage
JWT Tokens Secure token-based authentication for API requests
API Endpoints
Endpoint Method Description Auth Required /api/auth/register-with-codePOST Register with email verification No /api/auth/verify-registrationPOST Verify registration code No /api/auth/google-registerPOST Register with Google No /api/auth/loginPOST Login with email/password No /api/auth/googlePOST Login with Google No /api/auth/forgot-passwordPOST Request password reset code No /api/auth/verify-codePOST Verify reset code No /api/auth/reset-passwordPOST Set new password No /api/auth/profileGET Get user profile Yes /api/auth/profilePUT Update user profile Yes
All authentication endpoints include comprehensive logging and audit trails for security monitoring.