92 lines
5.2 KiB
Markdown
92 lines
5.2 KiB
Markdown
# Correção: login falha ("Credenciais inválidas") para alguns usuários com senha correta
|
|
|
|
## Contexto
|
|
|
|
Usuários relatam, de forma intermitente entre pessoas (não para todos), que digitam a senha
|
|
correta e recebem "Credenciais inválidas". A hipótese inicial ("será que está logando mas
|
|
mostra erro?") foi **descartada**: em `src/app/lib/userLoginAction.js` o `signIn` em caso de
|
|
sucesso lança `NEXT_REDIRECT`, que é corretamente relançado (linhas 32-39), redirecionando para
|
|
`/dispatcher`. Não existe caminho de sucesso que ainda exiba o erro. Trata-se de uma **falha real
|
|
de autenticação** (nenhuma sessão é criada).
|
|
|
|
### Causa raiz
|
|
O `username` é **gravado normalizado** mas **consultado cru**:
|
|
|
|
- Schema `src/app/models/User.js:9-10` define `trim: true` + `lowercase: true`. O Mongoose aplica
|
|
isso em todo `save`/`create`, então no banco todo username está minúsculo e sem espaços.
|
|
- Login `src/app/lib/utils/auth.js:31-32` busca com o valor cru:
|
|
`User.findOne({ username: credentials.username })`. O MongoDB faz match **case-sensitive**.
|
|
|
|
Resultado: quem cadastrou `Joao` (salvo como `joao`) e faz login digitando `Joao` gera busca por
|
|
`"Joao"` → nenhum match → `null` → "Credenciais inválidas", **sem nem comparar a senha**.
|
|
|
|
### Por que "alguns sim, outros não"
|
|
Quem digita o usuário todo em minúsculo entra; quem digita com maiúscula/espaço falha **sempre**
|
|
(consistente por usuário, não aleatório). Gatilho principal: teclado de **celular** auto-capitaliza
|
|
a primeira letra, e o input de login (`src/app/auth/login/LoginForm.jsx:31-37`) não tem
|
|
`autoCapitalize`/`autoCorrect`/`autoComplete`. Autofill com espaço final tem o mesmo efeito. Daí o
|
|
padrão "mobile reclama, desktop não".
|
|
|
|
**Observação sobre dados:** não é necessária migração de banco. Como o Mongoose já força lowercase
|
|
em toda gravação, não há usernames mixed-case armazenados — apenas a consulta precisa ser corrigida.
|
|
|
|
## Abordagem (escopo robusto)
|
|
|
|
### 1. Normalizar a consulta no provider de auth (correção central)
|
|
`src/app/lib/utils/auth.js`
|
|
- Derivar um username normalizado uma vez e usá-lo na consulta:
|
|
```js
|
|
const username = (credentials.username || "").trim().toLowerCase();
|
|
const password = credentials.password;
|
|
...
|
|
const user = await User.findOne({ username }).lean();
|
|
```
|
|
- Remover o uso duplicado de `credentials.username` na linha 32 (usar a variável já tratada).
|
|
|
|
### 2. Normalizar também no server action de login
|
|
`src/app/lib/userLoginAction.js`
|
|
- Após `formData.get("username")`, normalizar antes de validar/enviar e antes de preencher
|
|
`rawData` (para que o `defaultValue` re-exibido no form já volte normalizado):
|
|
```js
|
|
const username = (formData.get("username") || "").trim().toLowerCase();
|
|
```
|
|
- Mantém o tratamento de `NEXT_REDIRECT`/`CredentialsSignin` como está.
|
|
|
|
### 3. Endurecer o input de login contra auto-capitalização (mobile)
|
|
`src/app/auth/login/LoginForm.jsx` — no `UIInput` de `name="username"` adicionar:
|
|
`autoCapitalize="none"`, `autoCorrect="off"`, `spellCheck={false}`, `autoComplete="username"`.
|
|
- Confirmar que `src/components/ui/input.jsx` repassa `...props` (já repassa), então os atributos
|
|
fluem para o `<input>` nativo.
|
|
|
|
### 4. Alinhar a checagem de duplicado no cadastro
|
|
`src/app/lib/users/createUserAction.js:131` — a verificação `findOne({ username })` usa o valor cru
|
|
e é case-sensitive, enquanto o `User.create` grava lowercased. Normalizar o `username` logo na
|
|
leitura (linha 24) para `(formData.get("username") || "").trim().toLowerCase()`, de modo que a
|
|
checagem de duplicado, a mensagem de erro re-exibida e o valor gravado fiquem consistentes. A
|
|
validação de "sem espaços" (linha 55) continua válida.
|
|
- Aplicar a mesma normalização de leitura em `createWardUserAction.js` (criação de ward) para
|
|
manter consistência, caso ele leia username de formData da mesma forma.
|
|
|
|
## Arquivos críticos
|
|
- `src/app/lib/utils/auth.js` — fix central da consulta (CRÍTICO)
|
|
- `src/app/lib/userLoginAction.js` — normalização do input do login
|
|
- `src/app/auth/login/LoginForm.jsx` — atributos anti auto-capitalize
|
|
- `src/app/lib/users/createUserAction.js` — consistência na checagem/gravação
|
|
- `src/app/lib/users/createWardUserAction.js` — mesma consistência
|
|
- (referência, sem alteração) `src/app/models/User.js`, `src/components/ui/input.jsx`
|
|
|
|
## Verificação
|
|
1. **Repro do bug (antes do fix):** com um usuário existente (ex.: `joao`), tentar login digitando
|
|
`Joao` ou `joao ` (com espaço) → deve dar "Credenciais inválidas".
|
|
2. **Depois do fix:**
|
|
- Login com `Joao`, `JOAO`, ` joao `, `joao` → todos devem autenticar e redirecionar para
|
|
`/dispatcher`.
|
|
- Senha errada → continua "Credenciais inválidas" (regressão de segurança garantida).
|
|
- Usuário inexistente → "Credenciais inválidas".
|
|
3. **Mobile:** abrir `/auth/login` em viewport mobile / dispositivo e confirmar que o campo Usuário
|
|
não auto-capitaliza a primeira letra.
|
|
4. **Cadastro:** registrar `Maria`; conferir no banco que foi salvo como `maria`; tentar cadastrar
|
|
`maria` de novo → "Nome de usuario ja cadastrado".
|
|
5. Rodar a app localmente (`npm run dev`) e exercitar os fluxos acima; rodar a suíte de testes se
|
|
existir.
|