Skip to content

Commit

Permalink
Add description for tidb_auth_token authentication (#15818) (#16711)
Browse files Browse the repository at this point in the history
  • Loading branch information
ti-chi-bot authored Mar 1, 2024
1 parent 34773ce commit f75efa3
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 14 deletions.
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

0 comments on commit f75efa3

Please sign in to comment.