Files
SecScore/AUTH/API.MD
T
Yukino_fox 7a59572f11 feat(auth): 添加 SECTL Auth OAuth 登录功能
- 新增 OAuth 登录组件和回调页面
- 集成 Tauri 深度链接插件处理 OAuth 回调
- 添加账户设置页面显示登录信息
- 更新 CI 配置添加 OAuth 环境变量
- 扩展 API 接口支持 OAuth 相关操作
- 添加国际化支持
2026-03-29 19:30:27 +08:00

923 lines
22 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.
# SECTL Auth API 参考
本文档详细说明 SECTL Auth 提供的所有 API 接口。
## 基础信息
- **基础 URL**: `https://sectl.top`
- **认证方式**: OAuth 2.0 + Bearer Token
- **数据格式**: JSON
## 接口概览
| 接口 | 方法 | 说明 | 对应页面 |
| ----------------------- | ---- | ------------------- | ------------------------ |
| `/oauth/authorize` | GET | 获取授权码 | OAuthAuthorizeView.vue |
| `/api/oauth/token` | POST | 换取/刷新令牌 | AuthCallbackView.vue |
| `/api/oauth/userinfo` | GET | 获取用户信息 | PlatformUsersView.vue |
| `/api/oauth/config` | POST | 配置 Token 过期时间 | PlatformSettingsView.vue |
| `/api/oauth/revoke` | POST | 撤销令牌 | SecurityView.vue |
| `/api/oauth/introspect` | POST | 验证令牌 | - |
---
## OAuth 接口
### 1. 获取授权码
引导用户跳转到授权页面。
```http
GET /oauth/authorize
```
**请求参数:**
| 参数名 | 类型 | 必填 | 说明 |
| ------------- | ------ | ---- | ---------------- |
| client_id | string | ✅ | 平台 ID |
| redirect_uri | string | ✅ | 回调 URL |
| response_type | string | ✅ | 固定值 `code` |
| state | string | ❌ | 防 CSRF 状态参数 |
**示例请求:**
```
https://sectl.top/oauth/authorize?client_id=pf_AHmIhAiptyLFxk8x&redirect_uri=http://localhost:5000/callback&response_type=code
```
**成功响应:**
- 重定向到 `redirect_uri?code={authorization_code}&state={state}`
**错误响应:**
- 重定向到 `redirect_uri?error={error_code}&error_description={description}`
**错误码:**
| 错误码 | 说明 |
| ------------------------- | ------------------ |
| invalid_request | 请求参数缺失或无效 |
| unauthorized_client | 客户端未授权 |
| access_denied | 用户拒绝授权 |
| unsupported_response_type | 不支持的响应类型 |
| invalid_scope | 无效的权限范围 |
| server_error | 服务器内部错误 |
**相关页面:**
- [OAuthAuthorizeView.vue](../../src/views/OAuthAuthorizeView.vue) - 授权页面
- [LoginView.vue](../../src/views/LoginView.vue) - 登录页面
---
### 2. 获取访问令牌
使用授权码换取访问令牌。
```http
POST /api/oauth/token
```
**请求头:**
```
Content-Type: application/json
```
**请求体:**
| 参数名 | 类型 | 必填 | 说明 |
| ------------- | ------ | ---- | ------------------------------------------------ |
| grant_type | string | ✅ | `authorization_code``refresh_token` |
| code | string | 条件 | 授权码(grant_type=authorization_code 时必填) |
| refresh_token | string | 条件 | 刷新令牌(grant_type=refresh_token 时必填) |
| client_id | string | ✅ | 平台 ID |
| client_secret | string | ✅ | 平台密钥 |
| redirect_uri | string | 条件 | 回调地址(grant_type=authorization_code 时必填) |
**授权码模式示例:**
```json
{
"grant_type": "authorization_code",
"code": "NjliNDIyOTYwMDE4znLUNeWM6J8ye0MC",
"client_id": "pf_AHmIhAiptyLFxk8x",
"client_secret": "sk_UyMHuFf6oKXh8ZcHSb7lfOSgzumoOeg1",
"redirect_uri": "http://localhost:5000/callback"
}
```
**刷新令牌模式示例:**
```json
{
"grant_type": "refresh_token",
"refresh_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"client_id": "pf_AHmIhAiptyLFxk8x",
"client_secret": "sk_UyMHuFf6oKXh8ZcHSb7lfOSgzumoOeg1"
}
```
**成功响应:**
```json
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"token_type": "Bearer",
"expires_in": 3600
}
```
**响应字段:**
| 字段 | 类型 | 说明 |
| ------------- | ------ | ----------------------- |
| access_token | string | 访问令牌(JWT |
| refresh_token | string | 刷新令牌 |
| token_type | string | 令牌类型,固定为 Bearer |
| expires_in | number | 过期时间(秒) |
**错误响应:**
```json
{
"error": "invalid_grant",
"error_description": "Authorization code has expired"
}
```
**错误码:**
| 错误码 | HTTP 状态 | 说明 |
| ---------------------- | --------- | ------------------------ |
| invalid_request | 400 | 请求格式错误 |
| invalid_client | 401 | 客户端认证失败 |
| invalid_grant | 400 | 授权码无效或过期 |
| unauthorized_client | 400 | 客户端无权使用此授权类型 |
| unsupported_grant_type | 400 | 不支持的授权类型 |
| invalid_scope | 400 | 无效的权限范围 |
**相关页面:**
- [AuthCallbackView.vue](../../src/views/AuthCallbackView.vue) - 回调处理
---
### 3. 获取用户信息
使用访问令牌获取用户信息。
```http
GET /api/oauth/userinfo
```
**请求头:**
```
Authorization: Bearer {access_token}
```
**成功响应:**
```json
{
"user_id": "69bd422960018cf4d0e5",
"email": "user@example.com",
"name": "张三",
"github_username": "zhangsan",
"permission": 1
}
```
**响应字段:**
| 字段 | 类型 | 说明 |
| --------------- | ------ | --------------------- |
| user_id | string | 用户唯一标识 |
| email | string | 用户邮箱 |
| name | string | 用户名称 |
| github_username | string | GitHub 用户名(如有) |
| permission | number | 用户权限等级 |
**错误响应:**
```json
{
"error": "invalid_token",
"error_description": "The access token is invalid or has expired"
}
```
**相关页面:**
- [PlatformUsersView.vue](../../src/views/dashboard/manage/PlatformUsersView.vue) - 平台用户列表
---
### 4. 配置 Token 过期时间
配置平台的 access_token 过期时间(需要管理员权限)。
```http
POST /api/oauth/config
```
**请求头:**
```
Content-Type: application/json
```
**请求体:**
| 参数名 | 类型 | 必填 | 说明 |
| ------------ | ------ | ---- | ------------------------------------------- |
| platform_id | string | ✅ | 平台 ID |
| expires_in | number | ✅ | 过期时间(秒),-1 表示永不过期,最小 60 秒 |
| admin_secret | string | ✅ | 管理员密钥 |
**请求示例:**
```json
{
"platform_id": "pf_AHmIhAiptyLFxk8x",
"expires_in": 86400,
"admin_secret": "your-admin-secret"
}
```
**成功响应:**
```json
{
"success": true,
"message": "Token expiration time updated",
"expires_in": 86400
}
```
**错误响应:**
```json
{
"error": "unauthorized",
"error_description": "Invalid admin secret"
}
```
**相关页面:**
- [PlatformSettingsView.vue](../../src/views/dashboard/other/PlatformSettingsView.vue) - 平台设置
---
### 5. 撤销令牌
撤销指定的访问令牌或刷新令牌。
```http
POST /api/oauth/revoke
```
**请求头:**
```
Content-Type: application/json
```
**请求体:**
| 参数名 | 类型 | 必填 | 说明 |
| --------------- | ------ | ---- | --------------------------------- |
| token | string | ✅ | 要撤销的令牌 |
| token_type_hint | string | ❌ | `access_token``refresh_token` |
| client_id | string | ✅ | 平台 ID |
| client_secret | string | ✅ | 平台密钥 |
**请求示例:**
```json
{
"token": "eyJhbGciOiJIUzI1NiIs...",
"token_type_hint": "access_token",
"client_id": "pf_AHmIhAiptyLFxk8x",
"client_secret": "sk_UyMHuFf6oKXh8ZcHSb7lfOSgzumoOeg1"
}
```
**成功响应:**
```json
{
"success": true,
"message": "Token revoked successfully"
}
```
**相关页面:**
- [SecurityView.vue](../../src/views/dashboard/other/SecurityView.vue) - 安全设置
- [LoginPlatformsView.vue](../../src/views/dashboard/list/LoginPlatformsView.vue) - 登录平台列表
---
### 6. 验证令牌
验证访问令牌的有效性和获取令牌信息。
```http
POST /api/oauth/introspect
```
**请求头:**
```
Content-Type: application/json
```
**请求体:**
| 参数名 | 类型 | 必填 | 说明 |
| ------------- | ------ | ---- | ------------ |
| token | string | ✅ | 要验证的令牌 |
| client_id | string | ✅ | 平台 ID |
| client_secret | string | ✅ | 平台密钥 |
**请求示例:**
```json
{
"token": "eyJhbGciOiJIUzI1NiIs...",
"client_id": "pf_AHmIhAiptyLFxk8x",
"client_secret": "sk_UyMHuFf6oKXh8ZcHSb7lfOSgzumoOeg1"
}
```
**活跃令牌响应:**
```json
{
"active": true,
"user_id": "69bd422960018cf4d0e5",
"client_id": "pf_AHmIhAiptyLFxk8x",
"exp": 1704783600,
"iat": 1704780000
}
```
**非活跃令牌响应:**
```json
{
"active": false
}
```
**响应字段:**
| 字段 | 类型 | 说明 |
| --------- | ------- | ------------------------ |
| active | boolean | 令牌是否有效 |
| user_id | string | 用户 ID(仅活跃令牌) |
| client_id | string | 平台 ID(仅活跃令牌) |
| exp | number | 过期时间戳(仅活跃令牌) |
| iat | number | 签发时间戳(仅活跃令牌) |
---
## 平台管理 API
以下 API 用于管理平台信息,需要通过 Appwrite SDK 调用。
### 获取平台列表
```javascript
// 使用 Appwrite SDK
const result = await databases.listDocuments({
databaseId: "69bd89d8000304c37368",
collectionId: "platforms",
queries: [Query.orderDesc("$createdAt"), Query.limit(100)],
})
```
**相关页面:**
- [PlatformManagementView.vue](../../src/views/dashboard/manage/PlatformManagementView.vue)
### 获取平台详情
```javascript
const platform = await databases.getDocument({
databaseId: "69bd89d8000304c37368",
collectionId: "platforms",
documentId: "platform-document-id",
})
```
**相关页面:**
- [PlatformDetailView.vue](../../src/views/dashboard/detail/PlatformDetailView.vue)
### 更新平台信息
```javascript
await databases.updateDocument({
databaseId: "69bd89d8000304c37368",
collectionId: "platforms",
documentId: "platform-document-id",
data: {
callback_url: "http://new-callback.com",
token_expires_in: 7200,
},
})
```
**相关页面:**
- [PlatformSettingsView.vue](../../src/views/dashboard/other/PlatformSettingsView.vue)
### 申请创建平台
```javascript
await databases.createDocument({
databaseId: "69bd89d8000304c37368",
collectionId: "platform_applications",
documentId: ID.unique(),
data: {
name: "我的应用",
description: "应用描述",
callback_url: "http://localhost:5000/callback",
owner_id: currentUser.$id,
status: "pending",
created_at: new Date().toISOString(),
},
})
```
**相关页面:**
- [PlatformApplyView.vue](../../src/views/dashboard/form/PlatformApplyView.vue)
---
## 用户管理 API
### 获取用户授权的平台列表
```javascript
const result = await databases.listDocuments({
databaseId: "69bd89d8000304c37368",
collectionId: "oauth_tokens",
queries: [Query.equal("user_id", currentUser.$id), Query.equal("revoked", false)],
})
```
**相关页面:**
- [LoginPlatformsView.vue](../../src/views/dashboard/list/LoginPlatformsView.vue)
### 获取平台授权用户列表
```javascript
const result = await databases.listDocuments({
databaseId: "69bd89d8000304c37368",
collectionId: "oauth_tokens",
queries: [Query.equal("platform_id", "pf_xxx"), Query.equal("revoked", false)],
})
```
**相关页面:**
- [PlatformUsersView.vue](../../src/views/dashboard/manage/PlatformUsersView.vue)
---
## 云存储 API
云存储 API 提供文件上传、下载、管理等功能。需要通过 OAuth access_token 进行认证。
### 接口概览
| 接口 | 方法 | 说明 | SDK 方法 |
| ------------------------------- | ------ | ------------------------ | ------------------------------- |
| `/api/cloud/upload` | POST | 上传文件 | `uploadFile()` |
| `/api/cloud/files/{file_id}` | GET | 获取文件信息 | `getFile()` |
| `/api/cloud/download/{file_id}` | GET | 获取下载链接 | `downloadFile()` |
| `/api/cloud/view/{file_id}` | GET | 查看文件内容 | `viewFile()` |
| `/api/cloud/preview/{file_id}` | GET | 预览文件(支持图片处理) | `previewFile()` |
| `/api/cloud/info` | GET | 获取存储信息 | `getStorageInfo()` |
| `/api/cloud/files` | GET | 列出/搜索文件 | `listFiles()` / `searchFiles()` |
| `/api/cloud/files/{file_id}` | PUT | 更新文件(重命名) | `updateFile()` |
| `/api/cloud/files/{file_id}` | DELETE | 删除文件 | `deleteFile()` |
---
### 1. 上传文件
上传文件到云存储,系统会自动验证文件格式和检查存储容量。
```http
POST /api/cloud/upload
```
**请求头:**
```
Authorization: Bearer {access_token}
Content-Type: multipart/form-data
```
**请求参数:**
| 参数名 | 类型 | 必填 | 说明 |
| ----------- | ------ | ---- | ------------ |
| file | File | ✅ | 要上传的文件 |
| platform_id | string | ✅ | 平台 ID |
**请求示例(JavaScript):**
```javascript
const formData = new FormData()
formData.append("file", fileInput.files[0])
formData.append("platform_id", "pf_AHmIhAiptyLFxk8x")
const response = await fetch("https://sectl.top/api/cloud/upload", {
method: "POST",
headers: {
Authorization: "Bearer eyJhbGciOiJIUzI1NiIs...",
},
body: formData,
})
```
**成功响应:**
```json
{
"success": true,
"file_id": "cf_xxxxxxxx",
"filename": "example.jpg",
"size": 1024567,
"url": "https://cloud.appwrite.io/v1/storage/buckets/69c869010007b752a9b1/files/xxx/view",
"storage": {
"used": "50MB",
"limit": "100MB",
"available": "50MB",
"percentage": 50
}
}
```
**错误响应 - 格式不允许:**
```json
{
"error": "invalid_format",
"error_description": "File format 'exe' is not allowed",
"allowed_formats": ["jpg", "png", "pdf"]
}
```
**错误响应 - 超出容量:**
```json
{
"error": "storage_exceeded",
"error_description": "Upload would exceed storage limit",
"storage": {
"used": "95MB",
"limit": "100MB",
"available": "5MB",
"requested": "10MB"
}
}
```
**相关页面:**
- [CloudServiceView.vue](../../src/views/dashboard/CloudServiceView.vue) - 云服务总览
---
### 2. 下载文件
获取文件的下载链接。
```http
GET /api/cloud/download/{file_id}
```
**请求头:**
```
Authorization: Bearer {access_token}
```
**路径参数:**
| 参数名 | 类型 | 必填 | 说明 |
| ------- | ------ | ---- | ------- |
| file_id | string | ✅ | 文件 ID |
**成功响应:**
```json
{
"success": true,
"file_id": "cf_xxxxxxxx",
"filename": "example.jpg",
"download_url": "https://cloud.appwrite.io/v1/storage/buckets/69c869010007b752a9b1/files/xxx/download",
"expires_at": "2025-01-01T01:00:00Z"
}
```
---
### 3. 获取存储信息
获取用户在该平台的存储使用情况和配置信息。
```http
GET /api/cloud/info?platform_id={platform_id}
```
**请求头:**
```
Authorization: Bearer {access_token}
```
**查询参数:**
| 参数名 | 类型 | 必填 | 说明 |
| ----------- | ------ | ---- | ------- |
| platform_id | string | ✅ | 平台 ID |
**成功响应:**
```json
{
"success": true,
"platform_id": "pf_xxx",
"tier": "free",
"storage": {
"used": 52428800,
"used_formatted": "50MB",
"limit": 104857600,
"limit_formatted": "100MB",
"available": 52428800,
"available_formatted": "50MB",
"percentage": 50
},
"allowed_formats": ["jpg", "png", "pdf"],
"max_file_size": 10485760
}
```
---
### 4. 列出文件
获取用户在该平台的文件列表。
```http
GET /api/cloud/files?platform_id={platform_id}&limit=20&offset=0
```
**请求头:**
```
Authorization: Bearer {access_token}
```
**查询参数:**
| 参数名 | 类型 | 必填 | 说明 |
| ----------- | ------ | ---- | ----------------- |
| platform_id | string | ✅ | 平台 ID |
| limit | number | ❌ | 每页数量,默认 20 |
| offset | number | ❌ | 偏移量,默认 0 |
**成功响应:**
```json
{
"success": true,
"files": [
{
"file_id": "cf_xxx",
"filename": "example.jpg",
"size": 1024567,
"size_formatted": "1MB",
"created_at": "2025-01-01T00:00:00Z"
}
],
"total": 10,
"limit": 20,
"offset": 0
}
```
---
### 5. 删除文件
删除指定的文件。
```http
DELETE /api/cloud/files/{file_id}
```
**请求头:**
```
Authorization: Bearer {access_token}
```
**路径参数:**
| 参数名 | 类型 | 必填 | 说明 |
| ------- | ------ | ---- | ------- |
| file_id | string | ✅ | 文件 ID |
**成功响应:**
```json
{
"success": true,
"message": "File deleted successfully",
"storage": {
"used": "45MB",
"limit": "100MB",
"available": "55MB"
}
}
```
---
## 云存储 SDK
我们提供了 JavaScript SDK 简化云存储 API 的调用。
### 安装
```html
<script src="https://sectl.top/platform-sdk/cloud-storage.js"></script>
```
或使用 ES6 模块:
```javascript
import CloudStorage from "./cloud-storage.js"
```
### 初始化
```javascript
const cloud = new CloudStorage({
baseUrl: "https://sectl.top",
platformId: "your_platform_id",
accessToken: "your_access_token",
})
```
### 使用示例
```javascript
// 上传文件
try {
const result = await cloud.uploadFile(fileInput.files[0])
console.log("文件上传成功:", result.file_id)
console.log("存储使用情况:", result.storage.percentage + "%")
} catch (error) {
if (error.code === "invalid_format") {
console.error("不支持的文件格式:", error.data.allowed_formats)
} else if (error.code === "storage_exceeded") {
console.error("存储空间不足")
}
}
// 获取存储信息
const info = await cloud.getStorageInfo()
console.log("已用空间:", info.storage.used_formatted)
console.log("允许格式:", info.allowed_formats)
// 列出文件
const files = await cloud.listFiles({ limit: 10 })
files.files.forEach((file) => {
console.log(file.filename, file.size_formatted)
})
// 下载文件
const download = await cloud.downloadFile("cf_xxx")
window.location.href = download.download_url
// 删除文件
await cloud.deleteFile("cf_xxx")
```
**相关文件:**
- [cloud-storage.js](../../platform-sdk/cloud-storage.js) - SDK 源码
---
## 远程退登 API
### 创建退登事件
当用户退出登录时,系统会自动创建退登事件。
```javascript
await databases.createDocument({
databaseId: "69bd89d8000304c37368",
collectionId: "logout_events",
documentId: ID.unique(),
data: {
user_id: currentUser.$id,
platform_id: null, // null 表示全局退出
global: true,
created_at: new Date().toISOString(),
},
})
```
### 订阅退登事件
使用 Appwrite Realtime 订阅退登事件:
```javascript
import { Client } from "appwrite"
const client = new Client()
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("your-project-id")
const unsubscribe = client.subscribe(
"databases.69bd89d8000304c37368.collections.logout_events.documents",
(response) => {
const event = response.payload
if (event.user_id === currentUserId) {
// 执行本地退出
localLogout()
}
}
)
```
**相关页面:**
- [SecurityView.vue](../../src/views/dashboard/other/SecurityView.vue)
---
## 错误处理
### HTTP 状态码
| 状态码 | 说明 |
| ------ | ------------------ |
| 200 | 请求成功 |
| 400 | 请求参数错误 |
| 401 | 未授权,认证失败 |
| 403 | 禁止访问,权限不足 |
| 404 | 资源不存在 |
| 500 | 服务器内部错误 |
### 错误响应格式
```json
{
"error": "error_code",
"error_description": "详细的错误描述",
"error_uri": "https://docs.example.com/error/error_code"
}
```
---
## 安全建议
1. **使用 HTTPS** - 所有 API 通信必须使用 HTTPS
2. **保护密钥** - 不要在客户端代码中暴露 client_secret
3. **验证回调地址** - 确保 redirect_uri 与注册时一致
4. **使用状态参数** - 添加 state 参数防止 CSRF 攻击
5. **安全存储令牌** - Token 应安全存储,避免泄露
6. **及时撤销** - 用户退出时及时撤销令牌
---
## 相关页面
- [OAuthAuthorizeView.vue](../../src/views/OAuthAuthorizeView.vue) - OAuth 授权页面
- [AuthCallbackView.vue](../../src/views/AuthCallbackView.vue) - 认证回调
- [PlatformManagementView.vue](../../src/views/dashboard/manage/PlatformManagementView.vue) - 平台管理
- [PlatformDetailView.vue](../../src/views/dashboard/detail/PlatformDetailView.vue) - 平台详情
- [PlatformSettingsView.vue](../../src/views/dashboard/other/PlatformSettingsView.vue) - 平台设置
- [SecurityView.vue](../../src/views/dashboard/other/SecurityView.vue) - 安全设置
- [LoginPlatformsView.vue](../../src/views/dashboard/list/LoginPlatformsView.vue) - 登录平台列表