Anchor uses @tijs/atproto-oauth for OAuth authentication with AT Protocol.
import { createATProtoOAuth } from "jsr:@tijs/atproto-oauth";
import { SQLiteStorage } from "jsr:@tijs/atproto-storage";
const oauth = createATProtoOAuth({
baseUrl: "https://dropanchor.app",
cookieSecret: Deno.env.get("COOKIE_SECRET"),
mobileScheme: "anchor-app://auth-callback",
appName: "Anchor Location Feed",
logoUri: "https://cdn.dropanchor.app/images/anchor-logo.png",
policyUri: "https://dropanchor.app/privacy-policy",
sessionTtl: 60 * 60 * 24 * 30, // 30 days for mobile
storage: new SQLiteStorage(rawDb),
logger: console,
});
// Mount OAuth routes
app.route("/", oauth.routes);
| Setting | Value | Purpose |
|---|---|---|
| Base URL | https://dropanchor.app | Production backend URL |
| Mobile Scheme | anchor-app://auth-callback | iOS app custom URL scheme |
| Session TTL | 30 days | Extended for mobile app UX |
COOKIE_SECRET - Session encryption key (32+ characters, cryptographically
random)ANCHOR_BASE_URL - Override base URL for developmentAll authenticated endpoints support cookie-based authentication:
Cookie: sid=<session-token>
Alternative Bearer token authentication (for compatibility):
Authorization: Bearer <session-token>
Recommended: Use cookie-based authentication. After OAuth, create an HTTPCookie and add it to HTTPCookieStorage (iOS) or document.cookie (web).
For complete OAuth flow details, mobile integration, security considerations, and implementation examples:
📱 Mobile OAuth Guide (Package documentation)
This guide includes:
After authentication, use the session cookie to call authenticated endpoints:
curl -X POST "https://dropanchor.app/api/checkins" \ -b "sid=YOUR_SESSION_TOKEN" \ -H "Content-Type: application/json" \ -d '{"place": {...}, "message": "Great spot!"}'
curl -X DELETE "https://dropanchor.app/api/checkins/did:plc:abc/3k2abc" \ -b "sid=YOUR_SESSION_TOKEN"
See API Documentation for complete endpoint reference.
The Anchor iOS app uses ASWebAuthenticationSession for OAuth:
/mobile-authanchor-app://auth-callback?session_token=...See the Mobile OAuth Guide for implementation details.
const session = await oauth.validateSession(request);
if (!session.valid) {
// User needs to re-authenticate
}
For local development, override the base URL:
export ANCHOR_BASE_URL=http://localhost:8000
deno task dev/mobile-auth in browsertest.bsky.socialCOOKIE_SECRET is set correctlymobileScheme matches iOS app URL schemeanchor-app://auth-callbackSee Security Considerations in the Mobile OAuth Guide.