コンテンツにスキップ

認証

EmDashは、プライマリのログイン方法としてパスキー認証を使用します。パスキーはフィッシング耐性があり、パスワードを必要とせず、ブラウザやパスワードマネージャーを通じてデバイス間で動作します。

Cloudflareデプロイメントでは、オプションでCloudflare Accessを代替認証プロバイダーとして使用できます。

パスキーは、Web標準であるWebAuthnを使用し、デバイスに保存されるかパスワードマネージャーを通じて同期される公開鍵認証情報を作成します。ログイン時、デバイスはネットワーク上にパスワードを送信することなく、認証情報の所有を証明します。

パスキー認証の利点:

  • 記憶または漏洩するパスワードがない
  • フィッシング耐性 — 認証情報はサイトのドメインに紐付けられます
  • クロスデバイス同期 — iCloudキーチェーン、Googleパスワードマネージャー、1Passwordなどで動作します
  • 高速ログイン — 生体認証またはPINでワンタップ

初めて管理パネルにアクセスする際、セットアップウィザードが管理者アカウント作成を案内します。

  1. `http://localhost:4321/_emdash/admin“に移動します

  2. セットアップウィザードにリダイレクトされます。以下を入力します:

    • サイトタイトル — サイトの名前
    • タグライン — 短い説明
    • 管理者メール — メールアドレス
  3. サイトを作成をクリックしてパスキーを登録します

  4. ブラウザがパスキー作成を促します:

    • macOS: Touch ID、デバイスパスワード、またはセキュリティキー
    • Windows: Windows Helloまたはセキュリティキー
    • モバイル: Face ID、指紋、またはPIN
  5. パスキーが登録されると、ログイン状態になり管理ダッシュボードにリダイレクトされます。

セットアップ後、管理パネルに戻るとパスキー認証がトリガーされます:

  1. /_emdash/adminにアクセスします

  2. ログインしていない場合、ログインページが表示されます

  3. サインインをクリックして認証します

  4. ブラウザがパスキー(生体認証、PIN、またはセキュリティキー)を要求します

  5. 検証後、管理ダッシュボードにリダイレクトされます

パスキーが使用できない場合(例: デバイス紛失)、マジックリンクが代替手段を提供します。これにはメール設定が必要です。

  1. ログインページでメールでサインインをクリックします

  2. メールアドレスを入力します

  3. 受信トレイでログインリンクを確認します

  4. リンクをクリックして認証します(15分間有効)

EmDashは設定時にGitHubおよびGoogleでのOAuthログインをサポートします。ユーザーは初期パスキーセットアップ後にアカウントをリンクできます。

セットアップ手順については設定ガイドを参照してください。

EmDashは5つのレベルでロールベースのアクセス制御を使用します:

ロールレベル説明
購読者10閲覧専用アクセス
投稿者20コンテンツ作成(承認が必要)
作成者30自身のコンテンツの作成/編集/公開
編集者40すべてのコンテンツ管理
管理者50設定を含む完全アクセス

各ロールは下位レベルのすべての権限を継承します。最初のユーザーは常に管理者として作成されます。

管理者は管理パネルから新しいユーザーを招待できます:

  1. 設定 > ユーザーに移動します

  2. ユーザーを招待をクリックします

  3. ユーザーのメールアドレスを入力し、ロールを選択します

  4. 招待を送信をクリックします

  5. ユーザーは招待リンクを含むメールを受信します

  6. リンクをクリックし、パスキーを登録します

招待は7日間有効です。管理者はユーザーページから招待を再送信または取り消すことができます。

ユーザーはアカウント設定からパスキーを管理できます:

  • パスキー追加 — バックアップや他のデバイス用に追加のパスキーを登録します
  • パスキー削除 — 使用しなくなったパスキーを削除します
  • パスキー名変更 — パスキーに説明的な名前を付けます

各ユーザーは最大10個のパスキーを登録できます。

チームサイトでは、特定のメールドメインに対してセルフサインアップを有効にできます:

astro.config.mjs
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
},
},
});
  • パスキーは公開鍵として保存されます — 秘密鍵はデバイスから離れません
  • チャレンジ検証によりリプレイ攻撃を防止します
  • レート制限によりブルートフォース攻撃から保護します(5回/分/IP)
  • セッションはHttpOnly、Secure、SameSite=Laxでクッキーセキュリティを確保します
  • マジックリンクトークンはSHA-256ハッシュ化されます — 生のトークンは保存されません

「登録されたパスキーがありません」

Section titled “「登録されたパスキーがありません」”

ログイン時にこのエラーが表示される場合、パスワードマネージャーからパスキーが削除された可能性があります。管理者にマジックリンクまたは新しい招待を送信するよう依頼してください。

「パスキー認証に失敗しました」

Section titled “「パスキー認証に失敗しました」”

これは通常、パスキーが異なるドメイン用に作成されたことを意味します。パスキーはドメインに紐付けられます — localhost:4321用のパスキーはexample.comでは動作しません。各ドメイン用に新しいパスキーを登録してください。

「セッションが期限切れです」

Section titled “「セッションが期限切れです」”

セッションはデフォルトで30日間持続し、スライディング有効期限があります。予期せずログアウトした場合は、クッキーをクリアして再度ログインしてください。

登録したすべてのパスキーへのアクセスを失った場合:

  1. 別の管理者にマジックリンクを送信するよう依頼します(メール設定が必要)
  2. マジックリンクを使用してログインします
  3. アカウント設定で新しいパスキーを登録します

唯一の管理者でメールが設定されていない場合、データベースを通じてサイトの認証をリセットする必要があります。

Cloudflareにデプロイする場合、パスキーの代わりにCloudflare Accessを認証プロバイダーとして使用できます。Accessは既存のアイデンティティプロバイダーを使用してエッジで認証を処理します。

  • シングルサインオン — ユーザーは会社のIdPで認証します
  • 一元化されたアクセス制御 — Cloudflareダッシュボードで管理者にアクセスできるユーザーを管理できます
  • パスキー管理不要 — パスキーの登録や管理は不要です
  • グループベースのロール — IdPグループをEmDashロールに自動的にマッピングします
  1. EmDashサイト用のCloudflare Accessアプリケーションを作成します
  2. アプリケーション設定からApplication Audience (AUD) Tagをメモします
  3. 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
}),
}),
],
});
オプションタイプデフォルト説明
teamDomainstring必須あなたのAccessチームドメイン (例: myteam.cloudflareaccess.com)
audiencestring必須Access設定からのApplication Audience (AUD) タグ
autoProvisionbooleantrue初回Accessログイン時にEmDashユーザーを作成します
defaultRolenumber30どのグループにも一致しないユーザーのロール (30 = 著者)
syncRolesbooleanfalseIdPグループに基づいて各ログイン時にロールを更新します
roleMappingobject—IdPグループ名をロールレベルにマッピングします
audienceEnvVarstring"CF_ACCESS_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 を設定します。

  1. ユーザーが /_emdash/admin にアクセスします
  2. Cloudflare Accessがリクエストをインターセプトし、IdPにリダイレクトします
  3. ユーザーが認証します(SSO、MFAなど)
  4. Accessがリクエストに署名付きJWTを設定します
  5. EmDashがJWTを検証し、ユーザーを作成/認証します

Accessが有効になると、以下の機能は利用できなくなります:

  • ログインページ (/_emdash/admin/login)
  • パスキーの登録と管理
  • OAuthログイン
  • マジックリンクログイン
  • セルフサインアップ
  • ユーザー招待

ユーザー管理は、Cloudflare Accessポリシーを通じて完全に行われます。

リクエストがAccess JWTなしでEmDashに到達しました。これは以下を意味します:

  • Accessがアプリケーションを保護するように設定されていない
  • Accessポリシーが管理者ルートに一致していない

Accessアプリケーションが /_emdash/admin/* をカバーしていることを確認してください。

設定の audience がJWTと一致しません。Accessアプリケーション設定のApplication Audience Tagを再確認してください。

ユーザーはAccess経由で認証されましたが、autoProvision が false で、EmDashにユーザーが存在しません。以下のいずれかを行ってください:

  • autoProvision: true を設定する、または
  • ユーザーがログインする前に手動でユーザーを作成する