Skip to content
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
94 changes: 94 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ Easily add login, token refresh, and authorization to your Gin applications.
- [🗄️ Redis Store](#️-redis-store)
- [🛡️ Authorization](#️-authorization)
- [Configuration](#configuration)
- [JWT Parsing Options](#jwt-parsing-options)
- [Clock Skew Tolerance (Leeway)](#clock-skew-tolerance-leeway)
- [When to Use Leeway](#when-to-use-leeway)
- [Configuration Example](#configuration-example)
- [How Leeway Works](#how-leeway-works)
- [Other Parsing Options](#other-parsing-options)
- [JSON Number Handling](#json-number-handling)
- [Required Claims Validation](#required-claims-validation)
- [Combining Multiple Options](#combining-multiple-options)
- [Supporting Multiple JWT Providers](#supporting-multiple-jwt-providers)
- [Use Cases](#use-cases)
- [Solution: Dynamic Key Function](#solution-dynamic-key-function)
Expand Down Expand Up @@ -459,6 +468,91 @@ The `GinJWTMiddleware` struct provides the following configuration options:

---

## JWT Parsing Options

The `ParseOptions` field allows you to customize JWT parsing behavior using options from the [golang-jwt/jwt](https://github.com/golang-jwt/jwt) library. This is particularly useful for handling clock skew, custom validation rules, and numeric claim types.

### Clock Skew Tolerance (Leeway)

When running distributed systems across multiple servers, clock synchronization issues can cause valid tokens to be rejected. The `jwt.WithLeeway()` option adds a time buffer for validating time-based claims (`exp`, `nbf`, `iat`), preventing authentication failures due to minor clock differences between services.

#### When to Use Leeway

- 🌐 **Microservices Architecture**: Services on different machines with slightly unsynchronized clocks
- ☁️ **Cloud Deployments**: Distributed systems across different availability zones or regions
- 🔄 **Load Balanced Environments**: Multiple backend servers with small time drift
- 🧪 **Testing Environments**: Development/staging systems with less strict time synchronization

#### Configuration Example

```go
authMiddleware, err := jwt.New(&jwt.GinJWTMiddleware{
Realm: "your realm",
Key: []byte("your-secret-key"),
Timeout: time.Hour,
MaxRefresh: time.Hour * 24,

// Add 60 seconds leeway for clock skew tolerance
ParseOptions: []jwt.ParserOption{
jwt.WithLeeway(60 * time.Second),
},

Authenticator: func(c *gin.Context) (interface{}, error) {
// your authentication logic
},
// ... other configuration
})
```

#### How Leeway Works

With a 60-second leeway configuration:

- **Expired tokens**: A token that expired 30 seconds ago will still be accepted
- **Not-before tokens**: A token with `nbf` 30 seconds in the future will be accepted
- **Issued-at validation**: Tokens with `iat` slightly in the future will be accepted

**Security Note**: Use reasonable leeway values (30-120 seconds). Excessive leeway reduces token security by extending validity beyond intended expiration times.

### Other Parsing Options

#### JSON Number Handling

By default, JWT numeric claims are parsed as `float64`. Use `jwt.WithJSONNumber()` to preserve exact numeric values:

```go
ParseOptions: []jwt.ParserOption{
jwt.WithJSONNumber(),
}
```

This is useful when you need precise integer values or want to avoid floating-point precision issues.

#### Required Claims Validation

Enforce that certain claims must be present in the token:

```go
ParseOptions: []jwt.ParserOption{
jwt.WithExpirationRequired(), // Require 'exp' claim
jwt.WithIssuedAt(), // Validate 'iat' claim if present
}
```

#### Combining Multiple Options

You can combine multiple parser options:

```go
ParseOptions: []jwt.ParserOption{
jwt.WithLeeway(60 * time.Second), // 60s clock skew tolerance
jwt.WithJSONNumber(), // Preserve numeric precision
jwt.WithExpirationRequired(), // Require expiration claim
}
```

---

## Supporting Multiple JWT Providers

In some scenarios, you may need to accept JWT tokens from multiple sources, such as your own authentication system and external identity providers like Azure AD, Auth0, or other OAuth 2.0 providers. This section explains how to implement multi-provider token validation using the `KeyFunc` callback.
Expand Down
94 changes: 94 additions & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@
- [🗄️ Redis 存储](#️-redis-存储)
- [🛡️ 授权控制](#️-授权控制)
- [配置](#配置)
- [JWT 解析选项](#jwt-解析选项)
- [时钟偏差容错(Leeway)](#时钟偏差容错leeway)
- [何时使用 Leeway](#何时使用-leeway)
- [配置示例](#配置示例)
- [Leeway 工作原理](#leeway-工作原理)
- [其他解析选项](#其他解析选项)
- [JSON 数值处理](#json-数值处理)
- [必需声明验证](#必需声明验证)
- [组合多个选项](#组合多个选项)
- [支持多个 JWT 提供者](#支持多个-jwt-提供者)
- [使用场景](#使用场景)
- [解决方案:动态密钥函数](#解决方案动态密钥函数)
Expand Down Expand Up @@ -460,6 +469,91 @@ func helloHandler(c *gin.Context) {

---

## JWT 解析选项

`ParseOptions` 字段允许你使用 [golang-jwt/jwt](https://github.com/golang-jwt/jwt) 库提供的选项自定义 JWT 解析行为。这对于处理时钟偏差、自定义验证规则和数值类型声明特别有用。

### 时钟偏差容错(Leeway)

在多台服务器运行的分布式系统中,时钟同步问题可能导致有效的 Token 被拒绝。`jwt.WithLeeway()` 选项为验证基于时间的声明(`exp`、`nbf`、`iat`)添加时间缓冲,防止因服务之间的微小时钟差异而导致身份验证失败。

#### 何时使用 Leeway

- 🌐 **微服务架构**:不同机器上的服务时钟略有不同步
- ☁️ **云部署**:跨不同可用区或地区的分布式系统
- 🔄 **负载均衡环境**:多个后端服务器存在小的时间漂移
- 🧪 **测试环境**:开发/测试系统的时间同步要求不严格

#### 配置示例

```go
authMiddleware, err := jwt.New(&jwt.GinJWTMiddleware{
Realm: "your realm",
Key: []byte("your-secret-key"),
Timeout: time.Hour,
MaxRefresh: time.Hour * 24,

// 添加 60 秒的时钟偏差容错
ParseOptions: []jwt.ParserOption{
jwt.WithLeeway(60 * time.Second),
},

Authenticator: func(c *gin.Context) (interface{}, error) {
// 你的认证逻辑
},
// ... 其他配置
})
```

#### Leeway 工作原理

使用 60 秒的 leeway 配置:

- **过期的 Token**:30 秒前过期的 Token 仍会被接受
- **未生效的 Token**:`nbf`(不早于)时间在未来 30 秒内的 Token 会被接受
- **签发时间验证**:`iat`(签发时间)略在未来的 Token 会被接受

**安全提示**:使用合理的 leeway 值(30-120 秒)。过大的 leeway 会降低 Token 安全性,因为它会延长超出预期过期时间的有效期。

### 其他解析选项

#### JSON 数值处理

默认情况下,JWT 数值声明被解析为 `float64`。使用 `jwt.WithJSONNumber()` 保留精确的数值:

```go
ParseOptions: []jwt.ParserOption{
jwt.WithJSONNumber(),
}
```

这在需要精确整数值或想避免浮点精度问题时很有用。

#### 必需声明验证

强制要求 Token 中必须包含某些声明:

```go
ParseOptions: []jwt.ParserOption{
jwt.WithExpirationRequired(), // 要求 'exp' 声明
jwt.WithIssuedAt(), // 如果存在则验证 'iat' 声明
}
```

#### 组合多个选项

你可以组合多个解析器选项:

```go
ParseOptions: []jwt.ParserOption{
jwt.WithLeeway(60 * time.Second), // 60 秒时钟偏差容错
jwt.WithJSONNumber(), // 保留数值精度
jwt.WithExpirationRequired(), // 要求过期声明
}
```

---

## 支持多个 JWT 提供者

在某些场景中,你可能需要接受来自多个来源的 JWT Token,例如你自己的认证系统和外部身份提供者(如 Azure AD、Auth0 或其他 OAuth 2.0 提供者)。本节说明如何使用 `KeyFunc` 回调函数实现多提供者 Token 验证。
Expand Down
94 changes: 94 additions & 0 deletions README.zh-TW.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@
- [🗄️ Redis 儲存](#️-redis-儲存)
- [🛡️ 授權控制](#️-授權控制)
- [配置](#配置)
- [JWT 解析選項](#jwt-解析選項)
- [時鐘偏差容錯(Leeway)](#時鐘偏差容錯leeway)
- [何時使用 Leeway](#何時使用-leeway)
- [配置範例](#配置範例)
- [Leeway 工作原理](#leeway-工作原理)
- [其他解析選項](#其他解析選項)
- [JSON 數值處理](#json-數值處理)
- [必需聲明驗證](#必需聲明驗證)
- [組合多個選項](#組合多個選項)
- [支援多個 JWT 提供者](#支援多個-jwt-提供者)
- [使用場景](#使用場景)
- [解決方案:動態金鑰函數](#解決方案動態金鑰函數)
Expand Down Expand Up @@ -460,6 +469,91 @@ func helloHandler(c *gin.Context) {

---

## JWT 解析選項

`ParseOptions` 欄位允許你使用 [golang-jwt/jwt](https://github.com/golang-jwt/jwt) 函式庫提供的選項自訂 JWT 解析行為。這對於處理時鐘偏差、自訂驗證規則和數值類型聲明特別有用。

### 時鐘偏差容錯(Leeway)

在多台伺服器運行的分散式系統中,時鐘同步問題可能導致有效的 Token 被拒絕。`jwt.WithLeeway()` 選項為驗證基於時間的聲明(`exp`、`nbf`、`iat`)新增時間緩衝,防止因服務之間的微小時鐘差異而導致身份驗證失敗。

#### 何時使用 Leeway

- 🌐 **微服務架構**:不同機器上的服務時鐘略有不同步
- ☁️ **雲端部署**:跨不同可用區或地區的分散式系統
- 🔄 **負載平衡環境**:多個後端伺服器存在小的時間漂移
- 🧪 **測試環境**:開發/測試系統的時間同步要求不嚴格

#### 配置範例

```go
authMiddleware, err := jwt.New(&jwt.GinJWTMiddleware{
Realm: "your realm",
Key: []byte("your-secret-key"),
Timeout: time.Hour,
MaxRefresh: time.Hour * 24,

// 新增 60 秒的時鐘偏差容錯
ParseOptions: []jwt.ParserOption{
jwt.WithLeeway(60 * time.Second),
},

Authenticator: func(c *gin.Context) (interface{}, error) {
// 你的認證邏輯
},
// ... 其他配置
})
```

#### Leeway 工作原理

使用 60 秒的 leeway 配置:

- **過期的 Token**:30 秒前過期的 Token 仍會被接受
- **未生效的 Token**:`nbf`(不早於)時間在未來 30 秒內的 Token 會被接受
- **簽發時間驗證**:`iat`(簽發時間)略在未來的 Token 會被接受

**安全提示**:使用合理的 leeway 值(30-120 秒)。過大的 leeway 會降低 Token 安全性,因為它會延長超出預期過期時間的有效期。

### 其他解析選項

#### JSON 數值處理

預設情況下,JWT 數值聲明被解析為 `float64`。使用 `jwt.WithJSONNumber()` 保留精確的數值:

```go
ParseOptions: []jwt.ParserOption{
jwt.WithJSONNumber(),
}
```

這在需要精確整數值或想避免浮點精度問題時很有用。

#### 必需聲明驗證

強制要求 Token 中必須包含某些聲明:

```go
ParseOptions: []jwt.ParserOption{
jwt.WithExpirationRequired(), // 要求 'exp' 聲明
jwt.WithIssuedAt(), // 如果存在則驗證 'iat' 聲明
}
```

#### 組合多個選項

你可以組合多個解析器選項:

```go
ParseOptions: []jwt.ParserOption{
jwt.WithLeeway(60 * time.Second), // 60 秒時鐘偏差容錯
jwt.WithJSONNumber(), // 保留數值精度
jwt.WithExpirationRequired(), // 要求過期聲明
}
```

---

## 支援多個 JWT 提供者

在某些場景中,你可能需要接受來自多個來源的 JWT Token,例如你自己的驗證系統和外部身份提供者(如 Azure AD、Auth0 或其他 OAuth 2.0 提供者)。本節說明如何使用 `KeyFunc` 回呼函數實作多提供者 Token 驗證。
Expand Down
Loading
Loading