HelloJohn / docs
SDKsNext.js SDK

Server Components

Access authentication state in Next.js Server Components and Server Actions with the HelloJohn Next.js SDK.

Server Components

Access authenticated user data in React Server Components, Server Actions, and Route Handlers without client-side JavaScript.


auth() Helper

The auth() function returns the current session from Server Components and Server Actions:

import { auth } from "@hellojohn/nextjs/server";

// In a Server Component
export default async function Dashboard() {
  const { userId, orgId } = await auth();

  if (!userId) {
    redirect("/sign-in");
  }

  return <div>User: {userId}</div>;
}

Return Value

interface AuthResult {
  userId: string | null;
  sessionId: string | null;
  orgId: string | null;
  orgRole: string | null;
  getToken: () => Promise<string | null>;  // Get access token
}

currentUser() Helper

Get the full user object in a Server Component:

import { currentUser } from "@hellojohn/nextjs/server";

export default async function ProfilePage() {
  const user = await currentUser();

  if (!user) redirect("/sign-in");

  return (
    <div>
      <h1>Hello, {user.firstName}</h1>
      <p>{user.email}</p>
    </div>
  );
}

currentUser() fetches the user from HelloJohn's API using the access token. It makes one network request per call — cache the result if you need it in multiple places.


Fetching Data with Auth

Pass the access token to downstream APIs:

import { auth } from "@hellojohn/nextjs/server";

export default async function OrdersPage() {
  const { getToken } = await auth();
  const token = await getToken();

  const orders = await fetch("https://api.yourapp.com/orders", {
    headers: {
      Authorization: `Bearer ${token}`,
    },
    next: { revalidate: 60 }, // ISR: revalidate every 60s
  }).then((r) => r.json());

  return <OrderList orders={orders} />;
}

Server Actions

Protect mutations with auth() in Server Actions:

"use server";

import { auth } from "@hellojohn/nextjs/server";

export async function updateProfile(formData: FormData) {
  const { userId } = await auth();

  if (!userId) {
    throw new Error("Not authenticated");
  }

  await db.user.update({
    where: { hellojohnId: userId },
    data: {
      bio: formData.get("bio") as string,
    },
  });

  revalidatePath("/profile");
}

Route Handlers

Protect API routes built with the App Router:

// app/api/protected/route.ts
import { auth } from "@hellojohn/nextjs/server";
import { NextResponse } from "next/server";

export async function GET() {
  const { userId } = await auth();

  if (!userId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  return NextResponse.json({ data: "secret" });
}

Caching Considerations

currentUser() and getToken() make network requests. Use Next.js caching carefully:

// Cache user data for the duration of the request
import { cache } from "react";
import { currentUser } from "@hellojohn/nextjs/server";

export const getUser = cache(async () => {
  return currentUser();
});

// Now call getUser() multiple times without extra requests

Do not cache auth state across requests — each request must independently validate the session.


On this page