> ## Documentation Index
> Fetch the complete documentation index at: https://docs.acedata.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# 串接「使用 Ace Data Cloud 登入」（OAuth 2.0）

讓你自己的產品支援「使用 Ace Data Cloud 登入」，並在使用者授權後，**代表使用者**讀寫其 Ace Data Cloud 資源（個人資料、API Token、訂閱、用量、訂單等）。底層是標準的 **OAuth 2.0 授權碼模式（Authorization Code）+ PKCE**，與 GitHub / Google 登入的串接方式完全一致——你已有的任何 OAuth 用戶端函式庫都能直接使用。

> **適合情境**：你正在開發一個第三方應用程式 / Agent / MCP 用戶端 / 自動化工作流程，想讓使用者用 Ace Data Cloud 帳號一鍵登入，並依需求存取他在平台上的資源，而不必讓使用者手動複製貼上 API Key。

## 名詞 & 端點速查

所有端點都在 `https://auth.acedata.cloud`，可透過探索端點（Discovery）隨時取得最新位址：

```bash theme={null}
curl https://auth.acedata.cloud/.well-known/oauth-authorization-server
```

| 用途 | 端點 |
| - | - |
| 探索文件（Discovery） | `GET /.well-known/oauth-authorization-server` |
| 使用者授權頁（瀏覽器跳轉） | `GET https://auth.acedata.cloud/oauth2/authorize` |
| 權杖端點（交換 / 重新整理 token） | `POST https://auth.acedata.cloud/oauth2/token` |
| 撤銷權杖 | `POST https://auth.acedata.cloud/oauth2/revoke` |
| 使用者資訊（UserInfo） | `GET https://auth.acedata.cloud/api/v1/users/me` |
| 應用程式註冊管理（自助） | `https://auth.acedata.cloud/user/oauth-apps` |

支援的功能：`response_type=code`、`grant_types=authorization_code, refresh_token`、`code_challenge_methods=S256, plain`、用戶端驗證方式 `client_secret_post`（機密用戶端）/ `none`（PKCE 公開用戶端）。

## 權限範圍（Scope）

依「最小權限」申請，使用者會在授權頁看到你申請的每一項權限。

**身分類（OIDC 相容）**

| Scope | 含義 | `/users/me` 回傳欄位 |
| - | - | - |
| `openid` | 使用者唯一識別 | `id` |
| `profile` | 基本資料 | `username`、`nickname`、`avatar`、`is_verified`、`date_joined` |
| `email` | 電子郵件 | `email` |
| `phone` | 手機號碼（敏感） | `phone`、`region` |

**平台資源類**

| Scope | 含義 |
| - | - |
| `applications:read` / `applications:write` | 讀取 / 修改 使用者的服務訂閱與額度 |
| `credentials:read` / `credentials:write` | 讀取 / 建立撤銷 使用者的 API Token |
| `usage:read` | 讀取使用者的呼叫歷程 |
| `orders:read` / `orders:write` | 讀取訂單 / 下單並發起付款 |

**聚合類（自動展開）**

| Scope | 展開為 |
| - | - |
| `platform:read` | `applications:read` + `credentials:read` + `usage:read` + `orders:read` |
| `platform:write` | `applications:write` + `credentials:write` + `orders:write` |
| `platform` | `platform:read` + `platform:write` |

**特殊**

| Scope | 含義 |
| - | - |
| `offline_access` | 核發 **Refresh Token**（未申請則只發放 Access Token，過期需重新授權） |

> 典型組合：第三方「一鍵登入」=`openid profile`；MCP / IDE 用戶端需要自動設定 Key =`openid profile credentials:read credentials:write`；完整管理後台 =`openid profile email platform offline_access`。

## 第 1 步：註冊一個 OAuth 應用程式

開啟 [auth.acedata.cloud/user/oauth-apps](https://auth.acedata.cloud/user/oauth-apps) →「建立應用程式」，填寫：

1. **應用程式名稱 / 描述 / Logo**：會顯示在使用者的授權同意頁。
2. **用戶端類型（Client Type）**：
   * **機密（confidential）**——你有後端，能安全保管 `client_secret`（Web 服務、後端服務）。
   * **公開（public）**——純前端 / 桌面 / CLI / 行動裝置，**無法**保管密鑰，必須使用 **PKCE**。
3. **回呼位址（Redirect URIs）**：授權完成後使用者被重新導向回的位址，**必須與你發起授權時傳入的 `redirect_uri` 完全一致**，可填寫多個。
4. **權限範圍（Scopes）**：勾選上一節中你需要的 scope。

儲存後取得 **`client_id`**；機密用戶端還會**一次性**顯示 **`client_secret`**——立即儲存，關閉後無法再次查看（可在詳情頁「輪換密鑰 / Rotate Secret」重新產生，舊密鑰立即失效）。

> 每個帳號最多可建立 **20** 個 OAuth 應用程式。

## 第 2 步：將使用者重新導向至授權頁

在你的應用程式中，將使用者瀏覽器跳轉至授權頁，帶上查詢參數：

```
https://auth.acedata.cloud/oauth2/authorize
  ?response_type=code
  &client_id=<你的 client_id>
  &redirect_uri=<你注册的回调地址>
  &scope=openid%20profile%20credentials:read
  &state=<随机防 CSRF 串>
  &code_challenge=<PKCE 挑战值>          # 公开客户端必填
  &code_challenge_method=S256            # 公开客户端必填
```

* `state`：自行產生的隨機字串，回呼時原樣帶回，用來防範 CSRF，**務必驗證**。
* **PKCE（公開用戶端必做，機密用戶端也建議）**：先產生隨機 `code_verifier`，再計算
  `code_challenge = BASE64URL( SHA256( code_verifier ) )`，將 `code_challenge` 放入授權 URL，
  `code_verifier` 自己保留至第 4 步使用。

使用者登入並點擊「同意」後，瀏覽器會被重新導向回：

```
<redirect_uri>?code=<授权码>&state=<原样返回的 state>
```

若使用者拒絕：`<redirect_uri>?error=access_denied&error_description=...&state=...`。

> 授權碼有效期限為 **10 分鐘**，且**只能使用一次**。

## 第 3 步：使用授權碼交換權杖

在你的**後端**（機密用戶端）或用戶端（PKCE 公開用戶端）使用 `code` 呼叫權杖端點。

**機密用戶端（帶 client\_secret）：**

```bash theme={null}
curl -X POST https://auth.acedata.cloud/oauth2/token \
  -d grant_type=authorization_code \
  -d code=<上一步拿到的 code> \
  -d client_id=<你的 client_id> \
  -d client_secret=<你的 client_secret> \
  -d redirect_uri=<和第 2 步完全一致的回调地址>
```

**公開用戶端（PKCE，無 client\_secret）：**

```bash theme={null}
curl -X POST https://auth.acedata.cloud/oauth2/token \
  -d grant_type=authorization_code \
  -d code=<code> \
  -d client_id=<你的 client_id> \
  -d code_verifier=<第 2 步生成的 code_verifier> \
  -d redirect_uri=<回调地址>
```

成功回傳（`refresh_token` 僅在申請了 `offline_access` 時出現）：

```json theme={null}
{
  "access_token": "<JWT>",
  "token_type": "Bearer",
  "expires_in": 1296000,
  "scope": "openid profile credentials:read",
  "refresh_token": "<JWT，仅 offline_access 时>"
}
```

`access_token` 是一個 JWT，內含 `scope` 宣告；有效期 **15 天**（`expires_in` 秒數）。Refresh Token 有效期 **30 天**。

## 第 4 步：用 Access Token 呼叫介面

把權杖放進 `Authorization: Bearer` 標頭即可。

**讀取使用者資訊（UserInfo，欄位依已授權 scope 篩選）：**

```bash theme={null}
curl https://auth.acedata.cloud/api/v1/users/me \
  -H "Authorization: Bearer <access_token>"
```

**呼叫平台資源介面**（`platform.acedata.cloud`，依 scope 驗證）。例如已獲 `credentials:read`：

```bash theme={null}
curl "https://platform.acedata.cloud/api/v1/credentials/?user_id=<UserInfo返回的id>" \
  -H "Authorization: Bearer <access_token>"
```

平台後端會驗證 JWT 裡的 `scope` 宣告——權杖只能存取使用者授權過的資源。若存取了未授權的資源，會回傳 `403`。

## 重新整理權杖

Access Token 過期後，用 Refresh Token 換一對新權杖（需當初申請了 `offline_access`）：

```bash theme={null}
curl -X POST https://auth.acedata.cloud/oauth2/token \
  -d grant_type=refresh_token \
  -d refresh_token=<你的 refresh_token>
```

回傳結構同第 3 步；scope 會從原授權中**原樣保留**。重新整理後舊 Refresh Token 失效（輪換），請儲存新的。

## 撤銷權杖

```bash theme={null}
curl -X POST https://auth.acedata.cloud/oauth2/revoke \
  -d token=<access_token 或 refresh_token>
```

## 真實案例：我們自己的 MCP 伺服器就是這樣串接的

Ace Data Cloud 的 15+ 個 MCP 伺服器（NanoBanana、Midjourney、Suno、Seedance、Kling…）在 Claude Desktop / Cursor 裡出現的「Sign in with Ace Data Cloud」連線，走的就是這套流程：它們都是註冊為 **公開（PKCE）** 類型的 OAuth 應用程式，申請 `credentials` 相關 scope，使用者授權後 MCP 伺服器即可代表使用者呼叫 `api.acedata.cloud`——無需使用者手動貼上 API Key。你的串接方式和它們完全一樣。

## 常見錯誤

錯誤回應統一為 `{ "error": "<code>", "error_description": "&lt;人類可讀說明>" }`：

| error | 含義 / 排查 |
| - | - |
| `invalid_request` | 缺少或不合法參數（如沒傳 `code` / `client_id`） |
| `invalid_client` | `client_id` 不存在、應用程式被停用，或 `client_secret` 不對 |
| `invalid_grant` | 授權碼不存在 / 已過期（>10 分鐘）/ 已被用過 / PKCE 驗證失敗 / `redirect_uri` 與授權時不一致 |
| `access_denied` | 使用者在授權頁點了「拒絕」 |
| `unsupported_grant_type` | `grant_type` 不是 `authorization_code` 或 `refresh_token` |

## 限制速查

| 項目 | 值 |
| - | - |
| 每帳號最多 OAuth 應用程式數 | 20 |
| 授權碼有效期 | 10 分鐘，單次使用 |
| Access Token 有效期 | 15 天 |
| Refresh Token 有效期 | 30 天（輪換） |
| `redirect_uri` | 必須與註冊值精確相符 |
| `client_secret` | 僅建立 / 輪換時顯示一次，伺服器端以 SHA-256 雜湊儲存 |

## 在 Studio 首頁嵌入第三方 OAuth 應用程式

Studio 的「設定 → 首頁 → 網站元件」可啟用 OAuth，設定第三方應用程式的 `client_id` 和已登記的回呼地址。
網站與回呼必須使用 HTTPS、具有相同的來源（協定、網域名稱和連接埠），並與 Studio 使用不同的來源。
設定中不得填寫 `client_secret`；應用程式密鑰只能存放在第三方後端。

元件申請的權限為 `profile:read credentials:read`。每位訪客需要個別同意；站長設定元件不代表訪客授權。
第三方頁面產生隨機 `state` 和 PKCE verifier，向 Studio 傳送 S256 challenge。Studio 在元件區域承載官方授權頁，
使用者同意後，第三方收到一次性授權碼，呼叫 token 端點換取 OAuth access token，隨後存取
`GET https://platform.acedata.cloud/api/v1/credentials/?user_id=&lt;使用者ID>` 讀取現有 API Key。
使用者 ID 來自前一步 `GET https://auth.acedata.cloud/api/v1/users/me` 回傳的 `id`；憑證清單介面不接受 `user_id=me`。
Studio 不向第三方傳送自己的登入 token 或直接讀取並注入使用者的 Key。

公開用戶端必須使用 **S256 PKCE**。換取 token 時必須傳入與授權請求完全一致的 `redirect_uri`。
授權碼只能兌換一次。授權前會檢查回呼地址是否已登記。

第三方頁面需要實作訊息協定；任意現成網頁不能僅靠填寫 URL 自動接入。
完整範例見 [Studio OAuth 元件串接指南](https://github.com/AceDataCloud/Nexior/blob/main/docs/integrations/studio-home-oauth.md)。

**授權讀取 API Key 等於允許第三方儲存並使用該 Key。取消 OAuth 授權不會使第三方已複製的 Key 失效；
使用者需要另外撤銷或輪換 Key。**


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.