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

@tidecloak/create-nextjs

v0.13.27

Published

Scaffold a TideCloak-ready Next.js app with optional IAM setup and working auth - start building instantly with a live example

Readme

TideCloak NextJS SDK

Jump to:


Quickstart

Secure your Next.js app with TideCloak: authentication, session management, data encryption, and edge-middleware integration all in minutes.

Developer Walkthrough

1. Prerequisites

Before you begin, ensure you have:

  • A running TideCloak server you have admin control over. No need to set anything up - just start the server.

As well as

  • Next.js 13.5.7 or later
  • React 18 or later
  • Node.js ≥18.17.0

2. Initialize the template project

[!NOTE] The initialization will prompt you to create the realm and clients on your Tidecloak server. The script will also include Tide Realm Admin creation and IGA enablement.

sudo apt update && sudo apt install -y curl jq
npm init @tidecloak/nextjs@latest my-app

2.a Project structure

my-app/
├── app
|   └── api/
|   │   └── protected/
|   │       └── route.js            <- A protected API on your NextJS server that verifies the user's access token
|   ├── auth/
|   │   └── redirect/
|   │       └── page.jsx            <- A dedicated page to redirect the user back to once authentication is complete
|   ├── home/
|   |   └── page.jsx                <- Your home page the user goes to once autenticated
|   ├── public/
│   |   └── silent-check-sso.html
|   ├── layout.jsx                  <- Entry point of your app before the user sees any actual pages
|   └── page.jsx                    <- Your login page the user is brought to when they need to authenticate
|
├── tidecloak.json                  <- Where your Tidecloak configuration sits
├── next.config.json
├── middleware.js                   <- Run on each page navigation - this is where the Tideccloak token is verified
└── package.json

3. Test your app!

npm run dev

Here it is - localhost:3000 🎉

Expanding from the template

Implementing encryption/decryption

You will first need to create the required realm roles that enable each user to encrypt/decrypt their own date of births.

[!NOTE] You have already completed the pre-requisites asked for in the documentation to set up encrypt/decrypt roles AND also set up the required client.

Set up encrypt/decrypt roles

TideCloak lets you protect sensitive fields with tag-based encryption. Pass in an array of { data, tags } objects and receive encrypted strings (or vice versa).

Syntax Overview

// Encrypt payloads:
const encryptedArray = await doEncrypt([
  { data: /* string */, tags: ['tag1', 'tag2'] },
  // …
]);

// Decrypt blobs:
const decryptedArray = await doDecrypt([
  { encrypted: /* string from doEncrypt */, tags: ['tag1', 'tag2'] },
  // …
]);

Order guarantee: the returned array matches the input order.

  • Encryption requires access token roles _tide_<tag>.selfencrypt for each tag.
  • Decryption requires access token roles _tide_<tag>.selfdecrypt for each tag.

References

This bundle provides:

  • <TideCloakProvider> - application-level context
  • useTideCloak() hook - access tokens and auth actions
  • verifyTideCloakToken() - server-side JWT verification
  • <Authenticated> / <Unauthenticated> - UI guards
  • doEncrypt() / doDecrypt() - tag-based encryption/decryption
  • createTideCloakMiddleware() - Edge middleware for route protection (supports both Pages & App routers)

Using the useTideCloak Hook

Use this hook anywhere to manage auth:

'use client'
import { useTideCloak } from '@tidecloak/nextjs';

function Header() {
  const {
    authenticated,
    login,
    logout,
    token,
    tokenExp,
    refreshToken,
    getValueFromToken,
    getValueFromIdToken,
    hasRealmRole,
    hasClientRole,
    doEncrypt,
    doDecrypt,
  } = useTideCloak();

  return (
    <header>
      {authenticated ? (
        <>
          <span>Logged in</span>
          <button onClick={logout}>Log Out</button>
        </>
      ) : (
        <button onClick={login}>Log In</button>
      )}
      {token && (
        <small>Expires at {new Date(tokenExp * 1000).toLocaleTimeString()}</small>
      )}
    </header>
  );
}

| Name | Type | Description | | ------------------------------------- | -------------------------------------------- | ----------------------------------------------------------------------- | | authenticated | boolean | Whether the user is logged in. | | login() / logout() | () => void | Trigger the login or logout flows. | | token, tokenExp | string, number | Access token and its expiration timestamp. | | Automatic token refresh | built-in | Tokens refresh silently on expiration-no manual setup needed. | | refreshToken() | () => Promise<boolean> | Force a silent token renewal. | | getValueFromToken(key) | (key: string) => any | Read a custom claim from the access token. | | getValueFromIdToken(key) | (key: string) => any | Read a custom claim from the ID token. | | hasRealmRole(role) | (role: string) => boolean | Check a realm-level role. | | hasClientRole(role, client?) | (role: string, client?: string) => boolean | Check a client-level role; defaults to your app’s client ID if omitted. | | doEncrypt(data) / doDecrypt(data) | (data: any) => Promise<any> | Encrypt or decrypt payloads via TideCloak’s built-in service. |

Guard Components

Use out-of-the-box components to show or hide content:

'use client'
import { Authenticated, Unauthenticated } from '@tidecloak/nextjs';

function Dashboard() {
  return (
    <>
      <Authenticated>
        <h1>Dashboard</h1>
        {/* Protected widgets */}
      </Authenticated>

      <Unauthenticated>
        <p>Please log in to access the dashboard.</p>
      </Unauthenticated>
    </>
  );
}
  • <Authenticated>: renders children only when authenticated === true
  • <Unauthenticated>: renders children only when authenticated === false

Route Protection with TideCloak

