tl-shared-security
Version:
Enterprise-grade security module for frontend and backend applications with comprehensive protection against XSS, CSRF, SQL injection, and other security vulnerabilities
186 lines • 6.06 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.secureStorage = exports.SecureStorage = void 0;
class SecureStorage {
constructor(options) {
this.options = {
prefix: 'secure_',
encryptionKey: '',
useSessionStorage: false,
expiryInMinutes: 60, // 1 hour
...options,
};
// Check if we're in a browser environment
this.storage = typeof window !== 'undefined'
? (this.options.useSessionStorage ? window.sessionStorage : window.localStorage)
: null;
}
/**
* Sets an item in secure storage
* @param key - Storage key
* @param value - Value to store
* @param customExpiry - Custom expiry time in minutes
*/
setItem(key, value, customExpiry) {
if (!this.storage)
return;
try {
const prefixedKey = this.getPrefixedKey(key);
const expiryTime = Date.now() + ((customExpiry || this.options.expiryInMinutes) * 60 * 1000);
const dataToStore = {
value,
expiry: expiryTime,
};
const serialized = JSON.stringify(dataToStore);
const encrypted = this.options.encryptionKey
? this.encrypt(serialized, this.options.encryptionKey)
: serialized;
this.storage.setItem(prefixedKey, encrypted);
}
catch (error) {
console.error('Error setting secure storage item:', error);
}
}
/**
* Gets an item from secure storage
* @param key - Storage key
* @param defaultValue - Default value if item doesn't exist
* @returns Stored value or default value
*/
getItem(key, defaultValue) {
if (!this.storage)
return defaultValue;
try {
const prefixedKey = this.getPrefixedKey(key);
const encrypted = this.storage.getItem(prefixedKey);
if (!encrypted)
return defaultValue;
const serialized = this.options.encryptionKey
? this.decrypt(encrypted, this.options.encryptionKey)
: encrypted;
const data = JSON.parse(serialized);
// Check if expired
if (data.expiry && data.expiry < Date.now()) {
this.removeItem(key);
return defaultValue;
}
return data.value;
}
catch (error) {
console.error('Error getting secure storage item:', error);
return defaultValue;
}
}
/**
* Removes an item from secure storage
* @param key - Storage key
*/
removeItem(key) {
if (!this.storage)
return;
try {
const prefixedKey = this.getPrefixedKey(key);
this.storage.removeItem(prefixedKey);
}
catch (error) {
console.error('Error removing secure storage item:', error);
}
}
/**
* Clears all items from secure storage with the configured prefix
*/
clear() {
if (!this.storage)
return;
try {
const keysToRemove = [];
for (let i = 0; i < this.storage.length; i++) {
const key = this.storage.key(i);
if (key && key.startsWith(this.options.prefix)) {
keysToRemove.push(key);
}
}
keysToRemove.forEach(key => this.storage?.removeItem(key));
}
catch (error) {
console.error('Error clearing secure storage:', error);
}
}
/**
* Gets all keys in secure storage with the configured prefix
* @returns Array of keys
*/
getAllKeys() {
if (!this.storage)
return [];
try {
const keys = [];
for (let i = 0; i < this.storage.length; i++) {
const key = this.storage.key(i);
if (key && key.startsWith(this.options.prefix)) {
keys.push(key.slice(this.options.prefix.length));
}
}
return keys;
}
catch (error) {
console.error('Error getting secure storage keys:', error);
return [];
}
}
/**
* Removes expired items from secure storage
*/
removeExpiredItems() {
if (!this.storage)
return;
try {
const keys = this.getAllKeys();
keys.forEach(key => {
this.getItem(key); // This will remove the item if expired
});
}
catch (error) {
console.error('Error removing expired items:', error);
}
}
getPrefixedKey(key) {
return `${this.options.prefix}${key}`;
}
encrypt(text, key) {
if (typeof window === 'undefined')
return text;
try {
// Simple XOR encryption for browser compatibility
let result = '';
for (let i = 0; i < text.length; i++) {
result += String.fromCharCode(text.charCodeAt(i) ^ key.charCodeAt(i % key.length));
}
return btoa(result);
}
catch (error) {
console.error('Encryption error:', error);
return text;
}
}
decrypt(encrypted, key) {
if (typeof window === 'undefined')
return encrypted;
try {
const text = atob(encrypted);
let result = '';
for (let i = 0; i < text.length; i++) {
result += String.fromCharCode(text.charCodeAt(i) ^ key.charCodeAt(i % key.length));
}
return result;
}
catch (error) {
console.error('Decryption error:', error);
return encrypted;
}
}
}
exports.SecureStorage = SecureStorage;
// Export default instance
exports.secureStorage = new SecureStorage();
//# sourceMappingURL=secure-storage.js.map