Files
wehub-resource-sync b3a7f98e5a
CI / E2E Cloudflare (4/8) (push) Failing after 0s
CI / E2E Cloudflare (8/8) (push) Failing after 1s
CI / Lint (push) Failing after 1s
Auto Extract / Extract (push) Failing after 4s
CI / Version Check (push) Failing after 9s
CI / Integration Tests (push) Failing after 1s
CI / E2E tests (1/8) (push) Failing after 1s
CI / E2E tests (2/8) (push) Failing after 2s
CI / E2E tests (3/8) (push) Failing after 2s
CI / Browser Tests (push) Failing after 1s
CI / E2E tests (5/8) (push) Failing after 1s
CI / E2E Cloudflare (2/8) (push) Failing after 2s
CI / Typecheck (push) Failing after 1s
CI / Changeset Validation (push) Failing after 2s
CI / E2E Cloudflare (5/8) (push) Failing after 1s
CI / E2E Cloudflare (6/8) (push) Failing after 1s
CI / E2E Cloudflare (7/8) (push) Failing after 1s
CodeQL / Analyze (javascript-typescript) (push) Failing after 1s
Format / Format (push) Failing after 0s
CodeQL / Analyze (actions) (push) Failing after 4s
CI / E2E tests (4/8) (push) Failing after 1s
CI / E2E tests (6/8) (push) Failing after 1s
CI / E2E tests (7/8) (push) Failing after 2s
CI / E2E tests (8/8) (push) Failing after 1s
CI / E2E Cloudflare (1/8) (push) Failing after 1s
CI / E2E Cloudflare (3/8) (push) Failing after 2s
Preview Releases / Publish Preview (push) Failing after 0s
zizmor / Run zizmor (push) Failing after 1s
Release / Release (push) Failing after 2s
CI / Smoke Tests (push) Failing after 5m36s
CI / Tests (push) Failing after 6m36s
Release / Sync Templates (push) Has been skipped
CI / E2E Tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:23:53 +08:00
..

@emdash-cms/auth-atproto

Atmosphere/AT Protocol login provider for EmDash. Lets users sign in to your EmDash admin with their Atmosphere account — the same identity behind Bluesky and the wider AT Protocol network.

No client secrets, no OAuth-app registration. Users authenticate at their own provider; EmDash never sees a password.

Installation

pnpm add @emdash-cms/auth-atproto

Quick Start

// astro.config.mjs
import { defineConfig } from "astro/config";
import emdash from "emdash/astro";
import { atproto } from "@emdash-cms/auth-atproto";

export default defineConfig({
	server: {
		host: "127.0.0.1", // required for local dev — see below
	},
	integrations: [
		emdash({
			authProviders: [atproto()],
		}),
	],
});

This adds Sign in with Atmosphere to the login page and the setup wizard. With no allowlist, the first user becomes Admin and self-signup is closed for everyone after that.

Configuration

atproto({
	allowedDIDs: ["did:plc:abc123..."],
	allowedHandles: ["*.example.com", "alice.bsky.social"],
	defaultRole: 30, // Author
});
Option Type Default Description
allowedDIDs string[] DID allowlist. DIDs are permanent and can't be spoofed.
allowedHandles string[] Handle allowlist. Supports leading-wildcard patterns (*.example.com).
defaultRole number 10 (Subscriber) Role assigned to allowed users after the first. First user is always Admin.

If both lists are set, a user matching either is admitted. Handle matches are independently verified against the handle's DNS/HTTP record before being trusted.

Local development

The AT Protocol OAuth profile requires loopback redirect URIs to use the IP literal 127.0.0.1 rather than localhost. Vite (the dev server Astro uses) binds to localhost by default, so set server.host to 127.0.0.1 and visit http://127.0.0.1:4321/_emdash/admin for the whole flow. Otherwise the cookie set on localhost won't be visible after the redirect lands you on 127.0.0.1.

Production

The provider serves its own OAuth client metadata at /.well-known/atproto-client-metadata.json. Authorization servers fetch this URL during login, so your deployment needs to be reachable on the public internet over HTTPS. Set siteUrl if you're behind a TLS-terminating reverse proxy.

Documentation

See the Atmosphere login guide for the full reference, including allowlist semantics, role assignment, and troubleshooting.