Files
higress/plugins/wasm-cpp/extensions/oauth/README.md
2023-11-13 11:03:46 +08:00

130 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 功能说明
`OAuth2`插件实现了基于JWT(JSON Web Tokens)进行OAuth2 Access Token签发的能力, 遵循[RFC9068](https://datatracker.ietf.org/doc/html/rfc9068)规范
# 插件配置说明
## 配置字段
| 名称 | 数据类型 | 填写要求 | 默认值 | 描述 |
| ----------- | --------------- | ------------------------------------------- | ------ | ----------------------------------------------------------- |
| `consumers` | array of object | 必填 | - | 配置服务的调用者,用于对请求进行认证 |
| `_rules_` | array of object | 选填 | - | 配置特定路由或域名的访问权限列表,用于对请求进行鉴权 |
| `issuer` | string | 选填 | Higress-Gateway | 用于填充JWT中的issuer |
| `auth_path` | string | 选填 | /oauth2/token | 指定路径后缀用于签发Token路由级配置时要确保首先能匹配对应的路由 |
| `global_credentials` | bool | 选填 | ture | 是否开启全局凭证即允许路由A下的auth_path签发的Token可以用于访问路由B |
| `auth_header_name` | string | 选填 | Authorization | 用于指定从哪个请求头获取JWT |
| `token_ttl` | number | 选填 | 7200 | token从签发后多久内有效单位为秒 |
| `clock_skew_seconds` | number | 选填 | 60 | 校验JWT的exp和iat字段时允许的时钟偏移量单位为秒 |
| `keep_token` | bool | 选填 | ture | 转发给后端时是否保留JWT |
`consumers`中每一项的配置字段说明如下:
| 名称 | 数据类型 | 填写要求 | 默认值 | 描述 |
| ----------------------- | ----------------- | -------- | ------------------------------------------------- | ------------------------ |
| `name` | string | 必填 | - | 配置该consumer的名称 |
| `client_id` | string | 必填 | - | OAuth2 client id |
| `client_secret` | string | 必填 | - | OAuth2 client secret |
`_rules_` 中每一项的配置字段说明如下:
| 名称 | 数据类型 | 填写要求 | 默认值 | 描述 |
| ---------------- | --------------- | ------------------------------------------------- | ------ | -------------------------------------------------- |
| `_match_route_` | array of string | 选填,`_match_route_``_match_domain_`中选填一项 | - | 配置要匹配的路由名称 |
| `_match_domain_` | array of string | 选填,`_match_route_``_match_domain_`中选填一项 | - | 配置要匹配的域名 |
| `allow` | array of string | 必填 | - | 对于符合匹配条件的请求配置允许访问的consumer名称 |
**注意:**
- 对于开启该配置的路由,如果路径后缀和`auth_path`匹配则该路由到原目标服务而是用于生成Token
- 如果关闭`global_credentials`,请确保启用此插件的路由不是精确匹配路由,此时若存在另一条前缀匹配路由,则可能导致预期外行为
- 若不配置`_rules_`字段,则默认对当前网关实例的所有路由开启认证;
- 对于通过认证鉴权的请求请求的header会被添加一个`X-Mse-Consumer`字段,用以标识调用者的名称。
## 配置示例
### 对特定路由或域名开启
以下配置将对网关特定路由或域名开启 Jwt Auth 认证和鉴权注意如果一个JWT能匹配多个`jwks`,则按照配置顺序命中第一个匹配的`consumer`
```yaml
consumers:
- name: consumer1
client_id: 12345678-xxxx-xxxx-xxxx-xxxxxxxxxxxx
client_secret: abcdefgh-xxxx-xxxx-xxxx-xxxxxxxxxxxx
- name: consumer2
client_id: 87654321-xxxx-xxxx-xxxx-xxxxxxxxxxxx
client_secret: hgfedcba-xxxx-xxxx-xxxx-xxxxxxxxxxxx
# 使用 _rules_ 字段进行细粒度规则配置
_rules_:
# 规则一:按路由名称匹配生效
- _match_route_:
- route-a
- route-b
allow:
- consumer1
# 规则二:按域名匹配生效
- _match_domain_:
- "*.example.com"
- test.com
allow:
- consumer2
```
此例 `_match_route_` 中指定的 `route-a``route-b` 即在创建网关路由时填写的路由名称,当匹配到这两个路由时,将允许`name``consumer1`的调用者访问,其他调用者不允许访问;
此例 `_match_domain_` 中指定的 `*.example.com``test.com` 用于匹配请求的域名,当发现域名匹配时,将允许`name``consumer2`的调用者访问,其他调用者不允许访问。
#### 使用 Client Credential 授权模式
**获取 AccessToken**
```bash
# 通过 GET 方法获取
curl 'http://test.com/oauth2/token?grant_type=client_credentials&client_id=12345678-xxxx-xxxx-xxxx-xxxxxxxxxxxx&client_secret=abcdefgh-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
# 通过 POST 方法获取 (需要先匹配到有真实目标服务的路由)
curl 'http://test.com/oauth2/token' -H 'content-type: application/x-www-form-urlencoded' -d 'grant_type=client_credentials&client_id=12345678-xxxx-xxxx-xxxx-xxxxxxxxxxxx&client_secret=abcdefgh-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
# 获取响应中的 access_token 字段即可:
{
"token_type": "bearer",
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6ImFwcGxpY2F0aW9uXC9hdCtqd3QifQ.eyJhdWQiOiJkZWZhdWx0IiwiY2xpZW50X2lkIjoiMTIzNDU2NzgteHh4eC14eHh4LXh4eHgteHh4eHh4eHh4eHh4IiwiZXhwIjoxNjg3OTUxNDYzLCJpYXQiOjE2ODc5NDQyNjMsImlzcyI6IkhpZ3Jlc3MtR2F0ZXdheSIsImp0aSI6IjEwOTU5ZDFiLThkNjEtNGRlYy1iZWE3LTk0ODEwMzc1YjYzYyIsInN1YiI6ImNvbnN1bWVyMSJ9.NkT_rG3DcV9543vBQgneVqoGfIhVeOuUBwLJJ4Wycb0",
"expires_in": 7200
}
```
**使用 AccessToken 请求**
```bash
curl 'http://test.com' -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6ImFwcGxpY2F0aW9uXC9hdCtqd3QifQ.eyJhdWQiOiJkZWZhdWx0IiwiY2xpZW50X2lkIjoiMTIzNDU2NzgteHh4eC14eHh4LXh4eHgteHh4eHh4eHh4eHh4IiwiZXhwIjoxNjg3OTUxNDYzLCJpYXQiOjE2ODc5NDQyNjMsImlzcyI6IkhpZ3Jlc3MtR2F0ZXdheSIsImp0aSI6IjEwOTU5ZDFiLThkNjEtNGRlYy1iZWE3LTk0ODEwMzc1YjYzYyIsInN1YiI6ImNvbnN1bWVyMSJ9.NkT_rG3DcV9543vBQgneVqoGfIhVeOuUBwLJJ4Wycb0'
```
因为 test.com 仅授权了 consumer2但这个 Access Token 是基于 consumer1 的 `client_id``client_secret` 获取的,因此将返回 `403 Access Denied`
### 网关实例级别开启
以下配置未指定`_rules_`字段,因此将对网关实例级别开启 OAuth2 认证
```yaml
consumers:
- name: consumer1
client_id: 12345678-xxxx-xxxx-xxxx-xxxxxxxxxxxx
client_secret: abcdefgh-xxxx-xxxx-xxxx-xxxxxxxxxxxx
- name: consumer2
client_id: 87654321-xxxx-xxxx-xxxx-xxxxxxxxxxxx
client_secret: hgfedcba-xxxx-xxxx-xxxx-xxxxxxxxxxxx
```
# 常见错误码说明
| HTTP 状态码 | 出错信息 | 原因说明 |
| ----------- | ---------------------- | -------------------------------------------------------------------------------- |
| 401 | Invalid Jwt token | 请求头未提供JWT, 或者JWT格式错误或过期等原因 |
| 403 | Access Denied | 无权限访问当前路由 |