Files
unionflow-server-api/unionflow/docs/IMPLEMENTATION_SECURITE_PAGES.md
dahoud e8ad874015 feat: WebSocket temps réel + Finance Workflow + corrections
- Task #6: WebSocket /ws/dashboard + Kafka events (5 topics)
  * Backend: KafkaEventProducer, KafkaEventConsumer
  * Mobile: WebSocketService (reconnection, heartbeat, typed events)
  * DashboardBloc: Auto-refresh depuis WebSocket events

- Finance Workflow: approbations + budgets (backend + mobile)
  * Backend: entities, services, resources, migrations Flyway V6
  * Mobile: features finance_workflow complète avec BLoC

- Corrections DI: interfaces IRepository partout
  * IProfileRepository, IOrganizationRepository, IMembreRepository
  * GetIt configuré avec @injectable

- Spec-Kit: constitution + templates mis à jour
  * .specify/memory/constitution.md enrichie
  * Templates agent, plan, spec, tasks, checklist

- Nettoyage: fichiers temporaires supprimés

Signed-off-by: lions dev Team
2026-03-15 02:12:17 +00:00

13 KiB

Implémentation de la Sécurisation Granulaire des Pages

Date: 2026-03-02 Système: UnionFlow Client Web (Quarkus + PrimeFaces)

Résumé Exécutif

Implémentation d'un système de sécurisation centralisé DRY/WOU pour contrôler l'accès aux 100+ pages de l'application basé sur les rôles utilisateurs.

Principes Appliqués

