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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@zumito-team/discord-auth

v0.1.0

Published

Reusable Discord OAuth2 authentication module for Zumito Framework. Provides a configurable `DiscordAuthService` that handles the full login flow: Discord OAuth2 redirect, code exchange, user data fetching, JWT creation/signing, and cookie-based session m

Readme

discord-auth

Reusable Discord OAuth2 authentication module for Zumito Framework. Provides a configurable DiscordAuthService that handles the full login flow: Discord OAuth2 redirect, code exchange, user data fetching, JWT creation/signing, and cookie-based session management.

Both admin and userPanel modules use this shared service.

Features

  • Single service, multiple consumers — Admin and User Panel share the same auth logic via different configs (cookie names, token purpose, user data granularity).
  • Token purpose validation — Each consumer sets a purpose claim in the JWT. Cross-module token reuse is rejected at verification time.
  • Configurable per consumer: cookie name, prefix, httpOnly, JWT expiration, scope, whether to store full user profile or just ID.
  • Error handling — Validates DISCORD_CLIENT_ID, DISCORD_CLIENT_SECRET, and SECRET_KEY before processing. Returns clear error messages on failure.

Usage

Create a service extending DiscordAuthService:

import { DiscordAuthService } from '@zumito-team/discord-auth';

export class MyAuthService extends DiscordAuthService {
    constructor() {
        super({
            cookieName: 'my_token',
            routePrefix: '/myapp',
            loginRedirectPath: '/myapp',
            cookieHttpOnly: true,
            fetchFullUser: false,
            purpose: 'myapp',
        });
    }
}

Then create thin route files:

// Login route
class MyLogin extends Route {
    path = '/myapp/login';
    async execute(req, res) {
        const auth = ServiceContainer.getService(MyAuthService);
        if (await auth.isLoginValid(req).then(r => r.isValid)) return res.redirect('/myapp');
        res.redirect(auth.getDiscordAuthUrl(process.env.HOST ?? req.get('host')));
    }
}

// Callback route
class MyCallback extends Route {
    path = '/myapp/login/callback';
    async execute(req, res) {
        await ServiceContainer.getService(MyAuthService).handleCallback(req, res);
    }
}

// Logout route
class MyLogout extends Route {
    path = '/myapp/logout';
    async execute(req, res) {
        ServiceContainer.getService(MyAuthService).clearAuthCookie(res);
        res.redirect('/myapp');
    }
}

Configuration

| Option | Type | Default | Description | |---|---|---|---| | cookieName | string | required | Cookie name (e.g., 'admin_token', 'panel_token'). | | routePrefix | string | required | Route prefix for login/callback URLs (e.g., '/admin', '/panel'). | | loginRedirectPath | string | required | Where to redirect after successful login. | | cookieHttpOnly | boolean | required | Whether the cookie is httpOnly. | | fetchFullUser | boolean | required | Store full Discord user object (true) or just the ID (false). | | purpose | string | required | Claim embedded in JWT to prevent cross-module token reuse. | | scope | string | 'identify' | Discord OAuth2 scope. | | jwtExpirationTime | string | '2h' | JWT expiration time. | | cookieMaxAge | number | 30 * 24 * 60 * 60 * 1000 | Cookie max age in ms (30 days). | | cookiePath | string | '/' | Cookie path. | | cookieSecure | boolean | false | Cookie secure flag. | | cookieSameSite | 'lax' \| 'strict' \| 'none' | 'lax' | Cookie SameSite attribute. |

Environment Variables

| Variable | Required | Description | |---|---|---| | DISCORD_CLIENT_ID | Yes | Discord application client ID. | | DISCORD_CLIENT_SECRET | Yes | Discord application client secret. | | SECRET_KEY | Yes | Secret key for JWT signing (shared across modules using this service). | | HOST | No | Fallback host for redirect URIs (uses req.get('host') if not set). | | FRONTEND_URL | No | Override for the OAuth2 redirect URI. |

API

isLoginValid(req): Promise<{ isValid: boolean, data?: any }>

Reads the configured cookie from the request, verifies the JWT signature and expiration, and validates the purpose claim matches the service config.

getDiscordAuthUrl(host: string): string

Builds the Discord OAuth2 authorize URL for the configured scope and redirect URI.

handleCallback(req, res): Promise<void>

Handles the full OAuth2 callback flow: validates env vars, exchanges the authorization code for tokens, fetches the Discord user profile, creates a signed JWT with the purpose claim, sets the cookie, and redirects to loginRedirectPath.

clearAuthCookie(res): void

Clears the authentication cookie.

setAuthCookie(res, jwt: string): void

Sets the authentication cookie with configured options.

createJWT(payload): Promise<string>

Creates and signs a JWT with HS256 algorithm.

Security

  • Token purpose validation: Each consumer includes a purpose claim in the JWT. A token issued for 'panel' will be rejected when verified by the Admin module (expecting 'admin'), and vice versa.
  • Full user data vs ID only: Admin module stores only the Discord user ID (fetchFullUser: false). User Panel stores the full profile for display purposes (fetchFullUser: true).

Dependencies

  • jose — JWT signing and verification.
  • zumito-framework