docs(browser): document https to localhost compatibility and private network access
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
# Compatibilidade de Navegadores e Acesso de Rede Privada (CCSP/1)
|
||||
|
||||
Este documento detalha o funcionamento, as garantias de segurança e os requisitos de compatibilidade entre aplicações web (servidas sob **HTTPS**) e o agente desktop **CyberCore Signer** em loopback local (`http://127.0.0.1:21325`).
|
||||
|
||||
---
|
||||
|
||||
## 1. Contexto Arquitetural: HTTPS para Loopback HTTP
|
||||
|
||||
Tradicionalmente, navegadores modernos impedem o carregamento de recursos inseguros (`http://`) a partir de contextos seguros (`https://`), mecanismo conhecido como **Mixed Content**.
|
||||
|
||||
No entanto, para agentes de assinatura digital locais e periféricos de hardware, o consórcio **W3C (Secure Contexts Specification)** e os motores de renderização modernos tratam o loopback IPv4 (`127.0.0.1`) e `localhost` como **Origens Potencialmente Confiáveis (*Potentially Trustworthy Origins*)**.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Web as Aplicação Web (HTTPS)
|
||||
participant Browser as Navegador (Chrome/Firefox/Safari)
|
||||
participant Agent as CyberCore Signer (127.0.0.1:21325)
|
||||
|
||||
Note over Web,Agent: 1. Preflight CORS + Private Network Access (PNA)
|
||||
Web->>Browser: fetch("http://127.0.0.1:21325/ccsp/v1/sign", { method: "POST" })
|
||||
Browser->>Agent: OPTIONS /ccsp/v1/sign<br/>Origin: https://meusistema.com.br<br/>Access-Control-Request-Private-Network: true
|
||||
Agent-->>Browser: HTTP 204 No Content<br/>Access-Control-Allow-Origin: *<br/>Access-Control-Allow-Private-Network: true<br/>Access-Control-Allow-Methods: GET, POST, OPTIONS
|
||||
Note over Browser,Agent: 2. Requisição Real CCSP/1
|
||||
Browser->>Agent: POST /ccsp/v1/sign (JSON Digest)
|
||||
Agent-->>Browser: HTTP 200 OK (Assinatura Base64)
|
||||
Browser-->>Web: Retorno Promise Resolvida
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Private Network Access (PNA / W3C)
|
||||
|
||||
O **Private Network Access (PNA)** é uma especificação de segurança do W3C (adotada inicialmente pelo motor Chromium a partir do Chrome 98+) com o objetivo de proteger a rede local contra ataques de Cross-Site Request Forgery (CSRF).
|
||||
|
||||
### Como a especificação classifica as redes:
|
||||
1. **Pública (*public*):** A internet pública (ex: `https://meusistema.com.br`).
|
||||
2. **Privada (*private*):** Redes locais RFC 1918 (ex: `192.168.x.x`, `10.x.x.x`).
|
||||
3. **Local (*local*):** A máquina do próprio usuário (`127.0.0.1`, `localhost`).
|
||||
|
||||
Quando uma página em um espaço de IP mais público solicita um recurso em um espaço mais restrito (como `public` $\rightarrow$ `local`), o navegador dispara uma requisição preliminar **Preflight PNA**.
|
||||
|
||||
### Headers Enviados pelo Navegador:
|
||||
```http
|
||||
OPTIONS /ccsp/v1/sign HTTP/1.1
|
||||
Host: 127.0.0.1:21325
|
||||
Origin: https://meusistema.com.br
|
||||
Access-Control-Request-Method: POST
|
||||
Access-Control-Request-Headers: Content-Type, X-CyberCore-AppId
|
||||
Access-Control-Request-Private-Network: true
|
||||
```
|
||||
|
||||
### Resposta Padrão do CyberCore Signer (`CcspServer`):
|
||||
O servidor do agente desktop intercepta requisições `OPTIONS` e responde imediatamente com:
|
||||
```http
|
||||
HTTP/1.1 204 No Content
|
||||
Access-Control-Allow-Origin: *
|
||||
Access-Control-Allow-Methods: GET, POST, OPTIONS
|
||||
Access-Control-Allow-Headers: Content-Type, Authorization, X-CyberCore-AppId, Origin, Accept
|
||||
Access-Control-Allow-Private-Network: true
|
||||
Access-Control-Max-Age: 86400
|
||||
Connection: close
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> O cabeçalho `Access-Control-Allow-Private-Network: true` é fundamental para autorizar o navegador a enviar requisições privadas originadas de sites HTTPS públicos.
|
||||
|
||||
---
|
||||
|
||||
## 3. Matriz de Compatibilidade de Navegadores
|
||||
|
||||
| Navegador | Versão Mínima | Suporte HTTPS $\rightarrow$ 127.0.0.1 | Comportamento PNA | Requer Ação do Usuário? |
|
||||
| :--- | :---: | :---: | :---: | :---: |
|
||||
| **Google Chrome** | 88+ | ✅ Suportado | PNA ativo com preflight | Não (automático) |
|
||||
| **Microsoft Edge** | 88+ | ✅ Suportado | PNA ativo com preflight | Não (automático) |
|
||||
| **Mozilla Firefox** | 84+ | ✅ Suportado | Trata 127.0.0.1 como Secure Context | Não (automático) |
|
||||
| **Opera / Brave** | Recentes | ✅ Suportado | Idêntico ao Chromium (ver nota Brave) | Pode exigir ajuste no Shields |
|
||||
| **Apple Safari** | 15.4+ (macOS) | ✅ Suportado | Trata loopback como seguro | Não |
|
||||
|
||||
---
|
||||
|
||||
## 4. Casos de Borda e Soluções (Troubleshooting)
|
||||
|
||||
### 4.1. Navegador Brave (Brave Shields)
|
||||
O Brave possui um mecanismo agressivo de proteção que pode bloquear preflights para `127.0.0.1`.
|
||||
- **Sintoma:** O SDK lança `AgentNotRunningError`, mesmo com o agente em execução.
|
||||
- **Resolução:** O usuário deve clicar no ícone do escudo (Shields) na barra de endereços da aplicação e desativar temporariamente o bloqueio para a origem ou permitir conexões locais nas configurações (`brave://settings/shields`).
|
||||
|
||||
### 4.2. Extensões de Privacidade e AdBlockers
|
||||
Extensões como *uBlock Origin*, *Privacy Badger* ou *NoScript* podem conter regras genéricas de bloqueio para portas locais.
|
||||
- **Resolução:** Adicionar a URL da sua aplicação web à lista de permissões (*allowlist*) da extensão.
|
||||
|
||||
### 4.3. Softwares de Antivírus e Endpoint Protection
|
||||
Alguns antivírus com módulo de "Proteção Web" ou "Inspeção HTTPS" tentam atuar como proxy transparente no loopback local:
|
||||
- **Resolução:** Configurar o antivírus para excluir a porta `21325` da inspeção de tráfego local.
|
||||
|
||||
### 4.4. Políticas Corporativas de Grupo (GPO / Chromium Enterprise)
|
||||
Em ambientes corporativos restritos, administradores de rede podem bloquear chamadas a redes privadas via política:
|
||||
- Política Chromium: `InsecurePrivateNetworkRequestsAllowed` ou `InsecurePrivateNetworkRequestsAllowedForUrls`.
|
||||
- **Resolução:** Adicionar a URL do portal web corporativo na política `InsecurePrivateNetworkRequestsAllowedForUrls`.
|
||||
|
||||
---
|
||||
|
||||
## 5. Boas Práticas para Desenvolvedores Web
|
||||
|
||||
1. **Use sempre o SDK `@cybercore/signer-sdk`:** Ele gerencia timeouts, fallbacks de preflight e detecção de conectividade.
|
||||
2. **Utilize `isInstalled()` antes de iniciar fluxos de assinatura:**
|
||||
```javascript
|
||||
import { CyberCoreSigner } from '@cybercore/signer-sdk';
|
||||
|
||||
const signer = new CyberCoreSigner();
|
||||
|
||||
if (!(await signer.isInstalled())) {
|
||||
mostrarModalInstalacaoAgente();
|
||||
}
|
||||
```
|
||||
3. **Capture `AgentNotRunningError` e exiba o guia de ajuda:**
|
||||
```javascript
|
||||
import { AgentNotRunningError } from '@cybercore/signer-sdk';
|
||||
|
||||
try {
|
||||
await signer.connect();
|
||||
} catch (err) {
|
||||
if (err instanceof AgentNotRunningError) {
|
||||
console.info(err.actionableGuidance);
|
||||
exibirAjudaAoUsuario(err.actionableGuidance);
|
||||
}
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user