npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

bluesky-oauth-kit

v0.2.18

Published

A complete OAuth backend implementation for Bluesky

Downloads

9

Readme

Bluesky OAuth (2.0) Kit

A drop-in, ready-to-use, Bluesky OAuth login solution for Node.js and Javascript (any client).

Accelerate the migration of third-party Bluesky apps and integrations from insecure authentication methods (password stored in plaintext), to modern OAuth.

This package aims to adhere to OAuth 2.0 norms, while providing a simple to understand and ready-to-use Node.js backend that can be used with any sort of frontend client (Javascript, Vue, React, React Native, Ionic/Capacitor, Android, Swift, Electron, PWA, etc.)

Examples provided for Express (with hopefully more to come.) Testing an PRs welcome!

Installation

npm i -s bluesky-oauth-kit

Usage

See examples directory.

Express (Default Options)

const express = require('express');
const { setupExpressAuth } = require('bluesky-oauth-kit');

const app = express();

// Basic setup
await setupExpressAuth(app);

// With additional options
await setupExpressAuth(app, {
    baseUrl: 'http://localhost:5001',
    redirectUrl: '/dashboard',
    clientName: 'My OAuth App',
    // Optional: Custom storage implementations
    stateStore: customStateStore,
    sessionStore: customSessionStore
});

Express (composable)

const express = require('express');
const { initializeOAuth, authenticateToken, setupOauthRoutes } = require('bluesky-oauth-kit');

const app = express();

(async function() {
    const { client, sessionStore, stateStore } = await initializeOAuth(options);
    setupOauthRoutes(app, sessionStore);
})();

Framework Support

The library works with multiple frameworks:

  • Express (primary support)

Other frameworks can be supported by PR.

Environment Variables

# Required
OAUTH_JWT_SECRET=your-jwt-secret
OAUTH_BASE_URL=http://localhost:5001
OAUTH_PRIVATE_KEY_1=your-private-key-1
OAUTH_PRIVATE_KEY_2=your-private-key-2
OAUTH_PRIVATE_KEY_3=your-private-key-3

# Optional
OAUTH_CLIENT_NAME=My OAuth App
OAUTH_USE_COOKIES=true
OAUTH_REDIRECT_URL=/dashboard
NODE_ENV=development

Custom Storage

The library uses in-memory storage by default, but you can implement your own storage:

class CustomStore {
    async get(key) { /* ... */ }
    async set(key, value) { /* ... */ }
    async del(key) { /* ... */ }
}

// Redis example
class RedisStore {
    constructor(redis) {
        this.redis = redis;
    }
    async get(key) { return JSON.parse(await this.redis.get(key)); }
    async set(key, value) { await this.redis.set(key, JSON.stringify(value)); }
    async del(key) { await this.redis.del(key); }
}

Available Endpoints

The library sets up the following endpoints:

  • /login - Serves a login form (optional, can be disabled)
  • /oauth/login - Initiates the OAuth flow
  • /oauth/callback - Handles the OAuth callback
  • /oauth/userinfo - Returns info about the authenticated user
  • /oauth/revoke - Revokes the current session
  • /oauth/client-metadata.json - Serves OAuth client metadata
  • /oauth/jwks.json - Serves the JSON Web Key Set

Configuration

await setupExpressAuth(app, {
    baseUrl: 'http://localhost:5001',
    serveLoginPage: true,  // Set to false to disable built-in login page
    serveErrorPage: true,  // Set to false to disable built-in error page
    loginPageTitle: 'Login with Bluesky',  // Customize login page
    display: 'page',  // 'page', 'popup', or 'touch' for mobile
    maxAge: 48 * 60 * 60 * 1000,  // Cookie lifetime
    cookieDomain: '.yourdomain.com',
    cookiePath: '/',
    cookieSecret: 'your-secret',
    addHeaders: true,
    forceHTTPS: true,
    // ... other options
});

Development

Running the Example

  1. Clone the repository
  2. Install dependencies:
    npm install
  3. Copy .env.example to .env and fill in your values:
    cp .env.example .env
  4. Run the example:
    node examples/express.js

The example server will start on http://localhost:5001

Generating Keys

You can generate OAuth keys in two ways:

  1. Using npx (recommended):
npx bluesky-oauth-kit generate-oauth-keys
  1. After installing as a dependency:
npm run generate-keys

This will either create a new .env file or append OAuth keys to your existing one.

Authentication Flow

The library implements standard OAuth 2.0 authentication, providing:

  1. A JWT containing:

    • sub: The user's DID (standard OpenID Connect subject identifier)
    • did: The user's DID (AT Protocol identifier)
    • iss: The issuer ('bsky.social')
    • iat: Token issue timestamp
  2. The /oauth/userinfo endpoint returns this basic profile information.

Note: For richer profile data (handle, displayName, avatar, etc.), you'll need to:

  1. Install @atproto/api
  2. Use the session to create an Agent
  3. Call agent.getProfile()

Example:

const { Agent } = require('@atproto/api');

// Get rich profile data
const agent = new Agent(session);
const profile = await agent.getProfile({ actor: agent.did });
console.log(profile.data);  // Contains handle, displayName, avatar, etc.

Security Configuration

The library includes several security features that can be configured:

Cookie Options

When using OAUTH_USE_COOKIES=true, you can configure cookie security:

await setupExpressAuth(app, {
    maxAge: 7 * 24 * 60 * 60 * 1000,  // Cookie lifetime (default 48h)
    cookieDomain: '.yourdomain.com',   // Cookie domain
    cookiePath: '/',                   // Cookie path
    cookieSecret: 'your-secret',       // Enable signed cookies
});

Security Headers

The library automatically sets security headers:

  • X-Content-Type-Options: nosniff
  • X-Frame-Options: DENY
  • X-XSS-Protection: 1; mode=block

CORS

Configure CORS in your Express app:

app.use(cors({
    origin: process.env.OAUTH_BASE_URL,
    methods: ['GET', 'POST'],
    allowedHeaders: ['Content-Type', 'Authorization'],
}));

HTTPS

In production (NODE_ENV=production):

  • Cookies are automatically set as Secure
  • HTTP requests are redirected to HTTPS
  • Cookies use SameSite=Strict

Rate Limiting

The example includes rate limiting. You should include this (or something similar) in your app.

const rateLimit = require('express-rate-limit');
app.use(['/login', '/oauth/*'], rateLimit({
    windowMs: 15 * 60 * 1000,  // 15 minutes
    max: 100                    // Limit each IP to 100 requests per window
}));

Available Scopes

The Bluesky OAuth server supports these scopes:

  • atproto - Standard AT Protocol access
  • transition:generic - Generic transition scope
  • transition:chat.bsky - Chat transition scope (future use)

OAuth Implementation Details

This library implements the AT Protocol OAuth specification via @atproto/oauth-client-node:

  • Secure OAuth 2.0 flow with PAR, DPoP, and PKCE
  • Session management
  • Token handling and refresh
  • Framework integrations (Express)
  • Configurable storage backends

Using the Bluesky API (ATProto) with this package

This kit provides a helper function, getClient(), to retrieve your authenticated client instance, which can be passed to @atproto/api to make authenticated API requests.

See examples/express.js.