Logon único
O logon único permite que um provedor de identidade (IdP) externo decida quem pode entrar no seu servidor do Control Center. Dois protocolos são suportados — SAML 2.0 e OpenID Connect — e ambos chegam ao mesmo lugar: uma credencial de dispositivo recém-emitida, indistinguível de um convite ou de um emparelhamento por QR em todo o restante do caminho.
O formato de um login
Seção intitulada “O formato de um login”Os logins SAML são mediados pelo navegador. O IdP nunca abre uma conexão com o seu servidor; é o navegador do usuário que carrega tudo:
browser ──> /saml/login ──> IdP ──POST SAMLResponse──> /saml/acs │ verify ▼ provision user (maybe) │ ▼ browser handoff: device PSK in the URL fragment (never a query parameter)Como o navegador é o mensageiro, um servidor atrás de NAT funciona sem problemas para logins: localhost, LAN, Tailscale, VPN ou um túnel servem — apenas o navegador do usuário precisa alcançar a URL do ACS. O relay WebSocket usado pelo controle remoto por celular não consegue transportar o ida e volta HTTP, e é por isso que os pontos de entrada de SSO sempre miram a origem HTTP do servidor.
O OpenID Connect segue o mesmo formato, com um ida e volta de código de autorização + PKCE; as declarações são lidas do endpoint de token do emissor por TLS, então o navegador nunca fornece dados de identidade.
Os adaptadores
Seção intitulada “Os adaptadores”O Control Center divide a responsabilidade de propósito:
| Componente | Onde | Responsabilidade |
|---|---|---|
cc_saml nativo |
packages/cc_natives/native/saml/ |
Verificação de XML-DSig, canonicalização, validação de perfil SAML — delegadas ao crate saml de Rust puro fixado por versão, atrás de uma ABI C sem estado |
SamlService / OidcService |
cc_server_core |
estado de login (rastreadores de requisições pendentes, deduplicação de replay), ajustes de política de validação, a chamada de provisionamento compartilhada |
SsoProvisioner |
cc_server_core |
encontrar ou criar o usuário, fixar o sujeito do provedor, conceder associações sob a política de membro automático |
ScimService |
cc_server_core |
a superfície de push do SCIM 2.0 (ciclo de vida de provisionamento/desprovisionamento) |
SsoSettingsService |
cc_server_core |
as linhas de conexão salvas, a reaplicação em tempo real, o token do SCIM |
Não existe, de propósito, nenhum fallback de criptografia SAML em Dart
puro: XML-DSig/canonicalização feitos à mão são exatamente onde vivem as
vulnerabilidades de encapsulamento de assinatura, então a ausência da
biblioteca cc_saml recusa tanto o login SAML quanto a inicialização do
servidor. O nativo é sem estado por projeto — o estado entre requisições vive
nos serviços Dart, de uso único e curta duração.
O que um login verifica
Seção intitulada “O que um login verifica”Dentro do nativo verificado e do serviço, nesta ordem:
- a assinatura da asserção (sempre obrigatória; a do envelope de resposta é opcional conforme a configuração) — estruturalmente resistente a encapsulamento de assinatura, porque o payload validado está vinculado ao elemento verificado,
- o emissor corresponde ao IdP configurado,
- o audience nomeia este provedor de serviço,
- o destino é a nossa URL do ACS,
InResponseTocorresponde a um AuthnRequest pendente que nós emitimos (respostas não solicitadas, iniciadas pelo IdP, estão desativadas por padrão),- as janelas de tempo de vida se mantêm dentro do desvio de relógio (padrão de 90s) e
- o id da asserção nunca foi visto antes (cache de replay).
As falhas voltam como códigos tipados — signature, expired, audience, destination, issuer, request-match — e os endpoints respondem com erros genéricos, para que um atacante não descubra por que uma falsificação falhou.
Contas e fixação do sujeito
Seção intitulada “Contas e fixação do sujeito”O primeiro login por SSO fixa o sujeito imutável do provedor (issuer mais o
NameID do SAML / o sub do OIDC, ou o externalId do SCIM) na conta. A partir
daí, o sujeito — não o e-mail — identifica o login. Se outra pessoa mais tarde
apresentar o mesmo e-mail vindo do mesmo IdP ou de outro, a conta fixada a
recusa. É isso que impede que um e-mail reciclado em um provedor se torne uma
tomada de conta.
Provisionamento e desprovisionamento
Seção intitulada “Provisionamento e desprovisionamento”O provisionamento JIT acontece no login (SsoProvisioner). O SCIM é uma
superfície de push separada (ScimService) que fixa o mesmo sujeito na linha
do usuário; ele não concede associações a espaços de trabalho. O
desprovisionamento — SCIM active: false ou DELETE — recusa se a conta for
proprietária de um espaço de trabalho (transfira primeiro). Caso contrário, ele
revoga primeiro todas as credenciais de dispositivo (as sessões caem em
segundos pelo monitoramento de dispositivos), remove todas as associações a
espaços de trabalho e marca a conta como desativada. A linha do usuário
sobrevive: a atribuição é permanente. A reativação restaura o login, mas nunca
volta a conceder associações.
O que fica de fora
Seção intitulada “O que fica de fora”- O mapeamento de grupo → papel acontece no login, a partir dos atributos SAML / das declarações OIDC — grupos enviados por push via SCIM não são armazenados.
- O papel de proprietário é inalcançável a partir do SSO — nem como papel padrão nem por meio de um mapeamento de grupo.
- O relay WebSocket nunca é um canal de SSO; celulares que alcançam o servidor apenas pelo relay não conseguem completar um ida e volta pelo navegador contra ele.