Pular para o conteúdo principal

Endpoints de autenticação

Grupo /auth/* — criação de conta, login, gestão de sessão, reset de senha e convites de organização.

Tabela de endpoints

MétodoCaminhoAuthDescrição
POST/auth/bootstrapPública (1x)Bootstrap do primeiro admin quando a instância está vazia.
GET/auth/bootstrap-statusPúblicaVerifica se bootstrap ainda está disponível.
POST/auth/register-organizationPúblicaCria uma nova organização e seu primeiro admin.
POST/auth/loginPúblicaLogin com email e senha. Retorna sessão + cookie.
GET/auth/meSessãoSessão atual, usuário e organizações.
PATCH/auth/me/localeSessãoAtualiza a preferência de idioma do usuário.
POST/auth/logoutSessãoEncerra a sessão atual.
POST/auth/password-reset/requestPúblicaSolicita envio de email com link de reset.
POST/auth/password-reset/confirmPúblicaConfirma novo password com token do email.
GET/auth/organizations/{organization_id}/membersSessãoLista membros da organização.
POST/auth/organizations/{organization_id}/membersSessão (member:manage)Adiciona membro diretamente (sem convite).
GET/auth/organizations/{organization_id}/invitationsSessãoLista convites pendentes.
POST/auth/organizations/{organization_id}/invitationsSessão (member:manage)Cria um convite por email.
GET/auth/invitations/{token}PúblicaBusca o convite pelo token (para a tela de aceite).
POST/auth/invitations/{token}/acceptPúblicaAceita o convite e cria o usuário.

POST /auth/bootstrap

Cria o primeiro administrador e a primeira organização de uma instância zerada. Funciona apenas uma vez — depois disso responde 409.

Request body (AuthBootstrapRequest):

{
"organization_name": "Acme Security",
"organization_description": "SOC interno",
"email": "admin@acme.com",
"display_name": "Admin Inicial",
"password": "senha-forte-aqui"
}

Validações:

  • organization_name — 1–120 chars.
  • email — RFC válido, 3–254 chars.
  • display_name — 1–120 chars.
  • password — mínimo 10 chars.

Response 200 (AuthSessionResponse) — ver estrutura da sessão.

Erros:

  • 409 conflict — bootstrap já foi feito. Use /auth/login.

GET /auth/bootstrap-status

Indica se o bootstrap ainda está aberto e se o self-signup está habilitado.

Response 200:

{
"bootstrap_available": false,
"registration_enabled": true
}

POST /auth/register-organization

Mesmo schema de bootstrap, mas cria uma nova organização em uma instância que já tem outras. Depende de NATIVE_WAZUH_SELF_SIGNUP_ENABLED=true.

Request body: idêntico a AuthBootstrapRequest.

Response 200: AuthSessionResponse.

Erros:

  • 403 forbidden — self-signup desabilitado.
  • 409 conflict — email já cadastrado.
  • 429 rate_limited — mais de 10 registros/hora por IP.

POST /auth/login

Login com email + senha. Retorna a sessão no body e grava cookie.

Request body (LoginRequest):

{
"email": "admin@acme.com",
"password": "senha-forte-aqui",
"organization_id": "org_abc123"
}
  • organization_id é opcional — usado quando o usuário pertence a várias organizações e quer forçar uma.

Response 200 (AuthSessionResponse):

{
"access_token": "eyJhbGciOi…",
"token_type": "bearer",
"expires_at": "2026-04-25T03:30:00Z",
"user": {
"id": "usr_...",
"email": "admin@acme.com",
"display_name": "Admin Inicial",
"is_active": true,
"is_platform_admin": false,
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-04-24T12:00:00Z"
},
"organizations": [ { "id": "org_abc123", "slug": "acme", "name": "Acme Security", "role": "org_admin", "is_active": true, "...": "..." } ],
"current_organization": { "id": "org_abc123", "...": "..." },
"memberships": [ { "id": "mem_...", "organization_id": "org_abc123", "user_id": "usr_...", "role": "org_admin", "...": "..." } ]
}

Além do body, a resposta também grava o cookie:

Set-Cookie: ruleforge_session=<jwt>; HttpOnly; SameSite=Lax

Exemplo curl:

curl -X POST "$RF_BASE/auth/login" \
-H "Content-Type: application/json" \
-d '{"email":"admin@acme.com","password":"senha-forte-aqui"}'

Erros:

  • 401 unauthorized — email/senha inválidos.
  • 403 forbidden — usuário inativo ou organização suspensa.
  • 429 rate_limited — mais de 5 tentativas em 15 min.

GET /auth/me

Retorna a sessão ativa. Útil para o frontend renderizar o estado após refresh.

Auth: sessão (cookie ou Authorization: Bearer <jwt>).

Response 200: AuthSessionResponse — mesma estrutura do login. access_token é cookie-session quando vindo de cookie (o JWT real está no cookie).

PATCH /auth/me/locale

Muda a preferência de idioma do usuário logado.

Request body (UserLocaleUpdateRequest):

{ "locale": "pt-BR" }

Valores aceitos: "pt-BR", "en", ou null (limpa a preferência, usa o detectado pelo browser).

Response 200: {"status":"ok"}.

POST /auth/logout

Revoga a sessão atual (invalida o jti no servidor) e limpa o cookie.

Auth: sessão.

Response 200: {"status":"logged_out"}.

POST /auth/password-reset/request

Solicita envio de email com link de reset. Sempre retorna 200, mesmo se o email não existir — para não vazar quais usuários estão cadastrados.

Request body (PasswordResetRequestInput):

{ "email": "admin@acme.com" }

Response 200: {"status":"ok"}.

POST /auth/password-reset/confirm

Define nova senha usando o token que veio no email.

Request body (PasswordResetConfirmInput):

{
"token": "reset-token-do-email",
"new_password": "nova-senha-forte"
}
  • token — 1–256 chars.
  • new_password — mínimo 10 chars.

Response 200: {"status":"ok"}.

Erros:

  • 400 bad_request — token expirado ou inválido.

GET /auth/organizations/{organization_id}/members

Lista todos os membros da organização.

Auth: sessão. O usuário precisa pertencer à organização.

Response 200: array de OrganizationMembershipRecord:

[
{
"id": "mem_...",
"organization_id": "org_abc123",
"user_id": "usr_...",
"email": "analyst@acme.com",
"display_name": "Analista",
"role": "engineer",
"created_at": "...",
"updated_at": "..."
}
]

POST /auth/organizations/{organization_id}/members

Adiciona membro sem convite — cria o usuário com senha já definida. Útil para provisionamento automatizado.

Auth: sessão com permissão member:manage (papel org_admin).

Request body (OrganizationMemberCreateRequest):

{
"email": "analyst@acme.com",
"display_name": "Novo analista",
"password": "senha-forte",
"role": "engineer"
}
  • roleread_only.

Response 200: OrganizationMembershipRecord.

GET /auth/organizations/{organization_id}/invitations

Lista convites pendentes/aceitos/expirados.

Response 200: array de OrganizationInvitationRecord.

POST /auth/organizations/{organization_id}/invitations

Envia convite por email para um futuro membro.

Request body (OrganizationInvitationCreateRequest):

{
"email": "convidado@acme.com",
"role": "reviewer"
}

Response 200: OrganizationInvitationRecord com token, status, expires_at.

GET /auth/invitations/{token}

Busca o convite pelo token (usado pela tela pública de aceite).

Auth: pública.

Response 200: OrganizationInvitationRecord.

POST /auth/invitations/{token}/accept

Aceita o convite, cria o usuário (se necessário) e abre sessão.

Request body (OrganizationInvitationAcceptRequest):

{
"display_name": "Nome Visível",
"password": "senha-forte"
}
  • display_name é opcional quando o usuário já existe.
  • password — mínimo 10 chars.

Response 200: AuthSessionResponse.

Estruturas compartilhadas

AuthSessionResponse

{
"access_token": "string (JWT ou 'cookie-session')",
"token_type": "bearer",
"expires_at": "ISO 8601 UTC",
"user": "UserRecord",
"organizations": ["OrganizationRecord[]"],
"current_organization": "OrganizationRecord",
"memberships": ["OrganizationMembershipRecord[]"]
}

UserRecord

{
"id": "string",
"email": "string",
"display_name": "string",
"is_active": true,
"is_platform_admin": false,
"created_at": "ISO 8601",
"updated_at": "ISO 8601"
}

OrganizationRecord

{
"id": "string",
"slug": "string",
"name": "string",
"description": "string",
"role": "org_admin | security_content_lead | reviewer | engineer | read_only | null",
"is_active": true,
"created_at": "ISO 8601",
"updated_at": "ISO 8601"
}

OrganizationInvitationRecord

{
"id": "string",
"organization_id": "string",
"email": "string",
"role": "EnterpriseRole",
"token": "string",
"status": "pending | accepted | expired | linked",
"expires_at": "ISO 8601",
"created_at": "ISO 8601"
}