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

22 KiB
Raw Blame History

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. 获取授权码

引导用户跳转到授权页面。

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 服务器内部错误

相关页面:


2. 获取访问令牌

使用授权码换取访问令牌。

POST /api/oauth/token

请求头:

Content-Type: application/json

请求体:

参数名 类型 必填 说明
grant_type string authorization_coderefresh_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 时必填)

授权码模式示例:

{
  "grant_type": "authorization_code",
  "code": "NjliNDIyOTYwMDE4znLUNeWM6J8ye0MC",
  "client_id": "pf_AHmIhAiptyLFxk8x",
  "client_secret": "sk_UyMHuFf6oKXh8ZcHSb7lfOSgzumoOeg1",
  "redirect_uri": "http://localhost:5000/callback"
}

刷新令牌模式示例:

{
  "grant_type": "refresh_token",
  "refresh_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "client_id": "pf_AHmIhAiptyLFxk8x",
  "client_secret": "sk_UyMHuFf6oKXh8ZcHSb7lfOSgzumoOeg1"
}

成功响应:

{
  "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 过期时间(秒)

错误响应:

{
  "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 无效的权限范围

相关页面:


3. 获取用户信息

使用访问令牌获取用户信息。

GET /api/oauth/userinfo

请求头:

Authorization: Bearer {access_token}

成功响应:

{
  "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 用户权限等级

错误响应:

{
  "error": "invalid_token",
  "error_description": "The access token is invalid or has expired"
}

相关页面:


4. 配置 Token 过期时间

配置平台的 access_token 过期时间(需要管理员权限)。

POST /api/oauth/config

请求头:

Content-Type: application/json

请求体:

参数名 类型 必填 说明
platform_id string 平台 ID
expires_in number 过期时间(秒),-1 表示永不过期,最小 60 秒
admin_secret string 管理员密钥

请求示例:

{
  "platform_id": "pf_AHmIhAiptyLFxk8x",
  "expires_in": 86400,
  "admin_secret": "your-admin-secret"
}

成功响应:

{
  "success": true,
  "message": "Token expiration time updated",
  "expires_in": 86400
}

错误响应:

{
  "error": "unauthorized",
  "error_description": "Invalid admin secret"
}

相关页面:


5. 撤销令牌

撤销指定的访问令牌或刷新令牌。

POST /api/oauth/revoke

请求头:

Content-Type: application/json

请求体:

参数名 类型 必填 说明
token string 要撤销的令牌
token_type_hint string access_tokenrefresh_token
client_id string 平台 ID
client_secret string 平台密钥

请求示例:

{
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "token_type_hint": "access_token",
  "client_id": "pf_AHmIhAiptyLFxk8x",
  "client_secret": "sk_UyMHuFf6oKXh8ZcHSb7lfOSgzumoOeg1"
}

成功响应:

{
  "success": true,
  "message": "Token revoked successfully"
}

相关页面:


6. 验证令牌

验证访问令牌的有效性和获取令牌信息。

POST /api/oauth/introspect

请求头:

Content-Type: application/json

请求体:

参数名 类型 必填 说明
token string 要验证的令牌
client_id string 平台 ID
client_secret string 平台密钥

请求示例:

{
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "client_id": "pf_AHmIhAiptyLFxk8x",
  "client_secret": "sk_UyMHuFf6oKXh8ZcHSb7lfOSgzumoOeg1"
}

活跃令牌响应:

{
  "active": true,
  "user_id": "69bd422960018cf4d0e5",
  "client_id": "pf_AHmIhAiptyLFxk8x",
  "exp": 1704783600,
  "iat": 1704780000
}

非活跃令牌响应:

{
  "active": false
}

响应字段:

字段 类型 说明
active boolean 令牌是否有效
user_id string 用户 ID(仅活跃令牌)
client_id string 平台 ID(仅活跃令牌)
exp number 过期时间戳(仅活跃令牌)
iat number 签发时间戳(仅活跃令牌)

平台管理 API

以下 API 用于管理平台信息,需要通过 Appwrite SDK 调用。

获取平台列表

// 使用 Appwrite SDK
const result = await databases.listDocuments({
  databaseId: "69bd89d8000304c37368",
  collectionId: "platforms",
  queries: [Query.orderDesc("$createdAt"), Query.limit(100)],
})

相关页面:

获取平台详情

const platform = await databases.getDocument({
  databaseId: "69bd89d8000304c37368",
  collectionId: "platforms",
  documentId: "platform-document-id",
})

相关页面:

更新平台信息

await databases.updateDocument({
  databaseId: "69bd89d8000304c37368",
  collectionId: "platforms",
  documentId: "platform-document-id",
  data: {
    callback_url: "http://new-callback.com",
    token_expires_in: 7200,
  },
})

相关页面:

申请创建平台

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(),
  },
})

