@emdash-cms/auth-atproto 패키지는 EmDash에 Atmosphere 계정 로그인 옵션을 추가합니다. Atmosphere 계정은 Bluesky 및 AT Protocol 네트워크의 다른 앱에서 사용되는 이동 가능한 사용자 소유 ID입니다. 사용자는 핸들(예: alice.bsky.social)로 로그인하고 자신의 제공자에서 인증합니다 — EmDash는 비밀번호를 절대 보지 않습니다.
다음과 같은 경우에 적합합니다:
- 기여자들이 이미 Atmosphere 계정을 가지고 있는 경우.
- OAuth 앱이나 초대를 관리하지 않고 조직이 제어하는 도메인(
*.yourcompany.com)에 대한 액세스를 제어하려는 경우. - 더 넓은 Atmosphere의 일부인 무언가를 구축하고 있으며 스택의 나머지 부분과 일관된 ID를 원하는 경우.
설치
제공자 패키지를 설치합니다:
pnpm add @emdash-cms/auth-atproto
EmDash 통합에 제공자를 추가합니다:
import { defineConfig } from "astro/config";
import emdash from "emdash/astro";
import { atproto } from "@emdash-cms/auth-atproto";
export default defineConfig({
integrations: [
emdash({
authProviders: [atproto()],
server: {
host: "127.0.0.1", // required for local dev — see "Local development" below
},
}),
],
});
이것만으로 로그인 페이지와 설정 마법사에 Atmosphere로 로그인이 표시됩니다. 허용 목록이 구성되지 않은 경우, 첫 번째 사용자가 관리자가 되고 그 이후 모든 사람에 대한 자가 가입이 닫힙니다 — 열려면 허용 목록을 참조하세요.
제공자는 공개 OAuth 클라이언트이며 /.well-known/atproto-client-metadata.json에서 자체 메타데이터 문서를 제공하므로, 위의 구성만으로 작동합니다 — 환경 변수, 클라이언트 시크릿 또는 OAuth 앱 등록이 필요하지 않습니다.
구성
atproto() 제공자는 허용 목록과 기본 역할을 허용합니다:
atproto({
allowedDIDs: ["did:plc:abc123..."],
allowedHandles: ["*.example.com", "alice.bsky.social"],
defaultRole: 30, // Author
});
| 옵션 | 타입 | 기본값 | 설명 |
|---|---|---|---|
allowedDIDs | string[] | 없음 (첫 번째에서 모두 허용) | DID 허용 목록. DID는 영구적이며 위조할 수 없습니다. |
allowedHandles | string[] | 없음 (첫 번째에서 모두 허용) | 핸들 허용 목록. 와일드카드(*.example.com)를 지원합니다. |
defaultRole | number | 10 (Subscriber) | 첫 번째 이후 허용된 사용자에게 할당되는 역할. 첫 번째 사용자는 항상 관리자입니다. |
전체 역할 사다리는 메인 인증 가이드에 문서화되어 있습니다.
허용 목록
allowedDIDs와 allowedHandles 모두 설정되지 않은 경우, 첫 번째 사용자만 가입할 수 있습니다 — 로그인을 시도하는 다른 사람은 signup_not_allowed로 거부됩니다. 기존 사용자는 허용 목록에 관계없이 항상 다시 로그인할 수 있습니다(따라서 목록에서 자신을 제거해도 잠기지 않지만 새로운 사람도 들어오지 못합니다).
최소한 하나의 허용 목록이 구성되면, 둘 중 하나의 목록이 일치하면 사용자가 허용됩니다:
- DID 일치. 사용자의 DID가
allowedDIDs에 있는 경우. DID는 이동하거나 사칭할 수 없는 암호화 식별자이므로 이것이 가장 엄격한 형태의 게이팅입니다. - 핸들 일치. 사용자의 핸들이
allowedHandles의 항목과 정확히 일치하거나 선행 와일드카드 패턴(*.example.com은alice.example.com및bob.team.example.com과 일치)을 통해 일치하는 경우.
핸들은 변경 가능하지만 핸들 허용 목록은 안전합니다. 핸들 일치를 통해 사용자를 허용하기 전에 EmDash는 독립적으로 핸들의 DNS/HTTP 레코드를 해석하고 제공자가 주장하는 것과 동일한 DID를 가리키는지 확인합니다. 악의적인 제공자는 단순히 you@yourcompany.com을 소유하고 있다고 주장할 수 없습니다.
기본 역할
허용된 사용자는 defaultRole에서 설정한 역할에 도착합니다. 첫 번째 사용자 — 설정을 완료한 사용자 — 만 관리자로 강제됩니다. Atmosphere 계정에 대한 그룹/역할 매핑은 없습니다. 더 세밀한 역할이 필요한 경우, 한 번 로그인한 후 설정 → 사용자에서 사용자의 역할을 변경하세요.
첫 번째 사용자 설정
Atmosphere 제공자가 구성된 새 사이트를 시작하면 설정 마법사가 초기 관리자 계정을 생성하는 옵션으로 제공합니다.
-
/_emdash/admin을 방문하세요. 설정 마법사가 사이트 제목, 태그라인 및 관리자 이메일을 안내합니다. -
“관리자 계정 생성” 단계에서 Atmosphere를 선택하고 핸들(예:
alice.bsky.social)을 입력하세요. -
계정의 인증 페이지로 리디렉션되며, 여기서 제공자가 지원하는 방식으로 로그인합니다 — 비밀번호, 패스키 또는 기타 방법.
-
승인 후 EmDash로 돌아오며, 관리자 사용자가 역할 50(관리자)으로 생성되고 1단계에서 입력한 이메일이 계정에 저장됩니다.
모든 후속 로그인에도 동일한 흐름이 실행됩니다: 핸들을 입력하고, 제공자에서 인증하고, 로그인된 상태로 EmDash로 돌아옵니다.
로컬 개발
AT Protocol OAuth 프로필은 루프백 리디렉션 URI가 localhost가 아닌 IP 리터럴(127.0.0.1 또는 [::1])을 사용하도록 요구합니다. EmDash는 리디렉션 URI를 생성할 때 ://localhost를 ://127.0.0.1로 투명하게 재작성하지만, 이는 개발 세션도 127.0.0.1에서 시작해야 함을 의미합니다 — 그렇지 않으면 localhost에 설정된 세션 쿠키가 리디렉션이 127.0.0.1에 도착한 후 표시되지 않습니다.
Astro의 개발 서버는 Vite의 개발 서버이며, Vite는 기본적으로 localhost에 바인딩됩니다. 루프백 IP에서도 수신하도록 지시하세요:
export default defineConfig({
server: {
host: "127.0.0.1",
},
// ...
});
그런 다음 전체 흐름을 위해 http://127.0.0.1:4321/_emdash/admin을 여세요.
프로덕션
동일한 구성이 프로덕션에서 작동합니다. 제공자는 다음 위치에서 자체 클라이언트 메타데이터를 제공합니다:
https://your-site.example.com/.well-known/atproto-client-metadata.json
인증 서버는 로그인 중에 이 URL을 가져와 클라이언트의 리디렉션 URI를 확인합니다. 배포의 사이트 URL이 HTTPS를 통해 공개 인터넷에서 접근 가능한지 확인하세요 — VPN 뒤의 내부 전용 배포는 사용자의 인증 서버가 메타데이터 문서를 가져올 수 없기 때문에 로그인을 완료할 수 없습니다.
TLS 종료 리버스 프록시 뒤에서 EmDash를 실행하는 경우, EmDash가 올바른 리디렉션 URI를 구축하도록 siteUrl을 설정하세요. 이것이 없으면 요청이 http://internal-host:4321처럼 보이고 메타데이터가 인증 서버가 보는 것과 일치하지 않습니다.
문제 해결
”Account is not in the allowlist”
로그인한 핸들 또는 DID가 allowedDIDs / allowedHandles에 없습니다. 와일드카드 패턴을 확인하세요(*.로 시작해야 함). 핸들 일치는 DNS/HTTP에 대해 검증된다는 것을 기억하세요 — 핸들의 DID 레코드가 현재 제공자가 반환한 것과 동일한 DID로 해석되지 않으면 일치가 거부됩니다.
”Self-signup is not allowed”
콜백에 성공적으로 도달했지만 허용 목록이 구성되지 않았고 첫 번째 사용자가 아닙니다. allowedDIDs/allowedHandles에 자신을 추가하거나, 기존 관리자가 초대하여 로그인할 때 사용자가 이미 존재하도록 하세요.
로그인이 오류 없이 로그인 페이지로 리디렉션됨
이것은 거의 항상 로컬 개발에 설명된 루프백 쿠키 문제입니다. (server.host: "127.0.0.1"을 설정한 후) http://127.0.0.1:4321에서 관리자를 열고 다시 시도하세요.
자체 호스팅 핸들에 대한 핸들 해석 실패
제공자는 DNS-over-HTTPS(Cloudflare의 DoH 엔드포인트)와 HTTP /.well-known/atproto-did 조회를 경쟁시켜 핸들을 확인합니다. 자체 호스팅 핸들에는 다음 중 하나 이상이 필요합니다:
did=<your-did>를 포함하는_atproto.<handle>DNS TXT 레코드, 또는- DID를 포함하는
https://<handle>/.well-known/atproto-did파일.
두 방법이 모두 실패하면 기본 계정이 유효하더라도 핸들 일치가 거부됩니다. allowedDIDs의 DID는 영향을 받지 않습니다 — 직접 일치됩니다.