API ReferenceAuth
DELETE /auth/google/link
Desvincular conta Google (autenticado)
DELETE
/auth/google/linkAuth: accessTokenRemove o vínculo entre a conta atual e o Google. Apaga users.google_id e users.google_linked_at. Falha se a conta não tem senha local definida — caso contrário a conta ficaria sem método de login (orfã).
Quando chamar
- Tela "Configurações → Conexões" → botão "Desvincular Google"
- Antes de desvincular, garantir que o user tem senha local. Se não tiver, primeiro chamar
POST /auth/set-password
Request
Esta requisição não tem corpo.
Sem body. Header obrigatório: Authorization: Bearer <accessToken>.
Response
204
object400
| Campo | Tipo | Requerido | Descrição |
|---|---|---|---|
| error | string | sim | Mensagem ou código tipado do erro. Códigos canônicos: EMAIL_ALREADY_EXISTS, INVALID_CREDENTIALS, INVALID_RESET_TOKEN, PASSWORD_ALREADY_SET, USER_NOT_FOUND. |
404
| Campo | Tipo | Requerido | Descrição |
|---|---|---|---|
| error | string | sim | Mensagem ou código tipado do erro. Códigos canônicos: EMAIL_ALREADY_EXISTS, INVALID_CREDENTIALS, INVALID_RESET_TOKEN, PASSWORD_ALREADY_SET, USER_NOT_FOUND. |
409
| Campo | Tipo | Requerido | Descrição |
|---|---|---|---|
| error | string | sim | Mensagem ou código tipado do erro. Códigos canônicos: EMAIL_ALREADY_EXISTS, INVALID_CREDENTIALS, INVALID_RESET_TOKEN, PASSWORD_ALREADY_SET, USER_NOT_FOUND. |
204 No Content.
Erros
| Status | Códigos possíveis (extraídos do schema) |
|---|---|
| 400 | Mensagem ou código tipado do erro |
| 404 | Mensagem ou código tipado do erro |
| 409 | Mensagem ou código tipado do erro |
Como resolver cada caso:
| Status | Código | Causa | Como resolver |
|---|---|---|---|
| 401 | (sem corpo) | JWT ausente/inválido | Refresh ou login |
| 404 | USER_NOT_FOUND | User do JWT não existe mais | Logout + re-login |
| 404 | GOOGLE_NOT_LINKED | Conta atual nunca vinculou Google | Não há ação — a conta não está vinculada |
| 409 | PASSWORD_REQUIRED_BEFORE_UNLINK | Conta não tem password_hash | Chame POST /auth/set-password primeiro, depois retente |
Exemplos
curl -X DELETE 'http://localhost:3003/auth/google/link' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer SEU_ACCESS_TOKEN' \
-d '{}'await fetch('http://localhost:3003/auth/google/link', {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer ' + accessToken,
},
body: JSON.stringify({}),
})Fluxo no frontend
async function unlinkGoogle() {
const r = await fetch('/auth/google/link', {
method: 'DELETE',
headers: { Authorization: `Bearer ${accessToken}` },
})
if (r.status === 204) return // sucesso
const { error } = await r.json()
if (error === 'PASSWORD_REQUIRED_BEFORE_UNLINK') {
// Mostrar modal "Defina uma senha antes de desvincular"
promptSetPasswordFirst()
} else {
showError(error)
}
}Side effects
- DB:
UPDATE users SET google_id = NULL, google_linked_at = NULL WHERE id = userId - NÃO mexe em refresh_tokens — a sessão atual continua válida
- Avatar do Google permanece (
users.avatar_urlnão é tocado) — o user pode trocar manualmente depois - Sem notificação ou socket
Relacionados
- Endpoint:
POST /auth/set-password— pré-requisito quando não há senha local - Endpoint:
GET /auth/google/link— vincular novamente depois (operação inversa) - Tabela:
users— camposgoogle_id,google_linked_at