相关页面:


用户管理 API

获取用户授权的平台列表

const result = await databases.listDocuments({
  databaseId: "69bd89d8000304c37368",
  collectionId: "oauth_tokens",
  queries: [Query.equal("user_id", currentUser.$id), Query.equal("revoked", false)],
})

相关页面:

获取平台授权用户列表

const result = await databases.listDocuments({
  databaseId: "69bd89d8000304c37368",
  collectionId: "oauth_tokens",
  queries: [Query.equal("platform_id", "pf_xxx"), Query.equal("revoked", false)],
})

相关页面:


云存储 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. 上传文件

上传文件到云存储,系统会自动验证文件格式和检查存储容量。

POST /api/cloud/upload

请求头:

Authorization: Bearer {access_token}
Content-Type: multipart/form-data

请求参数:

参数名 类型 必填 说明
file File 要上传的文件
platform_id string 平台 ID

请求示例(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,
})

成功响应:

{
  "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
  }
}

错误响应 - 格式不允许:

{
  "error": "invalid_format",
  "error_description": "File format 'exe' is not allowed",
  "allowed_formats": ["jpg", "png", "pdf"]
}

错误响应 - 超出容量:

{
  "error": "storage_exceeded",
  "error_description": "Upload would exceed storage limit",
  "storage": {
    "used": "95MB",
    "limit": "100MB",
    "available": "5MB",
    "requested": "10MB"
  }
}

相关页面:


2. 下载文件

获取文件的下载链接。

GET /api/cloud/download/{file_id}

请求头:

Authorization: Bearer {access_token}

路径参数:

参数名 类型 必填 说明
file_id string 文件 ID

成功响应:

{
  "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. 获取存储信息

获取用户在该平台的存储使用情况和配置信息。

GET /api/cloud/info?platform_id={platform_id}

请求头:

Authorization: Bearer {access_token}

查询参数:

参数名 类型 必填 说明
platform_id string 平台 ID

成功响应:

{
  "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. 列出文件

获取用户在该平台的文件列表。

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

成功响应:

{
  "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. 删除文件

删除指定的文件。

DELETE /api/cloud/files/{file_id}

请求头:

Authorization: Bearer {access_token}

路径参数:

参数名 类型 必填 说明
file_id string 文件 ID

成功响应:

{
  "success": true,
  "message": "File deleted successfully",
  "storage": {
    "used": "45MB",
    "limit": "100MB",
    "available": "55MB"
  }
}

云存储 SDK

我们提供了 JavaScript SDK 简化云存储 API 的调用。

安装

<script src="https://sectl.top/platform-sdk/cloud-storage.js"></script>

或使用 ES6 模块:

import CloudStorage from "./cloud-storage.js"

初始化

const cloud = new CloudStorage({
  baseUrl: "https://sectl.top",
  platformId: "your_platform_id",
  accessToken: "your_access_token",
})

使用示例

// 上传文件
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")

相关文件:


远程退登 API

创建退登事件

当用户退出登录时,系统会自动创建退登事件。

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 订阅退登事件:

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()
    }
  }
)

相关页面:


错误处理

HTTP 状态码

状态码 说明
200 请求成功
400 请求参数错误
401 未授权,认证失败
403 禁止访问,权限不足
404 资源不存在
500 服务器内部错误

错误响应格式

{
  "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. 及时撤销 - 用户退出时及时撤销令牌

相关页面