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

authservice-nextjs

v1.0.0

Published

Next.js SDK for Auth Service - Server and client-side authentication with App Router support

Downloads

32

Readme

Auth Service Next.js SDK

Complete authentication and authorization SDK for Next.js applications with support for both Pages Router and App Router.

Features

  • 🚀 Full Next.js Support: Works with Pages Router and App Router
  • 🔐 Server-Side Auth: Secure authentication with getServerSideProps
  • 🛡️ API Route Protection: Middleware for protecting API endpoints
  • Edge Runtime Compatible: Works with Next.js middleware
  • 🎨 React Components: Pre-built auth components
  • 📱 Client-Side Hooks: React hooks for auth state
  • 🔄 Automatic Token Management: Handle refresh tokens seamlessly
  • 🎯 TypeScript First: Full type safety

Installation

npm install @auth-service/nextjs-sdk

Quick Start

1. Create Auth Instance

// lib/auth.ts
import { createAuth } from '@auth-service/nextjs-sdk';

export const auth = createAuth({
  authServiceUrl: process.env.NEXT_PUBLIC_AUTH_SERVICE_URL!,
  appId: process.env.NEXT_PUBLIC_APP_ID!,
  appSecret: process.env.APP_SECRET!, // Server-side only
  
  // Optional configuration
  cookieName: 'auth-token',
  loginUrl: '/login',
  unauthorizedUrl: '/unauthorized'
});

2. Add Provider (Pages Router)

// pages/_app.tsx
import { NextAuthProvider } from '@auth-service/nextjs-sdk';
import { auth } from '../lib/auth';

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <NextAuthProvider 
      config={auth.clientConfig}
      initialUser={pageProps.user}
    >
      <Component {...pageProps} />
    </NextAuthProvider>
  );
}

3. Protect Pages

// pages/dashboard.tsx
import { auth } from '../lib/auth';

export const getServerSideProps = auth.getServerSideProps.withAuth();

export default function Dashboard({ user }) {
  return (
    <div>
      <h1>Welcome {user.email}</h1>
    </div>
  );
}

Pages Router

Protecting Pages

Basic Authentication

// Require authentication
export const getServerSideProps = auth.getServerSideProps.withAuth();

// With custom logic
export const getServerSideProps = auth.getServerSideProps.withAuth(
  async (context) => {
    // context.user is available here
    const data = await fetchUserData(context.user.id);
    
    return {
      props: { data }
    };
  }
);

Permission-Based Protection

// Single permission
export const getServerSideProps = auth.getServerSideProps.withPermission('posts:create');

// Multiple permissions (ANY)
export const getServerSideProps = auth.getServerSideProps.withAnyPermission([
  'posts:edit',
  'posts:admin'
]);

// Multiple permissions (ALL)
export const getServerSideProps = auth.getServerSideProps.withAllPermissions([
  'admin:access',
  'posts:delete'
]);

Check Auth Without Redirect

// Check authentication status without redirecting
export const getServerSideProps = auth.getServerSideProps.checkAuth(
  async (context) => {
    // context.user might be null
    return {
      props: {
        isAuthenticated: !!context.user
      }
    };
  }
);

Protecting API Routes

Basic Authentication

// pages/api/profile.ts
export default auth.withAuth(async (req, res) => {
  // req.user is available
  res.json({ user: req.user });
});

Permission-Based Protection

// Single permission
export default auth.withPermission('posts:create')(
  async (req, res) => {
    // User has permission
    const post = await createPost(req.body);
    res.json(post);
  }
);

// Multiple permissions
export default auth.withAnyPermission(['posts:edit', 'posts:admin'])(
  async (req, res) => {
    // User has at least one permission
  }
);

Composed Middleware

// Combine multiple middlewares
const handler = async (req, res) => {
  res.json({ success: true });
};

export default auth.middleware.compose(
  auth.withAuth,
  auth.withPermission('admin:access')
)(handler);

App Router

Setup Middleware

// middleware.ts
import { createAuthMiddleware, authMiddlewareConfig } from '@auth-service/nextjs-sdk';

export const middleware = createAuthMiddleware({
  authServiceUrl: process.env.NEXT_PUBLIC_AUTH_SERVICE_URL!,
  appId: process.env.NEXT_PUBLIC_APP_ID!,
  cookieName: 'auth-token',
  loginUrl: '/login'
});

export const config = authMiddlewareConfig({
  protected: ['/dashboard', '/admin'],
  public: ['/login', '/signup']
});

Server Components

// lib/auth-app.ts
import { createAppRouterAuth } from '@auth-service/nextjs-sdk';

export const auth = createAppRouterAuth({
  authServiceUrl: process.env.AUTH_SERVICE_URL!,
  appId: process.env.APP_ID!,
  appSecret: process.env.APP_SECRET!
});

Protected Pages

// app/dashboard/page.tsx
import { auth } from '@/lib/auth-app';

export default async function Dashboard() {
  const user = await auth.requireAuth();
  
  return (
    <div>
      <h1>Welcome {user.id}</h1>
    </div>
  );
}

Permission-Based Pages

// app/admin/page.tsx
import { auth } from '@/lib/auth-app';

export default async function AdminPage() {
  const user = await auth.requirePermission('admin:access');
  
  return (
    <div>
      <h1>Admin Dashboard</h1>
    </div>
  );
}

Conditional Rendering

// app/posts/page.tsx
import { auth } from '@/lib/auth-app';

export default async function Posts() {
  const user = await auth.getCurrentUser();
  const canCreate = user ? await auth.hasPermission('posts:create') : false;
  
  return (
    <div>
      {canCreate && (
        <button>Create Post</button>
      )}
    </div>
  );
}

Server Actions

// app/actions/posts.ts
'use server';

import { auth } from '@/lib/auth-app';

// Protected server action
export const createPost = auth.withPermission('posts:create', 
  async (user, data: FormData) => {
    const title = data.get('title');
    // User is authenticated and has permission
    const post = await db.post.create({
      data: {
        title,
        authorId: user.id
      }
    });
    return post;
  }
);

Client-Side Components

Permission Guard

import { PermissionGuard } from '@auth-service/nextjs-sdk';

export function PostActions({ postId }) {
  return (
    <>
      <PermissionGuard permission="posts:edit">
        <button>Edit Post</button>
      </PermissionGuard>
      
      <PermissionGuard 
        permission="posts:delete"
        fallback={<span>No delete permission</span>}
      >
        <button>Delete Post</button>
      </PermissionGuard>
    </>
  );
}

Authentication Components

import { 
  RequireAuth, 
  AuthOnly, 
  GuestOnly,
  UserInfo 
} from '@auth-service/nextjs-sdk';

export function Header() {
  return (
    <header>
      <GuestOnly>
        <Link href="/login">Login</Link>
      </GuestOnly>
      
      <AuthOnly>
        <UserInfo showEmail showRoles />
        <Link href="/logout">Logout</Link>
      </AuthOnly>
    </header>
  );
}

// Protect entire page
export function ProtectedPage() {
  return (
    <RequireAuth redirectTo="/login">
      <div>Protected content</div>
    </RequireAuth>
  );
}

Hooks

import { useNextAuth } from '@auth-service/nextjs-sdk';

export function UserProfile() {
  const { 
    user, 
    loading, 
    error,
    hasPermission,
    hasRole,
    checkPermission,
    refreshPermissions
  } = useNextAuth();
  
  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
  if (!user) return <div>Not authenticated</div>;
  
  return (
    <div>
      <h1>{user.email}</h1>
      {hasPermission('posts:create') && (
        <button>Create Post</button>
      )}
      {hasRole('admin') && (
        <Link href="/admin">Admin Panel</Link>
      )}
    </div>
  );
}

Advanced Usage

Custom Token Extraction

// For API routes with custom token location
const handler = async (req, res) => {
  const token = req.headers['x-custom-token'];
  // Manual verification
  const user = await auth.server.getUserFromToken(token);
  res.json({ user });
};

Session Management

// Set custom auth cookie
auth.setAuthCookie(res, token, maxAge);

// Clear auth cookie (logout)
auth.clearAuthCookie(res);

Error Handling

import { AuthServiceError, TokenError, PermissionError } from '@auth-service/nextjs-sdk';

// API route error handling
export default auth.withAuth(async (req, res) => {
  try {
    // Your logic
  } catch (error) {
    if (error instanceof TokenError) {
      res.status(401).json({ error: 'Invalid token' });
    } else if (error instanceof PermissionError) {
      res.status(403).json({ error: 'Permission denied' });
    } else {
      res.status(500).json({ error: 'Internal error' });
    }
  }
});

Configuration Options

const auth = createAuth({
  // Required
  authServiceUrl: 'https://auth.example.com',
  appId: 'your-app-id',
  appSecret: 'your-app-secret',
  
  // Cookie options
  cookieName: 'auth-token',          // default: 'auth-token'
  cookieDomain: '.example.com',      // optional
  cookieSecure: true,                // default: true in production
  cookieHttpOnly: true,              // default: true
  cookieSameSite: 'lax',            // default: 'lax'
  cookiePath: '/',                   // default: '/'
  
  // Redirect options
  loginUrl: '/login',                // default: '/login'
  unauthorizedUrl: '/unauthorized',  // default: '/unauthorized'
  redirectOnError: true,             // default: true
  
  // Backend SDK options (inherited)
  cacheEnabled: true,                // default: true
  cacheTTL: 60,                     // default: 60 seconds
  timeout: 10000,                   // default: 10000ms
  retryAttempts: 3,                 // default: 3
});

Best Practices

  1. Environment Variables: Keep appSecret server-side only
  2. Error Boundaries: Wrap auth components in error boundaries
  3. Loading States: Always handle loading states in client components
  4. Permission Naming: Use consistent resource:action format
  5. Cache Wisely: Balance performance with data freshness
  6. Type Safety: Leverage TypeScript for better DX

Migration Guide

From Pages to App Router

// Pages Router
export const getServerSideProps = auth.getServerSideProps.withAuth();

// App Router
const user = await auth.requireAuth();

From Client-Side to Server-Side

// Client-side check
const { hasPermission } = useNextAuth();
if (hasPermission('posts:create')) { }

// Server-side check
const canCreate = await auth.hasPermission('posts:create');
if (canCreate) { }

TypeScript Support

Full TypeScript support with type inference:

import { NextApiRequestWithAuth } from '@auth-service/nextjs-sdk';

export default auth.withAuth(async (req: NextApiRequestWithAuth, res) => {
  // req.user is fully typed
  const userId = req.user.id;
  const permissions = req.user.permissions;
});

License

MIT