Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add description for tidb_auth_token authentication (#15979) #16652

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion basic-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ You can try out TiDB features on [TiDB Playground](https://play.tidbcloud.com/?u
| [Certificate-based authentication](/certificate-authentication.md) | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
| [`caching_sha2_password` authentication](/system-variables.md#default_authentication_plugin) | Y | Y | Y | Y | Y | Y | Y | N | N | N |
| [`tidb_sm3_password` authentication](/system-variables.md#default_authentication_plugin) | Y | Y | Y | N | N | N | N | N | N | N |
| [`tidb_auth_token` authentication](/system-variables.md#default_authentication_plugin) | Y | Y | Y | N | N | N | N | N | N | N |
| [`tidb_auth_token` authentication](/security-compatibility-with-mysql.md#tidb_auth_token) | Y | Y | Y | N | N | N | N | N | N | N |
| [`authentication_ldap_sasl` authentication](/system-variables.md#default_authentication_plugin) | Y | N | N | N | N | N | N | N | N |
| [`authentication_ldap_simple` authentication](/system-variables.md#default_authentication_plugin) | Y | Y | N | N | N | N | N | N | N | N |
| [Password management](/password-management.md) | Y | Y | Y | N | N | N | N | N | N | N |
Expand Down
123 changes: 121 additions & 2 deletions security-compatibility-with-mysql.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,9 @@ The implementation mechanisms are consistent between TiDB and MySQL. Both use th

## Authentication plugin status

TiDB supports multiple authentication methods. These methods can be specified on a per user basis using [`CREATE USER`](/sql-statements/sql-statement-create-user.md) and [`ALTER USER`](/sql-statements/sql-statement-create-user.md). These methods are compatible with the authentication methods of MySQL with the same names.
TiDB supports multiple authentication methods. These methods can be specified on a per user basis using [`CREATE USER`](/sql-statements/sql-statement-create-user.md) and [`ALTER USER`](/sql-statements/sql-statement-alter-user.md). These methods are compatible with the authentication methods of MySQL with the same names.

You can use one of the following supported authentication methods in the table. To specify a default method that the server advertises when the client-server connection is being established, set the [`default_authentication_plugin`](/system-variables.md#default_authentication_plugin) variable. `tidb_sm3_password` is the SM3 authentication method only supported in TiDB. Therefore, to authenticate using this method, you must connect to TiDB using [TiDB-JDBC](https://github.com/pingcap/mysql-connector-j/tree/release/8.0-sm3). `tidb_auth_token` is a JSON Web Token (JWT) based authentication method used only in TiDB Cloud.
You can use one of the following supported authentication methods in the table. To specify a default method that the server advertises when the client-server connection is being established, set the [`default_authentication_plugin`](/system-variables.md#default_authentication_plugin) variable. `tidb_sm3_password` is the SM3 authentication method only supported in TiDB. Therefore, to authenticate using this method, you must connect to TiDB using [TiDB-JDBC](https://github.com/pingcap/mysql-connector-j/tree/release/8.0-sm3). `tidb_auth_token` is a JSON Web Token (JWT)-based authentication method used in TiDB Cloud, and you can also configure it for use in TiDB Self-Hosted.

<CustomContent platform="tidb">

Expand Down Expand Up @@ -139,3 +139,122 @@ The support for TLS authentication is configured differently. For detailed infor
| ed25519 (MariaDB) | No |
| GSSAPI (MariaDB) | No |
| FIDO | No |

### `tidb_auth_token`

`tidb_auth_token` is a passwordless authentication method based on [JSON Web Token (JWT)](https://datatracker.ietf.org/doc/html/rfc7519). In v6.4.0, `tidb_auth_token` is only used for user authentication in TiDB Cloud. Starting from v6.5.0, you can also configure `tidb_auth_token` as a user authentication method for TiDB Self-Hosted. Different from password-based authentication methods such as `mysql_native_passsword` and `caching_sha2_password`, when you create users using `tidb_auth_token`, there is no need to set or store custom passwords. To log into TiDB, users only need to use a signed token instead of a password, which simplifies the authentication process and improves security.

#### JWT

JWT consists of three parts: Header, Payload, and Signature. After being encoded using base64, they are concatenated into a string separated by dots (`.`) for transmission between the client and server.

The Header describes the metadata of the JWT, including 3 parameters:

* `alg`: the algorithm for signature, which is `RS256` by default.
* `typ`: the type of token, which is `JWT`.
* `kid`: the key ID for generating token signature.

Here is an example for Header:

```json
{
"alg": "RS256",
"kid": "the-key-id-0",
"typ": "JWT"
}
```

Payload is the main part of JWT, which stores the user information. Each field in the Payload is called a claim. The claims required for TiDB user authentication are as follows:

* `iss`: if `TOKEN_ISSUER` is not specified or set to empty when [`CREATE USER`](/sql-statements/sql-statement-create-user.md), this claim is not required; otherwise, `iss` should use the same value as `TOKEN_ISSUER`.
* `sub`: this claim is required to be the same as the username to be authenticated.
* `iat`: it means `issued at`, the timestamp when the token is issued. In TiDB, this value must not be later than the authentication time or earlier than 15 minutes before authentication.
* `exp`: the timestamp when the token expires. If it is earlier than the time of authentication, the authentication fails.
* `email`: the email can be specified when creating a user by `ATTRIBUTE '{"email": "[email protected]"}`. If no email is specified when a user is created, this claim must be set as an empty string; otherwise, this claim must be the same as the specified value when the user is created.

Here is an example for Payload:

```json
{
"email": "[email protected]",
"exp": 1703305494,
"iat": 1703304594,
"iss": "issuer-abc",
"sub": "[email protected]"
}
```

Signature is used to sign the Header and Payload data.

> **Warning:**
>
> - The encoding of the Header and Payload in base64 is reversible. Do **Not** attach any sensitive information to them.
> - The `tidb_auth_token` authentication method requires clients to support the [`mysql_clear_password`](https://dev.mysql.com/doc/refman/8.0/en/cleartext-pluggable-authentication.html) plugin to send the token to TiDB in plain text. Therefore, you need to [enale TLS between clients and servers](/enable-tls-between-clients-and-servers.md) before using `tidb_auth_token`.

#### Usage

To configure and use `tidb_auth_token` as the authentication method for TiDB Self-Hosted users, take the following steps:

1. Configure [`auth-token-jwks`](/tidb-configuration-file.md#auth-token-jwks-new-in-v640) and [`auth-token-refresh-interval`](/tidb-configuration-file.md#auth-token-refresh-interval-new-in-v640) in the TiDB configuration file.

For example, you can get an example JWKS using the following command:

```bash
wget https://raw.githubusercontent.com/CbcWestwolf/generate_jwt/master/JWKS.json
```

Then, configure the path of the example JWKS in `config.toml`:

```toml
[security]
auth-token-jwks = "JWKS.json"
```

2. Start `tidb-server` and periodically update and save the JWKS to the path specified by `auth-token-jwks`.

3. Create a user with `tidb_auth_token`, and specify `iss` and `email` as needed using `REQUIRE TOKEN_ISSUER` and `ATTRIBUTE '{"email": "[email protected]"}`.

For example, create a user `[email protected]` with `tidb_auth_token`:

```sql
CREATE USER '[email protected]' IDENTIFIED WITH 'tidb_auth_token' REQUIRE TOKEN_ISSUER 'issuer-abc' ATTRIBUTE '{"email": "[email protected]"}';
```

4. Generate and sign a token for authentication, and authenticate using the `mysql_clear_text` plugin of the MySQL client.

Install the JWT generation tool via `go install github.com/cbcwestwolf/generate_jwt` (this tool is only used for testing `tidb_auth_token`). For example:

```text
generate_jwt --kid "the-key-id-0" --sub "[email protected]" --email "[email protected]" --iss "issuer-abc"
```

It prints the public key and token as follows:

```text
-----BEGIN PUBLIC KEY-----
MIIBCgKCAQEAq8G5n9XBidxmBMVJKLOBsmdOHrCqGf17y9+VUXingwDUZxRp2Xbu
LZLbJtLgcln1lC0L9BsogrWf7+pDhAzWovO6Ai4Aybu00tJ2u0g4j1aLiDdsy0gy
vSb5FBoL08jFIH7t/JzMt4JpF487AjzvITwZZcnsrB9a9sdn2E5B/aZmpDGi2+Is
f5osnlw0zvveTwiMo9ba416VIzjntAVEvqMFHK7vyHqXbfqUPAyhjLO+iee99Tg5
AlGfjo1s6FjeML4xX7sAMGEy8FVBWNfpRU7ryTWoSn2adzyA/FVmtBvJNQBCMrrA
hXDTMJ5FNi8zHhvzyBKHU0kBTS1UNUbP9wIDAQAB
-----END PUBLIC KEY-----

eyJhbGciOiJSUzI1NiIsImtpZCI6InRoZS1rZXktaWQtMCIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InVzZXJAcGluZ2NhcC5jb20iLCJleHAiOjE3MDMzMDU0OTQsImlhdCI6MTcwMzMwNDU5NCwiaXNzIjoiaXNzdWVyLWFiYyIsInN1YiI6InVzZXJAcGluZ2NhcC5jb20ifQ.T4QPh2hTB5on5xCuvtWiZiDTuuKvckggNHtNaovm1F4RvwUv15GyOqj9yMstE-wSoV5eLEcPC2HgE6eN1C6yH_f4CU-A6n3dm9F1w-oLbjts7aYCl8OHycVYnq609fNnb8JLsQAmd1Zn9C0JW899-WSOQtvjLqVSPe9prH-cWaBVDQXzUJKxwywQzk9v-Z1Njt9H3Rn9vvwwJEEPI16VnaNK38I7YG-1LN4fAG9jZ6Zwvz7vb_s4TW7xccFf3dIhWTEwOQ5jDPCeYkwraRXU8NC6DPF_duSrYJc7d7Nu9Z2cr-E4i1Rt_IiRTuIIzzKlcQGg7jd9AGEfGe_SowsA-w
```

Copy the preceding token in the last line for login:

```Shell
mycli -h 127.0.0.1 -P 4000 -u '[email protected]' -p '<the-token-generated>'
```

Ensure that the MySQL client here supports the `mysql_clear_password` plugin. [mycli](https://www.mycli.net/) supports and enables this plugin by default. If you are using the [mysql command-line client](https://dev.mysql.com/doc/refman/8.0/en/mysql.html), you need to use the `--enable-cleartext-plugin` option to enable this plugin:

```Shell
mysql -h 127.0.0.1 -P 4000 -u '[email protected]' -p'<the-token-generated>' --enable-cleartext-plugin
```

If an incorrect `--sub` is specified when the token is generated (such as `--sub "[email protected]"`), the authentication using this token would fail.

You can encode and decode a token using the debugger provided by [jwt.io](https://jwt.io/).
6 changes: 6 additions & 0 deletions sql-statements/sql-statement-alter-user.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ UserSpecList ::=
UserSpec ::=
Username AuthOption

RequireClauseOpt ::=
( 'REQUIRE' 'NONE' | 'REQUIRE' 'SSL' | 'REQUIRE' 'X509' | 'REQUIRE' RequireList )?

RequireList ::=
( "ISSUER" stringLit | "SUBJECT" stringLit | "CIPHER" stringLit | "SAN" stringLit | "TOKEN_ISSUER" stringLit )*

Username ::=
StringName ('@' StringName | singleAtIdentifier)? | 'CURRENT_USER' OptionalBraces

Expand Down
6 changes: 6 additions & 0 deletions sql-statements/sql-statement-create-user.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ IfNotExists ::=
UserSpecList ::=
UserSpec ( ',' UserSpec )*

RequireClauseOpt ::=
( 'REQUIRE' 'NONE' | 'REQUIRE' 'SSL' | 'REQUIRE' 'X509' | 'REQUIRE' RequireList )?

RequireList ::=
( "ISSUER" stringLit | "SUBJECT" stringLit | "CIPHER" stringLit | "SAN" stringLit | "TOKEN_ISSUER" stringLit )*

UserSpec ::=
Username AuthOption

Expand Down
1 change: 0 additions & 1 deletion system-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,6 @@ mysql> SELECT * FROM t1;
- Type: Enumeration
- Default value: `mysql_native_password`
- Possible values: `mysql_native_password`, `caching_sha2_password`, `tidb_sm3_password`, `tidb_auth_token`, `authentication_ldap_sasl`, and `authentication_ldap_simple`.
- The `tidb_auth_token` authentication method is used only for the internal operation of TiDB Cloud. **DO NOT** set the variable to this value.
- This variable sets the authentication method that the server advertises when the server-client connection is being established.
- To authenticate using the `tidb_sm3_password` method, you can connect to TiDB using [TiDB-JDBC](https://github.com/pingcap/mysql-connector-j/tree/release/8.0-sm3).

Expand Down
12 changes: 2 additions & 10 deletions tidb-configuration-file.md
Original file line number Diff line number Diff line change
Expand Up @@ -418,20 +418,12 @@ Configuration items related to security.

### `auth-token-jwks` <span class="version-mark">New in v6.4.0</span>

> **Warning:**
>
> The `tidb_auth_token` authentication method is used only for the internal operation of TiDB Cloud. **DO NOT** change the value of this configuration.

- Set the local file path of the JSON Web Key Sets (JWKS) for the `tidb_auth_token` authentication method.
- Set the local file path of the JSON Web Key Sets (JWKS) for the [`tidb_auth_token`](/security-compatibility-with-mysql.md#tidb_auth_token) authentication method.
- Default value: `""`

### `auth-token-refresh-interval` <span class="version-mark">New in v6.4.0</span>

> **Warning:**
>
> The `tidb_auth_token` authentication method is used only for the internal operation of TiDB Cloud. **DO NOT** change the value of this configuration.

- Set the JWKS refresh interval for the `tidb_auth_token` authentication method.
- Set the JWKS refresh interval for the [`tidb_auth_token`](/security-compatibility-with-mysql.md#tidb_auth_token) authentication method.
- Default value: `1h`

### `disconnect-on-expired-password` <span class="version-mark">New in v6.5.0</span>
Expand Down
Loading