TideCloak provides server-side route protection for both the Pages Router and the App Router in Next.js.

Options

  • config (TidecloakConfig): Your Tidecloak adapter JSON (downloaded from your TideCloak client settings).
  • protectedRoutes (ProtectedRoutesMap): Map of path patterns to arrays of required roles.
  • onRequest(ctx: { token: string | null }, req: NextRequest) => NextResponse | voidHook before auth logic; can short-circuit by returning a NextResponse.
  • onSuccess(ctx: { payload: Record<string, any> }, req: NextRequest) => NextResponse | voidHook after successful auth & role checks; override the response by returning one.
  • onFailure(ctx: { token: string | null }, req: NextRequest) => NextResponse | voidHook when auth or role check fails; return a NextResponse to override.
  • onError(err: any, req: NextRequest) => NextResponseHook for unexpected errors in middleware logic.

Next.js 16+ (proxy.ts)

Create proxy.ts at your project root. Proxy runs on Node.js runtime.

import { NextResponse } from 'next/server';
import tidecloakConfig from './tidecloakAdapter.json';
import { createTideCloakProxy } from '@tidecloak/nextjs/server';

export const proxy = createTideCloakProxy({
  config: tidecloakConfig,
  protectedRoutes: {
    '/admin/*': ['admin'],
    '/api/private/*': ['user'],
  },
  onFailure: ({ token }, req) => NextResponse.redirect(new URL('/login', req.url)),
  onError: (err, req) => NextResponse.rewrite(new URL('/error', req.url)),
});

Important: Do NOT add export const config to proxy.ts - it's not supported and will cause errors. Proxy files always run on Node.js runtime and don't need a matcher config.

Next.js 13-15 (middleware.ts)

Create middleware.ts at your project root. Middleware runs on Edge runtime.

import { NextResponse } from 'next/server';
import tidecloakConfig from './tidecloakAdapter.json';
import { createTideCloakMiddleware } from '@tidecloak/nextjs/server';

export default createTideCloakMiddleware({
  config: tidecloakConfig,
  protectedRoutes: {
    '/admin/*': ['admin'],
    '/api/private/*': ['user'],
  },
  onFailure: ({ token }, req) => NextResponse.redirect(new URL('/login', req.url)),
  onError: (err, req) => NextResponse.rewrite(new URL('/error', req.url)),
});

export const config = {
  matcher: [
    '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico)).*)',
    '/api/(.*)',
  ],
};

Flow:

  1. Bypass any publicRoutes
  2. Read the kcToken cookie
  3. Invoke onRequest hook (if provided)
  4. Match path against protectedRoutes patterns
  5. Verify signature, issuer, and roles via verifyTideCloakToken()
  6. On success: onSuccess hook or NextResponse.next()
  7. On failure: onFailure hook or default 403 response
  8. On unexpected errors: onError hook

Server‑Side Token Verification

You can verify TideCloak-issued JWTs on your server or API routes using verifyTideCloakToken:

import { verifyTideCloakToken } from '@tidecloak/nextjs/server';

// Returns the decoded payload if valid and roles pass, otherwise null
const payload = await verifyTideCloakToken(
  config,       // Your TideCloak adapter JSON
  token,        // Raw access token to verify
  ['admin', 'user'] // Optional roles; user must have at least one
);

if (!payload) {
  // Invalid token or insufficient roles
}

Under the hood, it uses jose for cryptographic verification and key management:

import { jwtVerify, createLocalJWKSet, createRemoteJWKSet } from 'jose';

export async function verifyTideCloakToken(config, token, allowedRoles = []) {
  // Implementation checks token presence, issuer, signature,
  // authorized party (azp), and at least one allowed role.
}

Parameters:

  • config (object): Your TideCloak adapter JSON (parsed Tidecloak client adapter config).
  • token (string): Access token string to verify.
  • allowedRoles (string[], optional): Array of realm or client roles; user must have at least one.

Returns:

  • Promise<object | null>: Decoded JWT payload if valid and role check passes; otherwise null.

Example: Protecting an API Route

Protect your server-side endpoints by verifying the JWT before proceeding.

Pages Router

// pages/api/secure.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { verifyTideCloakToken } from '@tidecloak/nextjs/server';
import config from '../../tidecloakAdapter.json';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  // Extract token from cookie or Authorization header
  const token = req.cookies.kcToken || req.headers.authorization?.split(' ')[1] || '';

  // Verify signature, issuer, and roles (e.g., 'user')
  const payload = await verifyTideCloakToken(config, token, ['user']);
  if (!payload) {
    return res.status(401).json({ error: 'Unauthorized' });
  }

  // Proceed with secure logic
  res.status(200).json({ data: 'Secure data response' });
}

App Router

// app/api/secure/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { verifyTideCloakToken } from '@tidecloak/nextjs/server';
import config from '../../../tidecloakAdapter.json';

export async function GET(req: NextRequest) {
  // Extract token from cookie
  const token = req.cookies.get('kcToken')?.value || '';

  // Verify signature, issuer, and roles (e.g., 'user')
  const payload = await verifyTideCloakToken(config, token, ['user']);
  if (!payload) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }

  // Proceed with secure logic
  return NextResponse.json({ data: 'Secure data response' });
}

Advanced & Best Practices

  • Auto-Refresh: built into the provider-no manual timers.
  • Error Handling: use the initError value from useTideCloak.
  • Custom Claims: read via getValueFromToken() / getValueFromIdToken().
  • Role-Based UI: combine hooks & guard components for fine-grained control.
  • Lazy Initialization: wrap <TideCloakProvider> around only protected sections in large apps.