Overview
Playground uses Firebase Authentication v8.10.0 to provide secure user authentication with email/password credentials. The system includes automatic session management, user validation, and secure error handling.
Authentication Flow
User Enters Credentials
User inputs username and password on the login page (login.html)
Username to Email Conversion
Firebase Authentication
Credentials are validated against Firebase Authentication service
Session Initialization
Upon success, user session is created with an 8-hour timeout timer
Redirect to Dashboard
User is redirected to index.html with full module access
Firebase Configuration
Configuration Structure
The Firebase configuration is initialized in both scriptLogin.js and Autorizacion.js:
const firebaseConfig = {
apiKey: "YOUR_FIREBASE_API_KEY" ,
authDomain: "playgroundbdstop.firebaseapp.com" ,
databaseURL: "https://playgroundbdstop-default-rtdb.firebaseio.com" ,
projectId: "playgroundbdstop" ,
storageBucket: "playgroundbdstop.appspot.com" ,
messagingSenderId: "YOUR_MESSAGING_SENDER_ID" ,
appId: "YOUR_FIREBASE_APP_ID"
};
// Initialize Firebase
if ( ! firebase . apps . length ) {
firebase . initializeApp ( firebaseConfig );
}
Production Security: In production environments, store Firebase credentials in environment variables or secure configuration management systems. Never commit real API keys to public repositories.
Required Firebase Services
Playground requires these Firebase services:
Authentication Email/Password sign-in method enabled
Realtime Database For storing and syncing application data
Login Implementation
The login form in login.html includes:
< div class = "login-container" >
< img src = "LogoLogin.png" alt = "Descripción de la imagen" id = "LogoLogin" >
< div id = "Formulario" >
< h2 > Iniciar sesión </ h2 >
< form id = "login-form" >
< div class = "input-group" >
< label for = "username" > Usuario </ label >
< input type = "text" id = "username" name = "username"
autocomplete = "username" required >
</ div >
< div class = "input-group" >
< label for = "password" > Contraseña </ label >
< input type = "password" id = "password" name = "password"
autocomplete = "current-password" required >
</ div >
< button type = "submit" > Ingresar </ button >
</ form >
< div id = "error-message" class = "error-message" style = "display: none;" ></ div >
</ div >
</ div >
<!-- Loading Screen -->
< div id = "loading-screen" style = "display: none;" >
< div class = "spinner" ></ div >
< p > Cargando... </ p >
</ div >
Authentication Logic
The complete authentication flow in scriptLogin.js:
document . addEventListener ( 'DOMContentLoaded' , () => {
const form = document . getElementById ( 'login-form' );
const loadingScreen = document . getElementById ( 'loading-screen' );
const errorMessage = document . getElementById ( 'error-message' );
if ( form ) {
form . addEventListener ( 'submit' , async ( e ) => {
e . preventDefault ();
loadingScreen . style . display = 'flex' ; // Show loading screen
errorMessage . style . display = 'none' ; // Hide error message
const username = document . getElementById ( 'username' ). value . trim ();
const password = document . getElementById ( 'password' ). value ;
// Store user's display name
localStorage . setItem ( 'nombreAsesorActual' ,
agentesA [ username ]?. nombre || 'Usuario Desconocido' );
try {
const user = await authenticateUser ( username , password );
console . log ( 'User logged in:' , user );
window . location . href = 'index.html' ;
} catch ( error ) {
console . error ( 'Authentication error:' , error );
errorMessage . textContent = getErrorMessage ( error );
errorMessage . style . display = 'block' ;
loadingScreen . style . display = 'none' ;
}
});
}
});
User Authentication Function
async function authenticateUser ( username , password ) {
// Validate username format
if ( ! validateUsername ( username )) {
throw new Error ( 'auth/invalid-username' );
}
// Convert username to email format
const email = ` ${ username } @playground.com` ;
try {
const userCredential = await firebase . auth ()
. signInWithEmailAndPassword ( email , password );
return userCredential . user ;
} catch ( error ) {
// Handle specific Firebase errors
if ( error . code === 'auth/user-not-found' ) {
throw new Error ( 'auth/user-not-found' );
} else if ( error . code === 'auth/wrong-password' ) {
throw new Error ( 'auth/wrong-password' );
} else if ( error . code === 'auth/invalid-email' ) {
throw new Error ( 'auth/invalid-email' );
} else {
throw new Error ( 'auth/generic-error' );
}
}
}
Username Validation
Usernames must meet specific format requirements:
function validateUsername ( username ) {
// Allow alphanumeric characters and dots only
const usernameRegex = / ^ [ a-zA-Z0-9. ] + $ / ;
return usernameRegex . test ( username );
}
Valid usernames: john.doe, user123, admin
Invalid usernames: user@name, user name, user_name
Error Handling
Error Messages
User-friendly error messages in Spanish:
function getErrorMessage ( error ) {
switch ( error . message ) {
case 'auth/user-not-found' :
return 'No se encontró ningún usuario con estas credenciales.' ;
case 'auth/wrong-password' :
return 'Contraseña incorrecta.' ;
case 'auth/invalid-email' :
return 'Formato de correo electrónico no válido.' ;
case 'auth/invalid-username' :
return 'Formato de usuario no válido.' ;
default :
return 'Fallo de autenticación. Por favor, inténtelo de nuevo.' ;
}
}
Error Display
.error-message {
margin-top : 10 px ;
padding : 10 px ;
background-color : #f8d7da ; /* Light red background */
color : #721c24 ; /* Dark red text */
border : 1 px solid #f5c6cb ;
border-radius : 4 px ;
font-family : 'Nunito' , sans-serif ;
font-size : 14 px ;
}
User Management
User Registry
Active users are defined in the agentesA object:
let agentesA = {
"andres.yepes" : { nombre: "Andrés_Felipe_Yepes_Tascón" },
"judy.buitrago" : { nombre: "Judy_Andrea_Buitrago_Solis" },
"yeison.torres" : { nombre: "Yeison_Torres_Ochoa" },
"maria.ospina" : { nombre: "Maria_Susana_Ospina_Vanegas" },
"ocaris.arango" : { nombre: "Ocaris_David_Arango_Aguilar" },
"johan.guzman" : { nombre: "Johan_Guzman_Alarcon" },
"diego.usuga" : { nombre: "Diego_Alejandro_Úsuga_Yepes" },
"santiago.ramirez" : { nombre: "Santiago_Ramirez_Guzman" }
};
Important: Users must exist in both Firebase Authentication AND the agentesA registry to access the application.
Adding New Users
Create in Firebase Console
Navigate to Firebase Console → Authentication → Users → Add user
Update User Registry
Add to agentesA object in scriptLogin.js: "new.user" : { nombre: "New_User_Full_Name" }
Deploy Changes
Deploy updated JavaScript files to your hosting platform
Session Management
Authentication State Observer
The application monitors authentication state in Autorizacion.js:
firebase . auth (). onAuthStateChanged ( user => {
if ( ! user && window . location . pathname !== '/login.html' ) {
// User not authenticated, redirect to login
localStorage . removeItem ( 'nombreAsesorActual' );
window . location . href = 'login.html' ;
} else if ( user && window . location . pathname === '/login.html' ) {
// User already authenticated, redirect to dashboard
window . location . href = 'index.html' ;
}
});
8-Hour Auto Logout
Automatic session timeout for security:
let signOutTimer = null ;
function scheduleSignOutEveryEightHours () {
// Clear previous timer
if ( signOutTimer ) {
clearTimeout ( signOutTimer );
signOutTimer = null ;
}
// Calculate 8 hours in milliseconds
const eightHoursInMs = 8 * 60 * 60 * 1000 ;
console . log ( `Programando cierre de sesión en 8 horas ( ${ new Date ( Date . now () + eightHoursInMs ). toLocaleString () } )` );
signOutTimer = setTimeout (() => {
firebase . auth (). signOut (). then (() => {
console . log ( 'Usuario desconectado automáticamente después de 8 horas.' );
localStorage . removeItem ( 'lastLoginDate' );
localStorage . removeItem ( 'nombreAsesorActual' );
window . location . href = 'login.html' ;
}). catch ( error => {
console . error ( 'Error al cerrar sesión:' , error );
});
// Reschedule for next 8 hours
scheduleSignOutEveryEightHours ();
}, eightHoursInMs );
}
// Initialize on page load
scheduleSignOutEveryEightHours ();
The timer is reset when the page loads, but persists across navigation within the application.
Cleanup on Page Unload
window . addEventListener ( 'beforeunload' , () => {
if ( signOutTimer ) {
clearTimeout ( signOutTimer );
}
});
Manual Logout
Logout Implementation
Users can manually log out via the user menu:
document . getElementById ( 'btnCerrarSesion' ). addEventListener ( 'click' , () => {
firebase . auth (). signOut (). then (() => {
console . log ( 'User signed out.' );
window . location . href = 'login.html' ;
}). catch ( error => {
console . error ( 'Sign out error:' , error );
});
});
Logout Modal
Modal confirmation for logout:
< div id = "myModal2" class = "modal" >
< div class = "modal-content2" >
< span id = "close2" style = "position: absolute; right: 1; top: 0;" > × </ span >
< div id = "modal-content2" style = "display: flex; flex-direction: column; align-items: center; gap:10px;" >
< h2 > ¿Quiere cerrar la sesión? </ h2 >
< button id = "btnCerrarSesion" > Cerrar sesión </ button >
</ div >
</ div >
</ div >
LocalStorage Management
Authentication-related data stored in localStorage:
Key Purpose Example Value nombreAsesorActualDisplay name of logged-in user Andrés_Felipe_Yepes_TascónlastLoginDateTimestamp of last login 2024-03-04T10:30:00.000Zpreferencias_[username]User-specific theme preferences {colorPrimario: "#e69500", ...}
Clearing User Data on Logout
firebase . auth (). signOut (). then (() => {
localStorage . removeItem ( 'nombreAsesorActual' );
localStorage . removeItem ( 'lastLoginDate' );
// Note: User preferences are preserved
window . location . href = 'login.html' ;
});
Security Best Practices
Firebase enforces default password policies:
Minimum 6 characters
Recommended: Use strong passwords with mixed case, numbers, and symbols
8-hour automatic timeout
Session state monitored across all pages
Automatic redirect on session expiration
Username converted to standardized email format
Regex validation prevents injection attacks
Firebase validates email format server-side
Generic error messages prevent user enumeration
Detailed errors only logged to console
User-friendly Spanish messages for end users
Firebase Security Rules
Recommended Realtime Database security rules:
{
"rules" : {
".read" : "auth != null" ,
".write" : "auth != null" ,
"users" : {
"$uid" : {
".read" : "auth.uid === $uid" ,
".write" : "auth.uid === $uid"
}
}
}
}
Production Deployment: Always configure proper security rules before deploying to production. The default test mode allows unrestricted access.
Troubleshooting Authentication Issues
Error: Formato de usuario no válidoCause: Username contains invalid charactersSolution: Use only alphanumeric characters and dots (a-z, A-Z, 0-9, .)
Error: No se encontró ningún usuario con estas credencialesCauses:
User doesn’t exist in Firebase Authentication
Typo in username
Email format conversion error
Solution: Verify user exists in Firebase Console and username is correct
Error: Contraseña incorrectaCauses:
Incorrect password
Caps Lock enabled
Password reset required
Solution: Verify password or use Firebase password reset
Session Expires Immediately
Advanced Configuration
Custom Session Duration
To modify the 8-hour timeout:
// Change from 8 hours to custom duration
const sessionDurationMs = 12 * 60 * 60 * 1000 ; // 12 hours
function scheduleSignOutEveryEightHours () {
if ( signOutTimer ) {
clearTimeout ( signOutTimer );
signOutTimer = null ;
}
signOutTimer = setTimeout (() => {
firebase . auth (). signOut (). then (() => {
console . log ( 'Session expired' );
localStorage . removeItem ( 'lastLoginDate' );
localStorage . removeItem ( 'nombreAsesorActual' );
window . location . href = 'login.html' ;
});
}, sessionDurationMs );
}
Multi-Factor Authentication (Future)
Firebase supports MFA for enhanced security:
// Example MFA implementation (not currently active)
import { getAuth , multiFactor } from "firebase/auth" ;
const auth = getAuth ();
const user = auth . currentUser ;
const multiFactorUser = multiFactor ( user );
// Configure MFA...
API Reference
Firebase Auth Methods Used
Method Purpose firebase.initializeApp(config)Initialize Firebase with configuration firebase.auth().signInWithEmailAndPassword(email, password)Sign in user with credentials firebase.auth().signOut()Sign out current user firebase.auth().onAuthStateChanged(callback)Monitor authentication state changes
Next Steps
User Preferences Learn about user-specific theme and configuration options
Core Features Explore available features after authentication
Firebase Console Manage users and authentication settings
Firebase Integration Learn about Firebase integration and security