Login único (SSO)
Use um provedor de identidade confiável no login do Nodaro self-hosted: configure EXTERNAL_SSO_PROVIDERS, a vinculação de contas e o login só por SSO.
O login único (SSO) permite que um provedor de identidade externo e confiável faça o login de usuários no seu Nodaro self-hosted. Você descreve cada provedor na variável EXTERNAL_SSO_PROVIDERS, e a página de login mostra um botão de SSO. A conta em que o usuário entra é um usuário comum da sua instalação: o SSO é só uma forma de iniciar uma sessão. Esta página trata do lado do operador; o protocolo está em Login externo (SSO) para desenvolvedores.
Que tipo de provedor usar
| Tipo | Use quando | Status |
|---|---|---|
assertion | O seu emissor não fala OpenID Connect nem SAML, mas consegue assinar um JWT de curta duração, por exemplo um app que incorpora o Nodaro. O Nodaro verifica o token e o troca por uma sessão comum. | Funciona de ponta a ponta. |
oidc | O seu provedor de identidade fala OpenID Connect e está configurado no Supabase Auth da sua instalação. O navegador faz um redirecionamento comum de login do Supabase, e o Supabase verifica o resultado. | O id do provedor precisa ser o nome do provedor OAuth no seu Supabase Auth, como keycloak ou azure. |
saml | — | As entradas passam na validação, mas a página de login não consegue enviar um domínio SAML, então elas não fazem o login de ninguém. Use assertion ou oidc. |
O SSO vem desativado por padrão. Com EXTERNAL_SSO_PROVIDERS sem definir, a página de login não mostra nenhum botão de SSO, GET /v1/sso/providers retorna uma lista vazia, e todas as rotas de provedor respondem 404 unknown_provider.
Configurar os provedores
Defina EXTERNAL_SSO_PROVIDERS como um array JSON, direto no valor ou como @/path/to/providers.json para ler um arquivo.
[
{
"id": "librechat",
"label": "LibreChat",
"kind": "assertion",
"secret": "a-dedicated-32+char-hmac-key-not-the-idp-session-secret",
"audience": "nodaro",
"claimMap": { "email": "email", "emailVerified": "email_verified", "subject": "sub" },
"initiateUrl": "https://chat.example.com/oauth/nodaro",
"maxLifetimeSeconds": 300
},
{
"id": "keycloak",
"label": "Acme (Keycloak)",
"kind": "oidc",
"supabaseProvider": "keycloak"
}
]Um valor malformado interrompe a inicialização. Um erro de digitação em uma entrada que guarda um segredo nunca pode descartar um provedor em silêncio, o que pareceria uma falha do SSO com 404, nem deixar o login configurado pela metade.
Na stack do Compose, adicione EXTERNAL_SSO_PROVIDERS e EXTERNAL_SSO_LINK_EXISTING em environment: do serviço nodaro, porque o arquivo do Compose não as repassa do .env. Para usar um arquivo, monte-o no contêiner e informe o caminho dele dentro do contêiner.
Campos do provedor
| Campo | Aplica-se a | O que faz |
|---|---|---|
id | Todos | Um nome seguro para URLs: primeiro uma letra minúscula ou um dígito, depois letras minúsculas, dígitos, _ ou -, de 1 a 63 caracteres no total, sem pontos. Ele aparece na rota /v1/sso/<id> e é guardado no usuário. Precisa ser único. |
label | Todos | O nome do provedor. Ele só aparece no botão de login quando existem dois ou mais provedores e o perfil de superfície não define auth.ssoLabel. |
kind | Todos | assertion, oidc ou saml. |
secret | assertion, obrigatório | A chave HS256 que verifica a assinatura da asserção, com pelo menos 16 caracteres. Use uma chave dedicada, nunca o segredo de sessão do próprio provedor de identidade, para que um vazamento do lado do Nodaro não permita forjar as sessões do provedor. |
audience | assertion, obrigatório | O valor a que a claim aud da asserção precisa ser igual. |
claimMap | assertion | Quais claims trazem o e-mail, o indicador de verificação e o subject. O padrão é { "email": "email", "emailVerified": "email_verified", "subject": "sub" }. |
initiateUrl | assertion | Uma URL absoluta. Quando um usuário clica no botão de login, o Nodaro redireciona para ela. O provedor faz o login do usuário e volta com a asserção. Sem ela, um clique responde 400 no_assertion. |
initiateUrlByHost | assertion | Um mapa de um nome de host simples, em minúsculas e sem porta, para uma URL absoluta. Um clique que chega por esse host vai para essa URL em vez de initiateUrl. Para instalações que respondem em vários nomes de host. Uma chave errada interrompe a inicialização, e o mapa nunca é publicado. |
maxLifetimeSeconds | assertion | O maior tempo de vida que uma asserção pode ter, exp menos iat. O padrão é 300, ou seja, 5 minutos, e o máximo é 3600. |
supabaseProvider | oidc | Validado, mas não usado: a página de login passa ao Supabase o id do provedor. |
domain | oidc, saml | Validado, mas não usado. Uma entrada oidc ou saml precisa de domain ou de supabaseProvider. |
Só id, label e kind são publicados, por GET /v1/sso/providers. O segredo nunca sai do servidor.
O que o Nodaro verifica em uma asserção
O servidor de identidade de um provedor assertion assina um JWT e envia o navegador para GET /v1/sso/<id>?assertion=<jwt>. O Nodaro só aceita a asserção quando todas estas condições são cumpridas:
- Ela é assinada com HS256 e com o
secretdo provedor. audé igual aoaudiencedo provedor.expestá presente e não está no passado, com 5 segundos de tolerância, e o tempo de vida está dentro demaxLifetimeSeconds.jtiestá presente e nunca foi usado. Cada asserção funciona uma vez.- A claim de e-mail está presente. A claim de e-mail verificado precisa ser
truepara criar ou vincular uma conta.
Uma verificação que falha responde 401. A rota aceita 20 requisições a cada 60 segundos de um mesmo endereço IP e, acima disso, responde 429. O contrato completo, os códigos de erro e o fluxo de redirecionamento estão em Login externo (SSO) para desenvolvedores.
Como as contas são vinculadas
Quando uma asserção passa, o Nodaro encontra ou cria o usuário correspondente. As regras garantem que uma asserção nunca possa assumir uma conta existente só porque ela tem o mesmo endereço de e-mail.
| Situação | Resultado |
|---|---|
| Nenhuma conta tem o e-mail, e o e-mail está verificado | Um usuário novo é criado e vinculado ao provedor. |
| Nenhuma conta tem o e-mail, e ele não está verificado | Recusado: 403 email_unverified. |
| A conta já está vinculada a este provedor | O usuário entra. |
| A conta está vinculada a outro provedor | Recusado: 403 account_linked_other_provider, mesmo com EXTERNAL_SSO_LINK_EXISTING=true. |
Existe uma conta local sem SSO, EXTERNAL_SSO_LINK_EXISTING=true, e o e-mail está verificado | A conta é vinculada ao provedor, e o usuário entra. |
Existe uma conta local sem SSO, e a opção é false ou o e-mail não está verificado | Recusado: 403 account_exists. |
O padrão de EXTERNAL_SSO_LINK_EXISTING é false, o que protege contra a tomada de contas. Só true ou 1, com qualquer combinação de maiúsculas e minúsculas, ativam a vinculação. Ative-a só quando você confiar nas claims de e-mail verificado dos seus provedores a ponto de associá-las a contas existentes.
account_exists e email_unverified usam o mesmo texto para todas as contas, então o formulário de login não pode ser usado para descobrir quais endereços existem. O log do servidor registra qual conta foi o alvo.
O botão de login
A página de login mostra um botão de SSO quando pelo menos um provedor está configurado.
- Um provedor: o botão mostra Entrar com SSO, ou o
auth.ssoLabeldo perfil de superfície. - Vários provedores: cada botão mostra o
labeldo provedor dele, a menos que o perfil de superfície definaauth.ssoLabel.
Depois do login, o usuário chega a /projects. O provedor pode enviar outra página adicionando &next=<path> ao redirecionar de volta. O Nodaro só respeita esse valor quando ele é um caminho relativo na mesma origem, começando com /, mas não com //. Qualquer outro valor leva a /projects. Nos hosts listados em CORS_ORIGIN, o redirecionamento para a página de destino continua relativo, no host pelo qual o usuário chegou.
Permitir o login só por SSO
Na Business edition, o perfil de superfície pode remover os outros métodos de login:
NODARO_SURFACE_PROFILE={"auth":{"methods":["sso"],"ssoLabel":"Sign in with Acme"}}Uma lista que cita só sso também ativa uma regra no servidor: toda conta logada precisa ter sido criada ou vinculada pelo SSO. Qualquer outra sessão é recusada na primeira chamada à API com 403 sso_required, então uma conta registrada diretamente no serviço de login não pode usar a instalação. Adicionar email à lista desativa a regra. Veja Edições e perfis de superfície.
Resumo de segurança
- Um segredo dedicado por provedor, diferente do segredo de sessão do próprio provedor.
- Asserções de uso único, com um tempo de vida curto, imposto pelo servidor.
- Só redirecionamentos na mesma origem depois do login.
- Nenhum segredo sai do servidor. As asserções e os tokens de uso único são removidos dos logs de requisições.
- Limites de taxa na rota de troca, por endereço IP.
- Sessões comuns. Depois da troca, o usuário é um usuário normal, sem nenhuma credencial especial.
Perguntas frequentes
Páginas relacionadas
Login externo (SSO)
Edições e perfis de superfície
Configuração
Primeiro usuário e administrador
Última atualização
MCP em uma instalação self-hosted
Ative o servidor MCP de um Nodaro self-hosted para que Claude, Cursor, ChatGPT e outros clientes MCP usem a instalação por OAuth, em um host MCP próprio.
Atualização
Atualize o Nodaro self-hosted com uma imagem mais nova, fixe uma tag de versão, faça um backup antes de uma versão major e reverta restaurando esse backup.