O ClickHouse pode autenticar usuários usando JSON Web Tokens (JWTs). Diferentemente de outros autenticadores externos, como LDAP ou Kerberos, a autenticação por JWT não verifica a identidade de usuários já existentes. Em vez disso, ela cria dinamicamente usuários efêmeros a partir das claims contidas em cada token. Esses usuários existem apenas na memória, recebem permissões de acesso derivadas das claims do token e são removidos automaticamente quando o token expira.
Isso torna a autenticação por JWT fundamentalmente diferente de métodos baseados em senha ou em certificado: não existe uma instrução CREATE USER ... IDENTIFIED WITH jwt, e tentar executá-la gera uma exceção. Os usuários JWT são totalmente gerenciados pelo ciclo de vida do token.
O fluxo de autenticação funciona da seguinte forma:
- Um cliente apresenta um JWT assinado por meio de um dos mecanismos de transporte compatíveis (cabeçalho HTTP
Authorization: Bearer, o protocolo nativo TCP ou o campo gRPC jwt).
- O ClickHouse valida a assinatura do token.
- As claims obrigatórias (
exp, iat, iss, sub, aud) são verificadas.
- Um usuário efêmero é criado na memória com direitos de acesso derivados das claims do token
clickhouse:grants e clickhouse:roles, em interseção com um limite de permissões.
- Quando o token expira, uma tarefa de coleta de lixo em segundo plano remove o usuário.
Todo JWT apresentado ao ClickHouse deve conter as seguintes claims:
| Claim | Descrição |
|---|
alg | Algoritmo de assinatura (claim do cabeçalho). Valores aceitos: HS256, RS256, ES256. |
exp | Tempo de expiração. Define o valid_until do usuário efêmero. |
iat | Horário de emissão. Usado para impedir a reutilização de tokens antigos para a mesma identidade. |
iss | Emissor. Comparado com o emissor esperado do provedor. |
sub | Sujeito. Passa a fazer parte do nome de usuário gerado. |
aud | Audiência. Comparado com a audiência esperada do provedor. |
A claim kid (ID da chave) do cabeçalho também é obrigatória quando a resolução de chaves baseada em JWKS é usada.
O modo JWKS oferece suporte apenas a chaves RSAEnquanto provedores com chave estática aceitam HS256, RS256 ou ES256, provedores baseados em JWKS aceitam apenas JWKs cujo kty é RSA (ou seja, tokens assinados com RS256). Tokens assinados com chaves HMAC (HS256) ou EC (ES256) não podem ser verificados em um endpoint JWKS e serão rejeitados.
Outras claims reconhecidas
| Claim | Description |
|---|
nbf | Horário a partir do qual o token passa a ser válido. Esta claim não é obrigatória, mas, se estiver presente, os tokens serão rejeitados antes desse horário. |
jti | Reservado. Aceito em tokens, mas atualmente não é validado nem usado. |
| Claim | Nome padrão | Descrição |
|---|
| Grants | clickhouse:grants | Um JSON array de fragmentos SQL GRANT, por exemplo ["SELECT ON db.*", "INSERT ON db.table1"]. Cada elemento é interpretado como o corpo de uma instrução GRANT. |
| Papéis | clickhouse:roles | Um JSON array de nomes de papéis a serem atribuídos, por exemplo ["analyst", "reader"]. |
| Os nomes padrão das claims podem ser remapeados para nomes de claims personalizados caso o seu provedor de identidade use convenções de nomenclatura diferentes. | | |
Exemplo de cabeçalho e payload do token
{
"alg": "RS256",
"kid": "my-key-id"
}
{
"iss": "https://idp.example.com",
"sub": "jane.doe",
"aud": "my-clickhouse-cluster",
"exp": 1719504000,
"iat": 1719500400,
"clickhouse:grants": ["SELECT ON analytics.*", "INSERT ON analytics.events"],
"clickhouse:roles": ["analyst"]
}
Comportamento de usuário efêmero
Os usuários JWT diferem dos usuários regulares do ClickHouse em vários aspectos importantes.
Identidade e nomenclatura
Cada usuário JWT recebe um UUID determinístico calculado a partir das claims iss, sub e aud. Esse UUID é estável entre logins. Um usuário que faz login várias vezes com tokens diferentes (mas com o mesmo emissor, sujeito e audiência) sempre recebe o mesmo UUID.
O nome de usuário, no entanto, é volátil. Ele é construído da seguinte forma:
JWT::<issuer>::<audience>::<subject>::<claims_hash>
A parte <claims_hash> muda sempre que as claims clickhouse:roles ou clickhouse:grants são alteradas. Isso significa que tokens com diferentes conjuntos de roles ou grants geram nomes de usuário diferentes, mesmo quando a identidade é a mesma.
Os direitos de acesso efetivos são calculados da seguinte forma:
effective_rights = permission_limit ∩ (token_grants ∪ token_roles)
Em que permission_limit representa o conjunto de direitos de acesso de uma role ou usuário de referência configurado como limite superior. Os direitos solicitados pelo token que excederem esse limite são descartados silenciosamente.
O ClickHouse rastreia a claim iat (issued-at) do token autenticado mais recentemente para cada identidade estável. Se for apresentado um token com iat igual ou anterior ao valor armazenado, o servidor reutiliza o usuário efêmero existente sem reavaliar as claims. Isso impede que tokens mais antigos reduzam as permissões do usuário.
Tempo de vida e coleta de lixo
Usuários efêmeros são criados quando um token é autenticado pela primeira vez e removidos por uma tarefa de coleta de lixo em segundo plano após valid_until (derivado de exp) expirar. O intervalo de GC é controlado pelo parâmetro gc_interval (padrão: 5 minutos).
Entre as execuções do GC, usuários expirados ainda podem aparecer em system.users, mas não podem mais se autenticar.
Atribuições persistentes de acesso
Como o UUID é estável, você pode atribuir perfis de configurações, cotas, políticas de linha e políticas de mascaramento de coluna a um usuário JWT usando instruções SQL. Essas atribuições permanecem no armazenamento de controle de acesso (em disco ou no ZooKeeper) e persistem após a expiração do token e uma nova autenticação.
Faça referência ao usuário pelo nome de usuário atual:
ALTER SETTINGS PROFILE my_profile ADD TO 'JWT::ClickHouse::my-service-id::jane.doe::<claims-hash>';
O nome de usuário e o UUID de uma determinada identidade podem ser encontrados nas colunas name e id de system.users enquanto o usuário estiver ativo.
Observe que ALTER USER não funciona diretamente com usuários JWT, pois eles são somente leitura. Para atribuir perfis de configurações, quotas ou políticas, use as instruções ALTER SETTINGS PROFILE, ALTER QUOTA ou ALTER ROW POLICY, como mostrado acima.
Diferenças em relação aos usuários regulares
| Funcionalidade | Usuários JWT | Usuários regulares |
|---|
| Criação | Automática com base nas claims do token | instrução CREATE USER |
| Armazenamento | Apenas em memória (efêmero) | Disco, ZooKeeper ou arquivo de configuração |
CREATE USER ... IDENTIFIED WITH jwt | Não suportado (gera exceção) | Todos os outros tipos de autenticação são suportados |
ALTER USER / DROP USER | Não suportado | Suportado |
| Backup e restauração | Não incluídos | Incluídos |
| Nome de usuário | Gerado automaticamente, volátil | Escolhido pelo administrador, fixo |
| UUID | Determinístico com base em iss+sub+aud | Aleatório no momento da criação |
| Tempo de vida | Limitado por exp do token | Até ser explicitamente removido |
| Direitos de acesso | Derivados das claims do token, limitados pelo limite de permissões | Explicitamente concedidos via GRANT |
| Restrições de host | Configuração de rede por provedor | cláusula HOST por usuário |
| Perfis de configuração | Podem ser atribuídos por UUID (persistente) | Configuráveis diretamente |
| Cotas e políticas de linha | Podem ser atribuídas por UUID (persistente) | Configuráveis diretamente |
| Roles padrão | Não configuráveis | Configuráveis |
Quando um usuário JWT efêmero cria uma view com SQL SECURITY DEFINER, o servidor cria automaticamente uma cópia sombra persistente desse usuário para servir como definidor da view. Esse usuário sombra:
- Tem o nome
<original_jwt_username>:definer
- Tem
NO_AUTHENTICATION (não pode ser usado para fazer login)
- Mantém os mesmos direitos de acesso do usuário JWT original no momento em que a view foi criada
Isso garante que a view continue funcionando depois que o token do usuário efêmero expirar e o usuário original for removido pelo coletor de lixo.
Use a flag --jwt com o clickhouse-client para autenticar usando um token obtido previamente:
clickhouse-client --host your-instance.clickhouse.cloud --secure --jwt '<your_jwt_token>'
A flag --jwt é incompatível com --user. Quando --jwt é especificada, o nome de usuário é derivado do token.
Envie o token como token Bearer no cabeçalho Authorization:
curl -H 'Authorization: Bearer <your_jwt_token>' \
'https://your-instance.clickhouse.cloud:8443/?query=SELECT+currentUser()'
Sempre envie JWTs por HTTPS. Um token Bearer enviado por HTTP sem criptografia fica exposto a qualquer pessoa no caminho da comunicação na rede e equivale ao vazamento da credencial.
O clickhouse-client oferece suporte a um fluxo interativo de código do dispositivo OAuth2 por meio da flag --login. Para endpoints do ClickHouse Cloud, o cliente faz automaticamente a troca de token para obter um JWT específico do ClickHouse. Os tokens são atualizados de forma transparente durante a sessão. Quando um novo token é obtido, o cliente se reconecta automaticamente.
clickhouse-client --host your-instance.clickhouse.cloud --login
Autenticador JWT integrado do ClickHouse Cloud
Todo ClickHouse Cloud service vem com um autenticador JWT predefinido usado pelo SQL Console e pelo fluxo --login do clickhouse-client. Esse autenticador é configurado com:
| Parâmetro | Valor |
|---|
iss (emissor) | ClickHouse |
aud (audiência) | O UUID do serviço (visível na URL do Cloud Console) |
sub (sujeito) | O endereço de e-mail da sua conta do ClickHouse Cloud |
O autenticador integrado tem um limite de permissões definido para a role default_role e para o usuário default. Isso significa que as permissões efetivas de qualquer usuário JWT ficam restritas à interseção com os grants dessas duas entidades, portanto um token nunca pode elevar privilégios além do que default_role e default têm permissão para fazer.
Você não precisa configurar nada para usar esse autenticador. Ele é provisionado automaticamente quando o serviço é criado.
Comunicação entre servidores
Quando uma consulta é encaminhada para outro shard ou réplica, o token JWT é incluído no protocolo de comunicação entre servidores. O nó remoto reautentica o token de forma independente, criando seu próprio usuário efêmero.
- Nenhum direito de acesso concedido: A role ou o usuário referenciado pode não ter os privilégios necessários. Verifique se as roles referenciadas em
clickhouse:roles existem e incluem os privilégios apropriados.
- Token rejeitado: Verifique se
iss, aud e o algoritmo de assinatura do seu token correspondem ao que o provedor JWT espera. Se JWKS estiver em uso, verifique se o kid do token corresponde a uma chave no conjunto de chaves do provedor.
- O usuário desaparece entre queries: Usuários efêmeros são removidos após a expiração do token. Use um cliente com suporte à renovação do token (por exemplo, no modo
--login) para sessões de longa duração.
CREATE USER ... IDENTIFIED WITH jwt falha: Isso é esperado. Usuários JWT não podem ser criados via DDL. Eles são gerenciados inteiramente pelo ciclo de vida do token.