diff --git a/.gitignore b/.gitignore index f2cff9f..3d49977 100644 --- a/.gitignore +++ b/.gitignore @@ -104,4 +104,6 @@ dist/ .env.development .env.test Giffgaff-swap-esim.json -giffgaff.html \ No newline at end of file +giffgaff.html +Simyo-swap-esim.json +simyo.html diff --git a/GIFFGAFF_CSP_CALLBACK_FIX.md b/GIFFGAFF_CSP_CALLBACK_FIX.md new file mode 100644 index 0000000..445b8f1 --- /dev/null +++ b/GIFFGAFF_CSP_CALLBACK_FIX.md @@ -0,0 +1,183 @@ +# Giffgaff CSP和OAuth回调问题修复 + +## 🔍 问题描述 + +用户在使用Giffgaff eSIM工具时遇到两个关键问题: + +### 1. CSP (Content Security Policy) 违规 +``` +Refused to connect to 'https://id.giffgaff.com/auth/oauth/token' because it violates the following Content Security Policy directive: "connect-src 'self' https://api.qrserver.com https://appapi.simyo.nl https://api.giffgaff.com". +``` + +### 2. OAuth回调URL处理问题 +- 系统返回了 `giffgaff://auth/callback/?code=...&state=...` 格式的回调URL +- 原有代码只支持标准HTTP/HTTPS URL格式解析 + +## 🛠️ 修复方案 + +### 1. 修复CSP配置 + +**问题原因**: CSP的 `connect-src` 指令中缺少 `https://id.giffgaff.com` 域名 + +**修复方案**: 添加完整的CSP配置,包含所有必要的Giffgaff域名 + +```html + +``` + +### 2. 修复OAuth回调URL解析 + +**问题原因**: 原有代码只能处理标准HTTP/HTTPS URL,无法解析 `giffgaff://` 协议 + +**修复前代码**: +```javascript +const url = new URL(callbackUrl); +const code = url.searchParams.get('code'); +``` + +**修复后代码**: +```javascript +let code, state; + +if (callbackUrl.startsWith('giffgaff://')) { + // 处理giffgaff://协议的回调URL + const match = callbackUrl.match(/[?&]code=([^&]+)/); + const stateMatch = callbackUrl.match(/[?&]state=([^&]+)/); + code = match ? decodeURIComponent(match[1]) : null; + state = stateMatch ? decodeURIComponent(stateMatch[1]) : null; +} else { + // 处理标准HTTP/HTTPS URL + const url = new URL(callbackUrl); + code = url.searchParams.get('code'); + state = url.searchParams.get('state'); +} +``` + +### 3. 改进用户界面 + +**增加了回调URL格式说明**: +```html +
+
回调URL格式说明:
+

支持的格式:

+ +

请复制包含 code 参数的完整URL

+
+``` + +## 📋 修复的文件 + +### `giffgaff_complete_esim.html` + +1. **CSP配置** (第6行) + - 添加了完整的Content Security Policy + - 包含所有必要的Giffgaff域名 + +2. **OAuth回调解析** (第817-837行) + - 支持 `giffgaff://` 协议URL解析 + - 支持标准HTTP/HTTPS URL解析 + - 添加了调试日志输出 + +3. **用户界面** (第470-478行) + - 添加了回调URL格式说明 + - 更新了占位符文本 + - 提供了具体的示例 + +## 🔄 OAuth认证流程 + +``` +1. 用户点击"开始OAuth登录" + ↓ +2. 打开Giffgaff登录页面 + ↓ +3. 用户输入邮箱验证码完成登录 + ↓ +4. 系统重定向到: giffgaff://auth/callback/?code=...&state=... + ↓ +5. 用户复制完整回调URL到工具中 + ↓ +6. 工具解析回调URL提取code和state + ↓ +7. 使用code交换access_token + ↓ +8. 继续后续的MFA和GraphQL流程 +``` + +## 🧪 测试步骤 + +### 1. CSP测试 +1. 打开浏览器开发者工具的控制台 +2. 点击"开始OAuth登录" +3. 确认没有CSP违规错误 + +### 2. 回调URL测试 +1. 完成OAuth登录流程 +2. 复制回调URL: `giffgaff://auth/callback/?code=EDXgE_Uq5Q96LT5s&state=7piz0IXfUIHHoxMURfaboQ` +3. 粘贴到回调URL输入框 +4. 点击"处理回调" +5. 检查控制台确认解析成功 + +### 预期结果 +- ✅ 无CSP违规错误 +- ✅ 成功解析giffgaff://协议URL +- ✅ 控制台显示解析到的code和state +- ✅ 成功交换access_token + +## 🔧 调试技巧 + +### 浏览器控制台检查 +```javascript +// 检查CSP是否允许连接 +console.log('Testing CSP for id.giffgaff.com...'); + +// 检查回调URL解析 +console.log('解析到的授权码:', code); +console.log('解析到的状态:', state); +``` + +### 常见问题排查 + +1. **CSP错误持续出现** + - 确认浏览器已刷新页面 + - 检查meta标签是否正确添加 + +2. **回调URL解析失败** + - 确认URL包含code参数 + - 检查URL格式是否正确 + - 查看控制台的调试输出 + +3. **OAuth token交换失败** + - 确认code未过期(通常有效期很短) + - 检查state参数是否匹配 + - 查看网络请求的详细错误 + +## ✅ 修复确认 + +经过修复后,Giffgaff eSIM工具应该能够: +- ✅ 无CSP违规错误地访问所有Giffgaff API +- ✅ 正确解析 `giffgaff://` 协议的回调URL +- ✅ 成功完成OAuth token交换 +- ✅ 继续执行后续的MFA和GraphQL流程 + +--- + +**注意**: +1. 如果仍有问题,请检查浏览器控制台的详细错误信息 +2. OAuth授权码有时间限制,需要及时处理回调 +3. 确保复制的回调URL完整且未被截断 \ No newline at end of file diff --git a/giffgaff_complete_esim.html b/giffgaff_complete_esim.html index 9746afd..7735ced 100644 --- a/giffgaff_complete_esim.html +++ b/giffgaff_complete_esim.html @@ -3,6 +3,7 @@ + Giffgaff eSIM 申请工具 @@ -466,9 +467,19 @@ 请从浏览器地址栏复制完整的回调URL并粘贴到下方:

+
+
回调URL格式说明:
+

支持的格式:

+ +

请复制包含 code 参数的完整URL

+
+
- +
@@ -813,13 +824,28 @@ showStatus(elements.callbackStatus, "正在处理OAuth回调...", "success"); // 解析回调URL中的code - const url = new URL(callbackUrl); - const code = url.searchParams.get('code'); + let code, state; + + if (callbackUrl.startsWith('giffgaff://')) { + // 处理giffgaff://协议的回调URL + const match = callbackUrl.match(/[?&]code=([^&]+)/); + const stateMatch = callbackUrl.match(/[?&]state=([^&]+)/); + code = match ? decodeURIComponent(match[1]) : null; + state = stateMatch ? decodeURIComponent(stateMatch[1]) : null; + } else { + // 处理标准HTTP/HTTPS URL + const url = new URL(callbackUrl); + code = url.searchParams.get('code'); + state = url.searchParams.get('state'); + } if (!code) { throw new Error("回调URL中未找到授权码"); } + console.log('解析到的授权码:', code); + console.log('解析到的状态:', state); + // 交换访问令牌 const tokenResponse = await fetch(oauthConfig.tokenUrl, { method: 'POST',