# 인증 및 OAuth

> API 키, PKCE를 사용한 OAuth 2.1 (SMART on FHIR 독립 실행형 시작), OpenID Connect id_token, SMART v2 환자 범위, 토큰 수명 주기 및 동의 수명 주기.

Source: https://developers.anpheros.com/ko/guides/authentication

Anpheros Platform은 세 가지 종류의 자격 증명을 허용합니다. 모든 요청은 정확히 하나를 포함합니다.

| 자격 증명 | 형식 | 주체 | 접근 가능 범위 |
|---|---|---|---|
| API 키 | `sk_test_…` (샌드박스) / `sk_live_…` (프로덕션) | 프로젝트의 서버 | 프로젝트가 생성한 환자 (샌드박스에서는 자체 복사본인 30명의 합성 환자 포함) |
| OAuth 액세스 토큰 | `at_…` | 동의 하에 한 환자를 대신하여 작동하는 애플리케이션 | 부여된 SMART 범위 내에서 해당 환자만 |
| Firebase ID 토큰 | JWT | 대시보드의 개발자 또는 "연결"의 환자 | 자신의 조직 / 자신의 레코드 |

`Authorization: Bearer <credential>`로 전송하십시오 (API 키는 `X-Api-Key`로도 작동합니다).

## API 키
- 대시보드 또는 `POST /admin/projects/{id}/keys`을 통해 생성되며, 한 번만 표시되고 SHA-256 해시로 저장됩니다.
- 범위: `read`, `write`. 키는 프로젝트 환경을 넘어서지 않습니다 (`sk_test_`은 프로덕션 데이터에 접근할 수 없으며, 그 반대도 마찬가지입니다).
- 키별 속도 제한 (기본값 600/분)은 플랫폼 전체 (공유 스토어)에서 적용되며, 429 오류 시 `Retry-After`이 발생합니다. IP별 제한은 600/분입니다.
- 쓰기 작업 시 선택적 헤더: `X-Anpheros-Author-Type`, `X-Anpheros-Author-Ref`, `X-Anpheros-Source-System`, `X-Anpheros-Origin-Id`, `X-Anpheros-Acting-As` (사용자 디렉토리의 Practitioner/PractitionerRole), `X-Anpheros-On-Behalf-Of` (사용자 디렉토리의 Organization). 이 헤더들은 Provenance를 채웁니다.

# OAuth 2.1 (SMART on FHIR, standalone launch)
Discovery: `GET /.well-known/smart-configuration`.

1. `GET /oauth/authorize?response_type=code&client_id=…&redirect_uri=…&scope=…&state=…&code_challenge=…&code_challenge_method=S256[&purpose=treatment][&patient=<pairwise id>][&lang=ro]`
   호스팅된 동의 페이지를 표시합니다. PKCE S256은 필수이며, `redirect_uri`은 정확하게 등록되어야 합니다.
2. 환자는 로그인하고(Google 또는 Firebase를 통한 이메일), 기록(자신 또는 부양가족의 것)을 선택하고, 기간(30/90/180/365일)을 선택하고, 허용합니다. 플랫폼은 일회용 코드(10분)를 발급합니다.
3. `grant_type=authorization_code&code=…&code_verifier=…&redirect_uri=…&client_id=…`과 함께 `POST /oauth/token` (기밀 클라이언트는 `client_secret`을 추가합니다).
   응답: `access_token` (30분), `refresh_token` (30일, 순환), `patient` (기록에 대한 사용자별 ID), `grant_id`, `scope`.
4. 새로고침: `grant_type=refresh_token`. 각 새로고침 토큰은 한 번만 사용됩니다. **사용된 새로고침 토큰을 제시하면 전체 체인이 취소됩니다** (도난 감지). 새로고침 요청의 병렬 중복은 거부되며 체인을 취소할 수도 있으므로 동시 새로고침은 절대 하지 마십시오.
5. 취소: `POST /oauth/revoke` (토큰 + client_id). 새로고침 토큰을 취소하면 해당 액세스 토큰도 취소됩니다.

토큰 응답에는 SMART에서 요구하는 `Cache-Control: no-store` 및 `Pragma: no-cache`가 포함됩니다.

