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

@tidecloak/nextjs

v0.12.43

Published

TideCloak nextjs SDK

Readme

TideCloak NextJS SDK

Quick Start Template

If you're new to TideCloak, the fastest way to get started is with our official Next.js template:
@tidecloak/create-nextjs
It scaffolds a working project with authentication, middleware, and optional IAM setup - so you can start building right away.


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

Developer Walkthrough


1. Prerequisites

Before you begin, ensure you have the following:

  • Next.js:

    • App Router (recommended): Next.js 13.4 or later (for layout.tsx support)
    • Pages Router (legacy): Next.js 12 or later (for _app.tsx support)
  • React 18 or later

  • Node.js ≥18.17.0

  • A running TideCloak server you have admin control over.

  • IGA enabled realm

  • A registered client in your realm with default user contexts approved and committed

  • A valid Tidecloak adapter JSON file (e.g., tidecloakAdapter.json)

Note: Choose either the App Router or the Pages Router for your project. You only need one routing system active.

2. Install @tidecloak/nextjs

Add @tidecloak/nextjs to your project:

npm install @tidecloak/nextjs
# or
yarn add @tidecloak/nextjs

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)

Note: Installing this package automatically adds a silent-check-sso.html file to your public directory. This file is required for silent SSO checks; if it doesn’t exist, create it manually at public/silent-check-sso.html with the following content, otherwise the app will break:

<html>
  <body>
    <script>parent.postMessage(location.href, location.origin)</script>
  </body>
</html>

3. Initialize the Provider

To begin using the SDK, wrap your application with <TideCloakProvider>.

This makes authentication state, token access, and authorization tools available throughout your app. You only need to wrap once-at the top level entry point depending on which routing system you're using.


App Router

File: /app/layout.tsx

import React from 'react';
import { TideCloakProvider } from '@tidecloak/nextjs';
import adapter from '../tidecloakAdapter.json';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <TideCloakProvider config={{ ...adapter }}>
          {children}
        </TideCloakProvider>
      </body>
    </html>
  );
}

Description: This layout.tsx is used by Next.js’s App Router. It defines the root HTML structure and wraps all nested pages and layouts with TideCloakProvider, making authentication context available everywhere in the /app directory.


Pages Router

File: /pages/_app.tsx

import React from 'react';
import { TideCloakProvider } from '@tidecloak/nextjs';
import adapter from '../tidecloakAdapter.json';

function MyApp({ Component, pageProps }) {
  return (
    <TideCloakProvider config={adapter}>
      <Component {...pageProps} />
    </TideCloakProvider>
  );
}

export default MyApp;

Description: The _app.tsx file is the entry point for the Pages Router. It wraps every page component in the /pages directory with TideCloakProvider, so that authentication state and methods are accessible across all your pages.


4. Redirect URI Handling

TideCloak supports an optional redirectUri parameter. This is the URL users are sent to after login or logout.

If omitted, it defaults to:

`${window.location.origin}/auth/redirect`

If your app runs at http://localhost:3000, then by default users will be redirected to http://localhost:3000/auth/redirect after login or logout.

If that route doesn't exist in your project, you must create it or explicitly define a different redirectUri in your TideCloak config.

If you use the default, you must create a page at /auth/redirect in your app.

You can customize this URI in your provider config:

<TideCloakProvider config={{ ...adapter, redirectUri: 'https://yourapp.com/auth/callback' }}>
  {children}
</TideCloakProvider>

Example: /app/auth/redirect/page.tsx

'use client';

import { useEffect } from 'react';
import { useRouter } from 'next/navigation';
import { useTideCloak } from '@tidecloak/nextjs';

export default function RedirectPage() {
  const { authenticated, isInitializing, logout } = useTideCloak();
  const router = useRouter();

  useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    if (params.get("auth") === "failed") {
      sessionStorage.setItem("tokenExpired", "true");
      logout();
    }
  }, []);

  useEffect(() => {
    if (!isInitializing) {
      router.push(authenticated ? '/home' : '/');
    }
  }, [authenticated, isInitializing, router]);

  return (
    <div style={{
      minHeight: '100vh',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      fontSize: '1rem',
      color: '#555',
    }}>
      <p>Waiting for authentication...</p>
    </div>
  );
}

This page helps finalize the login or logout flow, and also reacts to token expiration events that may have triggered a redirect from the middleware.


4. Using the useTideCloak Hook

Use this hook anywhere in your React component tree to manage authentication:

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

export default 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. |


5. Guard Components

Use these components to conditionally render UI based on auth state:

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

export default function Dashboard() {
  return (
    <>
      <Authenticated>
        <h1>Dashboard</h1>
        {/* Protected widgets here */}
      </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

6. Encrypting & Decrypting Data

Protect sensitive payloads using tag-based encryption/decryption:

// Encrypt payloads:
const encryptedArray = await doEncrypt([
  { data: { email: '[email protected]' }, tags: ['email'] },
]);

// Decrypt blobs:
const decryptedArray = await doDecrypt([
  { encrypted: encryptedArray[0], tags: ['email'] },
]);

Important: The data property must be either a string or a Uint8Array (raw bytes).
When you encrypt a string, decryption returns a string.
When you encrypt a Uint8Array, decryption returns a Uint8Array.

Valid example:

// Before testing below, ensure you've set up the necessary roles:
const multi_encrypted_addresses = await doEncrypt([
  {
    data: "10 Smith Street",
    tags: ["street"]
  },
  {
    data: "Southport",
    tags: ["suburb"]
  },
  {
    data: "20 James Street - Burleigh Heads",
    tags: ["street", "suburb"]
  }
]);

Invalid (will fail):

// Prepare data for encryption
const dataToEncrypt = {
  title: noteData.title,
  content: noteData.content
};

// Encrypt the note data using TideCloak (this will error)
const encryptedArray = await doEncrypt([{ data: dataToEncrypt, tags: ['note'] }]);
  • Permissions: Encryption requires _tide_<tag>.selfencrypt; decryption requires _tide_<tag>.selfdecrypt.
  • Order guarantee: Output preserves input order.

7. Edge Middleware with TideCloak

Place your middleware at the project root for both routers.

File: /middleware.ts

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

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/(.*)',
  ],
  runtime: 'edge',
};

Description: The middleware.ts file runs at the Edge runtime before any page or API request. It applies authentication and role-based access control globally, using your adapter settings to verify tokens and redirect or rewrite responses as needed.


8. Server‑Side Token Verification

Pages Router

File: /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) {
  const token = req.cookies.kcToken || req.headers.authorization?.split(' ')[1] || '';
  const payload = await verifyTideCloakToken(config, token, ['user']);
  if (!payload) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  res.status(200).json({ data: 'Secure data response' });
}

App Router

File: /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) {
  const token = req.cookies.get('kcToken')?.value || '';
  const payload = await verifyTideCloakToken(config, token, ['user']);
  if (!payload) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }
  return NextResponse.json({ data: 'Secure data response' });
}

9. Advanced & Best Practices

  • Auto-Refresh: built into the provider-no manual timers.
  • Error Handling: use the initError property 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.