
# keenauth test login으로 테스트 사용자 로그인하기

`keenauth test login`은 `development` 환경의 테스트 사용자를 로그인시키고 토큰을 출력하므로, 로그인 페이지를 클릭하지 않고도 API를 호출하거나 백엔드를 테스트할 수 있습니다. 브라우저와 같은 방식으로 실제 호스티드 로그인을 거치며, 고정된 개발용 코드 `424242`를 사용합니다([프로덕션이 아닌 환경의 테스트 사용자 및 메시지](/docs/guides/test-environments) 참조).

이 명령에는 API 키나 `keenauth login` 세션이 필요하지 않습니다. 로그인하는 대상은 본인이 아니라 테스트 사용자입니다.

## 시작하기 전에

- **테스트 사용자.** 이메일 주소의 로컬 부분에 `+test` 태그가 있어야 합니다(예: `ada+test@example.com` 또는 `ada+test_1@example.com`). 먼저 사용자를 생성하십시오(예: `keenauth users create --email ada+test@example.com`). 명령은 이 형식이 아닌 주소를 요청 전에 거부하고 종료 코드 2로 끝납니다.
- **공개 애플리케이션.** `--client-id`로 환경의 네이티브 또는 단일 페이지 애플리케이션 ID를 전달하십시오. 해당 애플리케이션은 이메일 코드 로그인(비밀번호 없는 `email_otp`)을 허용해야 합니다.
- **리디렉션 URI.** 기본적으로 명령은 `http://127.0.0.1:<임의 포트>/callback`을 사용합니다. 애플리케이션에 `http://127.0.0.1/callback`을 등록하십시오. 루프백 리디렉션 URI는 모든 포트를 허용합니다(RFC 8252). 해당 주소에서는 아무것도 수신하지 않으며, 리디렉션은 명령이 직접 읽습니다. 등록된 다른 리디렉션 URI를 사용하려면 `--redirect-uri`를 전달하십시오.
- **환경의 발급자.** `--issuer`로 전달하거나 `KEENAUTH_ISSUER`를 설정하십시오(예: `https://acme-dev.keenauth.app`).

## 사용법

```sh
export KEENAUTH_ISSUER=https://acme-dev.keenauth.app
keenauth test login --user ada+test@example.com --client-id app_01j9z3k4m5n6p7q8r9s0t1v2w3
```

| 플래그 | 설명 |
|---|---|
| `--user` | 테스트 사용자의 이메일 주소(필수). |
| `--client-id` | 환경의 공개 애플리케이션 ID(필수). |
| `--issuer` | 환경의 발급자 URL. 기본값: `KEENAUTH_ISSUER` 환경 변수. |
| `--scope` | 요청할 스코프(공백으로 구분). 기본값: `openid profile email`. 리프레시 토큰을 받으려면 `offline_access`를 추가하십시오. |
| `--resource` | 액세스 토큰의 대상 API 리소스 지시자(RFC 8707). |
| `--redirect-uri` | 애플리케이션에 등록된 리디렉션 URI. |
| `--output`, `-o` | `json`, `yaml` 또는 `table`. 플래그를 생략하면 터미널에서는 표, 그 외에는 JSON으로 출력합니다. |

출력에는 `token_type`, `access_token`, `id_token`(`openid`를 요청한 경우), `refresh_token`(`offline_access`를 요청한 경우에만), `expires_in`, `scope`가 포함됩니다. 토큰은 비밀번호처럼 취급하십시오. 만료될 때까지 테스트 사용자로 동작합니다. 명령은 토큰을 표준 출력에만 쓰며, 코드는 어디에도 출력하지 않습니다.

```sh
ACCESS_TOKEN=$(keenauth test login --user ada+test@example.com --client-id app_01j9z3k4m5n6p7q8r9s0t1v2w3 -o json | jq -r .access_token)
curl -H "Authorization: Bearer $ACCESS_TOKEN" http://localhost:3000/api/orders
```

## 명령이 하는 일

1. 환경의 디스커버리 문서를 읽고, PKCE(`S256`), `state`, `nonce`를 포함한 인증 요청을 엽니다.
2. 호스티드 로그인에서 주소를 입력하고, 이메일 코드를 요청한 뒤 `424242`를 제출합니다. 환경이 이어서 두 번째 인증 요소로 이메일 코드를 요구하면 그 코드를 요청받아 `424242`를 다시 제출합니다.
3. 리디렉션 URI로 돌아오는 리디렉션을 따라가 `state`와 `iss`를 확인하고, 토큰 엔드포인트에서 인증 코드를 교환합니다.
4. ID 토큰이 요청의 `nonce`와 함께 애플리케이션용 발급자가 발급한 것인지 확인한 뒤 토큰을 출력합니다.

로그인에 다른 단계가 필요하면 명령은 오류와 함께 중단됩니다. 예를 들어 비밀번호, 패스키, 인증 앱, 주소 도메인의 Single Sign-On, 동의 페이지, 조직 선택 등이 해당합니다.

## 환경

고정 코드는 `development` 환경에서만 허용됩니다. 명령은 개발 환경에서만 사용하십시오.

- `staging`에서는 테스트 주소로 아무것도 전송되지 않지만, 고정 코드는 거부됩니다(`401 invalid_credentials`).
- `production`에서는 `+test` 주소도 일반 주소입니다. 이메일 코드가 실제로 전송되며, 고정 코드는 거부됩니다.

서버가 단계를 거부하면 CLI는 문제 응답을 변경 없이 출력합니다(`error`, `code`, `status`, `detail`, `request_id`). 예를 들어 `code: test_feature_not_in_production`처럼 표시됩니다.

## 종료 코드

| 코드 | 의미 |
|---|---|
| `0` | 테스트 사용자가 로그인했으며 토큰이 출력되었습니다. |
| `1` | 로그인에 실패했습니다. OAuth 오류, `state`, `iss` 또는 `nonce` 불일치, 또는 명령이 완료할 수 없는 단계가 있습니다. |
| `2` | 사용 오류입니다. 주소에 `+test` 태그가 없거나, 필수 플래그나 발급자가 없거나, 값이 잘못되었습니다. 요청은 전송되지 않았습니다. |
| `3` | 서버가 `401` 또는 `403`으로 응답했습니다(예: `invalid_credentials`, `test_feature_not_in_production`). |