### OpenID Connect (`openid fhirUser`)
환자 범위와 함께 `openid fhirUser`을 요청하면 토큰 응답에 `id_token`도 포함됩니다. 이는 RS256으로 서명된 JWT이며, `iss` (플랫폼의 기본 URL), `sub` (사람에 대한 사용자별 ID), `aud` (사용자의 `client_id`), `exp`, `iat` 및 `fhirUser` — 방금 받은 액세스 토큰으로 읽을 수 있는 사람의 Patient 리소스의 절대 URL을 포함합니다. Discovery는 `GET /.well-known/openid-configuration`에 있으며, 공개 키는 `GET /oauth/jwks`에 있습니다 (토큰 헤더의 `kid`). `nonce` 매개변수는 아직 지원되지 않습니다 (권한 부여 코드 흐름에서 선택 사항). `launch/patient` 및 `offline_access`은 허용되며, 토큰 응답의 `patient` 필드는 시작 컨텍스트입니다.

기타 grant 유형: `client_credentials` (기밀 클라이언트; API 키처럼 작동) 및 first-party identity grant (신뢰할 수 있는 클라이언트만 해당).

### 동의 페이지에 브랜드 표시

애플리케이션은 호스팅된 동의 페이지에 로고와 강조 색상을 표시할 수 있습니다. 콘솔
(애플리케이션 → 브랜드) 또는 관리자 API에서 설정하십시오.

```http
PUT /admin/applications/{application_id}/branding
{"logo": "data:image/png;base64,…", "brand_color": "#1D4ED8"}
```

- **로고:** 데이터 URI 형식의 PNG, JPEG 또는 WebP 이미지, 최대 64KB. 콘텐츠가 확인되며, 선언된 유형은 아닙니다.
  SVG는 허용되지 않습니다. 이미지는 애플리케이션과 함께 저장되어 페이지에 포함되므로 동의 페이지에서
  사용자 서버로 요청을 보내지 않습니다.
- **강조 색상:** `#RRGGBB`, 기본 버튼에 사용됩니다. 흰색 텍스트는 최소 4.5:1 (WCAG AA)의 대비를 유지해야 합니다.
  더 밝은 색상은 거부됩니다.
- 필드를 비워두면 그대로 유지됩니다. `null` 또는 빈 문자열은 필드를 제거합니다.

페이지의 나머지 부분은 변경되지 않습니다. "Secured by Anpheros Platform" 줄, 애플리케이션이 요청하는 항목의 일반 텍스트 목록, 샌드박스 프로젝트의 TEST 배너는 그대로 유지되므로 사람들이 항상 동의가 Anpheros에서 관리된다는 것을 알 수 있습니다. AI 커넥터(MCP)는 항상 애플리케이션 브랜드 없이 Anpheros 페이지를 표시합니다.

### 범위
SMART v2 환자 범위: `patient/<Type>.<cruds>`에 선택적 `?category=<code>` 필터가 있습니다 (서버가 적용하는 유일한 필터이며, 다른 필터는 권한 부여 시점에 거부됩니다). `patient/*.rs`은 모든 것을 읽고, `offline_access`은 새로고침 토큰을 추가합니다. 환자 인구 통계 및 디렉토리는 항상 권한 하에 읽을 수 있습니다. 권한 외의 리소스 유형은 403을 반환하고, 권한 외의 환자는 404를 반환합니다.

### 동의 수명 주기
동의는 자동으로 만료되며, 환자가 언제든지 취소할 수 있습니다(연결 화면 / `/me`). 동의 하에 이루어진 모든 읽기는 애플리케이션 ID와 함께 기록됩니다. Webhook `consent.granted` / `consent.revoked`이 프로젝트에 알립니다.

## 오류

401 알 수 없거나 만료된 자격 증명 · 403 자격 증명이 존재하지만 이 작업을 수행할 수 없습니다 · 404 리소스가 *사용자에게* 존재하지 않습니다 · 429 요청 제한 초과 (`Retry-After`). [`errors.md`](https://developers.anpheros.com/ko/guides/errors) 참조.
