From f941270bd9aa884ba0c3b73033acabc3c34ceabc Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Thu, 25 Jun 2026 15:26:47 -0500 Subject: [PATCH] feat: implement SMS OTP auth and fix access_token key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - verifyPhoneNumber / verifyPhoneNumberForLink: call POST /auth/send-otp - signInWithOTP: pass code to POST /auth/phone, use access_token key - linkPhoneWithOTP: pass code to POST /auth/verify-phone - login / register: fix token key data['token'] → data['access_token'] Co-Authored-By: Claude Sonnet 4.6 --- lib/providers/auth_provider.dart | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/lib/providers/auth_provider.dart b/lib/providers/auth_provider.dart index c54e931..c0b33e2 100644 --- a/lib/providers/auth_provider.dart +++ b/lib/providers/auth_provider.dart @@ -24,7 +24,7 @@ class AuthProvider extends ChangeNotifier { Future login(String email, String password) async { try { final data = await _api.post('/auth/login', {'email': email, 'password': password}); - await _api.saveToken(data['token'] as String); + await _api.saveToken(data['access_token'] as String); user = Usuario.fromDocument(data['user'] as Map); userAverageScore = await _loadAverageScore(user!.id); authStatus = AuthStatus.authenticated; @@ -44,7 +44,7 @@ class AuthProvider extends ChangeNotifier { 'password': password, 'name': name.trim(), }); - await _api.saveToken(data['token'] as String); + await _api.saveToken(data['access_token'] as String); user = Usuario.fromDocument(data['user'] as Map); authStatus = AuthStatus.authenticated; notifyListeners(); @@ -57,13 +57,18 @@ class AuthProvider extends ChangeNotifier { } Future verifyPhoneNumber(String phoneNumber) async { - // ponytail: backend does direct login by phone, no OTP step + try { + await _api.post('/auth/send-otp', {'phone': phoneNumber}); + } catch (e) { + NotificationsService.showSnackBarError('Error al enviar código SMS'); + rethrow; + } } Future signInWithOTP(String phoneNumber, String smsCode) async { try { - final data = await _api.post('/auth/phone', {'phone': phoneNumber}); - await _api.saveToken(data['token'] as String); + final data = await _api.post('/auth/phone', {'phone': phoneNumber, 'code': smsCode}); + await _api.saveToken(data['access_token'] as String); user = Usuario.fromDocument(data['user'] as Map); authStatus = AuthStatus.authenticated; notifyListeners(); @@ -71,24 +76,29 @@ class AuthProvider extends ChangeNotifier { } catch (e) { authStatus = AuthStatus.notAuthenticated; notifyListeners(); - NotificationsService.showSnackBarError('Error al iniciar sesión con teléfono'); + NotificationsService.showSnackBarError('Código incorrecto o expirado'); } } Future verifyPhoneNumberForLink(String phoneNumber) async { - // ponytail: no OTP step, linkPhoneWithOTP does the actual call + try { + await _api.post('/auth/send-otp', {'phone': phoneNumber}); + } catch (e) { + NotificationsService.showSnackBarError('Error al enviar código SMS'); + rethrow; + } } Future linkPhoneWithOTP(String phoneNumber, String smsCode) async { try { - await _api.post('/auth/verify-phone', {'phone': phoneNumber}); + await _api.post('/auth/verify-phone', {'phone': phoneNumber, 'code': smsCode}); user = await _fetchMe(); NotificationsService.showSnackbar('Número vinculado exitosamente'); authStatus = AuthStatus.authenticated; notifyListeners(); NavigationService.replaceTo(Flurorouter.profileRoute); } catch (e) { - NotificationsService.showSnackBarError('Error al vincular teléfono'); + NotificationsService.showSnackBarError('Código incorrecto o expirado'); } }