最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Issues with User Authentication using Cognito in Flutter (GoRouter, StreamBuilder, and FutureBuilder) - Stack Overflow

programmeradmin2浏览0评论

I am working on a Flutter project where I am trying to implement authentication using Amazon Cognito. I am facing issues with the authentication flow, and the app is stuck in an endless waiting state when attempting to authenticate users. I am using GoRouter for routing and StreamBuilder / FutureBuilder to manage authentication state. However, the user is not being properly authenticated, and the page doesn’t load as expected.

Here are the files I am working with:

  1. main.dart (App entry point, router setup)
  2. auth_controller.dart (Handles authentication logic)
  3. login_controller.dart (Handles login logic)
  4. sign_up_controller.dart (Handles signup logic)
  5. login_screen.dart (Login UI)
  6. auth_service.dart (Interacts with Cognito for authentication)
  7. login_form.dart (Login form widget)

The problem: When I try to authenticate, it stays in the loading state indefinitely. I cannot access the login page, and it seems the Stream in authStateChanges is not emitting any data, causing the app to remain stuck in the waiting state.

The following code snippets illustrate the setup:

main

import 'package:checkee/theme/theme.dart';
import 'package:flutter/material.dart';
import 'core/router.dart'; // Importer router.dart pour gérer la logique de routage

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      title: 'Checkee',
      theme: checkeeTheme,
      routerConfig: appRouter,  // Utiliser appRouter configuré dans router.dart
    );
  }
}

auth_controller

import 'dart:async';
import 'package:amazon_cognito_identity_dart_2/cognito.dart';

class AuthController {
  final userPool = CognitoUserPool(
    'eu-west-1_eYRgcALYR',  // Remplace par ton User Pool ID
    'rih16pulnrf9ihflpqiobjomk',    // Remplace par ton App Client ID
  );

  final _authStateController = StreamController<CognitoUser?>.broadcast();

  // Connexion de l'utilisateur
  Future<CognitoUserSession?> signInWithEmailPassword(String email, String password) async {
    try {
      final cognitoUser = CognitoUser(email, userPool);
      final authDetails = AuthenticationDetails(
        username: email,
        password: password,
      );

      final session = await cognitoUser.authenticateUser(authDetails);
      _authStateController.add(cognitoUser); // Envoie l'utilisateur dans le stream
      return session;
    } catch (e) {
      print("Erreur de connexion avec Cognito : $e");
      _authStateController.add(null); // Envoie null en cas d'échec
      return null;
    }
  }

  // Fonction pour surveiller l'état de l'authentification
  Stream<CognitoUser?> authStateChanges() {
    return _authStateController.stream;
  }

  // Méthode pour se déconnecter
  Future<void> signOut() async {
    _authStateController.add(null);  // Met à jour le stream avec null pour indiquer la déconnexion
  }

  // Récupère le type d'utilisateur (locataire, propriétaire, etc.)
  Future<String> getUserType(String username) async {
    final cognitoUser = CognitoUser(username, userPool);
    final session = await cognitoUser.getSession();
    final userGroups = await getUserGroups(session!);
    if (userGroups.contains('Propriétaire')) {
      return 'Propriétaire';
    } else if (userGroups.contains('Locataire')) {
      return 'Locataire';
    }
    return 'Locataire';  // Par défaut
  }

  // Récupère les groupes de l'utilisateur
  Future<List<String>> getUserGroups(CognitoUserSession session) async {
    final idToken = session.idToken;
    final claims = idToken.payload;
    final groups = claims['cognito:groups'] as List<dynamic>? ?? [];
    return groups.map((group) => group.toString()).toList();
  }
}

login_controller

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import '../services/auth_service.dart'; // Assurez-vous que AuthService est correctement importé

class LoginController {
  final TextEditingController emailController;
  final TextEditingController passwordController;

  LoginController({
    required this.emailController,
    required this.passwordController,
  });

  Future<void> login(BuildContext context) async {
    try {
      final session = await AuthService().signInWithEmailPassword(
        emailController.text,
        passwordController.text,
      );

      if (session != null) {
        // Vérifie le groupe de l'utilisateur via Cognito et redirige en fonction du rôle
        final userGroups = await AuthService().getUserGroups(session);
        if (userGroups.contains('Admin')) {
          context.go('/adminHome'); // Rediriger vers la page Admin
        } else if (userGroups.contains('Propriétaire')) {
          context.go('/ownerHome'); // Rediriger vers la page Propriétaire
        } else if (userGroups.contains('Locataire')) {
          context.go('/tenantHome'); // Rediriger vers la page Locataire
        } else {
          context.go('/'); // Redirection par défaut si aucun groupe spécifique
        }
      } else {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Email ou mot de passe invalide')),
        );
      }
    } catch (e) {
      print("Erreur de connexion avec Cognito : $e");
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Erreur de connexion : $e')),
      );
    }
  }

  void dispose() {
    emailController.dispose();
    passwordController.dispose();
  }
}

