🚨 Shai-Hulud Strikes Again:834 Packages Compromised.Technical Analysis
Socket
Book a DemoInstallSign in
Socket

@amsom-habitat/user-manager

Package Overview
Dependencies
Maintainers
1
Versions
36
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@amsom-habitat/user-manager

Gestionnaire centralisé d'authentification utilisateur pour les applications AMSOM Habitat.

latest
npmnpm
Version
1.12.0
Version published
Weekly downloads
101
-56.28%
Maintainers
1
Weekly downloads
 
Created
Source

@amsom-habitat/user-manager

Gestionnaire centralisé d'authentification utilisateur pour les applications AMSOM Habitat.

🎯 Objectifs

  • Gestion unifiée : Gérer les utilisateurs de la même manière sur tous les outils
  • Token partagé : Partage du token JWT via cookies entre les sites du même domaine
  • Réactivité : Synchronisation bidirectionnelle automatique avec les stores (Pinia/Vue)
  • Cross-tab : Détection automatique des changements de token depuis d'autres onglets

📦 Installation

npm install @amsom-habitat/user-manager

🚀 Utilisation de base

Configuration initiale

import userManager from '@amsom-habitat/user-manager'

// Configuration (dans main.js)
userManager.setLoginPageUrl('/login')
userManager.setDefaultLoginUrl('https://api.example.com/login')
userManager.setDefaultDomain('example.com')
userManager.setRoleHierarchy({
  ROLE_ADMIN: ['ROLE_USER']
})
userManager.setRoleKey('mon-application')

Authentification

// Login
const credentials = {
  _username: 'user@example.com',
  _password: 'password123'
}

userManager.login(credentials)
  .then(token => {
    console.log('Connecté avec succès')
  })
  .catch(error => {
    console.error('Erreur de connexion:', error)
  })

// Logout
userManager.logout()

// Vérifier si connecté
if (userManager.isLogged()) {
  console.log('Utilisateur connecté')
}

// Redirection vers la page de login
userManager.goToLoginPage() // Sauvegarde l'URL actuelle pour redirection après login

Gestion du token

// Récupérer le token
const token = userManager.getToken()

// Définir un token manuellement
userManager.setToken(token, expirationTimestamp, domain)

// Décoder le token
const payload = userManager.getDecodedToken()
console.log(payload.login, payload.email, payload.roles)

// Vérifier la validité
if (userManager.isTokenValid()) {
  console.log('Token valide et non expiré')
}

// Temps restant avant expiration (en secondes)
const remaining = userManager.getTokenTimeRemaining()
console.log(`Token expire dans ${remaining} secondes`)

Gestion des rôles

// Récupérer les rôles
const roles = userManager.getRoles()

// Vérifier un rôle (avec hiérarchie)
if (userManager.isGranted('ROLE_ADMIN')) {
  console.log('Utilisateur admin')
}

⚡ Nouvelles fonctionnalités - Réactivité (v1.12.0)

Synchronisation automatique avec Pinia

// stores/user.js
import { defineStore } from 'pinia'
import userManager from '@amsom-habitat/user-manager'

let unwatchTokenCallback = null

export default defineStore('user', {
  state: () => ({
    token: userManager.getToken(),
  }),

  getters: {
    isLogged: (state) => userManager.isLogged(state.token),
    isTokenValid: (state) => userManager.isTokenValid(state.token),
    tokenTimeRemaining: (state) => userManager.getTokenTimeRemaining(state.token),
  },

  actions: {
    initTokenSync() {
      // Active la synchronisation bidirectionnelle
      unwatchTokenCallback = userManager.watchToken((newToken) => {
        if (newToken !== this.token) {
          console.log('Token synchronisé depuis userManager')
          this.token = newToken
        }
      })
    },

    stopTokenSync() {
      if (unwatchTokenCallback) {
        unwatchTokenCallback()
        unwatchTokenCallback = null
      }
    },

    logout() {
      this.token = null
      userManager.logout()
    },
  },
})

Initialisation dans l'application

// App.vue
import useUserStore from '@/stores/user'

export default {
  setup() {
    const userStore = useUserStore()
    return { userStore }
  },

  mounted() {
    // Initialise la synchronisation bidirectionnelle
    this.userStore.initTokenSync()
  },

  beforeUnmount() {
    // Nettoie les watchers
    this.userStore.stopTokenSync()
  },

  watch: {
    'userStore.token': function (newValue) {
      // Synchronisation store → userManager
      if (newValue) {
        this.$userManager.setToken(newValue)
      } else {
        this.$userManager.logout()
      }
    }
  },
}

Watchers personnalisés

// Écouter les changements de token
const unwatch = userManager.watchToken((newToken, oldToken) => {
  console.log('Token changé:', {
    from: oldToken ? 'token présent' : 'pas de token',
    to: newToken ? 'token présent' : 'pas de token'
  })

  // Réagir au changement
  if (!newToken) {
    // Utilisateur déconnecté
    router.push('/login')
  }
})

