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 (#15818) #16711

Merged
2 changes: 1 addition & 1 deletion basic-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ summary: 了解 TiDB 的功能概览。
| [证书鉴权](/certificate-authentication.md) | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
| [`caching_sha2_password` 认证](/system-variables.md#default_authentication_plugin) | Y | Y | Y | Y | Y | Y | Y | N | N | N |
| [`tidb_sm3_password` 认证](/system-variables.md#default_authentication_plugin) | Y | Y | Y | N | N | N | N | N | N | N |
| [`tidb_auth_token` 认证](/system-variables.md#default_authentication_plugin) | Y | Y | Y | N | N | N | N | N | N | N |
| [`tidb_auth_token` 认证](/security-compatibility-with-mysql.md#tidb_auth_token) | Y | Y | Y | N | N | N | N | N | N | N |
| [`authentication_ldap_sasl` 认证](/system-variables.md#default_authentication_plugin) | Y | Y | N | N | N | N | N | N | N | N |
| [`authentication_ldap_simple` 认证](/system-variables.md#default_authentication_plugin) | Y | Y | N | N | N | N | N | N | N | N |
| [密码管理](/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 @@ TiDB 的密码重用策略功能与 MySQL 一致,在实现密码重用策略

## 可用的身份验证插件

TiDB 支持多种身份验证方式。通过使用 [`CREATE USER`](/sql-statements/sql-statement-create-user.md) 语句和 [`ALTER USER`](/sql-statements/sql-statement-create-user.md) 语句,即可创建新用户或更改 TiDB 权限系统内的已有用户。TiDB 身份验证方式与 MySQL 兼容,其名称与 MySQL 保持一致。
TiDB 支持多种身份验证方式。通过使用 [`CREATE USER`](/sql-statements/sql-statement-create-user.md) 语句和 [`ALTER USER`](/sql-statements/sql-statement-alter-user.md) 语句,即可创建新用户或更改 TiDB 权限系统内的已有用户。TiDB 身份验证方式与 MySQL 兼容,其名称与 MySQL 保持一致。

TiDB 目前支持的身份验证方式可在以下的表格中查找到。服务器和客户端建立连接时,如要指定服务器对外通告的默认验证方式,可通过 [`default_authentication_plugin`](/system-variables.md#default_authentication_plugin) 变量进行设置。`tidb_sm3_password` 为仅在 TiDB 支持的 SM3 身份验证方式,使用该方式登录的用户需要使用 [TiDB-JDBC](https://github.com/pingcap/mysql-connector-j/tree/release/8.0-sm3)。`tidb_auth_token` 为仅用于 TiDB Cloud 内部的基于 JSON Web Token (JWT) 的认证方式
TiDB 目前支持的身份验证方式可在以下的表格中查找到。服务器和客户端建立连接时,如要指定服务器对外通告的默认验证方式,可通过 [`default_authentication_plugin`](/system-variables.md#default_authentication_plugin) 变量进行设置。`tidb_sm3_password` 为仅在 TiDB 支持的 SM3 身份验证方式,使用该方式登录的用户需要使用 [TiDB-JDBC](https://github.com/pingcap/mysql-connector-j/tree/release/8.0-sm3)。`tidb_auth_token` 用于 TiDB Cloud 内部的基于 JSON Web Token (JWT) 的认证,用户通过配置也可以用于自托管环境

针对 TLS 身份验证,TiDB 目前采用不同的配置方案。具体情况请参见[为 TiDB 客户端服务端间通信开启加密传输](/enable-tls-between-clients-and-servers.md)。

Expand All @@ -129,3 +129,122 @@ TiDB 目前支持的身份验证方式可在以下的表格中查找到。服务
| ed25519 (MariaDB) | 否 |
| GSSAPI (MariaDB) | 否 |
| FIDO | 否 |

### `tidb_auth_token`

`tidb_auth_token` 是一种基于 [JSON Web Token (JWT)](https://datatracker.ietf.org/doc/html/rfc7519) 的无密码认证方式。在 v6.4.0 中,`tidb_auth_token` 仅用于 TiDB Cloud 内部的用户认证,从 v6.5.0 起,你也可以将 `tidb_auth_token` 配置为 TiDB 自托管环境中用户的认证方式。不同于 `mysql_native_passsword`、`caching_sha2_password` 等使用密码的认证方式,`tidb_auth_token` 认证方式在创建用户时无需设置并保存自定义密码,在用户登录时只需使用一个签发的 token,从而简化用户的认证过程并提升安全性。

#### JWT

JWT 由 Header、Payload 和 Signature 三部分组成。这三部分分别通过 base64 编码后,使用点号(`.`)拼接成一个字符串,以便在客户端和服务器之间传输。

Header 描述 JWT 的元数据,包含 3 个属性:

* `alg`:表示签名使用的算法,默认为 `RS256`。
* `typ`:表示 token 的类型,为 `JWT`。
* `kid`:表示用于生成 token 签名的 key ID。

Header 示例:

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

Payload 是 JWT 的主体部分,用于保存用户的信息。Payload 中的每个字段称为一个 claim(声明)。TiDB 用户认证要求提供的声明如下:

* `iss`:如果[创建用户](/sql-statements/sql-statement-create-user.md)时未指定 `TOKEN_ISSUER` 或者将其设置为了空字符串,则可以不包含该声明;否则 `iss` 应该与 `TOKEN_ISSUER` 设置值相同。
* `sub`:TiDB 中要求该值与待认证的用户名相同。
* `iat`:发布 token 的时间戳。TiDB 中要求该值不得晚于认证时的时间,也不得早于认证前 15 分钟。
* `exp`:token 到期的时间戳。如果 token 在认证时已经过期,则认证失败。
* `email`:邮件地址。创建用户时可以通过 `ATTRIBUTE '{"email": "xxxx@pingcap.com"}'` 指定 email 信息。如果创建用户时未指定 email 信息,则该声明应设置为空字符串;否则该声明应该与创建用户时的设置值相同。

Payload 示例:

```json
{
"email": "user@pingcap.com",
"exp": 1703305494,
"iat": 1703304594,
"iss": "issuer-abc",
"sub": "user@pingcap.com"
}
```

Signature 用于对 Header 和 Payload 这两部分数据进行签名。

> **警告:**
>
> - Header 与 Payload 使用 base64 进行编码的过程是可逆的,请勿在 Payload 中携带敏感数据。
> - `tidb_auth_token` 认证方式要求客户端支持 [`mysql_clear_password`](https://dev.mysql.com/doc/refman/8.0/en/cleartext-pluggable-authentication.html) 插件,并将 token 以明文的方式发送至 TiDB,因此请[为 TiDB 开启加密传输](/enable-tls-between-clients-and-servers.md) 后再使用 `tidb_auth_token` 进行认证。

#### 使用方法

配置并使用 `tidb_auth_token` 作为 TiDB 自托管环境中用户的认证方式,有以下几个步骤:

1. 在 TiDB 配置文件中设置 [`auth-token-jwks`](/tidb-configuration-file.md#auth-token-jwks-从-v640-版本开始引入) 和 [`auth-token-refresh-interval`](/tidb-configuration-file.md#auth-token-refresh-interval-从-v640-版本开始引入)。

例如,可以通过下列命令获取示例 JWKS:

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

然后在 TiDB 的配置文件 `config.toml` 中配置上述 JWKS 文件的路径:

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

2. 启动 `tidb-server`,并定期更新保存 JWKS 至 `auth-token-jwks` 指定的路径。

3. 创建使用 `tidb_auth_token` 认证的用户,并根据需要通过 `REQUIRE TOKEN_ISSUER` 和 `ATTRIBUTE '{"email": "xxxx@pingcap.com"}` 指定 `iss` 与 `email` 信息。

例如,创建一个使用 `tidb_auth_token` 认证的用户 `user@pingcap.com`:

```sql
CREATE USER 'user@pingcap.com' IDENTIFIED WITH 'tidb_auth_token' REQUIRE TOKEN_ISSUER 'issuer-abc' ATTRIBUTE '{"email": "user@pingcap.com"}';
```

4. 生成并签发用于认证的 token,通过 mysql 客户端的 `mysql_clear_text` 插件进行认证。

通过 `go install github.com/cbcwestwolf/generate_jwt` 安装 JWT 生成工具。该工具仅用于生成测试 `tidb_auth_token` 的 JWT。例如:

```text
generate_jwt --kid "the-key-id-0" --sub "user@pingcap.com" --email "user@pingcap.com" --iss "issuer-abc"
```

打印公钥和 token 形式如下:

```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
```

复制上面最后一行的 token 用于登录:

```Shell
mycli -h 127.0.0.1 -P 4000 -u 'user@pingcap.com' -p '<the-token-generated>'
```

注意这里使用的 mysql 客户端必须支持 `mysql_clear_password` 插件。[mycli](https://www.mycli.net/) 默认开启这一插件,如果使用 [mysql 命令行客户端](https://dev.mysql.com/doc/refman/8.0/en/mysql.html) 则需要 `--enable-cleartext-plugin` 选项来开启这个插件:

```Shell
mysql -h 127.0.0.1 -P 4000 -u 'user@pingcap.com' -p'<the-token-generated>' --enable-cleartext-plugin
```

如果在生成 token 的时候指定了错误的 `--sub`(比如 `--sub "wronguser@pingcap.com"`),则无法使用该 token 进行认证。

可以使用 [jwt.io](https://jwt.io/) 提供的 debugger 对 token 进行编解码。
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 @@ -414,7 +414,6 @@ mysql> SELECT * FROM t1;
- 类型:枚举型
- 默认值:`mysql_native_password`
- 可选值:`mysql_native_password`,`caching_sha2_password`,`tidb_sm3_password`,`tidb_auth_token`,`authentication_ldap_sasl` 或 `authentication_ldap_simple`。
- `tidb_auth_token` 认证方式仅用于 TiDB Cloud 内部实现,**不要设置为该值**。
- 服务器和客户端建立连接时,这个变量用于设置服务器对外通告的默认身份验证方式。如要了解该变量的其他可选值,参见[可用的身份验证插件](/security-compatibility-with-mysql.md#可用的身份验证插件)。
- 若要在用户登录时使用 `tidb_sm3_password` 插件,需要使用 [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 @@ -414,20 +414,12 @@ TiDB 配置文件比命令行参数支持更多的选项。你可以在 [config/

### `auth-token-jwks` <span class="version-mark">从 v6.4.0 版本开始引入</span>

> **警告:**
>
> `tidb_auth_token` 认证方式仅用于 TiDB Cloud 内部实现,**不要修改该配置**。

+ 设置 `tidb_auth_token` 认证方式的 JSON Web Key Sets (JWKS) 的本地文件路径。
+ 设置 [`tidb_auth_token`](/security-compatibility-with-mysql.md#tidb_auth_token) 认证方式的 JSON Web Key Sets (JWKS) 的本地文件路径。
+ 默认值:""

### `auth-token-refresh-interval` <span class="version-mark">从 v6.4.0 版本开始引入</span>

> **警告:**
>
> `tidb_auth_token` 认证方式仅用于 TiDB Cloud 内部实现,**不要修改该配置**。

+ 设置 `tidb_auth_token` 认证方式的 JWKS 刷新时间间隔。
+ 设置 [`tidb_auth_token`](/security-compatibility-with-mysql.md#tidb_auth_token) 认证方式的 JWKS 刷新时间间隔。
+ 默认值:1h

### `disconnect-on-expired-password` <span class="version-mark">从 v6.5.0 版本开始引入</span>
Expand Down
Loading