Direct Cloud database connections with JWT auth (no password, no Query API key)
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 25/100
Research direction
Start by reading crates/clickhousectl/src/cloud/auth.rs and tracing how the existing cloud service client and cloud service query commands obtain credentials. The issue leaves key dependencies unresolved, including whether token exchange is supported and how direct connections handle access controls. Done means those questions have answers and the implementation scope for the proposed phases is clear.
Written by the indexing model from the issue text.
Description
End result
A user who has run clickhousectl cloud auth login can work with a Cloud ClickHouse service directly, with no password and no Query API key:
clickhousectl cloud service client --name prod # interactive clickhouse-client session
clickhousectl cloud service query --name prod -q '…' # SQL over direct HTTPS instead of the Query API
clickhousectl cloud service token --name prod # short-lived token for a driver or script
Each connection runs as the user's own Cloud identity, with rights capped at the service's default user, and the token expires on its own.
What it improves
- Connecting without a password. Today the default user's password is only shown by
service createandreset-password. That is why we removedcloud service client: it needed both a 200 MB local binary and that password. With JWT auth the password problem goes away, and the binary becomes optional rather than required. - No minted or bound Query API keys for OAuth users.
cloud service querycurrently provisions or binds a Query API key (#1043). A direct connection would just use the user's token. - The full ClickHouse interface. Every output format, streaming, session settings and the native protocol, instead of the Query API's single statement per request.
- Audit. Queries show up as the person who ran them (
JWT::<email>::…), not asdefault.
How it works today (research, 2026-10-30)
- Cloud services accept a short-lived JWT over HTTPS (
Authorization: Bearer) and native TCP. The built-in Cloud authenticator is listed for all plans. Its tokens carryiss=ClickHouse,aud=<service UUID>andsub=<account email>. A session runs as an in-memory userJWT::<sub>::<hash>, limited todefault+default_roleand further narrowed by the token's grant and role claims. The user expires atexp. Sources: https://clickhouse.com/docs/concepts/features/security/external-authenticators/jwt, https://clickhouse.com/blog/introducing-jwt-authentication-in-clickhouse-cloud clickhouse-client --jwt <token>was added in PR ClickHouse/ClickHouse#62829 (24.7, inferred).clickhouse-client --login(ClickHouse/ClickHouse#89261, 25.12, inferred) runs the whole flow itself and refreshes the token during a session. Its flow, fromsrc/Client/CloudJWTProvider.cpp:- An Auth0 device flow at
auth.clickhouse.cloudwith audiencetoken-exchange. POST https://console-api-internal.clickhouse.cloud/.api/auth/tokenExchangewith the IdP token as Bearer and body{"hostname": "<service host>"}.- The response is
{"token": "<ClickHouse JWT>"}.
- An Auth0 device flow at
- The public OpenAPI (
/v1) has no endpoint that issues database tokens. - clickhousectl's own OAuth token uses audience
clickhousectl(crates/clickhousectl/src/cloud/auth.rs), nottoken-exchange. - Drivers already accept a bearer token: clickhouse-js and clickhouse-connect (
access_token), Go (GetJWT), Java (useBearerTokenAuth), and Rust (clickhousecrate,Client::with_access_token). - Cloud Postgres services: we found no JWT support; credentials there are still a password.
Proposed phases
cloud service client, delegating toclickhouse-client --login. If a localclickhouse-client≥ 25.12 is installed (or one thatlocal installmanages), execclickhouse-client --host <service host> --secure --login. The client owns the token, so this needs nothing new from Cloud. It still needs a human to complete the device flow in a browser.- Direct
cloud service queryfor OAuth sessions. Exchange the CLI's token for a database JWT and send SQL over HTTPS from Rust. Keep the Query API path for API-key auth, CI and agents. Needs a supported exchange (see below). cloud service token/ a JWT incloud service dotenv. Hand a short-lived token to drivers and scripts. Same dependency as phase 2.
What we need to resolve (Cloud team)
- Will
/.api/auth/tokenExchangebecome a supported public contract, or get a/v1equivalent? Can third-party clients such as clickhousectl rely on it? - Can the exchange accept clickhousectl's Auth0 audience or client, or should the CLI also request
token-exchange? - Can an organization API key be exchanged for a database JWT? This would serve CI and agents, which can't do a device flow.
- What is a token's lifetime, and is there refresh or revocation?
- Can a token carry rights narrower than
default, for example a read-only mode? - Does the built-in authenticator need enabling per service? The activity log has a
service_update_sql_console_jwt_authtype. - How do direct connections behave with IP access lists and private-endpoint-only services, which the Query API handles today? How does an idle service wake on a direct connection?
- Is JWT auth planned for Cloud Postgres?
Not in scope
- Bring-your-own-identity-provider JWT (Enterprise, configured per service in the console).
- Postgres, until question 8 is answered.
🤖 Generated with Claude Code
- Dominant language
- Rust
- Stars
- 80
- Forks
- 9
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 51
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from ClickHouse/clickhousectl
-
cargo audit red on main: RUSTSEC-2026-0387 (crypto-bigint 0.5.5 via aws-config credentials-login)Possibly taken @sdairs claimed this 1 day ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
ClickHouse/clickhousectl#1183 ·
Maintainers usually reply within 1 day
-
dependencies
Difficulty 2/5 1-3 hours Newbie friendliness 35/100
ClickHouse/clickhousectl#1185 ·
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 5/100
ClickHouse/clickhousectl#1182 ·
Maintainers usually reply within 1 day
-
rust test-coverage
Difficulty 5/5 Over a week Newbie friendliness 35/100
ClickHouse/clickhousectl#1175 · 2 comments ·
Maintainers usually reply within 1 day
-
rust test-coverage
Difficulty 4/5 3-5 days Newbie friendliness 45/100
ClickHouse/clickhousectl#1174 · 1 comment ·
Maintainers usually reply within 1 day
All issues in ClickHouse/clickhousectl
Similar issues
-
docs(metrics): replace stale src/metrics.rs line anchors in dashboard-metrics.md with symbol namesOpen
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
Maintainers usually reply within 1 day
-
ci-cd desktop size:low telemetry-improvement telemetry-round-1
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
vfarcic/dot-agent-deck#2079 ·
Maintainers usually reply within 1 day
-
enhancement user-priority/P3
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
Maintainers usually reply within 2 days