// Arrêter l'écoute
unwatch()

// Ou avec unwatchToken
userManager.unwatchToken(callback)

Détection cross-tab

Les changements de token dans un onglet sont automatiquement détectés dans tous les autres onglets du même domaine :

// Onglet 1 : l'utilisateur se connecte
userManager.login(credentials)

// Onglet 2 : le watcher détecte automatiquement le nouveau token
// → L'interface se met à jour automatiquement
// → L'utilisateur est connecté dans tous les onglets

📚 API complète

Configuration

FonctionDescription
setDefaultDomain(domain)Définit le domaine pour les cookies
setDefaultExpirationToken(timestamp)Définit l'expiration par défaut
setDefaultLoginUrl(url)Définit l'URL de l'API de login
setLoginPageUrl(url)Définit l'URL de la page de login
setRoleHierarchy(hierarchy)Définit la hiérarchie des rôles
setRoleKey(key)Définit la clé pour les rôles multi-apps
getDomain()Récupère le domaine actuel

Authentification

FonctionDescription
login(credentials, url?, domain?)Connecte l'utilisateur
logout()Déconnecte l'utilisateur
goToLoginPage(saveRedirect?)Redirige vers la page de login
redirectionAfterLogin(callback)Gère la redirection après login

Gestion du token

FonctionDescription
getToken()Récupère le token actuel
setToken(token, exp?, domain?)Définit le token
getDecodedToken(token?)Décode le token JWT
isTokenExpired(token?)Vérifie si le token est expiré
isTokenValid(token?)Vérifie si le token est valide ⭐
getTokenTimeRemaining(token?)Temps restant (secondes) ⭐
refreshTokenCache()Rafraîchit le cache ⭐

Rôles

FonctionDescription
getRoles(token?)Récupère la liste des rôles
isGranted(role, token?)Vérifie si un rôle est accordé
isLogged(token?)Vérifie si l'utilisateur est connecté

Réactivité ⭐ Nouveau

FonctionDescription
watchToken(callback)Écoute les changements de token ⭐
unwatchToken(callback)Arrête l'écoute ⭐
getWatchersCount()Nombre de watchers actifs ⭐

⭐ = Nouvelles fonctionnalités v1.12.0

🔄 Flux de synchronisation

┌─────────────────┐
│  Cookie Token   │ ◄──────────────────┐
│  (Partagé)      │                    │
└────────┬────────┘                    │
         │                             │
         │ getToken()          setToken()
         │                             │
         ▼                             │
┌─────────────────┐    watchToken()   │
│  userManager    │ ────────────────► │
│    (Cache)      │                   │
└────────┬────────┘                   │
         │                            │
         │ watchToken()               │
         │                            │
         ▼                            │
┌─────────────────┐     watch        │
│  Store Pinia    │ ─────────────────┘
│   (Réactif)     │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│   Composants    │
│      Vue        │
└─────────────────┘

🛡️ Sécurité

  • Validation automatique des tokens avant utilisation
  • Détection des tokens expirés dans le cache
  • Protection contre les cookies trop volumineux
  • Validation des paramètres des fonctions critiques
  • Gestion sécurisée des erreurs

📝 Structure du token

interface TokenInterface {
  typeUSer: string
  login: string
  nomComplet: string
  email: string
  nom: string
  prenom: string
  poste: string
  departement: string
  extras: Record<string, any>
  roles: { [key: string]: string[] } | string[]
  exp: number          // Expiration du token
  expRefresh?: number  // Expiration du refresh token
}

🎯 Cas d'usage

Déconnexion automatique sur expiration

userManager.watchToken((newToken) => {
  if (!newToken || !userManager.isTokenValid(newToken)) {
    // Token expiré ou supprimé
    router.push('/login')
  }
})

Affichage du temps restant

setInterval(() => {
  const remaining = userManager.getTokenTimeRemaining()
  if (remaining !== null && remaining < 300) { // 5 minutes
    showWarning(`Session expire dans ${remaining}s`)
  }
}, 30000) // Vérifier toutes les 30s

Synchronisation multi-onglets

// L'utilisateur se déconnecte dans l'onglet A
// → Tous les onglets B, C, D détectent le changement via watchToken
// → Redirection automatique vers /login dans tous les onglets

🔧 Debug

// Afficher les informations du token
console.log('Token:', userManager.getToken())
console.log('Payload:', userManager.getDecodedToken())
console.log('Valide:', userManager.isTokenValid())
console.log('Temps restant:', userManager.getTokenTimeRemaining(), 's')
console.log('Watchers actifs:', userManager.getWatchersCount())

// Rafraîchir manuellement le cache
userManager.refreshTokenCache()

📄 Changelog

Voir CHANGELOG.md

📜 Licence

Propriétaire - AMSOM Habitat

FAQs

Package last updated on 12 Nov 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts