Skip to content

Add AT Protocol (Bluesky) authentication provider#102

Merged
sergeychernyshev merged 4 commits into
mainfrom
claude/atproto-auth-provider-6m2yze
Jun 27, 2026
Merged

Add AT Protocol (Bluesky) authentication provider#102
sergeychernyshev merged 4 commits into
mainfrom
claude/atproto-auth-provider-6m2yze

Conversation

@sergeychernyshev

Copy link
Copy Markdown
Member

Implements a spec-compliant atproto OAuth login provider alongside the
existing Google/Twitch/Patreon providers. atproto's flow is heavier than
classic OAuth2, so this also extends the provider abstraction to support
async, multi-step flows without changing existing providers' behavior.

Highlights:

  • Full identity discovery with no hardcoded Bluesky/PDS hosts:
    handle -> DID (HTTPS .well-known/atproto-did, then DNS _atproto.
    over DoH) -> DID document (did:plc via the PLC directory, did:web via the
    domain) -> PDS (#atproto_pds service) -> authorization server
    (.well-known/oauth-protected-resource -> oauth-authorization-server).
  • PKCE, DPoP-bound tokens (RFC 9449, with use_dpop_nonce retry), and Pushed
    Authorization Requests (PAR), as required by the atproto OAuth profile.
  • Public OAuth client: serves its own client-metadata.json (the client_id),
    no client secret. Enabled via ATPROTO_ENABLED; PLC/DoH endpoints overridable
    via ATPROTO_PLC_URL / ATPROTO_DOH_URL.
  • Transient PKCE verifier + DPoP key + discovered endpoints are persisted in
    an encrypted, short-lived flow cookie across the redirect round-trip.
  • Handle-entry form shown when no identifier is supplied (standard atproto UX).
  • OAuthProvider gains optional authorize()/exchange()/handleExtraRoute() hooks;
    shared user/session creation extracted into finishLogin().
  • Power-strip + profile UI: "Continue with Bluesky" button and provider icons.
  • Tests covering metadata, handle form, PAR+DPoP+PKCE (with nonce retry),
    callback token exchange/session/credential, and state-mismatch rejection.

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_015SgFKgH1gqfP2Zx3yrnzY2

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 18, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
startup-api 70ddb2c Jun 27 2026, 07:49 PM

claude added 3 commits June 27, 2026 15:43
Implements a spec-compliant atproto OAuth login provider alongside the
existing Google/Twitch/Patreon providers. atproto's flow is heavier than
classic OAuth2, so this also extends the provider abstraction to support
async, multi-step flows without changing existing providers' behavior.

Highlights:
- Full identity discovery with no hardcoded Bluesky/PDS hosts:
  handle -> DID (HTTPS .well-known/atproto-did, then DNS _atproto.<handle>
  over DoH) -> DID document (did:plc via the PLC directory, did:web via the
  domain) -> PDS (#atproto_pds service) -> authorization server
  (.well-known/oauth-protected-resource -> oauth-authorization-server).
- PKCE, DPoP-bound tokens (RFC 9449, with use_dpop_nonce retry), and Pushed
  Authorization Requests (PAR), as required by the atproto OAuth profile.
- Public OAuth client: serves its own client-metadata.json (the client_id),
  no client secret. Enabled via ATPROTO_ENABLED; PLC/DoH endpoints overridable
  via ATPROTO_PLC_URL / ATPROTO_DOH_URL.
- Transient PKCE verifier + DPoP key + discovered endpoints are persisted in
  an encrypted, short-lived flow cookie across the redirect round-trip.
- Handle-entry form shown when no identifier is supplied (standard atproto UX).
- OAuthProvider gains optional authorize()/exchange()/handleExtraRoute() hooks;
  shared user/session creation extracted into finishLogin().
- Power-strip + profile UI: "Continue with Bluesky" button and provider icons.
- Tests covering metadata, handle form, PAR+DPoP+PKCE (with nonce retry),
  callback token exchange/session/credential, and state-mismatch rejection.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015SgFKgH1gqfP2Zx3yrnzY2
atproto is a public OAuth client with no secrets, so per the project's
configuration philosophy (env holds only secrets/per-deployment values) all of
its settings now live in the createStartupAPI factory config rather than env:

- enabled, clientName, plcUrl, dohUrl moved onto ProviderOptions (alongside the
  existing Patreon-specific campaignId); enablement is providers.atproto.enabled.
- isAtprotoEnabled() now takes ProviderOptions; AtprotoProvider.create reads
  clientName/plcUrl/dohUrl from options.
- getActiveProviders(env, providerConfigs) is config-aware; providerConfigs is
  threaded through handleSSR and handleAdmin so the power-strip/profile/admin UIs
  list atproto when enabled.
- Removed ATPROTO_* fields from StartupAPIEnv and wrangler.jsonc; regenerated
  worker-configuration.d.ts.
- README + tests updated to enable atproto via the config object.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015SgFKgH1gqfP2Zx3yrnzY2
atproto has no env credentials, so the natural equivalent of "enabled because
credentials are present" is "enabled because the config key is present".
`providers: { atproto: {} }` now enables it; `enabled: false` remains as an
explicit opt-out for dynamically-built config.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015SgFKgH1gqfP2Zx3yrnzY2
@sergeychernyshev
sergeychernyshev force-pushed the claude/atproto-auth-provider-6m2yze branch from 7abb5f6 to 8b6a791 Compare June 27, 2026 19:44
Minor release for the new AT Protocol (Bluesky) authentication provider.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sergeychernyshev
sergeychernyshev merged commit 857bcf0 into main Jun 27, 2026
2 checks passed
@sergeychernyshev
sergeychernyshev deleted the claude/atproto-auth-provider-6m2yze branch June 27, 2026 20:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants