# 2 tipos de autenticação

Disponibilizamos 2 formas de autenticação na API v2:
- Basic Auth
- JWT

Todos os endpoints aceitam JWT, enquanto alguns endpoints aceitam Basic Auth. Em regra, os endpoints de listagem e de geração de cobrança aceitam Basic Auth, enquanto os endpoints de informação de conta ou cash-out aceitam exclusivamente JWT. Consulte a documentação de cada endpoint para saber qual tipo de autenticação é aceita.


## Autenticação via BASIC AUTH

A API suporta autenticação segura através de **BASIC AUTH**. Para autenticar, envie o seu Token de acesso no campo **username** e deixe o campo **password** em branco.

Por padrão, o método basic auth utiliza uma string única de **username** e **password**, separada por dois-pontos ( : ). Como o Token gerado pelo sistema LURI não contém senha, utilize este Token diretamente no campo **username** e deixe o campo **password** em branco.

Exemplo: {credencial}:{}

Em seguida, a string resultante é codificada utilizando **Base64 (RFC 4648)**.

### Exemplo de requisição:

```http
POST /v2/endpoint/ HTTP/1.1
Host: api.luri.io
Authorization: Basic YWJjMTIzNDU2Nzg5MA==
Content-Type: application/json
```


# Autenticação via JWT (JSON Web Token)

A API suporta autenticação segura através de JWT assinado assimetricamente utilizando o algoritmo **RS256**. Esta abordagem é ideal para comunicações B2B seguras, dispensando o tráfego contínuo de chaves estáticas ou senhas.

## Como funciona?

Em vez de enviar sua credencial base64 diretamente (como no Basic Auth), você usará sua **Chave Privada** (`Private Key`) para assinar um token JWT. 
A LURI utilizará a sua **Chave Pública** (previamente cadastrada na nossa plataforma, utilizando os endpoints abaixo) para verificar a autenticidade e a integridade matemática daquela requisição, validando você como emissor.

## Estrutura do Token

### 1. Header
O cabeçalho deve obrigatoriamente especificar o algoritmo `RS256` para que o cofre virtual da LURI reconheça o pacote.
```json
{
  "alg": "RS256",
  "typ": "JWT"
}
```

### 2. Payload
O corpo do JWT possui os dados abertos do seu sistema. Requer as seguintes *claims*:
- `iss` (Issuer): **Obrigatório.** Deve ser exatamente o **hash do seu marketplace** (identificador único) fornecido pelo sistema LURI. É a partir desta chave que o sistema localizará sua chave pública.
- `exp` (Expiration Time): **Obrigatório.** O timestamp (Unix Epoch) de quando o token irá expirar. Recomenda-se um tempo de vida muito curto (ex: 5 a 15 minutos) garantindo segurança caso interceptado.
- `iat` (Issued At): Opcional, o momento em que foi gerado.
- `jti` (JWT ID): Opcional, um ID para ratrear/debugging o uso.

*Exemplo de Payload:*
```json
{
  "iss": "hash_exemplo_a1b2c3d4",
  "iat": 1713361200,
  "exp": 1713361500
}
```

### 3. Signature
A assinatura do token ocorre juntando o Header e Payload (ambos codificados em Base64Url), e criptografando essa string usando OpenSSL (SHA256) com sua Chave Privada (`PRIVATE KEY` PEM).

## Realizando a Requisição
Uma vez gerado o token pelas suas funções backend, inclua-o no cabeçalho HTTP `Authorization` usando o esquema `Bearer`:

```http
POST /v2/endpoint/ HTTP/1.1
Host: api.luri.io
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJt... (seu token completo)
Content-Type: application/json
```

---

# Gerenciamento de Chaves Públicas Assimétricas (API v2)

Documentação técnica oficial para cadastro, listagem, revogação e rotação segura de **Chaves Públicas Assimétricas (RSA / RS256)** utilizadas na autenticação JWT B2B da **LURI**.

---

## 1. Visão Geral e Princípios de Segurança

A autenticação assimétrica RS256 elimina a necessidade de trafegar credenciais estáticas nas requisições da API. O cliente assina seus tokens JWT com sua **Chave Privada** e a LURI valida a assinatura utilizando a correspondente **Chave Pública** cadastrada previamente.

### Diretrizes e Regras Gerais
- **Escopo Exclusivo**: Todas as rotas estão centralizadas exclusivamente em `/v2/auth/public-keys`.
- **Canal Seguro Obrigatório**: Conexão obrigatória via HTTPS com **TLS 1.2 ou superior**. Requisições em canal inseguro são rejeitadas com `HTTP 403 Forbidden`.
- **Formato Aceito**: Exclusivamente **PEM** (`-----BEGIN PUBLIC KEY-----` ou `-----BEGIN RSA PUBLIC KEY-----`).
- **Força Criptográfica**: Exige algoritmo **RSA** com tamanho mínimo de **2048 bits**.
- **Bloqueio Sumário de Chaves Privadas**: O cofre da LURI rejeita imediatamente requisições que contenham chaves privadas (`BEGIN PRIVATE KEY`, `BEGIN RSA PRIVATE KEY`, etc.) com `HTTP 400 Bad Request`.
- **Retrocompatibilidade Ativa**: Chaves legadas presentes na coluna `public_key` da tabela `api_boleto_marketplace` permanecem **100% ativas e funcionais** (identificadas na listagem com o KID `legacy-default`).
- **Notificações em Tempo Real**: Cada evento de criação ou revogação dispara notificações de segurança via **Webhook** para a URL configurada no marketplace.

---

## 2. Matriz de Endpoints e Autenticação

| Método | Rota | Método de Autenticação | Descrição |
| :--- | :--- | :--- | :--- |
| **POST** | `/v2/auth/public-keys` | **Basic Auth** | Cadastra uma nova chave pública RSA (2048+ bits). |
| **GET** | `/v2/auth/public-keys` | **JWT** (`Bearer <token>`) | Lista todas as chaves cadastradas (ativas, revogadas e legadas). |
| **DELETE** | `/v2/auth/public-keys/{kid}` | **JWT** (`Bearer <token>`) | Revoga uma chave pública (exige chave diferente para autorizar). |

---

## 3. Especificação Detalhada das Chamadas

### 3.1. Cadastrar Chave Pública

Cadastra uma nova chave pública PEM associada à conta do marketplace.

- **Rota**: `POST /v2/auth/public-keys`
- **Canal**: HTTPS (TLS 1.2+)
- **Autenticação**: **Basic Auth**
  - Username: `{secret_marketplace}` (token/credencial do marketplace)
  - Password: em branco
  - Cabeçalho HTTP: `Authorization: Basic {base64(secret_marketplace:)}`
- **Content-Type**: `application/json`

#### Parâmetros do Payload (JSON)

| Campo | Tipo | Obrigatório | Descrição |
| :--- | :--- | :--- | :--- |
| `public_key` | `string` | **Sim** | Conteúdo da chave pública no formato PEM. |
| `kid` | `string` | Não | Identificador único da chave (de 3 a 128 caracteres: alfanuméricos, hífen, underline ou ponto). Se omitido, a LURI gerará um `kid` seguro automaticamente. |

#### Exemplo de Requisição (cURL)

```bash
curl -X POST "https://api.luri.io/v2/auth/public-keys" \
  -H "Authorization: Basic YWJjMTIzNDU2Nzg5MA==" \
  -H "Content-Type: application/json" \
  -d '{
    "kid": "prod-key-2026-v1",
    "public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyQKhZOSn8W/7x+is46OV\nJxiX30yXg79OWUicGOZkbC7GXjZ5UEIN8Xqo0GfXsiEOcz5L5RsJ7jGxTU3Niuu0\nVf1QHJek9vY+pGuPRKK4sVEWESK7CmX7n0jGqvXIgLBpSTXfjurkys2pkvaZGPlq\nyxrEbYf4pQApB8+HoxMHVZ2xBd/0Cb3sXQGoSaHL9qhVtRCegNYAk3crNySrBiVb\ncgZz0pImQ+FIgmpn+pG147fFCY7PeeBv1rQ65ibOJ+X1GG7uCBGPNk/tl+0kPt0n\nE21hX4OjxQaYZPNkkahSFLkDXP8wGtQBzsxGyAIowR845Q5QLg6KCyPEh3d0mE9N\nAgMBAAE=\n-----END PUBLIC KEY-----"
  }'
```

#### Exemplo de Resposta de Sucesso (`HTTP 201 Created`)

```json
{
  "success": true,
  "message": "Chave pública cadastrada com sucesso.",
  "data": {
    "kid": "prod-key-2026-v1",
    "algorithm": "RS256",
    "key_type": "RSA",
    "key_size": 2048,
    "fingerprint_sha256": "4b68e982d6fc5732c4d622955f269389e1b2123d24268e3b5df51a84f506ee4f",
    "status": "active",
    "created_at": "2026-10-23T16:30:00Z"
  }
}
```

---

### 3.2. Listar Chaves Públicas

Retorna a relação de todas as chaves públicas (ativas, revogadas e chaves legadas) vinculadas ao marketplace emissor do token JWT.

- **Rota**: `GET /v2/auth/public-keys`
- **Canal**: HTTPS (TLS 1.2+)
- **Autenticação**: **Obrigatoriamente JWT**
  - Cabeçalho HTTP: `Authorization: Bearer <seu_token_jwt>`
  - *(Requisições com Basic Auth ou sem cabeçalho Authorization são rejeitadas com HTTP 401).*

#### Exemplo de Requisição (cURL)

```bash
curl -X GET "https://api.luri.io/v2/auth/public-keys" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."
```

#### Exemplo de Resposta de Sucesso (`HTTP 200 OK`)

```json
{
  "success": true,
  "data": [
    {
      "kid": "prod-key-2026-v2",
      "algorithm": "RS256",
      "key_type": "RSA",
      "key_size": 2048,
      "fingerprint_sha256": "4b68e982d6fc5732c4d622955f269389e1b2123d24268e3b5df51a84f506ee4f",
      "is_legacy": false,
      "status": "active",
      "created_at": "2026-10-23T16:30:00Z",
      "revoked_at": null,
      "last_used_at": "2026-10-23T16:35:10Z"
    },
    {
      "kid": "prod-key-2026-v1",
      "algorithm": "RS256",
      "key_type": "RSA",
      "key_size": 2048,
      "fingerprint_sha256": "8a7c293817498127394872938471923847192837491827394817293847192837",
      "is_legacy": false,
      "status": "revoked",
      "created_at": "2026-09-01T10:00:00Z",
      "revoked_at": "2026-10-23T16:20:00Z",
      "last_used_at": "2026-10-23T16:19:40Z"
    },
    {
      "kid": "legacy-default",
      "algorithm": "RS256",
      "key_type": "RSA",
      "key_size": 2048,
      "fingerprint_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
      "is_legacy": true,
      "status": "active",
      "created_at": null,
      "revoked_at": null,
      "last_used_at": null
    }
  ]
}
```

---

### 3.3. Revogar Chave Pública (Key Revocation)

Invalida logicamente uma chave pública, bloqueando instantaneamente qualquer autenticação futura assinada por ela.

- **Rota**: `DELETE /v2/auth/public-keys/{kid}`
- **Canal**: HTTPS (TLS 1.2+)
- **Autenticação**: **Obrigatoriamente JWT**
  - Cabeçalho HTTP: `Authorization: Bearer <seu_token_jwt>`

> [!IMPORTANT]
> **Regra Crítica de Segurança na Rotação (Anti-Lockout)**
> O token JWT utilizado para autorizar a requisição de revogação **NÃO** pode ter sido assinado com a mesma chave (`kid`) que está sendo excluída!
> Se você tentar revogar o mesmo `kid` com o qual assinou a chamada, o sistema rejeitará a operação com **HTTP 403 Forbidden**.
>
> **Fluxo de Rotação sem Downtime (Zero Downtime Rotation)**:
> 1. Cadastre a chave pública nova via `POST /v2/auth/public-keys`.
> 2. No seu backend, passe a assinar suas requisições com a nova chave privada (enviando o novo `kid` no cabeçalho JWT).
> 3. Dispare a requisição `DELETE /v2/auth/public-keys/{kid_antigo}` utilizando o JWT assinado com a chave nova.

#### Exemplo de Requisição (cURL)

```bash
curl -X DELETE "https://api.luri.io/v2/auth/public-keys/prod-key-2026-v1" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."
```

#### Exemplo de Resposta de Sucesso (`HTTP 200 OK`)

```json
{
  "success": true,
  "message": "Chave pública revogada com sucesso. Tokens futuros assinados com este kid serão rejeitados.",
  "data": {
    "kid": "prod-key-2026-v1",
    "status": "revoked",
    "revoked_at": "2026-10-23T16:40:00Z"
  }
}
```

#### Exemplo de Bloqueio por Auto-Revogação (`HTTP 403 Forbidden`)

```json
{
  "status": "Forbidden",
  "status_code": 403,
  "message": "Operação não permitida: Não é permitido revogar a mesma chave pública ('prod-key-2026-v1') utilizada para assinar o token desta requisição. Realize a rotação utilizando outra chave ativa."
}
```

---

## 4. Como Utilizar o `kid` nas Requisições JWT

Quando o seu sistema emitir um JWT para autenticação em qualquer endpoint da API v2 (ex: pagamentos, consultas de saldo, conciliações), inclua o `kid` no cabeçalho do token:

### 1. Cabeçalho (Header) do Token
```json
{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "prod-key-2026-v1"
}
```

### 2. Corpo (Payload) do Token
```json
{
  "iss": "4b7e010c54a048efab973279355dbc51",
  "iat": 1713361200,
  "exp": 1713361500
}
```

### Como a LURI Valida:
1. Extrai o `iss` (`hash_marketplace`) do payload e o `kid` do cabeçalho.
2. Localiza no cofre a chave pública ativa correspondente àquele par `(hash_marketplace, kid)`.
3. Valida a integridade da assinatura matemática (RS256).
4. Se o `kid` for omitido (tokens legados), o validador utiliza a chave pública configurada na coluna legada `api_boleto_marketplace.public_key` ou a chave ativa mais recente.

---

## 5. Notificações de Segurança via Webhook

Sempre que uma chave pública for cadastrada ou revogada, a LURI dispara um evento HTTP POST seguro para a `url_webhook` configurada no marketplace.

### Estrutura do Payload Enviado

```json
{
  "event": "public_key.created",
  "request_id": "req_a1b2c3d4e5f67890",
  "timestamp": "2026-10-23T16:30:00Z",
  "data": {
    "hash_marketplace": "4b7e010c54a048efab973279355dbc51",
    "kid": "prod-key-2026-v1",
    "algorithm": "RS256",
    "key_size": 2048,
    "fingerprint_sha256": "4b68e982d6fc5732c4d622955f269389e1b2123d24268e3b5df51a84f506ee4f",
    "status": "active",
    "created_at": "2026-10-23T16:30:00Z",
    "ip_address": "177.18.25.10"
  }
}
```

#### Eventos Possíveis:
- `public_key.created`: Emitido imediatamente após o cadastro de uma nova credencial assimétrica.
- `public_key.revoked`: Emitido imediatamente após a revogação de uma credencial existente.

---

## 6. Tabela de Códigos de Retorno e Diagnóstico

| Código HTTP | Causa Provável | Ação Recomendada |
| :--- | :--- | :--- |
| **200 OK** | Operação realizada com sucesso (Listagem ou Revogação). | — |
| **201 Created** | Chave pública cadastrada com sucesso. | Armazene o `kid` retornado para envio nos cabeçalhos JWT. |
| **400 Bad Request** | Formato de chave PEM inválido, chave fraca (< 2048 bits) ou chave privada enviada. | Verifique se você enviou apenas a chave pública (`BEGIN PUBLIC KEY`) e se ela possui no mínimo 2048 bits RSA. |
| **401 Unauthorized** | Falha no Basic Auth (ao cadastrar) ou JWT ausente/inválido (ao listar/revogar). | Confirme as credenciais enviadas no cabeçalho `Authorization`. |
| **403 Forbidden** | Conexão sem HTTPS/TLS 1.2+ ou tentativa de auto-revogação da mesma chave do token. | Conecte via HTTPS e use outra chave ativa para assinar o token de revogação. |
| **404 Not Found** | O `kid` informado para exclusão não foi encontrado para este marketplace. | Liste as chaves via `GET /v2/auth/public-keys` para confirmar os identificadores existentes. |
| **409 Conflict** | Já existe uma chave ativa ou revogada com este mesmo `kid`. | Utilize um novo `kid` único ou deixe em branco para auto-geração. |
