DéveloppeurWeb.Com
    DéveloppeurWeb.Com
    • Agile Zone
    • AI Zone
    • Cloud Zone
    • Database Zone
    • DevOps Zone
    • Integration Zone
    • Web Dev Zone
    DéveloppeurWeb.Com
    Home»Security Zone»Clustering de session OAuth 2.0
    Security Zone

    Clustering de session OAuth 2.0

    novembre 16, 2021
    Clustering de session OAuth 2.0
    Share
    Facebook Twitter Pinterest Reddit WhatsApp Email

    « Comment contrôler OAuth dans une application à équilibrage de charge ? » est typique des questions OAuth 2.0 que nous entendons. La réponse courte est : le clustering de session pour OAuth n’est en aucun cas unique. La réponse plus longue est que la gestion des sessions de cluster est toujours susceptible d’être un problème. Cet article explique comment une connexion OAuth affecte votre session d’application. Pour le démontrer, nous allons créer une application de base, sécurisée et à charge équilibrée.

    Table des matières

    • Sessions et applications OAuth 2.0
    • Apatride avec JWT
    • Sessions persistantes de l’équilibreur de charge
    • Configurer HAproxy et Redis
      • Configurer HAproxy
      • Démarrez HAproxy et Redis avec Docker
    • Construire une application de démarrage sécurisé Spring
      • Démarrer l’application Spring Boot
    • Secure Spring Boot avec OAuth 2.0
    • Partager des sessions avec Redis
    • En savoir plus OAuth 2.0 et gestion de session

    Conditions préalables

    Sessions et applications OAuth 2.0

    Une application qui utilise une redirection OAuth 2.0, un « octroi de code d’autorisation », utilise généralement une session côté serveur pour stocker temporairement l’état du processus de connexion jusqu’à ce qu’il se termine. Examinons un flux de connexion OAuth simplifié :

    Flux de connexion OAuth simplifié

    1. Un utilisateur demande à se connecter – soit en cliquant sur un bouton de connexion, soit automatiquement lorsqu’il demande une page protégée.

    2. L’application Web stocke des informations sur la session en cours – des informations sur l’état OAuth et éventuellement un vérificateur de code PKCE et/ou un nonce pour OpenId Connect (OIDC).

    3. La réponse est une redirection du navigateur vers le serveur d’autorisation.

    4. L’utilisateur interagit avec le serveur d’autorisation pour fournir des informations d’identification et confirmer le consentement.

    5. Les problèmes du serveur d’autorisation sont redirigés avec un code vers l’application Web.

    6. L’autorisation de l’utilisateur est finalisée sur le backend.

    7. L’application Web lit les données OAuth précédemment stockées à partir de la session.

    8. Vérification que l’utilisateur a été autorisé avec le serveur d’autorisation.

    9. Réponse du serveur d’authentification avec un jeton d’accès OAuth.

    10. L’application Web stocke les jetons d’accès dans la session.

    11. L’utilisateur est connecté.

    Deux requêtes distinctes sont adressées à l’application Web : la demande de connexion initiale et une étape de vérification. Les deux requêtes accèdent aux mêmes informations de session. Pour votre application, cela signifie qu’une fois que vous démarrez la mise à l’échelle, vous devez penser à la gestion des sessions.

    Apatride avec JWT

    À ce stade, vous pouvez vous demander si vous pouvez tout mettre dans un JWT (JSON Web Token) et rendre ce processus sans état ; supprimant le besoin de tout regroupement de session. Tu pourrait, mais vous devrez utiliser un JWE (JSON Web Encryption) pour vous assurer que le navigateur n’a pas accès à des données sensibles. Il existe de nombreuses raisons de ne pas utiliser les JWT comme jetons de session, mais ces problèmes sortent du cadre de cet article.

    Sessions persistantes de l’équilibreur de charge

    Une autre option pour éviter la réplication de session ou le clustering consiste à utiliser des « sessions persistantes » (ou « affinité de session »), mais cela crée un environnement fragile. Si un serveur Web tombe en panne ou est arrêté pour une raison quelconque, tous les utilisateurs associés à ce serveur seront essentiellement déconnectés. Les sessions persistantes violent également les principes à 12 facteurs de l’apatridie des processus.

    Ne confondez pas la référence de 12 Factor à « processus d’apatridie » avec ce que l’on entend par « apatride » dans la section précédente. On y fait spécifiquement référence à la nécessité d’un relais applicatif sur « l’état » d’un serveur entre des requêtes, par exemple, des données mises en cache en mémoire ou un fichier. Au lieu de cela, un service de support doit être utilisé. Dans le cas du stockage de session, l’exemple de Redis est utilisé, ce que nous allons faire exactement dans la section suivante.

    Configurer HAproxy et Redis

    Pour créer une application à charge équilibrée, nous avons besoin d’au moins trois éléments : un équilibreur de charge (HAproxy), un stockage de session partagé (Redis) et plusieurs instances d’une application Web (Spring Boot).

    Si vous souhaitez passer directement au code, jetez un œil à ce référentiel GitHub.

    Créez un nouveau répertoire pour ce projet :

    mkdir oauth-sessions
    cd oauth-sessions
    

    Configurer HAproxy

    HAproxy est utilisé pour répartir les requêtes entre plusieurs backend applications et créer un fichier de configuration, haproxy.cfg, qui servira deux applications Web différentes (une sur le port 8081, et un autre sur 8082).

    global
        daemon
        maxconn 2000
    
        # send request logs to stdout, to make debugging easier
        log stdout format raw local0
    
    defaults
        mode http
        log global
        option httplog
        timeout connect 5000ms
        timeout client 50000ms
        timeout server 50000ms
    
    frontend http-in
        bind *:8080
        default_backend webapps
    
    backend webapps
        balance roundrobin
    
        # `host.docker.internal` refers to host that is running Docker Desktop
        # On Linux add `--add-host=host.docker.internal:host-gateway` to `docker run` to
        # mimic the functionality
        server webapp1 host.docker.internal:8081
        server webapp2 host.docker.internal:8082

    Assurez-vous qu’il y a une nouvelle ligne de fin, ou vous pourriez avoir des difficultés à démarrer HAproxy.

    Démarrer HAproxy et Redis avec Docker

    J’exécuterai l’exemple d’application Web directement sur mon ordinateur portable, mais HAproxy et Redis peuvent tous deux s’exécuter en tant que conteneurs Docker. Créer un docker-compose.yml déposer:

    version: '3.8'
    services:
    
      haproxy:
        image: docker.io/haproxy:2.4-alpine
        volumes:
          - ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
        extra_hosts:
          # Docker Desktop uses `host.docker.internal` for the host,
          # mimic this for linux installs, requires Docker 20.10+
          - host.docker.internal:host-gateway
        ports:
          - 8080:8080
    
      redis:
        # Starts Redis without persistence
        image: docker.io/redis:6.2.5-alpine
        ports:
          - 6379:6379

    Démarrez HAproxy et Redis en exécutant :

    Vous pouvez arrêter le processus en appuyant sur Ctrl+C ou en exécutant la commande docker-compose down à partir du même répertoire.

    Construire une application de démarrage sécurisé Spring

    Maintenant que les dépendances du système sont éliminées, passons à la création d’une application Spring Boot.

    Créez une nouvelle application Spring Boot en visitant start.spring.io et en sélectionnant le la toile et Octa dépendances ou en exécutant la commande suivante :

    https start.spring.io/starter.tgz 
      bootVersion==2.5.4 
      dependencies==web,okta 
      groupId==com.example 
      artifactId==webapp 
      name=="Web Application" 
      description=="Demo Web Application" 
      packageName==com.example 
      javaVersion==11 
    | tar -xzvf -

    Pour donner une indication visuelle du serveur qui a traité la demande, créez un contrôleur REST qui affiche le port du serveur dans src/main/java/com/example/Endpoints.java:

    package com.example;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class Endpoints {
    
        @GetMapping("https://dzone.com/")
        String serverInfo(@Value("${server.port}") int port) {
            return "Hello, your server port is: " + port;
        }
    }

    Démarrer l’application Spring Boot

    Dans la section précédente, HAproxy était lié au port 8080, qui est également le port par défaut pour Spring Boot. Démarrer l’application sur le port 8081 à l’aide de:

    SERVER_PORT=8081 ./mvnw spring-boot:run
    

    À ce stade, l’application Spring Boot n’a PAS été configurée pour utiliser Redis ou OAuth, mais vous pouvez toujours tester le serveur en saisissant le mot de passe généré automatiquement à partir de la sortie de la console. Cela ressemblera à quelque chose comme ceci :

    Using generated security password: 4302a714-580b-4d01-91d9-5d9597ee1bb5
    

    Copiez le mot de passe et faites une demande à l’application Spring Boot :

    http :8081/ --auth user:<your-password>
    

    Vous verrez une réponse contenant le port du serveur :

    Hello, your server port is: 8081
    

    Génial, cela signifie que l’application Spring Boot est opérationnelle ! Assurez-vous maintenant que vous pouvez accéder au serveur via l’équilibreur de charge sur le port 8080:

    http :8080/ --auth user:<your-password>
    

    Vous devriez voir la même réponse ; si vous voyez un 503 Service Unavailable, réessayez la demande.

    La configuration HAproxy utilisée dans cet article n’a PAS de vérification de l’état activée, elle alternera donc les demandes entre les ports 8081 et 8082 ; ceci est intentionnel pour simplifier la configuration. Jetez un œil à Spring Actuator si vous souhaitez ajouter des vérifications de l’état et d’autres surveillances à votre application.

    Arrêtez le serveur Spring Boot en utilisant Ctrl+C. Il est temps de sécuriser l’application avec OAuth 2.0.

    Démarrage sécurisé du printemps avec OAuth 2.0

    Avant de commencer, vous aurez besoin d’un compte développeur Okta gratuit. Installez l’Okta CLI et exécutez okta register pour ouvrir un nouveau compte. Si vous avez déjà un compte, lancez okta login. Ensuite, exécutez okta apps create. Sélectionnez le nom de l’application par défaut ou modifiez-le comme bon vous semble. Choisir la toile et appuyez sur Entrer.

    Sélectionner Démarreur de démarrage à ressort Okta. Acceptez les valeurs d’URI de redirection par défaut qui vous sont fournies. Autrement dit, une redirection de connexion de http://localhost:8080/login/oauth2/code/okta et une redirection de déconnexion de http://localhost:8080.

    Que fait la CLI d’Okta ?

    Maintenant que l’application a été configurée pour utiliser OAuth 2.0, démarrez deux instances différentes (ouvrez deux fenêtres de terminal différentes) :

    SERVER_PORT=8081 ./mvnw spring-boot:run
    

    Et le second sur le port 8082:

    SERVER_PORT=8082 ./mvnw spring-boot:run
    

    L’accès aux applications via l’équilibreur de charge produira des résultats étranges ; ouvrir une fenêtre privée/incognito pour http://localhost:8080 et essayez de vous connecter. Vous serez redirigé vers Okta où vous pourrez saisir les informations d’identification de votre compte. Cependant, après avoir appuyé sur la S’identifier, vous verrez une page d’erreur :

    Erreur de connexion Okta

    Repensez au diagramme de séquence au début de cet article et voyez si vous pouvez repérer le problème. La demande de connexion initiale (étape un) s’est produite sur une instance et la dernière s’est produite sur une autre (étape six). La mise à jour de l’application pour utiliser le stockage de session partagé résoudra le problème.

    Faisons cela!

    Partager des sessions avec Redis

    Si vous suivez, vous avez déjà un serveur Redis en cours d’exécution ; nous allons maintenant configurer l’application Spring Boot pour l’utiliser. Heureusement, Spring Session rend le processus indolore.

    Ouvrez le pom.xml et ajoutez ce qui suit à l’intérieur du <dependencies> bloquer:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session-data-redis</artifactId>
    </dependency>

    Par défaut, Spring Session configure Redis pour se connecter à localhost sur le port 6379 et AUCUN mot de passe. Consultez la documentation Spring Session pour connaître les différentes options de configuration.

    Redémarrez les applications Spring Boot. (Rappelez-vous qu’il y en a un sur le port 8081 et un autre sur 8082).

    Ouvrez à nouveau votre navigateur et essayez d’accéder http://localhost:8080/; cette fois, vous pourrez vous connecter sans problème !

    Actualisez le navigateur plusieurs fois et vous verrez la réponse alterner entre les ports :

    Hello, your server port is: 8081
    

    Et:

    Hello, your server port is: 8082
    

    Assez facile, juste quelques dépendances pour configurer le stockage de session partagé ! Si Redis n’est pas votre confiture, Spring Session prend également en charge les bases de données, Hazelcast, MongoDB et Apache Geode.

    En savoir plus OAuth 2.0 et gestion de session

    Cet article montre comment gérer les sessions pour une application simple à charge équilibrée qui utilise OAuth 2.0. Notre exemple s’est concentré sur la partie Spring Boot du…

    Share. Facebook Twitter Pinterest LinkedIn WhatsApp Reddit Email
    Add A Comment

    Leave A Reply Cancel Reply

    Catégories

    • Politique de cookies
    • Politique de confidentialité
    • CONTACT
    • Politique du DMCA
    • CONDITIONS D’UTILISATION
    • Avertissement
    © 2023 DéveloppeurWeb.Com.

    Type above and press Enter to search. Press Esc to cancel.