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

@melvinprince/next-authz

v0.1.0

Published

A reusable Next.js authentication library with Google OAuth support

Readme

@melvin/next-authz

A secure, edge-compatible authentication library for Next.js with Google OAuth support.

Features

  • 🔐 Secure OAuth Flow - PKCE, state validation, nonce protection
  • Edge Compatible - Runs on Vercel Edge Functions and Cloudflare Workers
  • 🍪 Secure Cookies - httpOnly, secure, sameSite with rotation support
  • 🔄 Key Rotation - Seamless secret rotation without downtime
  • 📦 Tree Shakeable - ESM-only with minimal bundle size
  • 🛡️ Type Safe - Full TypeScript support with strict types

Quick Start

1. Install

npm install @melvin/next-authz

2. Environment Variables

Create .env.local:

AUTH_SECRET="your-32-character-secret-here"
AUTH_APP_URL="http://localhost:3000"
GOOGLE_CLIENT_ID="your-google-client-id"
GOOGLE_CLIENT_SECRET="your-google-client-secret"
GOOGLE_REDIRECT_URI="http://localhost:3000/api/auth/callback"

3. Create Auth Configuration

// lib/auth.ts
import { googleProvider, createAuth } from '@melvin/next-authz'

const authConfig = {
  appUrl: process.env.AUTH_APP_URL!,
  callbackPath: '/api/auth/callback',
  secrets: [process.env.AUTH_SECRET!],
  clockSkewTolerance: 60,
}

const provider = googleProvider(
  process.env.GOOGLE_CLIENT_ID!,
  process.env.GOOGLE_CLIENT_SECRET!,
  process.env.GOOGLE_REDIRECT_URI!
)

export const auth = createAuth(authConfig, provider)

4. Add Route Handlers

// app/api/auth/start/route.ts
import { auth } from '@/lib/auth'

export const GET = auth.startHandler
// app/api/auth/callback/route.ts
import { auth } from '@/lib/auth'

export const GET = auth.callbackHandler
// app/api/auth/session/route.ts
import { auth } from '@/lib/auth'
import { NextRequest, NextResponse } from 'next/server'

export async function GET(request: NextRequest) {
  const session = await auth.getSession(request)
  return NextResponse.json({ user: session.user, valid: session.valid })
}

5. Add Middleware

// middleware.ts
import { auth } from '@/lib/auth'

export default auth.middleware

6. Protect Routes

// app/dashboard/page.tsx
import { auth } from '@/lib/auth'
import { requireSession } from '@melvin/next-authz'

export default async function DashboardPage(request: NextRequest) {
  const session = await requireSession(request, auth.getConfig())

  return (
    <div>
      <h1>Welcome, {session.name}!</h1>
      <p>Email: {session.email}</p>
    </div>
  )
}

7. Client-Side Session

// components/UserProfile.tsx
'use client'
import { useSession } from '@melvin/next-authz/client'

export function UserProfile() {
  const { user, loading, error } = useSession()

  if (loading) return <div>Loading...</div>
  if (error) return <div>Error: {error.message}</div>
  if (!user) return <div>Please sign in</div>

  return (
    <div>
      <h2>{user.name}</h2>
      <p>{user.email}</p>
    </div>
  )
}

Configuration

AuthConfig Options

interface AuthConfig {
  appUrl: string // Your app's base URL
  callbackPath: string // OAuth callback path
  cookiePrefix?: string // Cookie name prefix (default: 'auth')
  secrets: string[] // Array of secrets for rotation
  sessionStrategy?: 'jwt' // Session strategy (default: 'jwt')
  clockSkewTolerance?: number // Clock skew tolerance in seconds (default: 60)
  allowedOrigins?: string[] // Allowed origins for CSRF protection
  logger?: {
    // Telemetry hooks
    onLoginStart?: (data) => void
    onLoginSuccess?: (data) => void
    onLoginFailure?: (data) => void
  }
}

Middleware Configuration

