> For the complete documentation index, see [llms.txt](https://portal-integracao.intelbras.com.br/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://portal-integracao.intelbras.com.br/defense-ia-and-lite/readme/autenticacao-via-api-passo-a-passo.md).

# Autenticação via API (passo a passo)

Passo a passo do login em duas etapas na API do Defense IA, com geração da assinatura MD5 (5x), envio da publicKey do cliente, uso do X-Subject-Token, keepAlive e updateToken.

## Pré‑requisitos essenciais

* **Par de chaves RSA** do cliente (para enviar a **publicKey** em Base64 X.509 no 2º login).
* Relógio sincronizado (NTP). Diferenças de tempo atrapalham a janela de uso de `randomKey`.
* Usar **HTTPS** sempre que disponível.

## Glossário rápido

* **Realm**: Identificador lógico do domínio de autenticação.
* **RandomKey**: Desafio de curta duração (segundos) recebido no 1º login.
* **EncryptType**: Algoritmo para a *signature* (no Defense IA, **MD5**).
* **Publickey**: Chave pública RSA da **plataforma** (retornada no 1º login).
* **PublicKey**: Chave pública **do cliente** (enviada no 2º login, Base64 X.509).
* **SecretKey / SecretVector**: Chaves **AES** que a plataforma envia cifradas via RSA (usadas para cifrar cargas sensíveis em **AES/CBC/PKCS7**).
* **Token**: Credencial de sessão para chamadas de API (header `X-Subject-Token`).
* **Credential**: T*oken* específico para **imagens** (via `?token=...` na URL), diferente de `X-Subject-Token`.
* **Duration**: Intervalo (s) para *heartbeat*.
* **TokenRate**: Validade total do token de sessão (ex.: \~1800 s ≈ 30 min).

## Visão geral

### Autenticação em duas etapas resumida:

{% stepper %}
{% step %}

### Primeiro Login (desafio)

* Requisição inicial que retorna 401 com parâmetros necessários para calcular a assinatura do segundo login.
* Endpoint: `POST /brms/api/v1.0/accounts/authorize`
* Resposta 401 inclui: `realm`, `randomKey`, `encryptType=MD5`, `publickey`.
  {% endstep %}

{% step %}

### Segundo Login (autenticação)

* Envie `signature` (MD5 5x), sua `publicKey` (cliente) e dados do usuário.
* Endpoint: `POST /brms/api/v1.0/accounts/authorize`
* Resposta 200 inclui: `token`, `duration`, `tokenRate`, `secretKey`, `secretVector`, `credential`.
* Observação: execute logo após o 1º login; `randomKey` expira rápido.
  {% endstep %}

{% step %}

### Heartbeat

* Mantenha a sessão viva chamando `PUT /keepalive` periodicamente (veja `duration`).
* Pode atualizar `duration` e ocasionalmente o próprio `token`.
  {% endstep %}

{% step %}

### Update Token

* Antes de `tokenRate`, renove com `POST /updateToken` para obter um novo `token`.
* Gera um novo `token`; troque imediatamente.
  {% endstep %}

{% step %}

### Logout

* Encerre a sessão com `POST /unauthorize`.
* Invalida a sessão atual.
  {% endstep %}
  {% endstepper %}

{% hint style="warning" %}
Dica: faça o 2º login logo após o 1º (a `randomKey` expira rápido — pense em \~10 s).
{% endhint %}

#### Diagrama de sequência (alto nível)

<figure><img src="https://3558738335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fu2gr1s2Izdazx5BlQHLu%2Fuploads%2FwfASjOLDhP2BSbj7ObeR%2FCI_CD%20Pipeline%20with%20Lint%20_%20Mermaid%20Chart-2025-12-15-154307.png?alt=media&amp;token=d533cbcd-ced4-4d43-b2ba-2fa9ac67e8c6" alt=""><figcaption></figcaption></figure>

#### Endpoints (tabela de bolso)

| Ação                    |                              Método/Path | Header            | Corpo (chaves principais)                                       | Retorno principal                                                                       | Quando usar                |
| ----------------------- | ---------------------------------------: | ----------------- | --------------------------------------------------------------- | --------------------------------------------------------------------------------------- | -------------------------- |
| 1º Login (desafio)      | `POST /brms/api/v1.0/accounts/authorize` | —                 | `userName`, `clientType="WINPC_V2"`, `ipAddress`                | **401** com `realm`, `randomKey`, `encryptType`, `publickey`                            | Sempre inicia por aqui     |
| 2º Login (autenticação) |                        `POST /authorize` | —                 | `signature`, `randomKey`, `publicKey`, `userName`, `clientType` | **200** com `token`, `duration`, `tokenRate`, `secretKey`, `secretVector`, `credential` | Até \~10 s após o 1º login |
| Heartbeat               |                         `PUT /keepalive` | `X-Subject-Token` | `{}`                                                            | **200** (pode atualizar `duration`/`token`)                                             | A cada \~`duration*0,75`   |
| Atualizar token         |                      `POST /updateToken` | `X-Subject-Token` | `signature = md5(temp4+":"+token_atual)`                        | **200** com **novo**`token`                                                             | Antes de `tokenRate`       |
| Logout                  |                      `POST /unauthorize` | `X-Subject-Token` | `{}`                                                            | **200**                                                                                 | Ao encerrar                |

{% hint style="info" %}
Observação: clientType obrigatório: use `WINPC_V2`.
{% endhint %}

## Passo a passo detalhado

{% stepper %}
{% step %}

### Primeiro Login (desafio)

Request:

{% code title="Request" %}

```http
POST /brms/api/v1.0/accounts/authorize
Content-Type: application/json;charset=UTF-8
{
  "userName": "<usuario>",
  "ipAddress": "",
  "clientType": "WINPC_V2"
}
```

{% endcode %}

Esperado: `401` com `realm`, `randomKey`, `encryptType=MD5`, `publickey`.
{% endstep %}

{% step %}

### Segundo Login (autenticação)

Como calcular a signature (5x MD5):

```
temp1 = md5(password)
temp2 = md5(userName + temp1)
temp3 = md5(temp2)
temp4 = md5(userName + ":" + realm + ":" + temp3)
signature = md5(temp4 + ":" + randomKey)
```

```
Use hex minúsculo (32 chars) em todos os passos.
```

Request:

{% code title="Request" %}

```http
POST /brms/api/v1.0/accounts/authorize
Content-Type: application/json;charset=UTF-8
{
  "mac": "C8:D9:D2:16:AF:F6",
  "signature": "<assinatura_MD5>",
  "userName": "<usuario>",
  "randomKey": "<do primeiro login>",
  "publicKey": "<RSA_X509_Base64_do_cliente>",
  "encryptType": "MD5",
  "ipAddress": "",
  "clientType": "WINPC_V2",
  "userType": "0"
}
```

{% endcode %}

Resposta (200) inclui: `token`, `duration`, `tokenRate`, `secretKey`, `secretVector`, `credential`, além de metadados (`userId`, `versionInfo`, ...).
{% endstep %}

{% step %}

### Heartbeat (mantendo a sessão viva)

Quando: a cada `~duration * 0,75` (ex.: `duration=30` → \~22 s).

Request:

{% code title="Request" %}

```http
PUT /brms/api/v1.0/accounts/keepalive
X-Subject-Token: <token>
Content-Type: application/json;charset=UTF-8
{}
```

{% endcode %}

Resposta (200): pode atualizar `duration` e, ocasionalmente, o próprio `token`.
{% endstep %}

{% step %}

### Update Token (renovação)

Por quê: o `token` expira após `tokenRate` (≈ 30 min típico). Renove alguns minutos antes.

Assinatura para update:

```
signature = md5(temp4 + ":" + token_atual)
```

```
`temp4` é reutilizado do cálculo do 2º login.
```

Request:

{% code title="Request" %}

```http
POST /brms/api/v1.0/accounts/updateToken
X-Subject-Token: <token_atual>
Content-Type: application/json;charset=UTF-8
{
  "signature": "<md5(temp4 + ':' + token_atual)>"
}
```

{% endcode %}

Resposta (200): retorna **novo** `token` (troque de imediato). O antigo é invalidado pouco depois.
{% endstep %}

{% step %}

### Logout (encerrar sessão)

Request:

{% code title="Request" %}

```http
POST /brms/api/v1.0/accounts/unauthorize
X-Subject-Token: <token>
Content-Type: application/json;charset=UTF-8
{}
```

{% endcode %}

Efeito: invalida a sessão atual.
{% endstep %}
{% endstepper %}

## Linha do tempo (exemplo prático)

Suponha `duration = 30 s` e `tokenRate = 1800 s`:

* t=0: 1º login (401) → 2º login (200) → recebe `token`.
* t=22 s: primeiro *heartbeat* (`PUT /keepalive`).
* t=44 s, 66 s, ...: *heartbeats* subsequentes.
* t=25 min (1500 s): `POST /updateToken` com `signature = md5(temp4 + ":" + token_atual)`.
* t=25:00–25:01: trocar para o **novo**`token`. O antigo expira logo após.
* t=30 min: estaria no limite de `tokenRate`; não deixe chegar aqui.

Acesso a imagens (não use `X-Subject-Token`)

* Use o `credential` (retornado no 2º login/`updateToken`) **na query string**:

{% code title="Exemplo" %}

```
https://<host>:<port>/<path/to/img>.jpg?token=<credential>
```

{% endcode %}

* **Não** confunda com `X-Subject-Token` (API). Para imagens, o `credential` é a regra.

## Criptografia de cargas sensíveis

{% stepper %}
{% step %}
Receba `secretKey` e `secretVector` (AES) cifrados com sua `publicKey` RSA.
{% endstep %}

{% step %}
Decifre com sua chave privada RSA no cliente.
{% endstep %}

{% step %}
Ao enviar dados sensíveis, use **AES/CBC/PKCS7** com `secretKey`/`secretVector` e envie o conteúdo cifrado (ex.: em **hex**).

{% hint style="info" %}
Dica: mantenha as chaves **só** em memória e por tempo mínimo.
{% endhint %}
{% endstep %}
{% endstepper %}

## Exemplos prontos para copiar

#### JavaScript (Postman) — calcular assinatura do 2º login

{% code title="Postman pre-request JS" %}

```javascript
// Variáveis de ambiente: username, password, firstLoginRealm, firstLoginRandomKey
const u = pm.environment.get("username");
const p = pm.environment.get("password");
const realm = pm.environment.get("firstLoginRealm");
const rk = pm.environment.get("firstLoginRandomKey");
const t1 = CryptoJS.MD5(p).toString();
const t2 = CryptoJS.MD5(u + t1).toString();
const t3 = CryptoJS.MD5(t2).toString();
const t4 = CryptoJS.MD5(`${u}:${realm}:${t3}`).toString();
const signature = CryptoJS.MD5(`${t4}:${rk}`).toString();
pm.variables.set("secondLoginSignature", signature);
pm.environment.set("temp4", t4); // reutilize no updateToken
```

{% endcode %}

#### Python — assinatura do updateToken

{% code title="Python" %}

```python
import hashlib

def md5_hex(s: str) -> str:
    return hashlib.md5(s.encode('utf-8')).hexdigest()

temp4 = "<armazenado_do_segundo_login>"
token_atual = "<token>"
signature = md5_hex(f"{temp4}:{token_atual}")
```

{% endcode %}

#### GO — MD5 helper (hex minúsculo)

{% code title="Go" %}

```go
package main

import (
    "crypto/md5"
    "encoding/hex"
)

func md5Hex(s string) string {
    sum := md5.Sum([]byte(s))
    return hex.EncodeToString(sum[:])
}

// Assinatura do 2º login (retorna signature e temp4)
func secondLoginSignature(userName, password, realm, randomKey string) (signature, temp4 string) {
    t1 := md5Hex(password)
    t2 := md5Hex(userName + t1)
    t3 := md5Hex(t2)
    t4 := md5Hex(userName + ":" + realm + ":" + t3)
    sig := md5Hex(t4 + ":" + randomKey)
    return sig, t4
}

// Assinatura do updateToken
func updateSignature(temp4, token string) string {
    return md5Hex(temp4 + ":" + token)
}
```

{% endcode %}

## Postman — como organizar sua collection

1. Login (1º passo) → Salve `realm` e `randomKey` em variáveis de ambiente.
2. Pre‑request do 2º passo → compute `signature` com o script JS acima.
3. Login (2º passo) → Salve `token`, `duration`, `tokenRate`, `credential` e `temp4`.
4. Keepalive (folder com Pre‑scripts para injetar `X-Subject-Token`).
5. UpdateToken (pre‑script usa `temp4` + `token`).
6. Logout.

## Erros comuns e como resolver

* Assinatura inválida no 2º login: confira `realm`, `randomKey`, concatenações com `:` e uso de **hex minúsculo**.
* `randomKey` expirado: refaça o 1º login e execute o 2º sem atrasos.
* Token inválido/expirado em heartbeat ou chamadas de negócio: realize **updateToken** ou repita o fluxo de login.
* Imagens não carregam: verifique se está usando `?token=<credential>` (não o `X-Subject-Token`).
* Falha de decriptação AES: confirme que `secretKey/secretVector` foram decifrados com **sua chave privada RSA** correta.

## Boas práticas de segurança

* Nunca deixe a **senha** em claro; se possível, armazene somente `temp4`.
* Elimine chaves e *tokens* após **Logout** (memória e disco).
* Rotacione RSA e limite o acesso a arquivos de chave privada.
* Use **HTTPS** e **HSTS** no front.

## TL;DR (cola rápida)

* Autenticação em 2 passos: `POST /authorize` → 401 → `POST /authorize` (signature 5x MD5 + sua `publicKey`).
* Header: `X-Subject-Token: <token>` em todas as APIs.
* Heartbeat a cada `~duration*0,75`.
* Update antes de `tokenRate` com `md5(temp4+":"+token)`.
* Imagens: `...jpg?token=<credential>` (não use `X-Subject-Token`).

## Como usar: Defina variáveis de ambiente e execute.

Obrigatórias: `BASE_URL` (ex.: `http://host/brms/api/v1.0/accounts`), `USERNAME`, `PASSWORD`, `CLIENT_PUBLIC_KEY` (RSA X.509 em Base64)

Opcionais: `MAC` (ex.: `C8:D9:D2:16:AF:F6`), `CLIENT_TYPE` (padrão `WINPC_V2`)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://portal-integracao.intelbras.com.br/defense-ia-and-lite/readme/autenticacao-via-api-passo-a-passo.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