sign_up_controller

import '../services/auth_service.dart'; // Assurez-vous que AuthService est importé

class SignUpController {
  final AuthService _authService = AuthService();

  Future<String?> signUp({
    required String email,
    required String password,
    required String firstName,
    required String lastName,
    required String phoneNumber,
    String? address,
    String? tvaNumber,
    required String userType,
  }) async {
    try {
      // Appel à la méthode signUpWithEmailPassword d'AuthService pour créer un utilisateur
      final errorMessage = await _authService.signUpWithEmailPassword(email, password);

      if (errorMessage != null) {
        return errorMessage; // Retourner un message d'erreur si l'inscription échoue
      }

      // Ajouter les autres informations utilisateur si l'inscription réussit
      // Par exemple, enregistrer ces informations dans une base de données

      return null; // Inscription réussie
    } catch (e) {
      print("Erreur lors de l'inscription : $e");
      return 'Erreur lors de l\'inscription'; // Message générique en cas d'échec
    }
  }
}

login_screen

import 'package:flutter/material.dart';
import 'package:checkee/features/auth/controllers/login_controller.dart'; // Assurez-vous d'avoir la référence du login_controller.dart

class LoginScreen extends StatelessWidget {
  final TextEditingController emailController = TextEditingController();
  final TextEditingController passwordController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    final loginController = LoginController(
      emailController: emailController,
      passwordController: passwordController,
    );

    return Scaffold(
      appBar: AppBar(title: Text('Login')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(
              controller: emailController,
              decoration: InputDecoration(labelText: 'Email'),
            ),
            TextField(
              controller: passwordController,
              decoration: InputDecoration(labelText: 'Password'),
              obscureText: true,
            ),
            ElevatedButton(
              onPressed: () async {
                await loginController.login(context);  // Appel de la méthode login() de LoginController
              },
              child: Text('Login'),
            ),
          ],
        ),
      ),
    );
  }
}

auth_service

import 'dart:async';
import 'package:amazon_cognito_identity_dart_2/cognito.dart';

class AuthService {
  final userPool = CognitoUserPool(
    'eu-west-1_eYRgcALYR',  // Remplace par ton User Pool ID
    'rih16pulnrf9ihflpqiobjomk',    // Remplace par ton App Client ID
  );

  final _authStateController = StreamController<CognitoUser?>.broadcast();

  // Connexion de l'utilisateur
  Future<CognitoUserSession?> signInWithEmailPassword(String email, String password) async {
    try {
      final cognitoUser = CognitoUser(email, userPool);
      final authDetails = AuthenticationDetails(
        username: email,
        password: password,
      );

      final session = await cognitoUser.authenticateUser(authDetails);
      _authStateController.add(cognitoUser);  // Envoie l'utilisateur dans le stream
      return session;
    } catch (e) {
      print("Erreur de connexion avec Cognito : $e");
      _authStateController.add(null);  // Envoie null en cas d'échec
      return null;
    }
  }

  // Inscription de l'utilisateur
  Future<String?> signUpWithEmailPassword(String email, String password) async {
    try {
      final userAttributes = [
        AttributeArg(name: 'email', value: email),
      ];

      final signUpResult = await userPool.signUp(email, password, userAttributes: userAttributes);
      if (signUpResult != null) {
        return null;  // Inscription réussie
      } else {
        return 'Erreur lors de la création de l\'utilisateur';
      }
    } catch (e) {
      print("Erreur lors de l'inscription : $e");
      return e.toString();
    }
  }

  // Récupère la session d'un utilisateur avec son email
  Future<CognitoUserSession?> getSession(String email) async {
    final cognitoUser = CognitoUser(email, userPool);
    try {
      final session = await cognitoUser.getSession();
      return session;  // Retourne la session si disponible
    } catch (e) {
      print("Erreur lors de la récupération de la session : $e");
      return null;  // Retourne null en cas d'erreur
    }
  }

  // Méthode pour récupérer les groupes de l'utilisateur à partir de la session
  Future<List<String>> getUserGroups(CognitoUserSession session) async {
    try {
      final idToken = session.idToken;  // On accède au ID token
      final claims = idToken.payload;   // Récupère les claims de l'ID token

      // Récupérer les groupes à partir des claims (s'il y en a)
      final groups = claims['cognito:groups'] as List<dynamic>? ?? [];
      return groups.map((group) => group.toString()).toList();  // Convertir en liste de chaînes
    } catch (e) {
      print("Erreur de récupération des groupes : $e");
      return [];
    }
  }

  // Fonction de déconnexion
  Future<void> signOut() async {
    _authStateController.add(null);  // Envoie null dans le stream lors de la déconnexion
  }

  // Fonction pour surveiller l'état de l'authentification
  Stream<CognitoUser?> authStateChanges() {
    return _authStateController.stream;
  }
}

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论