-
-
Notifications
You must be signed in to change notification settings - Fork 13.5k
♻️ refactor: refactor jose-JWT to xor obfuscation #8595
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
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
Reviewer's GuideThis refactor replaces JWT-based payload encoding/decoding with a custom XOR-based obfuscation mechanism by introducing new client/server XOR utilities, updating all service/middleware calls and tests accordingly, removing the old JWT utilities, and bumping relevant dependencies. Sequence diagram for payload obfuscation and de-obfuscation (XOR-based)sequenceDiagram
participant Client
participant Server
participant XORClient as obfuscatePayloadWithXOR
participant XORServer as getXorPayload
Client->>XORClient: obfuscatePayloadWithXOR(payload)
XORClient-->>Client: obfuscatedToken (Base64)
Client->>Server: Send obfuscatedToken in Authorization header
Server->>XORServer: getXorPayload(obfuscatedToken)
XORServer-->>Server: JWTPayload (decoded)
Class diagram for XOR obfuscation utilities (client/server)classDiagram
class obfuscatePayloadWithXOR {
+obfuscatePayloadWithXOR<T>(payload: T): string
}
class getXorPayload {
+getXorPayload(token: string): JWTPayload
}
class JWTPayload {
+accessCode: string
+apiKey: string
+azureApiVersion: string
+userId: string
...
}
obfuscatePayloadWithXOR --|> JWTPayload : obfuscates
getXorPayload --|> JWTPayload : decodes
Class diagram for removed JWT utilitiesclassDiagram
class createJWT {
+createJWT<T>(payload: T): string
}
class getJWTPayload {
+getJWTPayload(token: string): JWTPayload
}
class JWTPayload {
+accessCode: string
+apiKey: string
+azureApiVersion: string
+userId: string
...
}
createJWT --|> JWTPayload : encodes
getJWTPayload --|> JWTPayload : decodes
Class diagram for updated auth constantsclassDiagram
class auth {
+SECRET_XOR_KEY: string
-JWT_SECRET_KEY (removed)
-NON_HTTP_PREFIX (removed)
}
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
👍 @arvinxx Thank you for raising your pull request and contributing to our Community |
TestGru AssignmentSummary
Files
Tip You can |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @arvinxx - I've reviewed your changes and they look great!
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location> `src/utils/server/xor.ts:29` </location>
<code_context>
+ return new TextDecoder().decode(arr);
+};
+
+export const getXorPayload = (token: string): JWTPayload => {
+ const keyBytes = new TextEncoder().encode(SECRET_XOR_KEY);
+
</code_context>
<issue_to_address>
No validation or error handling for malformed or invalid tokens.
Add error handling for invalid base64 input or malformed JSON to prevent unhandled exceptions and ensure the function fails gracefully.
</issue_to_address>
### Comment 2
<location> `src/utils/client/xor-obfuscation.ts:38` </location>
<code_context>
+
+ // 将 Uint8Array 转换为 Base64 字符串
+ // 浏览器环境 btoa 只能处理 Latin-1 字符,所以需要先转换为适合 btoa 的字符串
+ return btoa(String.fromCharCode(...xoredBytes));
+};
</code_context>
<issue_to_address>
Potential performance issue with large payloads using spread operator.
For large Uint8Arrays, the spread operator may cause stack overflows or slowdowns. Use a loop or Buffer to convert the array before encoding.
Suggested implementation:
```typescript
// 将 Uint8Array 转换为 Base64 字符串
// 浏览器环境 btoa 只能处理 Latin-1 字符,所以需要先转换为适合 btoa 的字符串
return btoa(uint8ArrayToString(xoredBytes));
```
```typescript
/**
* 将 Uint8Array 转换为 Latin-1 字符串,适用于 btoa
* 避免使用扩展运算符以防止堆栈溢出
*/
function uint8ArrayToString(arr: Uint8Array): string {
let result = '';
const chunkSize = 0x8000; // 32k chunks
for (let i = 0; i < arr.length; i += chunkSize) {
result += String.fromCharCode.apply(
null,
arr.subarray(i, Math.min(i + chunkSize, arr.length)) as unknown as number[]
);
}
return result;
}
/**
* 对 Uint8Array 进行 XOR 运算
* @param data 要处理的 Uint8Array
* @param key 用于 XOR 的密钥 (Uint8Array)
* @returns 经过 XOR 运算的 Uint8Array
*/
const xorProcess = (data: Uint8Array, key: Uint8Array): Uint8Array => {
const result = new Uint8Array(data.length);
for (const [i, datum] of data.entries()) {
```
</issue_to_address>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
src/utils/server/xor.ts
Outdated
return new TextDecoder().decode(arr); | ||
}; | ||
|
||
export const getXorPayload = (token: string): JWTPayload => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (bug_risk): No validation or error handling for malformed or invalid tokens.
Add error handling for invalid base64 input or malformed JSON to prevent unhandled exceptions and ensure the function fails gracefully.
|
||
// 将 Uint8Array 转换为 Base64 字符串 | ||
// 浏览器环境 btoa 只能处理 Latin-1 字符,所以需要先转换为适合 btoa 的字符串 | ||
return btoa(String.fromCharCode(...xoredBytes)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (performance): Potential performance issue with large payloads using spread operator.
For large Uint8Arrays, the spread operator may cause stack overflows or slowdowns. Use a loop or Buffer to convert the array before encoding.
Suggested implementation:
// 将 Uint8Array 转换为 Base64 字符串
// 浏览器环境 btoa 只能处理 Latin-1 字符,所以需要先转换为适合 btoa 的字符串
return btoa(uint8ArrayToString(xoredBytes));
/**
* 将 Uint8Array 转换为 Latin-1 字符串,适用于 btoa
* 避免使用扩展运算符以防止堆栈溢出
*/
function uint8ArrayToString(arr: Uint8Array): string {
let result = '';
const chunkSize = 0x8000; // 32k chunks
for (let i = 0; i < arr.length; i += chunkSize) {
result += String.fromCharCode.apply(
null,
arr.subarray(i, Math.min(i + chunkSize, arr.length)) as unknown as number[]
);
}
return result;
}
/**
* 对 Uint8Array 进行 XOR 运算
* @param data 要处理的 Uint8Array
* @param key 用于 XOR 的密钥 (Uint8Array)
* @returns 经过 XOR 运算的 Uint8Array
*/
const xorProcess = (data: Uint8Array, key: Uint8Array): Uint8Array => {
const result = new Uint8Array(data.length);
for (const [i, datum] of data.entries()) {
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #8595 +/- ##
==========================================
+ Coverage 85.58% 85.63% +0.05%
==========================================
Files 910 910
Lines 69093 69346 +253
Branches 4530 6664 +2134
==========================================
+ Hits 59134 59387 +253
Misses 9959 9959
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
❤️ Great PR @arvinxx ❤️ The growth of project is inseparable from user feedback and contribution, thanks for your contribution! If you are interesting with the lobehub developer community, please join our discord and then dm @arvinxx or @canisminor1990. They will invite you to our private developer channel. We are talking about the lobe-chat development or sharing ai newsletter around the world. |
### [Version 1.105.2](v1.105.1...v1.105.2) <sup>Released on **2025-07-29**</sup> #### ♻ Code Refactoring - **misc**: Clean mcp sitemap, refactor jose-JWT to xor obfuscation. #### 💄 Styles - **misc**: Add more OpenAI SDK Text2Image providers, update i18n. <br/> <details> <summary><kbd>Improvements and Fixes</kbd></summary> #### Code refactoring * **misc**: Clean mcp sitemap, closes [#8596](#8596) ([b9e3e66](b9e3e66)) * **misc**: Refactor jose-JWT to xor obfuscation, closes [#8595](#8595) ([be98d56](be98d56)) #### Styles * **misc**: Add more OpenAI SDK Text2Image providers, closes [#8573](#8573) ([403aebd](403aebd)) * **misc**: Update i18n, closes [#8593](#8593) ([356cf0c](356cf0c)) </details> <div align="right"> [](#readme-top) </div>
🎉 This PR is included in version 1.105.2 🎉 The release is available on: Your semantic-release bot 📦🚀 |
### [Version 1.104.1](v1.104.0...v1.104.1) <sup>Released on **2025-07-29**</sup> #### ♻ Code Refactoring - **misc**: Clean mcp sitemap, refactor jose-JWT to xor obfuscation. #### 💄 Styles - **misc**: Add more OpenAI SDK Text2Image providers, support more Text2Image from Qwen, update i18n. <br/> <details> <summary><kbd>Improvements and Fixes</kbd></summary> #### Code refactoring * **misc**: Clean mcp sitemap, closes [lobehub#8596](https://github.com/jaworldwideorg/OneJA-Bot/issues/8596) ([b9e3e66](b9e3e66)) * **misc**: Refactor jose-JWT to xor obfuscation, closes [lobehub#8595](https://github.com/jaworldwideorg/OneJA-Bot/issues/8595) ([be98d56](be98d56)) #### Styles * **misc**: Add more OpenAI SDK Text2Image providers, closes [lobehub#8573](https://github.com/jaworldwideorg/OneJA-Bot/issues/8573) ([403aebd](403aebd)) * **misc**: Support more Text2Image from Qwen, closes [lobehub#8574](https://github.com/jaworldwideorg/OneJA-Bot/issues/8574) ([b8c0e2d](b8c0e2d)) * **misc**: Update i18n, closes [lobehub#8593](https://github.com/jaworldwideorg/OneJA-Bot/issues/8593) ([356cf0c](356cf0c)) </details> <div align="right"> [](#readme-top) </div>
* refactor jose-jwt to xor obfuscation * rename JWTPayload type to ClientSecretPayload * fix tests * revert next version
### [Version 1.105.2](lobehub/lobe-chat@v1.105.1...v1.105.2) <sup>Released on **2025-07-29**</sup> #### ♻ Code Refactoring - **misc**: Clean mcp sitemap, refactor jose-JWT to xor obfuscation. #### 💄 Styles - **misc**: Add more OpenAI SDK Text2Image providers, update i18n. <br/> <details> <summary><kbd>Improvements and Fixes</kbd></summary> #### Code refactoring * **misc**: Clean mcp sitemap, closes [lobehub#8596](lobehub#8596) ([9715349](lobehub@9715349)) * **misc**: Refactor jose-JWT to xor obfuscation, closes [lobehub#8595](lobehub#8595) ([06b7164](lobehub@06b7164)) #### Styles * **misc**: Add more OpenAI SDK Text2Image providers, closes [lobehub#8573](lobehub#8573) ([221488e](lobehub@221488e)) * **misc**: Update i18n, closes [lobehub#8593](lobehub#8593) ([89d4059](lobehub@89d4059)) </details> <div align="right"> [](#readme-top) </div>
* refactor jose-jwt to xor obfuscation * rename JWTPayload type to ClientSecretPayload * fix tests * revert next version
### [Version 1.105.2](lobehub/lobe-chat@v1.105.1...v1.105.2) <sup>Released on **2025-07-29**</sup> #### ♻ Code Refactoring - **misc**: Clean mcp sitemap, refactor jose-JWT to xor obfuscation. #### 💄 Styles - **misc**: Add more OpenAI SDK Text2Image providers, update i18n. <br/> <details> <summary><kbd>Improvements and Fixes</kbd></summary> #### Code refactoring * **misc**: Clean mcp sitemap, closes [lobehub#8596](lobehub#8596) ([b9e3e66](lobehub@b9e3e66)) * **misc**: Refactor jose-JWT to xor obfuscation, closes [lobehub#8595](lobehub#8595) ([be98d56](lobehub@be98d56)) #### Styles * **misc**: Add more OpenAI SDK Text2Image providers, closes [lobehub#8573](lobehub#8573) ([403aebd](lobehub@403aebd)) * **misc**: Update i18n, closes [lobehub#8593](lobehub#8593) ([356cf0c](lobehub@356cf0c)) </details> <div align="right"> [](#readme-top) </div>
💻 变更类型 | Change Type
🔀 变更说明 | Description of Change
重构客户端
LOBE_CHAT_AUTH_HEADER
生成逻辑的理由和实现细节。旧的实现方式使用jose
库进行 JWT 签名(JWS),现已被一个基于 XOR 和 Base64 编码的轻量级载荷混淆机制所取代。此变更解决了前端构建问题,并专为在纯 HTTP 环境下自部署的用户提供一层基础的数据混淆,同时避免了引入真正加密带来的复杂性。📝 补充信息 | Additional Information
旧实现存在两个主要问题:
客户端构建失败:
jose
库在进行签名操作时依赖 Node.js 核心模块(例如node:buffer
),这导致在现代前端框架如 Next.js 中,把该逻辑纳入客户端打包时构建失败,因为浏览器环境中不存在这些模块。JWS 的安全错觉: 使用
SignJWT
(JWS)仅对负载进行了签名,未加密。载荷中包含敏感的用户 API 密钥,实际上只是经过 Base64 编码,任何截获流量的人都能轻易读取,造成了虚假的安全感。业务上的主要限制是要支持在内部基于 IP 的网络环境中自部署应用且无 HTTPS 的用户。在此类环境下,无法保证端到端的真正安全,但需要一个简单的机制以防止敏感数据被随意观察。
新方案用两步的混淆机制替代了 JWT 签名流程:
XOR 混淆: 对含敏感数据的 JSON 载荷进行字节级的 XOR 操作,使用一个硬编码的共享密钥(
SECRET_XOR_KEY
)。该密钥在客户端代码和服务器端代码中均有配置。Base64 编码: 将 XOR 结果(字节数组)编码为 Base64 字符串,确保生成的内容为可打印的 ASCII 字符,方便通过 HTTP 头部安全传输。
服务器端 API 接口将反向执行该流程:先 Base64 解码头部内容,再用相同的 XOR 密钥解混淆,恢复原始 JSON 载荷。
该方案是低复杂度的务实措施,用以阻止随意窥视。
Summary by Sourcery
Refactor authentication flow to replace JWT-based payload encoding with XOR obfuscation and update related utilities, middleware, routes, and tests accordingly
Enhancements:
Build: