> ## 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 모드(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.