- Updated the backend to support token-based authentication, replacing basic auth. - Added session management functions for creating, invalidating, and refreshing sessions. - Refactored user routes to include login and logout endpoints. - Modified frontend to handle token storage and session validation. - Improved user experience by ensuring sessions are invalidated upon password changes.
179 lines
4.2 KiB
JavaScript
179 lines
4.2 KiB
JavaScript
// Servicio de autenticación para gestionar tokens
|
|
|
|
const AUTH_STORAGE_KEY = 'wallabicher_token';
|
|
const USERNAME_STORAGE_KEY = 'wallabicher_username';
|
|
|
|
class AuthService {
|
|
constructor() {
|
|
this.token = this.loadToken();
|
|
this.username = this.loadUsername();
|
|
}
|
|
|
|
// Cargar token desde localStorage
|
|
loadToken() {
|
|
try {
|
|
return localStorage.getItem(AUTH_STORAGE_KEY) || '';
|
|
} catch (error) {
|
|
console.error('Error cargando token:', error);
|
|
return '';
|
|
}
|
|
}
|
|
|
|
// Cargar username desde localStorage
|
|
loadUsername() {
|
|
try {
|
|
return localStorage.getItem(USERNAME_STORAGE_KEY) || '';
|
|
} catch (error) {
|
|
console.error('Error cargando username:', error);
|
|
return '';
|
|
}
|
|
}
|
|
|
|
// Guardar token y username en localStorage
|
|
saveSession(token, username) {
|
|
try {
|
|
this.token = token;
|
|
this.username = username;
|
|
localStorage.setItem(AUTH_STORAGE_KEY, token);
|
|
localStorage.setItem(USERNAME_STORAGE_KEY, username);
|
|
return true;
|
|
} catch (error) {
|
|
console.error('Error guardando sesión:', error);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Eliminar token y username
|
|
clearSession() {
|
|
try {
|
|
this.token = '';
|
|
this.username = '';
|
|
localStorage.removeItem(AUTH_STORAGE_KEY);
|
|
localStorage.removeItem(USERNAME_STORAGE_KEY);
|
|
return true;
|
|
} catch (error) {
|
|
console.error('Error eliminando sesión:', error);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Obtener token actual
|
|
getToken() {
|
|
return this.token;
|
|
}
|
|
|
|
// Obtener username actual
|
|
getUsername() {
|
|
return this.username;
|
|
}
|
|
|
|
// Verificar si hay sesión activa (token guardado)
|
|
hasCredentials() {
|
|
return !!this.token;
|
|
}
|
|
|
|
// Generar header de autenticación Bearer
|
|
getAuthHeader() {
|
|
if (!this.token) {
|
|
return null;
|
|
}
|
|
return `Bearer ${this.token}`;
|
|
}
|
|
|
|
// Hacer login (llamar al endpoint de login)
|
|
async login(username, password) {
|
|
try {
|
|
const response = await fetch('/api/users/login', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({ username, password }),
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (!response.ok) {
|
|
throw new Error(data.error || 'Error en login');
|
|
}
|
|
|
|
if (data.success && data.token) {
|
|
this.saveSession(data.token, data.username);
|
|
return { success: true, token: data.token, username: data.username };
|
|
}
|
|
|
|
throw new Error('Respuesta inválida del servidor');
|
|
} catch (error) {
|
|
console.error('Error en login:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// Hacer logout (llamar al endpoint de logout)
|
|
async logout() {
|
|
try {
|
|
const token = this.token;
|
|
|
|
if (token) {
|
|
try {
|
|
await fetch('/api/users/logout', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Authorization': `Bearer ${token}`,
|
|
'Content-Type': 'application/json',
|
|
},
|
|
});
|
|
} catch (error) {
|
|
// Si falla el logout en el servidor, aún así limpiar localmente
|
|
console.error('Error al cerrar sesión en el servidor:', error);
|
|
}
|
|
}
|
|
|
|
this.clearSession();
|
|
return true;
|
|
} catch (error) {
|
|
console.error('Error en logout:', error);
|
|
this.clearSession(); // Limpiar localmente de todas formas
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Verificar si el token sigue siendo válido
|
|
async validateSession() {
|
|
if (!this.token) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
const response = await fetch('/api/users/me', {
|
|
method: 'GET',
|
|
headers: {
|
|
'Authorization': `Bearer ${this.token}`,
|
|
},
|
|
});
|
|
|
|
if (response.ok) {
|
|
const data = await response.json();
|
|
if (data.success && data.authenticated) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// Si el token es inválido, limpiar sesión
|
|
if (response.status === 401) {
|
|
this.clearSession();
|
|
}
|
|
|
|
return false;
|
|
} catch (error) {
|
|
console.error('Error validando sesión:', error);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Exportar instancia singleton
|
|
const authService = new AuthService();
|
|
export default authService;
|
|
|