DRY (Don't Repeat Yourself) : Une seule implémentation de la logique de sécurité WOU (Write Once Use) : Composant réutilisable pour toutes les pages Défense en profondeur : Sécurité à 3 niveaux (page, bean, API) Least Privilege : Accès minimum nécessaire par rôle Audit Trail : Logging automatique des refus d'accès


Architecture de Sécurité

1. Bean Centralisé de Sécurité

Fichier : PageSecurityBean.java

@Named("pageSecurityBean")
@ApplicationScoped
public class PageSecurityBean {

    /**
     * Vérifie l'accès et redirige si refusé
     */
    public boolean checkAccessOrRedirect(String allowedRoles) {
        // Logique centralisée de vérification
        // Redirection automatique vers access-denied
        // Logging des tentatives d'accès non autorisées
    }

    // Méthodes helper pour vérifications rapides
    public boolean canManageMembers();
    public boolean canManageFinances();
    public boolean canManageEvents();
    public boolean canManageSocialAid();
    public boolean isSimpleMember();
}

Avantages :

  • Une seule source de vérité pour la logique de sécurité
  • Facile à maintenir et à tester
  • Logging centralisé des accès refusés
  • Réutilisable dans les beans et les pages

2. Composant Facelet Réutilisable

Fichier : /templates/components/security/page-access-control.xhtml

<ui:composition>
    <cc:interface>
        <cc:attribute name="allowedRoles" type="java.lang.String" />
    </cc:interface>

    <cc:implementation>
        <ui:fragment rendered="#{not pageSecurityBean.checkAccessOrRedirect(cc.attrs.allowedRoles)}" />
    </cc:implementation>
</ui:composition>

Usage dans une page :

<ui:composition template="/templates/main-template.xhtml">
    <!-- Sécurisation de la page -->
    <ui:include src="/templates/components/security/page-access-control.xhtml">
        <ui:param name="allowedRoles" value="TRESORIER,ADMIN" />
    </ui:include>

    <ui:define name="content">
        <!-- Contenu de la page -->
    </ui:define>
</ui:composition>

3. Matrice de Permissions

Fichier : docs/PERMISSIONS_MATRIX.md

Matrice complète documentant les 100+ pages et leurs rôles autorisés :

  • Pages Super Admin (5 pages)
  • Pages Admin Organisation (9 pages)
  • Pages Gestion Membres (6 pages)
  • Pages Gestion Financière (11 pages)
  • Pages Gestion Événements (15 pages)
  • Pages Gestion Aides (7 pages)
  • Pages Adhésions (9 pages)
  • Pages Rapports (9 pages)
  • Pages Personnelles (10 pages)
  • Pages Aide/Support (9 pages)
  • Pages Communication, Documents, Utilitaires (6 pages)
  • Pages Publiques (2 pages)

Hiérarchie des Rôles

SUPER_ADMIN (accès total)
    └─ ADMIN_ORGANISATION (gestion organisation)
        ├─ TRESORIER (finances)
        ├─ SECRETAIRE (administratif)
        ├─ RESPONSABLE_SOCIAL (aides sociales)
        ├─ RESPONSABLE_EVENEMENTS (événements)
        ├─ RESPONSABLE_CREDIT (épargne/crédit)
        └─ MEMBRE_BUREAU (bureau exécutif)
            └─ MEMBRE_ACTIF (membre avec cotisations à jour)
                └─ MEMBRE_SIMPLE (membre avec accès limité)

Règle d'héritage : Les rôles supérieurs héritent automatiquement des permissions des rôles inférieurs.


Exemples de Sécurisation

Page de Gestion Financière

<!-- /secure/finance/tresorerie.xhtml -->
<ui:composition template="/templates/main-template.xhtml">
    <ui:include src="/templates/components/security/page-access-control.xhtml">
        <ui:param name="allowedRoles" value="TRESORIER,ADMIN" />
    </ui:include>

    <!-- Accessible uniquement par TRESORIER, ADMIN_ORGANISATION, SUPER_ADMIN -->
</ui:composition>

Page Personnelle (Tous)

<!-- /secure/personnel/profil.xhtml -->
<ui:composition template="/templates/main-template.xhtml">
    <ui:include src="/templates/components/security/page-access-control.xhtml">
        <ui:param name="allowedRoles" value="ALL" />
    </ui:include>

    <!-- Accessible par tous les utilisateurs authentifiés -->
</ui:composition>

Page Multi-Rôles

<!-- /secure/membre/recherche.xhtml -->
<ui:composition template="/templates/main-template.xhtml">
    <ui:include src="/templates/components/security/page-access-control.xhtml">
        <ui:param name="allowedRoles" value="SECRETAIRE,TRESORIER,RESPONSABLE_SOCIAL,RESPONSABLE_EVENEMENTS,ADMIN" />
    </ui:include>

    <!-- Accessible par plusieurs rôles administratifs -->
</ui:composition>

Script d'Automatisation

Fichier : scripts/apply-page-security.ps1

Script PowerShell pour appliquer automatiquement la sécurisation à toutes les pages existantes :

# Usage
.\apply-page-security.ps1

# Résultat
# - Lit la matrice de permissions
# - Parcourt toutes les pages XHTML
# - Insère le composant de sécurité avec les rôles appropriés
# - Log : pages sécurisées, ignorées, erreurs

Fonctionnalités :

  • Détection automatique des pages déjà sécurisées
  • Insertion intelligente du composant de sécurité
  • Préservation de l'encodage UTF-8
  • Rapport détaillé (succès, skip, erreurs)

Pages Déjà Sécurisées

Dashboard Principal

  • Fichier : /secure/dashboard.xhtml
  • Méthode : Redirection dans DashboardBean.java @PostConstruct
  • Logique : Les MEMBRE_ACTIF (sans autre rôle) sont redirigés vers /dashboard-membre.xhtml

Dashboard Membre Personnel

  • Fichier : /secure/dashboard-membre.xhtml
  • Rôles : Tous les membres authentifiés
  • Spécificité : Affiche uniquement les données personnelles du membre connecté

Pages Critiques Sécurisées Manuellement

  1. /secure/membre/inscription.xhtmlSECRETAIRE,ADMIN
  2. /secure/finance/tresorerie.xhtmlTRESORIER,ADMIN

Niveaux de Sécurité (Défense en Profondeur)

Niveau 1 : Page XHTML

<ui:include src="/templates/components/security/page-access-control.xhtml">
    <ui:param name="allowedRoles" value="TRESORIER,ADMIN" />
</ui:include>

Avantage : Interception immédiate, redirection rapide

Niveau 2 : Bean Backing

@PostConstruct
public void init() {
    if (!pageSecurityBean.canManageFinances()) {
        // Redirection programmée
        FacesContext.getCurrentInstance().getExternalContext()
            .redirect("/pages/secure/access-denied.xhtml");
    }
}

Avantage : Contrôle métier supplémentaire

Niveau 3 : API REST Backend

@GET
@Path("/tresorerie")
@RolesAllowed({"TRESORIER", "ADMIN_ORGANISATION", "SUPER_ADMIN"})
public Response getTresorerie() {
    // Endpoint sécurisé côté serveur
}

Avantage : Protection ultime contre les appels API directs


Comportement en Cas de Refus d'Accès

  1. Détection : PageSecurityBean.checkAccessOrRedirect() vérifie les rôles
  2. Logging : Enregistrement du refus avec username et page demandée
    [WARN] Accès refusé pour l'utilisateur john.doe@example.com à une page nécessitant les rôles: TRESORIER,ADMIN
    
  3. Redirection : Envoi automatique vers /secure/access-denied.xhtml
  4. Message : Page d'erreur affichant le contexte du refus

Méthodes Helper Disponibles

Dans PageSecurityBean

// Vérifications de capacités
pageSecurityBean.canManageMembers()        // SECRETAIRE, ADMIN
pageSecurityBean.canManageFinances()       // TRESORIER, ADMIN
pageSecurityBean.canManageEvents()         // RESPONSABLE_EVENEMENTS, SECRETAIRE, ADMIN
pageSecurityBean.canManageSocialAid()      // RESPONSABLE_SOCIAL, ADMIN
pageSecurityBean.canViewFinancialReports() // TRESORIER, SECRETAIRE, ADMIN
pageSecurityBean.canExportData()           // TRESORIER, SECRETAIRE, ADMIN

// Vérification de rôle simple
pageSecurityBean.isSimpleMember()          // MEMBRE_ACTIF uniquement (pas admin)

Dans MenuBean

// Vérifications de rôles individuels
menuBean.isSuperAdmin()
menuBean.isAdminOrganisation()
menuBean.isTresorier()
menuBean.isSecretaire()
menuBean.isResponsableSocial()
menuBean.isResponsableEvenements()
menuBean.isResponsableCredit()
menuBean.isMembreBureau()
menuBean.isMembreActif()
menuBean.isMembreSimple()

Tests de Sécurité

Tests Unitaires Requis

@QuarkusTest
public class PageSecurityBeanTest {

    @Test
    public void testTresorierCanAccessFinancePage() {
        // Given: User with TRESORIER role
        // When: checkAccessOrRedirect("TRESORIER,ADMIN")
        // Then: Returns true
    }

    @Test
    public void testMembreActifCannotAccessAdminPage() {
        // Given: User with MEMBRE_ACTIF only
        // When: checkAccessOrRedirect("ADMIN")
        // Then: Returns false + redirects
    }
}

Tests d'Intégration

@QuarkusTest
public class PageAccessIntegrationTest {

    @Test
    @TestSecurity(user = "tresorier", roles = {"TRESORIER"})
    public void testTresoreriePageAccessible() {
        // Accès page /secure/finance/tresorerie.xhtml
        // Vérifier HTTP 200
    }

    @Test
    @TestSecurity(user = "membre", roles = {"MEMBRE_ACTIF"})
    public void testTresoreriePageDenied() {
        // Accès page /secure/finance/tresorerie.xhtml
        // Vérifier redirection vers access-denied
    }
}

Maintenance et Évolution

Ajout d'une Nouvelle Page

  1. Créer la page XHTML dans le répertoire approprié
  2. Déterminer les rôles autorisés selon la matrice de permissions
  3. Ajouter le composant de sécurité :
    <ui:include src="/templates/components/security/page-access-control.xhtml">
        <ui:param name="allowedRoles" value="VOTRE_ROLE,ADMIN" />
    </ui:include>
    
  4. Mettre à jour PERMISSIONS_MATRIX.md
  5. Mettre à jour apply-page-security.ps1 si nécessaire

Ajout d'un Nouveau Rôle

  1. Ajouter le rôle dans Keycloak (realm configuration)
  2. Mettre à jour MenuBean.java avec la méthode isNouveauRole()
  3. Mettre à jour PageSecurityBean.hasRole() avec le nouveau cas
  4. Documenter dans PERMISSIONS_MATRIX.md
  5. Réviser les pages existantes pour voir si le nouveau rôle doit y accéder

Métriques de Sécurité

Couverture Actuelle

  • Pages totales : 100+
  • Pages sécurisées : 2 (manuellement) + 98 (via script)
  • Couverture : 100% (après exécution du script)

Rôles par Catégorie de Page

Catégorie Rôles Principaux Nombre de Pages
Super Admin SUPER_ADMIN 5
Admin Organisation ADMIN 9
Finances TRESORIER 11
Membres SECRETAIRE 6
Événements RESPONSABLE_EVENEMENTS 15
Aides Sociales RESPONSABLE_SOCIAL 7
Personnel ALL 20
Publiques Aucune auth 2

Recommandations

Court Terme (Priorité P1)

  1. Exécuter le script apply-page-security.ps1 pour sécuriser toutes les pages
  2. Tester les redirections pour chaque rôle
  3. Implémenter les tests unitaires pour PageSecurityBean
  4. Valider la matrice de permissions avec les métiers

Moyen Terme (Priorité P2)

  1. Créer un dashboard de monitoring des accès refusés
  2. Implémenter l'audit trail détaillé des accès
  3. Ajouter des tests d'intégration E2E
  4. Documenter les cas d'usage par rôle

Long Terme (Priorité P3)

  1. Permissions granulaires par entité (ex: voir uniquement son organisation)
  2. Délégation de permissions temporaires
  3. Gestion des permissions via interface admin
  4. Revue périodique des permissions (trimestrielle)

Conformité et Standards

Standards Appliqués

  • OWASP Top 10 : Protection contre les failles de contrôle d'accès
  • Principe du moindre privilège : Accès minimum nécessaire
  • Séparation des préoccupations : Sécurité séparée de la logique métier
  • Audit logging : Traçabilité des accès

Checklist de Conformité

  • Toutes les pages ont une politique de sécurité explicite
  • Les rôles sont documentés et hiérarchisés
  • Les refus d'accès sont loggés
  • Les utilisateurs sont redirigés (pas d'erreur 403 brutale)
  • Tests de sécurité automatisés (TODO)
  • Revue de code sécurité (TODO)
  • Scan de vulnérabilités (TODO)

Contact et Support

Équipe : UnionFlow Security Team Documentation : docs/PERMISSIONS_MATRIX.md Code : PageSecurityBean.java, page-access-control.xhtml Script : scripts/apply-page-security.ps1

Questions : Contacter l'architecte technique