|
| 1 | +--- |
| 2 | +slug: /en/operations/external-authenticators/jwt |
| 3 | +--- |
| 4 | +# JWT |
| 5 | +import SelfManaged from '@site/docs/en/_snippets/_self_managed_only_no_roadmap.md'; |
| 6 | + |
| 7 | +<SelfManaged /> |
| 8 | + |
| 9 | +Existing and properly configured ClickHouse users can be authenticated via JWT. |
| 10 | + |
| 11 | +Currently, JWT can only be used as an external authenticator for existing users, which are defined in `users.xml` or in local access control paths. |
| 12 | +The username will be extracted from the JWT after validating the token expiration and against the signature. Signature can be validated by: |
| 13 | +- static public key |
| 14 | +- static JWKS |
| 15 | +- received from the JWKS servers |
| 16 | + |
| 17 | +It is mandatory for a JWT tot indicate the name of the ClickHouse user under `"sub"` claim, otherwise it will not be accepted. |
| 18 | + |
| 19 | +A JWT may additionally be verified by checking the JWT payload. |
| 20 | +In this case, the occurrence of specified claims from the user settings in the JWT payload is checked. |
| 21 | +See [Enabling JWT authentication in `users.xml`](#enabling-jwt-auth-in-users-xml) |
| 22 | + |
| 23 | +To use JWT authentication, JWT validators must be configured in ClickHouse config. |
| 24 | + |
| 25 | + |
| 26 | +## Enabling JWT validators in ClickHouse {#enabling-jwt-validators-in-clickhouse} |
| 27 | + |
| 28 | +To enable JWT validators, add `token_validators` section in `config.xml`. This section may contain several JWT verifiers, minimum is 1. |
| 29 | + |
| 30 | +### Verifying JWT signature using static key {$verifying-jwt-signature-using-static-key} |
| 31 | + |
| 32 | +**Example** |
| 33 | +```xml |
| 34 | +<clickhouse> |
| 35 | + <!- ... --> |
| 36 | + <jwt_validators> |
| 37 | + <my_static_key_validator> |
| 38 | + <algo>HS256</algo> |
| 39 | + <static_key>my_static_secret</static_key> |
| 40 | + </my_static_key_validator> |
| 41 | + </jwt_validators> |
| 42 | +</clickhouse> |
| 43 | +``` |
| 44 | + |
| 45 | +#### Parameters: |
| 46 | + |
| 47 | +- `algo` - Algorithm for validate signature. Supported: |
| 48 | + |
| 49 | + | HMAC | RSA | ECDSA | PSS | EdDSA | |
| 50 | + |-------| ----- | ------ | ----- | ------- | |
| 51 | + | HS256 | RS256 | ES256 | PS256 | Ed25519 | |
| 52 | + | HS384 | RS384 | ES384 | PS384 | Ed448 | |
| 53 | + | HS512 | RS512 | ES512 | PS512 | | |
| 54 | + | | | ES256K | | | |
| 55 | + Also support None. |
| 56 | +- `static_key` - key for symmetric algorithms. Mandatory for `HS*` family algorithms. |
| 57 | +- `static_key_in_base64` - indicates if the `static_key` key is base64-encoded. Optional, default: `False`. |
| 58 | +- `public_key` - public key for asymmetric algorithms. Mandatory except for `HS*` family algorithms and `None`. |
| 59 | +- `private_key` - private key for asymmetric algorithms. Optional. |
| 60 | +- `public_key_password` - public key password. Optional. |
| 61 | +- `private_key_password` - private key password. Optional. |
| 62 | + |
| 63 | +### Verifying JWT signature using static JWKS {$verifying-jwt-signature-using-static-jwks} |
| 64 | + |
| 65 | +:::note |
| 66 | +Only RS* family algorithms are supported! |
| 67 | +::: |
| 68 | + |
| 69 | +**Example** |
| 70 | +```xml |
| 71 | +<clickhouse> |
| 72 | + <!- ... --> |
| 73 | + <jwt_validators> |
| 74 | + <my_static_jwks_validator> |
| 75 | + <static_jwks>{"keys": [{"kty": "RSA", "alg": "RS256", "kid": "mykid", "n": "_public_key_mod_", "e": "AQAB"}]}</static_jwks> |
| 76 | + </my_static_jwks_validator> |
| 77 | + </jwt_validators> |
| 78 | +</clickhouse> |
| 79 | +``` |
| 80 | + |
| 81 | +#### Parameters: |
| 82 | +- `static_jwks` - content of JWKS in json |
| 83 | +- `static_jwks_file` - path to file with JWKS |
| 84 | + |
| 85 | +:::note |
| 86 | +Only one of `static_jwks` or `static_jwks_file` keys must be present in one verifier |
| 87 | +::: |
| 88 | + |
| 89 | +### Verifying JWT signature using JWKS servers {$verifying-jwt-signature-using-static-jwks} |
| 90 | + |
| 91 | +**Example** |
| 92 | +```xml |
| 93 | +<clickhouse> |
| 94 | + <!- ... --> |
| 95 | + <jwt_validators> |
| 96 | + <basic_auth_server> |
| 97 | + <uri>http://localhost:8000/.well-known/jwks.json</uri> |
| 98 | + <connection_timeout_ms>1000</connection_timeout_ms> |
| 99 | + <receive_timeout_ms>1000</receive_timeout_ms> |
| 100 | + <send_timeout_ms>1000</send_timeout_ms> |
| 101 | + <max_tries>3</max_tries> |
| 102 | + <retry_initial_backoff_ms>50</retry_initial_backoff_ms> |
| 103 | + <retry_max_backoff_ms>1000</retry_max_backoff_ms> |
| 104 | + <refresh_ms>300000</refresh_ms> |
| 105 | + </basic_auth_server> |
| 106 | + </jwt_validators> |
| 107 | +</clickhouse> |
| 108 | +``` |
| 109 | + |
| 110 | +#### Parameters: |
| 111 | + |
| 112 | +- `uri` - JWKS endpoint. Mandatory. |
| 113 | +- `refresh_ms` - Period for resend request for refreshing JWKS. Optional, default: 300000. |
| 114 | + |
| 115 | +Timeouts in milliseconds on the socket used for communicating with the server (optional): |
| 116 | +- `connection_timeout_ms` - Default: 1000. |
| 117 | +- `receive_timeout_ms` - Default: 1000. |
| 118 | +- `send_timeout_ms` - Default: 1000. |
| 119 | + |
| 120 | +Retry parameters (optional): |
| 121 | +- `max_tries` - The maximum number of attempts to make an authentication request. Default: 3. |
| 122 | +- `retry_initial_backoff_ms` - The backoff initial interval on retry. Default: 50. |
| 123 | +- `retry_max_backoff_ms` - The maximum backoff interval. Default: 1000. |
| 124 | + |
| 125 | +### Verifying access tokens {$verifying-access-tokens} |
| 126 | + |
| 127 | +Access tokens that are not JWT (and thus no data can be extracted from the token directly) need to be resolved by external providers. |
| 128 | + |
| 129 | +**Example** |
| 130 | +```xml |
| 131 | +<clickhouse> |
| 132 | + <!- ... --> |
| 133 | + <access_token_processors> |
| 134 | + <my_access_token_processor> |
| 135 | + <provider>google</provider> |
| 136 | + </my_access_token_processor> |
| 137 | + </access_token_processors> |
| 138 | +</clickhouse> |
| 139 | +``` |
| 140 | + |
| 141 | +#### Parameters: |
| 142 | + |
| 143 | +- `provider` - name of provider that will be used for token processing. Mandatory parameter. Possible options: `google`. |
| 144 | + |
| 145 | + |
| 146 | +### Enabling JWT authentication in `users.xml` {#enabling-jwt-auth-in-users-xml} |
| 147 | + |
| 148 | +In order to enable JWT authentication for the user, specify `jwt` section instead of `password` or other similar sections in the user definition. |
| 149 | + |
| 150 | +Parameters: |
| 151 | +- `claims` - An optional string containing a json object that should be contained in the token payload. |
| 152 | + |
| 153 | +Example (goes into `users.xml`): |
| 154 | +```xml |
| 155 | +<clickhouse> |
| 156 | + <!- ... --> |
| 157 | + <my_user> |
| 158 | + <!- ... --> |
| 159 | + <jwt> |
| 160 | + <claims>{"resource_access":{"account": {"roles": ["view-profile"]}}}</claims> |
| 161 | + </jwt> |
| 162 | + </my_user> |
| 163 | +</clickhouse> |
| 164 | +``` |
| 165 | + |
| 166 | +Here, the JWT payload must contain `["view-profile"]` on path `resource_access.account.roles`, otherwise authentication will not succeed even with a valid JWT. |
| 167 | + |
| 168 | +``` |
| 169 | +{ |
| 170 | +... |
| 171 | + "resource_access": { |
| 172 | + "account": { |
| 173 | + "roles": ["view-profile"] |
| 174 | + } |
| 175 | + }, |
| 176 | +... |
| 177 | +} |
| 178 | +``` |
| 179 | + |
| 180 | +:::note |
| 181 | +JWT authentication cannot be used together with any other authentication method. The presence of any other sections like `password` alongside `jwt` will force ClickHouse to shut down. |
| 182 | +::: |
| 183 | + |
| 184 | +### Enabling JWT authentication using SQL {#enabling-jwt-auth-using-sql} |
| 185 | + |
| 186 | +When [SQL-driven Access Control and Account Management](/docs/en/guides/sre/user-management/index.md#access-control) is enabled in ClickHouse, users identified by JWT authentication can also be created using SQL statements. |
| 187 | + |
| 188 | +```sql |
| 189 | +CREATE USER my_user IDENTIFIED WITH jwt CLAIMS '{"resource_access":{"account": {"roles": ["view-profile"]}}}' |
| 190 | +``` |
| 191 | + |
| 192 | +Or without additional JWT payload checks: |
| 193 | + |
| 194 | +```sql |
| 195 | +CREATE USER my_user IDENTIFIED WITH jwt |
| 196 | +``` |
| 197 | + |
| 198 | +## JWT authentication examples {#jwt-authentication-examples} |
| 199 | + |
| 200 | +#### Console client |
| 201 | + |
| 202 | +``` |
| 203 | +clickhouse-client -jwt <token> |
| 204 | +``` |
| 205 | + |
| 206 | +#### HTTP requests |
| 207 | + |
| 208 | +``` |
| 209 | +curl 'http://localhost:8080/?' \ |
| 210 | + -H 'Authorization: Bearer <TOKEN>' \ |
| 211 | + -H 'Content type: text/plain;charset=UTF-8' \ |
| 212 | + --data-raw 'SELECT current_user()' |
| 213 | +``` |
| 214 | +:::note |
| 215 | +ClickHouse will look for a JWT token in (by priority): |
| 216 | +1. `X-ClickHouse-JWT-Token` header. |
| 217 | +2. `Authorization` header. |
| 218 | +3. `token` request parameter. In this case, the "Bearer" prefix should not exist. |
| 219 | +::: |
0 commit comments