인증
EmDash는 기본 로그인 방식으로 패스키 인증을 사용합니다. 패스키는 피싱 방지 기능이 있으며, 비밀번호가 필요하지 않으며, 브라우저나 비밀번호 관리자를 통해 여러 기기에서 작동합니다.
Cloudflare 배포의 경우, 선택적으로 Cloudflare Access를 대체 인증 공급자로 사용할 수 있습니다.
작동 방식
섹션 제목: “작동 방식”패스키는 웹 표준인 WebAuthn을 사용하여, 기기에 저장되거나 비밀번호 관리자를 통해 동기화되는 공개 키 자격 증명을 생성합니다. 로그인 시, 기기는 네트워크를 통해 비밀번호를 전송하지 않고도 자격 증명 소유를 증명합니다.
패스키 인증의 장점:
- 기억하거나 유출될 비밀번호 없음
- 피싱 방지 — 자격 증명이 사이트 도메인에 바인딩됨
- 크로스 디바이스 동기화 — iCloud 키체인, Google 비밀번호 관리자, 1Password 등과 호환
- 빠른 로그인 — 생체 인식 또는 PIN으로 한 번의 탭
첫 사용자 설정
섹션 제목: “첫 사용자 설정”관리자 패널에 처음 접근할 때, 설정 마법사가 관리자 계정 생성 과정을 안내합니다.
-
설정 마법사로 리디렉션됩니다. 다음을 입력하세요:
- 사이트 제목 — 사이트 이름
- 태그라인 — 간단한 설명
- 관리자 이메일 — 이메일 주소
-
사이트 생성을 클릭하여 패스키를 등록합니다.
-
브라우저가 패스키 생성 프롬프트를 표시합니다:
- macOS: Touch ID, 기기 비밀번호 또는 보안 키
- Windows: Windows Hello 또는 보안 키
- 모바일: Face ID, 지문 또는 PIN
-
패스키가 등록되면, 로그인되어 관리자 대시보드로 리디렉션됩니다.
로그인
섹션 제목: “로그인”설정 후, 관리자 패널로 돌아가면 패스키 인증이 트리거됩니다:
-
/_emdash/admin방문 -
로그인되지 않은 경우, 로그인 페이지가 표시됨
-
로그인을 클릭하여 인증
-
브라우저가 패스키(생체 인식, PIN 또는 보안 키)를 요청함
-
확인 후, 관리자 대시보드로 리디렉션됨
매직 링크 대체 방법
섹션 제목: “매직 링크 대체 방법”패스키를 사용할 수 없는 경우(예: 기기 분실), 매직 링크가 대안을 제공합니다. 이 기능은 이메일 구성이 필요합니다.
-
로그인 페이지에서 이메일로 로그인 클릭
-
이메일 주소 입력
-
수신함에서 로그인 링크 확인
-
링크 클릭하여 인증(15분 동안 유효)
OAuth 로그인
섹션 제목: “OAuth 로그인”EmDash는 구성 시 GitHub 및 Google과의 OAuth 로그인을 지원합니다. 사용자는 초기 패스키 설정 후 계정을 연결할 수 있습니다.
설정 지침은 구성 가이드를 참조하세요.
사용자 역할
섹션 제목: “사용자 역할”EmDash는 다섯 가지 수준의 역할 기반 접근 제어를 사용합니다:
| 역할 | 수준 | 설명 |
|---|---|---|
| 구독자 | 10 | 읽기 전용 접근 |
| 기여자 | 20 | 콘텐츠 생성(승인 필요) |
| 작성자 | 30 | 자신의 콘텐츠 생성/편집/게시 |
| 편집자 | 40 | 모든 콘텐츠 관리 |
| 관리자 | 50 | 설정을 포함한 전체 접근 권한 |
각 역할은 모든 하위 수준의 권한을 상속합니다. 첫 번째 사용자는 항상 관리자로 생성됩니다.
사용자 초대
섹션 제목: “사용자 초대”관리자는 관리자 패널을 통해 새 사용자를 초대할 수 있습니다:
-
설정 > 사용자로 이동
-
사용자 초대 클릭
-
사용자의 이메일 입력 및 역할 선택
-
초대 보내기 클릭
-
사용자는 초대 링크가 포함된 이메일을 수신
-
링크를 클릭하고 패스키 등록
초대는 7일 동안 유효합니다. 관리자는 사용자 페이지에서 초대를 재전송하거나 취소할 수 있습니다.
패스키 관리
섹션 제목: “패스키 관리”사용자는 계정 설정에서 패스키를 관리할 수 있습니다:
- 패스키 추가 — 백업 또는 다른 기기를 위한 추가 패스키 등록
- 패스키 제거 — 더 이상 사용하지 않는 패스키 삭제
- 패스키 이름 변경 — 설명이 포함된 이름 지정
각 사용자는 최대 10개의 패스키를 등록할 수 있습니다.
자체 가입
섹션 제목: “자체 가입”팀 사이트의 경우, 특정 이메일 도메인에 대해 자체 가입을 활성화할 수 있습니다:
import { defineConfig } from "astro/config";import emdash from "emdash/astro";
export default defineConfig({ integrations: [ emdash({ auth: { selfSignup: { domains: ["example.com"], defaultRole: "contributor", }, }, }), ],});일치하는 이메일 도메인을 가진 사용자는 초대 없이 가입할 수 있습니다. 확인 이메일을 받고 패스키를 등록하여 가입을 완료합니다.
세션 구성
섹션 제목: “세션 구성”세션은 합리적인 기본값을 가진 안전한 HttpOnly 쿠키를 사용합니다:
js title="astro.config.mjs"emdash({ auth: { session: { maxAge: 30 * 24 * 60 * 60, // 30 days (default) sliding: true, // Reset expiry on activity }, },});보안 참고 사항
섹션 제목: “보안 참고 사항”- 패스키는 공개 키로 저장됨 — 개인 키는 기기를 떠나지 않음
- 챌린지 검증으로 재생 공격 방지
- 속도 제한으로 무차별 대입 공격 방어(분당/IP당 5회 시도)
- 세션은 HttpOnly, Secure, SameSite=Lax로 쿠키 보안 유지
- 매직 링크 토큰은 SHA-256 해시 처리됨 — 원시 토큰은 저장되지 않음
문제 해결
섹션 제목: “문제 해결””등록된 패스키 없음”
섹션 제목: “”등록된 패스키 없음””로그인 시 이 오류가 표시되면, 비밀번호 관리자에서 패스키가 삭제되었을 수 있습니다. 관리자에게 매직 링크 또는 새 초대를 요청하세요.
”패스키 인증 실패”
섹션 제목: “”패스키 인증 실패””이는 일반적으로 패스키가 다른 도메인용으로 생성되었음을 의미합니다. 패스키는 도메인에 바인딩됩니다 — localhost:4321용 패스키는 example.com에서 작동하지 않습니다. 각 도메인에 대해 새 패스키를 등록하세요.
”세션 만료”
섹션 제목: “”세션 만료””세션은 기본적으로 30일 동안 지속되며 슬라이딩 만료를 사용합니다. 예기치 않게 로그아웃된 경우, 쿠키를 지우고 다시 로그인하세요.
모든 패스키 분실
섹션 제목: “모든 패스키 분실”등록된 모든 패스키에 대한 접근 권한을 잃은 경우:
- 다른 관리자에게 매직 링크 전송 요청(이메일 구성 필요)
- 매직 링크를 사용하여 로그인
- 계정 설정에서 새 패스키 등록
유일한 관리자이고 이메일이 구성되지 않은 경우, 데이터베이스를 통해 사이트의 인증을 재설정해야 합니다.
Cloudflare Access
섹션 제목: “Cloudflare Access”Cloudflare에 배포할 때, 패스키 대신 Cloudflare Access를 인증 공급자로 사용할 수 있습니다. Access는 기존 ID 공급자를 사용하여 에지에서 인증을 처리합니다.
Cloudflare Access를 사용하는 이유
섹션 제목: “Cloudflare Access를 사용하는 이유”- 싱글 사인온 — 사용자가 회사의 IdP로 인증합니다
- 중앙 집중식 접근 제어 — Cloudflare 대시보드에서 관리자에 접근할 수 있는 사람을 관리합니다
- 패스키 관리 불필요 — 패스키를 등록하거나 관리할 필요가 없습니다
- 그룹 기반 역할 — IdP 그룹을 EmDash 역할에 자동으로 매핑합니다
- EmDash 사이트에 대한 Cloudflare Access 애플리케이션을 생성합니다
- 애플리케이션 설정에서 Application Audience (AUD) Tag를 기록합니다
- EmDash가 Access를 사용하도록 구성합니다:
js title="astro.config.mjs"import { defineConfig } from "astro/config";import cloudflare from "@astrojs/cloudflare";import emdash from "emdash/astro";import { d1, access } from "@emdash-cms/cloudflare";
export default defineConfig({ output: "server", adapter: cloudflare(), integrations: [ emdash({ database: d1({ binding: "DB" }), auth: access({ teamDomain: "myteam.cloudflareaccess.com", audience: "abc123def456...", // From Access app settings }), }), ],});구성 옵션
섹션 제목: “구성 옵션”| 옵션 | 타입 | 기본값 | 설명 |
|---|---|---|---|
teamDomain | string | 필수 | Access 팀 도메인 (예: myteam.cloudflareaccess.com) |
audience | string | 필수 | Access 설정의 Application Audience (AUD) 태그 |
autoProvision | boolean | true | 첫 번째 Access 로그인 시 EmDash 사용자 생성 |
defaultRole | number | 30 | 어떤 그룹에도 속하지 않는 사용자의 역할 (30 = Author) |
syncRoles | boolean | false | IdP 그룹에 따라 각 로그인 시 역할 업데이트 |
roleMapping | object | — | IdP 그룹 이름을 역할 수준에 매핑 |
audienceEnvVar | string | "CF_ACCESS_AUDIENCE" | audience 태그의 환경 변수 이름 (하드코딩 대안) |
역할 매핑
섹션 제목: “역할 매핑”IdP 그룹을 EmDash 역할에 매핑합니다:
js title="astro.config.mjs"emdash({ auth: access({ teamDomain: "myteam.cloudflareaccess.com", audience: "abc123...", roleMapping: { Admins: 50, // Admin "Content Editors": 40, // Editor Writers: 30, // Author }, defaultRole: 20, // Contributor for users not in any group }),});사용자가 여러 그룹에 속한 경우, 첫 번째로 일치하는 그룹이 우선합니다. 사이트에 접근하는 첫 번째 사용자는 그룹에 관계없이 항상 관리자가 됩니다.
역할 동기화 동작
섹션 제목: “역할 동기화 동작”기본적으로 (syncRoles: false), 사용자의 역할은 처음 로그인할 때 설정되며 이후에는 변경되지 않습니다. 이를 통해 관리자가 EmDash에서 수동으로 역할을 조정할 수 있습니다.
IdP 그룹을 권위 있는 것으로 설정하려면 syncRoles: true로 설정하세요 — 사용자의 역할은 현재 그룹을 기반으로 매 로그인 시 업데이트됩니다.
작동 방식
섹션 제목: “작동 방식”- 사용자가
/_emdash/admin을 방문합니다 - Cloudflare Access가 가로채서 IdP로 리디렉션합니다
- 사용자가 인증합니다 (SSO, MFA 등)
- Access가 요청에 서명된 JWT를 설정합니다
- EmDash가 JWT를 검증하고 사용자를 생성/인증합니다
비활성화된 기능
섹션 제목: “비활성화된 기능”Access가 활성화되면, 다음 기능을 사용할 수 없습니다:
- 로그인 페이지 (
/_emdash/admin/login) - 패스키 등록 및 관리
- OAuth 로그인
- 매직 링크 로그인
- 자체 가입
- 사용자 초대
사용자 관리는 전적으로 Cloudflare Access 정책을 통해 수행됩니다.
문제 해결
섹션 제목: “문제 해결””Access JWT가 없음”
섹션 제목: “”Access JWT가 없음””요청이 Access JWT 없이 EmDash에 도달했습니다. 이는 다음을 의미합니다:
- Access가 애플리케이션을 보호하도록 구성되지 않았습니다
- Access 정책이 관리자 경로와 일치하지 않습니다
Access 애플리케이션이 /_emdash/admin/*을 포함하는지 확인하세요.
”JWT audience 불일치”
섹션 제목: “”JWT audience 불일치””구성의 audience가 JWT와 일치하지 않습니다. Access 애플리케이션 설정의 Application Audience Tag를 다시 확인하세요.
”사용자가 승인되지 않음”
섹션 제목: “”사용자가 승인되지 않음””사용자가 Access를 통해 인증했지만 autoProvision이 false이고 EmDash에 존재하지 않습니다. 다음 중 하나를 수행하세요:
autoProvision: true로 설정하거나,- 로그인 전에 사용자를 수동으로 생성하세요