Fluxo de Recuperação de Senha
Escopo: Recuperação e atualização de senha no app Flutter (Coezzion Vendas)
Data: 2026-07-06
1. Resumo
O fluxo de recuperação de senha permite que o usuário redefina sua senha de acesso sem estar autenticado. O processo segue quatro etapas principais:
- Informar o CPF
- Escolher o método de verificação (SMS ou E-mail)
- Validar o código de 6 dígitos recebido
- Definir a nova senha
Após a troca bem-sucedida, o app remove as credenciais biométricas salvas e redireciona o usuário à tela de login com CPF e nova senha preenchidos.
O fluxo é protegido por tokens de API (x-api-key) obtidos via Firebase Remote Config, sem necessidade de autenticação JWT do usuário.
2. Pontos de Entrada
Existem dois caminhos que levam ao mesmo fluxo de recuperação:
| Entrada | Condição | Arquivo |
|---|---|---|
| Botão "Esqueci minha senha" na tela de login | enable_forgot_password == true (Remote Config) | lib/controllers/login/login_controller.dart |
| Atualização obrigatória após login | auth.needChangePassword == true na resposta de autenticação | lib/screens/login/login_manager.dart |
No segundo caso, um bottom sheet informa que a senha precisa ser atualizada por novos recursos de segurança. Se o usuário confirmar, é redirecionado para a mesma tela de CPF do fluxo de recuperação.
3. Fluxo Principal
Passo a passo
| Etapa | Tela | Ação do usuário | Chamada API |
|---|---|---|---|
| 1 | ForgotPasswordScreen | Informa CPF e toca CONTINUAR | POST /api/auth/recover-methods/{cpf} |
| 2 | UpdateUserContactByMethodsScreen | Escolhe Telefone (SMS) ou E-mail | — |
| 3 | CodeVerificationByMethodScreen | Aguarda código e informa 6 dígitos | POST /api/auth/verify-recover-method (envio) + POST /api/auth/verify-code-recover (validação) |
| 4 | ForgotPasswordNewPasswordScreen | Define e confirma nova senha | POST /api/auth/change-password |
| 5 | LoginScreen | Faz login com nova senha | — |
4. Endpoints
Base URL dinâmica: {baseUrl} obtida via PrefsService.getEnvConfig().
4.1 Fluxo principal
| # | Método | Endpoint | Controller | Request Body | Resposta relevante |
|---|---|---|---|---|---|
| 1 | POST | /api/auth/recover-methods/{cpf} | ForgotPasswordController.findRecoverMethods | {} (corpo vazio) | success[] com {type, maskedValue} |
| 2 | POST | /api/auth/verify-recover-method | CodeVerificationByMethodScreenController.sendCode | {cpf, type} | Confirmação de envio do código |
| 3 | POST | /api/auth/verify-code-recover | CodeVerificationByMethodScreenController.verifyCode | {cpf, type, verificationCode} | success.token para troca de senha |
| 4 | POST | /api/auth/change-password | ForgotPasswordNewPasswordController.finish | {token, cpf, password} | success.title, success.message |
Detalhes dos payloads:
// POST /api/auth/verify-recover-method
{ "cpf": "12345678900", "type": "sms" }
// POST /api/auth/verify-code-recover
{ "cpf": "12345678900", "type": "sms", "verificationCode": "123456" }
// POST /api/auth/change-password
{ "token": "<token>", "cpf": "12345678900", "password": "novaSenha1" }
Resposta de recover-methods (sucesso):
{
"isSuccess": true,
"success": [
{ "type": "sms", "maskedValue": "(**) *****-1234" },
{ "type": "email", "maskedValue": "u***@email.com" }
]
}
Resposta de verify-code-recover (sucesso):
{
"isSuccess": true,
"success": {
"userCpf": "12345678900",
"contact": "(**) *****-1234",
"token": "<token>",
"expirationDate": "2026-07-06T12:00:00Z"
}
}
Constantes definidas em lib/shared/utils/api_utils.dart:
static Future<String> getRecoverMethodsUrl({required String cpf}) async {
return '${await _getBaseUrl}$authApi/recover-methods/$cpf';
}
static Future<String> getRecoverMethodsValidateCodeUrl() async {
return '${await _getBaseUrl}$authApi/verify-code-recover';
}
static Future<String> getRecoverMethodSendCodeUrl() async {
return '${await _getBaseUrl}$authApi/verify-recover-method';
}
static const forgetPasswordChangePassword = '$authApi/change-password';
4.2 Endpoints legados (atualização de contato)
Usados no sub-fluxo quando o usuário não recebe o código SMS e precisa atualizar telefone ou e-mail antes de reiniciar a recuperação (CodeVerificationByMethodScreenController.tryAnotherMethod).
| Método | Endpoint | Uso |
|---|---|---|
| POST | /api/auth/verify-phone | Enviar código SMS (fluxo legado de atualização de telefone) |
| POST | /api/auth/verify-email | Enviar código por e-mail (fluxo legado de atualização de e-mail) |
| POST | /api/auth/verify-code | Validar código (sem sufixo -recover) |
| POST | /api/auth/change-cellphone | Atualizar telefone após validação |
| POST | /api/auth/change-email | Atualizar e-mail após validação |
| — | /api/auth/{cpf}/cellphone | Configurado em ForgotPasswordProvider, mas não utilizado pelo controller atual |
5. Telas e Navegação
5.1 Telas do fluxo principal
Rota (AppRoutes) | Constante | Tela | Título exibido | Controller |
|---|---|---|---|---|
/forgot_password | changePassword | ForgotPasswordScreen | Atualizar senha | ForgotPasswordController |
/update_user_contact_by_methods | updateUserContactByMethods | UpdateUserContactByMethodsScreen | Opções de atualização | UpdateUserContactByMethodsController |
/code_verification_by_method | codeVerificationByMethod | CodeVerificationByMethodScreen | Código de verificação | CodeVerificationByMethodScreenController |
/forgot_password_new_password | forgotPasswordNewPassword | ForgotPasswordNewPasswordScreen | Atualizar senha | ForgotPasswordNewPasswordController |
/login | login | LoginScreen | — | LoginController |
Nota: A rota
AppRoutes.changePasswordaponta para/forgot_passworde renderizaForgotPasswordScreen— o nome da constante é legado, mas representa a tela de entrada do fluxo de recuperação.
5.2 Argumentos de navegação
| Tela | Classe de argumentos | Campos |
|---|---|---|
ForgotPasswordScreen | ForgotPasswordScreenArguments | rememberCpfOnLogin |
UpdateUserContactByMethodsScreen | UpdateUserContactByMethodsScreenArgument | availableMethods, customAuthorizationToken, cpf, rememberCpfOnLogin |
CodeVerificationByMethodScreen | CodeVerificationByMethodScreenArguments | verifyMethodsSuccessResponseItem, options, customAuthorizationToken, cpf, rememberCpfOnLogin, hasConfirmedEmail |
ForgotPasswordNewPasswordScreen | ForgotPasswordNewPasswordScreenArguments | token, cpf, rememberCpfOnLogin |
LoginScreen (retorno) | LoginScreenArguments | cpf, password, rememberCpf |
5.3 Telas auxiliares (atualização de contato)
| Rota | Tela | Quando é acionada |
|---|---|---|
/update_phone | UpdatePhoneScreen | Usuário excede limite de tentativas SMS e opta por atualizar telefone |
/code_verification_by_phone | CodeVerificationByPhoneScreen | Verificação SMS legada após informar novo telefone |
/update_email | UpdateEmailScreen | Usuário troca método de verificação para e-mail |
/code_verification_by_email | CodeVerificationByEmailScreen | Verificação e-mail legada após informar novo e-mail |
6. Keys e Configurações
6.1 Firebase Remote Config
| Key | Tipo | Propriedade Dart | Uso |
|---|---|---|---|
enable_forgot_password | bool | FirebaseRemoteConfigService.dictionary.enableForgotPassword | Controla visibilidade do botão "Esqueci minha senha" no login |
recover_methods_token | string | FirebaseRemoteConfigService.dictionary.recoverMethodsToken | Valor do header x-api-key para endpoints de recuperação |
recover_password_token | string | FirebaseRemoteConfigService.dictionary.recoverPasswordToken | Valor do header x-api-key para paths contendo cellphone |
Definições em lib/services/firebase_remote_config_service.dart (FirebaseRemoteConfigKeysEnum).
6.2 Headers HTTP e Interceptors
| Header | Interceptor | Condição de aplicação | Valor |
|---|---|---|---|
x-api-key | VerifyMethodsInterceptor | Path contém: recover-methods, verify-recover-method, verify-email, verify-phone, verify-code, verify-code-recover, change-password | recover_methods_token |
x-api-key | RecoverPasswordInterceptor | Path contém: cellphone | recover_password_token |
Authorization | ChangePasswordInterceptor | Fluxos com customAuthorizationToken (atualização de contato autenticada) | Token Bearer customizado |
Interceptors registrados globalmente em DioUtils._addInterceptor:
dio.interceptors.add(RecoverPasswordInterceptor());
dio.interceptors.add(VerifyMethodsInterceptor());
7. Modelos de Request/Response
Requests
| Modelo | Campos | Endpoint |
|---|---|---|
SendCodeVerificationByMethodsRequest | cpf, type | verify-recover-method |
ValidateCodeVerificationByMethodsRequest | cpf, type, verificationCode | verify-code-recover |
ForgotPasswordChangePasswordRequest | token, cpf, password | change-password |
Responses
| Modelo | Campos relevantes |
|---|---|
VerifyMethodsResponse | isSuccess, success[] (type, maskedValue), error (title, message, needConfirm) |
SendCodeVerificationByMethodsResponse | isSuccess, success/error |
ValidateCodeVerificationByMethodsResponse | isSuccess, success.token, success.expirationDate, error.message |
ForgotPasswordChangePasswordResponse | isSuccess, success (title, message), error (title, message, needConfirm) |
8. Regras de Negócio
Validação de senha
A nova senha deve atender todos os critérios (validados em tempo real em ForgotPasswordNewPasswordController):
- Mínimo de 6 caracteres
- Pelo menos 1 número
- Pelo menos 1 letra
- Confirmação idêntica à senha informada
Timer de reenvio de código
- Intervalo de 2 minutos entre solicitações de reenvio
- Controlado por
CodeVerificationTimerController(instâncias separadas para SMS e E-mail via DI tags) - Botão "Reenviar código" habilitado apenas após expiração do timer
Limite de tentativas SMS
Implementado em PhoneCodeVerificationCounterService:
- Máximo de 3 tentativas de SMS em 1 hora (0 em modo debug)
- Após exceder o limite, exibe bottom sheet oferecendo validação por e-mail
- Regra só se aplica quando o usuário possui e-mail cadastrado (
hasConfirmedEmail == true)
Comportamento pós-troca de senha
| Cenário | Comportamento |
|---|---|
| Sucesso | Remove biometria, exibe bottom sheet de confirmação, redireciona ao login com CPF/senha preenchidos (Get.offAllNamed) |
| Erro | Exibe bottom sheet com mensagem de erro, retorna à tela de CPF (Get.offNamed → /forgot_password) |
Tratamento de erros em recover-methods
| Condição | Comportamento |
|---|---|
error.needConfirm == true | Exibe bottom sheet informativo |
error.needConfirm == false | Exibe mensagem de erro inline no campo CPF |
9. Diagramas
9.1 Fluxo completo com decisões
9.2 Sequência de chamadas API
9.3 Tratamento de erros
9.4 Sub-fluxo de atualizaç ão de contato
Acionado quando o usuário excede o limite de tentativas SMS ou opta por atualizar telefone/e-mail durante a verificação.
10. Arquivos Relacionados
Controllers
| Arquivo | Responsabilidade |
|---|---|
lib/controllers/forgot_password/forgot_password_controller.dart | CPF e chamada recover-methods |
lib/controllers/forgot_password/forgot_password_new_password_controller.dart | Nova senha e chamada change-password |
lib/controllers/code_verification/by_method/code_verification_by_method_controller.dart | Envio e validação de código no fluxo principal |
lib/controllers/update_user_contact_by_methods/update_user_contact_by_methods_controller.dart | Navegação para verificação por método |
lib/controllers/login/login_controller.dart | Entrada via "Esqueci minha senha" |
lib/controllers/code_verification/phone/code_verification_by_phone_controller.dart | Verificação SMS legada |
lib/controllers/code_verification/email/code_verification_by_email_controller.dart | Verificação e-mail legada |
lib/controllers/update_phone/update_phone_controller.dart | Atualização de telefone |
lib/controllers/update_email/update_email_controller.dart | Atualização de e-mail |
Screens
| Arquivo | Rota |
|---|---|
lib/screens/forgot_password/forgot_password_screen.dart | /forgot_password |
lib/screens/forgot_password/forgot_password_new_password_screen.dart | /forgot_password_new_password |
lib/screens/update_user_contact_by_methods/update_user_contact_by_methods_screen.dart | /update_user_contact_by_methods |
lib/screens/code_verification/by_method/code_verification_by_method_screen.dart | /code_verification_by_method |
lib/screens/code_verification/phone/code_verification_by_phone_screen.dart | /code_verification_by_phone |
lib/screens/code_verification/email/code_verification_by_email_screen.dart | /code_verification_by_email |
lib/screens/update_phone/update_phone_screen.dart | /update_phone |
lib/screens/update_email/update_email_screen.dart | /update_email |
lib/screens/login/login_screen.dart | /login |
lib/screens/login/login_manager.dart | Entrada obrigatória (needChangePassword) |
Providers
| Arquivo | URL base |
|---|---|
lib/providers/forgot_password/forgot_password_provider.dart | api/auth/{cpf}/cellphone (legado, não usado) |
lib/providers/forgot_password/forgot_password_new_password_provider.dart | api/auth/change-password |
lib/providers/code_verification/by_method/code_verification_by_method_provider.dart | URL dinâmica via controller |
Models
| Arquivo | Descrição |
|---|---|
lib/models/forgot_password/verify_methods_response.dart | Resposta de recover-methods |
lib/models/forgot_password/forgot_password_change_password_request.dart | Request de change-password |
lib/models/forgot_password/forgot_password_change_password_response.dart | Resposta de change-password |
lib/controllers/forgot_password/send_code_verification_by_methods_request.dart | Request de envio de código |
lib/controllers/forgot_password/send_code_verification_by_methods_response.dart | Resposta de envio de código |
lib/controllers/forgot_password/validate_code_verification_by_methods_request.dart | Request de validação de código |
lib/controllers/forgot_password/validate_code_verification_by_methods_response.dart | Resposta de validação de código |
Middlewares e infraestrutura
| Arquivo | Descrição |
|---|---|
lib/middlewares/http/recover_methods_interceptor.dart | Injeta x-api-key para endpoints de recover |
lib/middlewares/http/recover_password_interceptor.dart | Injeta x-api-key para paths com cellphone |
lib/middlewares/http/change_password.dart | Injeta Authorization para fluxos autenticados |
lib/shared/utils/api_utils.dart | Constantes e builders de URL |
lib/shared/utils/dio_utils.dart | Registro de interceptors |
lib/shared/routes/app_routes.dart | Constantes de rotas |
lib/shared/routes/app_pages.dart | Registro de páginas GetX |
lib/services/firebase_remote_config_service.dart | Keys de Remote Config |
lib/screens/code_verification/by_method/code_verification_counter_service.dart | Controle de tentativas SMS |