> For the complete documentation index, see [llms.txt](https://docs.roboflow.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.roboflow.com/reference/ko/authentication/authentication/sign-in-with-roboflow-developer-reference.md).

# Roboflow로 로그인(개발자 참고)

Roboflow로 로그인에 대한 OAuth 참고 자료, 표시 여부, 오류, 예제 앱.

Roboflow로 로그인하기 위한 통합자 참고 문서입니다. 앱 등록, PKCE, 승인 흐름에 대해서는 다음을 참조하세요 [Roboflow로 로그인(시작하기)](/reference/ko/authentication/authentication/sign-in-with-roboflow-getting-started.md).

## 예제 앱

[roboflow/siwr\_example\_app](https://github.com/roboflow/siwr_example_app) 은 다음을 대상으로 프로덕션 OAuth를 구현하는 최소한의 Node.js 앱입니다. `app.roboflow.com` 및 `api.roboflow.com`. 토큰은 Express 세션에 유지되며, 브라우저는 클라이언트 비밀을 절대 보지 않습니다.

```bash
git clone https://github.com/roboflow/siwr_example_app.git
cd siwr_example_app
cp .env.example .env
# RF_CLIENT_ID, RF_CLIENT_SECRET, SESSION_SECRET 설정
npm install && npm run dev
```

리디렉션 URI가 다음인 OAuth 앱을 등록하세요 `http://localhost:3001/oauth/callback` 및 허용된 범위가 앱과 일치하는 (`openid`, `profile`, `email`, `workspace:read`, `project:read`, `model:infer`).

| 경로                    | 용도                  |
| --------------------- | ------------------- |
| `GET /`               | 랜딩 페이지 또는 로그인된 대시보드 |
| `GET /oauth/start`    | OAuth 시작(PKCE 리디렉션) |
| `GET /oauth/callback` | 코드를 교환하고 대시보드 표시    |
| `POST /logout`        | 토큰을 폐기하고 세션을 지움     |

### PKCE 및 승인 URL

출처 [`src/oauth.ts`](https://github.com/roboflow/siwr_example_app/blob/main/src/oauth.ts):

```typescript
export function pkcePair(): { verifier: string; challenge: string } {
    const verifier = crypto.randomBytes(48).toString("base64url");
    const challenge = crypto.createHash("sha256").update(verifier).digest("base64url");
    return { verifier, challenge };
}

export function buildAuthorizeUrl(state: string, codeChallenge: string): string {
    const url = new URL(`${config.appHost}/oauth/authorize`);
    url.searchParams.set("response_type", "code");
    url.searchParams.set("client_id", config.clientId);
    url.searchParams.set("redirect_uri", config.redirectUri);
    url.searchParams.set("scope", REQUESTED_SCOPE_STRING);
    url.searchParams.set("state", state);
    url.searchParams.set("code_challenge", codeChallenge);
    url.searchParams.set("code_challenge_method", "S256");
    return url.toString();
}
```

`GET /oauth/start` 세션에 `verifier를` 및 `state` 저장한 다음 이 URL로 리디렉션합니다.

### 토큰 교환(서버 측)

```typescript
const body = new URLSearchParams({
    grant_type: "authorization_code",
    code,
    redirect_uri: config.redirectUri,
    client_id: config.clientId,
    client_secret: config.clientSecret,
    code_verifier: codeVerifier
});

const response = await fetch(`${config.appHost}/oauth/token`, {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body
});
```

### 콜백: 유효성 검사 `state`

출처 [`src/server.ts`](https://github.com/roboflow/siwr_example_app/blob/main/src/server.ts):

```typescript
const pending = req.session.oauth;
req.session.oauth = undefined;

if (!pending || !code || state !== pending.state) {
    // 거부: state가 올바르지 않거나 code가 없음
    return;
}

const data = await exchangeCodeForTokens(code, pending.verifier);
req.session.tokens = tokensFromTokenResponse(data);
```

코드를 교환하기 전에 한 번만 사용하는 OAuth 세션 데이터를 항상 지우세요.

## 토큰 엔드포인트 인증

토큰 엔드포인트는 기밀 클라이언트를 위한 두 가지 방법을 지원합니다(공개 클라이언트는 비밀을 생략하고 PKCE에 의존합니다):

| 방법                    | 작동 방식                                                                           |
| --------------------- | ------------------------------------------------------------------------------- |
| `client_secret_post`  | 전송 `client_secret` 을 요청 본문의 폼 매개변수로 전송(기본값)                                     |
| `client_secret_basic` | HTTP `Authorization: Basic` 헤더로 자격 증명 전송(base64 인코딩된 `client_id:client_secret`) |

클라이언트나 게이트웨이에 맞는 방법을 선택하세요. 다음에서 OAuth 앱을 만들거나 편집할 때 설정하세요. **워크스페이스 설정 > 개발자**.

다음을 사용한 예제 토큰 교환 `client_secret_basic`:

```bash
curl -X POST https://app.roboflow.com/oauth/token \
  -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \\
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "code=AUTHORIZATION_CODE" \
  -d "redirect_uri=https://yourapp.com/callback" \
  -d "code_verifier=YOUR_CODE_VERIFIER"
```

## 호스트

| 서비스           | 기본 URL                     |
| ------------- | -------------------------- |
| 로그인, 토큰, OIDC | `https://app.roboflow.com` |
| REST API      | `https://api.roboflow.com` |

## 가시성

어떤 워크스페이스가 OAuth 앱으로 로그인할 수 있는지 제어합니다.

| 대시보드 옵션    | 로그인 가능한 사용자                                   |
| ---------- | --------------------------------------------- |
| **내부**     | 앱을 만든 워크스페이스의 구성원만                            |
| **비공개 목록** | 클라이언트 ID가 있으면 어떤 워크스페이스든 가능                   |
| **공개**     | 비공개 + 활성화 시 Sign in with Roboflow 디렉터리에 목록 표시 |

별도의 "External" 표시 유형은 없습니다. 워크스페이스 간 통합은 **비공개 목록**.

각 고객 워크스페이스는 또한 **외부 OAuth 앱 정책을** (모두 허용, 클라이언트 ID 허용 목록, 또는 모두 차단). 워크스페이스 밖에서 로그인에 실패하면, 고객에게 워크스페이스 설정에서 클라이언트 ID를 허용하도록 요청하세요.

## 로그인 및 토큰(app.roboflow\.com)

| 용도         | 방법   | URL                                                         | 참고                                  |
| ---------- | ---- | ----------------------------------------------------------- | ----------------------------------- |
| 승인         | GET  | `https://app.roboflow.com/oauth/authorize`                  | PKCE + `state` 필수                   |
| 토큰 / 갱신    | POST | `https://app.roboflow.com/oauth/token`                      | `application/x-www-form-urlencoded` |
| 폐기         | POST | `https://app.roboflow.com/oauth/revoke`                     | 본문: `token=...`                     |
| 사용자 정보     | GET  | `https://app.roboflow.com/oauth/userinfo`                   | Bearer; 필요 `openid`                 |
| 검사         | POST | `https://app.roboflow.com/oauth/introspect`                 | 폼 `token=...`; client id + secret   |
| 검증         | GET  | `https://app.roboflow.com/oauth/validate`                   | Bearer 토큰; 클라이언트 자격 증명 불필요          |
| OIDC 디스커버리 | GET  | `https://app.roboflow.com/.well-known/openid-configuration` |                                     |
| JWKS       | GET  | `https://app.roboflow.com/.well-known/jwks.json`            | 검증 `id_token` JWT                   |

## REST API에서 토큰 사용하기

전송 `Authorization: Bearer {access_token}` on `api.roboflow.com`로 구성됩니다.  [REST API로 인증하기](/reference/ko/platform/rest-api/authenticate-with-the-rest-api.md).

## 흔한 오류

| HTTP                 | 의미                          | 조치                              |
| -------------------- | --------------------------- | ------------------------------- |
| 400 `invalid_scope`  | 범위가 앱의 허용 목록에 없음            | 대시보드에서 범위를 추가하거나 요청에서 제거하세요     |
| 401 `OAuthException` | 토큰이 만료되었거나 폐기됨              | 한 번 새로고침한 뒤 다시 로그인 요청           |
| 403(범위)              | 토큰에 범위가 없음                  | 더 넓은 범위로 다시 동의 받기               |
| 403(기타)              | 사용자 역할에 권한이 없음              | 워크스페이스 관리자가 역할을 조정              |
| 리디렉션 불일치             | `리디렉션 URI` 가 등록 내용과 일치하지 않음 | 대시보드 항목 또는 authorize URL을 수정하세요 |

## 보안

* 모든 승인 요청에서 PKCE를 사용하세요.
* 검증 `state` 모든 콜백에서.
* 절대 노출하지 마세요 `client_secret` 또는 갱신 토큰을 브라우저에.
* 로그아웃 시 토큰을 폐기하세요.
* 최소한의 범위만 요청하세요. 전체 목록은 다음에서 확인하세요. [시작하기](/reference/ko/authentication/authentication/sign-in-with-roboflow-getting-started.md#available-scopes).