// middleware.ts
import { createAuthMiddleware } from '@melvin/next-authz'

export default createAuthMiddleware(authConfig, {
  matcher: {
    include: ['/dashboard/:path*', '/admin/:path*'],
    exclude: ['/api/auth/:path*', '/_next/:path*'],
  },
  redirectTo: '/login',
  return401: false, // Return 401 instead of redirect
})

Advanced Usage

Role-Based Access Control

// Add roles to session
const session = await requireSession(request, authConfig)

if (!session.roles?.includes('admin')) {
  return NextResponse.json({ error: 'Forbidden' }, { status: 403 })
}

Google API Integration

// Get access token for Google APIs
const accessToken = await getGoogleAccessToken(session)

const response = await fetch('https://www.googleapis.com/calendar/v3/calendars/primary/events', {
  headers: { Authorization: `Bearer ${accessToken}` },
})

Custom Error Handling

import { AuthError, OAuthError, SessionError } from '@melvin/next-authz'

try {
  const session = await requireSession(request, authConfig)
} catch (error) {
  if (error instanceof SessionError) {
    // Handle session errors
  } else if (error instanceof OAuthError) {
    // Handle OAuth errors
  }
}

Security

Cookie Security

All cookies use secure defaults:

  • httpOnly - Prevents XSS attacks
  • secure - HTTPS only
  • sameSite=lax - CSRF protection
  • Short TTL for temporary cookies
  • Encryption for sensitive data

OAuth Security

  • PKCE - Prevents authorization code interception
  • State Parameter - CSRF protection
  • Nonce Validation - Prevents replay attacks
  • Clock Skew Tolerance - Handles time sync issues

Environment Variables

| Variable | Description | Required | | ---------------------- | -------------------------------------- | -------- | | AUTH_SECRET | Primary secret for signing (32+ chars) | Yes | | AUTH_SECRETS | Comma-separated secrets for rotation | No | | AUTH_APP_URL | Your application URL | Yes | | AUTH_CALLBACK_PATH | OAuth callback path | No | | GOOGLE_CLIENT_ID | Google OAuth client ID | Yes | | GOOGLE_CLIENT_SECRET | Google OAuth client secret | Yes | | GOOGLE_REDIRECT_URI | OAuth redirect URI | Yes |

Examples

API Reference

Server-Side Functions (from @melvin/next-authz)

  • createAuth(config, provider) - Create auth instance
  • googleProvider(clientId, clientSecret, redirectUri) - Google provider
  • createStartHandler(config, provider) - Login start handler
  • createCallbackHandler(config, provider) - OAuth callback handler
  • createAuthMiddleware(config, options) - Authentication middleware
  • getSession(request, config) - Get session (server-side)
  • requireSession(request, config) - Require session (server-side)
  • rotateKeys(config, newSecret) - Rotate secrets

Client-Side Functions (from @melvin/next-authz/client)

  • useSession(options) - Session hook (client-side)

Note: Client-side functions must be imported from the /client entry point and used in components marked with 'use client'.

Types

  • AuthUser - User profile data
  • AuthSession - Session with JWT claims
  • AuthConfig - Configuration options
  • AuthProvider - Provider interface
  • AuthErrorCode - Standardized error codes

Build Considerations

Client-Side Bundle

The client-side bundle (@melvin/next-authz/client) is optimized for browser usage:

  • Bundle Size: Minimized for optimal performance
  • Tree Shaking: Unused code is automatically removed
  • ESM Only: Modern module format for better tree shaking
  • React Hooks: Includes useSession hook for client-side session management

Note: The build process strips the 'use client' directive from the compiled bundle as it's handled by Next.js at runtime. This is expected behavior and doesn't affect functionality.

Development vs Production

  • Development: Source maps included for debugging
  • Production: Minified and optimized for size
  • TypeScript: Full type definitions included

Contributing

See CONTRIBUTING.md for development setup and guidelines.

License

MIT License - see LICENSE for details.

Support