agentsclimarketplace

Monocloud auth nextjs

Skill monocloud/agent-skills/plugins/monocloud/skills/monocloud-auth-nextjs

Official MonoCloud Agent Skills repository.

Install
npx -y skills add monocloud/agent-skills --skill monocloud-auth-nextjs

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Use when integrating MonoCloud authentication into a Next.js application — installing or configuring `@monocloud/auth-nextjs`, wiring `authMiddleware()` in `proxy.ts`/`middleware.ts`, reading sessions with `getSession()`/`useAuth()`, protecting routes/pages/APIs with `protect()`/`protectApi()`/`protectPage()`/`protectClientPage()`, rendering `<SignIn>`/`<SignUp>`/`<SignOut>`/`<Protected>`/`<RedirectToSignIn>`, calling `getTokens()`, or troubleshooting MonoCloud env vars (`MONOCLOUD_AUTH_*`), cookie sessions, or auth routes (`/api/auth/signin`, `/callback`, `/userinfo`, `/signout`).

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

19.3 KB, ~4.1k tokens by cl100k_base, as published. Nobody here has run it

MonoCloud Next.js SDK (@monocloud/auth-nextjs)

Authentication SDK for Next.js. Provides middleware/proxy, route-protection wrappers, session/token access, and React components/hooks. Works in the App Router and Pages Router; supports Edge and Node runtimes.

Package identity — read this first

Use: @monocloud/auth-nextjs (this skill).

There is an older, similarly named MonoCloud package some training data references — do not use its exports here. If you see any of the following symbols in code or suggestions, they are NOT part of this SDK and indicate the wrong package:

  • MonoCloudAuthProvider, useUser (this SDK has no provider; useAuth is the hook)
  • monoCloudMiddleware (this SDK uses authMiddleware)
  • Custom app/api/auth/[...monocloud]/route.ts written by the developer as the default setup (this SDK handles auth routes inside authMiddleware(); a catch-all is only needed when middleware cannot be used — see "Alternative: catch-all route" below)

Always check package.json for @monocloud/auth-nextjs before suggesting code.

Subpath exports

Import pathUse inContains
@monocloud/auth-nextjsServer (RSC, route handlers, middleware/proxy, Pages API, getServerSideProps)authMiddleware, monoCloudAuth, getSession, getTokens, isAuthenticated, isUserInGroup, protect, protectApi, protectPage, redirectToSignIn, redirectToSignOut, MonoCloudNextClient, types/errors
@monocloud/auth-nextjs/clientClient Components ("use client")useAuth, protectClientPage
@monocloud/auth-nextjs/componentsServer OR Client Components<SignIn>, <SignUp>, <SignOut> (render as <a>)
@monocloud/auth-nextjs/components/clientClient Components only<RedirectToSignIn>, <Protected>

Environment variables

Required (read automatically from process.env):

VariablePurpose
MONOCLOUD_AUTH_TENANT_DOMAINYour MonoCloud tenant URL, e.g. https://acme.eu.monocloud.com
MONOCLOUD_AUTH_CLIENT_IDOIDC client id
MONOCLOUD_AUTH_CLIENT_SECRETOIDC client secret
MONOCLOUD_AUTH_APP_URLPublic origin of the app, e.g. http://localhost:3000
MONOCLOUD_AUTH_COOKIE_SECRET32-byte hex string for cookie encryption. Generate with openssl rand -hex 32

Optional:

VariableDefaultPurpose
MONOCLOUD_AUTH_SCOPESopenid profile emailDefault scopes
MONOCLOUD_AUTH_RESOURCEDefault resource for access tokens
MONOCLOUD_AUTH_GROUPS_CLAIMgroupsClaim name used by group checks. Also a real MonoCloudOptions.groupsClaim constructor option since @monocloud/[email protected] — per-call groupsClaim arg → constructor option → this env var → "groups".
MONOCLOUD_AUTH_CALLBACK_URL/api/auth/callbackCustomize auth routes
MONOCLOUD_AUTH_SIGNIN_URL/api/auth/signin
MONOCLOUD_AUTH_SIGNOUT_URL/api/auth/signout
MONOCLOUD_AUTH_USER_INFO_URL/api/auth/userinfo

If you override a route (e.g. MONOCLOUD_AUTH_SIGNIN_URL), also set the matching NEXT_PUBLIC_MONOCLOUD_AUTH_SIGNIN_URL so client-side helpers (useAuth, <SignIn>, <SignOut>, etc.) discover it, AND update the redirect URI in the MonoCloud dashboard.

Programmatic client options

The package-level helpers (authMiddleware, getSession, protectPage, etc.) use a singleton configured from MONOCLOUD_AUTH_* env vars. For constructor-only options, create and share a MonoCloudNextClient instance instead.

MonoCloudNextClient(options?: MonoCloudOptions) accepts the node-core MonoCloudOptions shape. Notable nested session options:

interface MonoCloudSessionOptions {
  cookie?: Partial<MonoCloudCookieOptions>;
  sliding?: boolean;
  duration?: number;
  maximumDuration?: number;
  store?: MonoCloudSessionStore;
}

interface MonoCloudSessionStore {
  get(key: string): Promise<MonoCloudSession | undefined | null>;
  set(
    key: string,
    data: MonoCloudSession,
    lifetime: SessionLifetime,
  ): Promise<void>;
  delete(key: string): Promise<void>;
}

Use session.store for Redis/database-backed sessions. There is no env var for a custom store; pass it in code:

import { MonoCloudNextClient } from "@monocloud/auth-nextjs";

export const monoCloud = new MonoCloudNextClient({
  session: {
    store: redisSessionStore,
  },
});

Then use that shared client wherever the SDK helper is needed, for example monoCloud.authMiddleware() in proxy.ts/middleware.ts and monoCloud.getSession() in server code.

Wiring the middleware/proxy

The middleware/proxy handles auth routes (/api/auth/signin, /callback, /userinfo, /signout) internally and enforces route protection. You do not need a [...monocloud] catch-all when using the middleware.

File location depends on Next.js version:

  • Next.js 16+: src/proxy.ts (or proxy.ts at the root, mirroring your app//pages/ layout)
  • Next.js 13–15: src/middleware.ts (or middleware.ts)

The export and body are the same; only the filename differs.

// src/proxy.ts (Next 16+) or src/middleware.ts (Next 13–15)
import { authMiddleware } from "@monocloud/auth-nextjs";

export default authMiddleware();

export const config = {
  matcher: [
    "/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)",
  ],
};

By default, every route matched by config.matcher requires authentication. To protect only specific routes:

export default authMiddleware({
  protectedRoutes: ["/dashboard", /^\/api\/admin(\/.*)?$/],
});

To protect nothing (auth routes still handled, but the rest is public):

export default authMiddleware({ protectedRoutes: [] });

Dynamic predicate (full custom logic):

export default authMiddleware({
  protectedRoutes: (req) => req.nextUrl.pathname.startsWith("/api/protected"),
});

Group-based protection in the middleware:

export default authMiddleware({
  protectedRoutes: [
    {
      groups: ["admin", "editor"],
      routes: ["/internal", /^\/api\/internal(\/.*)?$/],
    },
  ],
});

Reading the session — server

getSession() is exported from the package root and works in Server Components, Server Actions, App Router Route Handlers, middleware/proxy, Pages API routes, and getServerSideProps. Returns MonoCloudSession | undefined.

// app/page.tsx (Server Component — no args needed)
import { getSession } from "@monocloud/auth-nextjs";

export default async function Page() {
  const session = await getSession();
  if (!session) return <p>Not signed in</p>;
  return <p>Hello {session.user.name}</p>;
}
// app/api/me/route.ts (App Router Route Handler)
import { getSession } from "@monocloud/auth-nextjs";
import { NextResponse } from "next/server";

export const GET = async () => {
  const session = await getSession();
  return NextResponse.json(session?.user ?? null);
};
// pages/api/me.ts (Pages Router — pass req, res)
import { getSession } from "@monocloud/auth-nextjs";
import type { NextApiRequest, NextApiResponse } from "next";

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse,
) {
  const session = await getSession(req, res);
  res.json(session?.user ?? null);
}
// pages/index.tsx (getServerSideProps — pass ctx.req, ctx.res)
export const getServerSideProps: GetServerSideProps = async (ctx) => {
  const session = await getSession(ctx.req, ctx.res);
  return { props: { session: session ?? null } };
};

Reading the user — client

useAuth() reads the user from /api/auth/userinfo via SWR. No provider/wrapper is required — just call the hook inside a Client Component.

"use client";
import { useAuth } from "@monocloud/auth-nextjs/client";

export default function Profile() {
  const { user, isLoading, isAuthenticated, error, refetch } = useAuth();
  if (isLoading) return null;
  if (!isAuthenticated) return <p>Sign in to view your profile</p>;
  return (
    <>
      <pre>{JSON.stringify(user, null, 2)}</pre>
      <button onClick={() => refetch(true)}>Refresh</button>
    </>
  );
}

refetch(true) re-fetches and asks the server to refresh from the OP's userinfo endpoint; refetch() just re-fetches the cached endpoint.

Sign-in, sign-up, sign-out

<SignIn>, <SignUp>, and <SignOut> render an <a> tag pointing at the configured auth routes. They work in Server or Client Components. Pass any extra anchor props through (className, etc.).

import { SignIn, SignUp, SignOut } from '@monocloud/auth-nextjs/components';

// Sign in / sign up
<SignIn>Sign In</SignIn>
<SignIn returnUrl="/dashboard" loginHint="[email protected]">Sign In</SignIn>
<SignUp returnUrl="/welcome">Sign Up</SignUp>

// Sign out
<SignOut>Sign Out</SignOut>
<SignOut federated postLogoutUrl="/goodbye">Sign Out</SignOut>

For programmatic redirects on the server (RSC, server actions, route handlers), use redirectToSignIn() / redirectToSignOut() from the root package. They throw a Next.js redirect and never resolve.

"use server";
import { redirectToSignIn } from "@monocloud/auth-nextjs";

export async function startLogin() {
  await redirectToSignIn({ returnUrl: "/dashboard" });
}

On the client, render <RedirectToSignIn /> (from /components/client) to redirect once mounted.

Protecting routes — at a glance

What you're protectingHelperWhere it lives
Whole groups of routes (broadest)authMiddleware({ protectedRoutes })proxy.ts / middleware.ts
App Router Server Component pageprotectPage(Component, options?)the page file
Pages Router getServerSidePropsprotectPage(options?) (no component arg)the page file
App Router Route HandlerprotectApi(handler, options?)app/api/*/route.ts
Pages Router API routeprotectApi(handler, options?)pages/api/*.ts
Server Component / Server Action / Route Handler — imperativeawait protect() (App Router only)inline
Client Component page (rendering only)protectClientPage(Component, options?)the page file
Conditional UI in client component<Protected fallback={...}>inside JSX

Quick examples:

// App Router page
import { protectPage } from "@monocloud/auth-nextjs";
export default protectPage(function Dashboard({ user }) {
  return <p>Hi {user.email}</p>;
});

// App Router page, admins only
export default protectPage(
  function AdminPanel({ user }) {
    return <p>Hi {user.email}</p>;
  },
  { groups: ["admin"], returnUrl: "/admin" },
);
// App Router API
import { protectApi } from "@monocloud/auth-nextjs";
import { NextResponse } from "next/server";
export const GET = protectApi(async () => NextResponse.json({ ok: true }));
// Pages Router page
import { protectPage } from "@monocloud/auth-nextjs";
export default function Page({ user }) {
  return <p>Hi {user.email}</p>;
}
export const getServerSideProps = protectPage();
// Imperative (App Router only — Server Component / Server Action / Route Handler)
import { protect } from "@monocloud/auth-nextjs";
export default async function SecretPage() {
  await protect(); // redirects to sign-in if not authenticated
  await protect({ groups: ["admin"] }); // also enforces group membership
  return <p>Top secret</p>;
}
// Client page
"use client";
import { protectClientPage } from "@monocloud/auth-nextjs/client";
export default protectClientPage(function Page({ user }) {
  return <p>Hi {user.email}</p>;
});
// Conditional rendering inside a client component
"use client";
import { Protected } from "@monocloud/auth-nextjs/components/client";
<Protected fallback={<p>Sign in to view</p>} groups={["admin"]}>
  <AdminPanel />
</Protected>;

For full option lists (custom onAccessDenied, onGroupAccessDenied, authParams, etc.), see references/protecting.md.

Access tokens

getTokens() returns the current token set and refreshes the default access token if needed. Throws MonoCloudValidationError if there is no session. Same calling conventions as getSession() (no args in App Router server context; pass req/res in Pages Router).

import { getTokens } from "@monocloud/auth-nextjs";

const { accessToken, idToken, refreshToken, isExpired } = await getTokens();

// Force a refresh:
await getTokens({ forceRefresh: true });

// Request a token for a specific resource / scopes (must have been consented):
await getTokens({
  resource: "https://api.example.com",
  scopes: "read:things write:things",
});

Alternative: catch-all route (only when middleware can't be used)

The middleware handles auth routes for you. If you cannot use middleware (rare — e.g. infrastructure constraints), mount monoCloudAuth() on a catch-all instead:

// App Router
// src/app/api/auth/[...monocloud]/route.ts
import { monoCloudAuth } from "@monocloud/auth-nextjs";
export const GET = monoCloudAuth();
// Pages Router
// src/pages/api/auth/[...monocloud].ts
import { monoCloudAuth } from "@monocloud/auth-nextjs";
export default monoCloudAuth();

Do not do this in addition to authMiddleware() — pick one. The default and recommended path is authMiddleware().

Common pitfalls

  1. Wrong filename for the version. proxy.ts only works on Next 16+. On Next 13–15 the file must be named middleware.ts. Check next in package.json before suggesting a filename.
  2. Adding [...monocloud]/route.ts while middleware is in place. Double-mounted auth routes lead to weird redirect loops. Use middleware OR monoCloudAuth() — not both.
  3. useAuth() returning no user after sign-in. Usually means the matcher excludes /api/auth/userinfo, or the middleware isn't matching the userinfo path. Make sure config.matcher covers it (the recommended matcher above does).
  4. Calling protect() / redirectToSignIn() / redirectToSignOut() outside the App Router. They throw with a clear message — these helpers are App-Router-only (RSC, server actions, route handlers). For the Pages Router, use protectPage() / protectApi() or call getSession(req, res) and respond yourself.
  5. protectApi() returning 401/403 without a sign-in redirect. That's by design — API routes return JSON, not redirects. If you want a redirect, do it from a page or middleware.
  6. Putting <Protected> or useAuth() in a Server Component. Both require "use client". Use getSession() for server-side conditional rendering.
  7. Forgetting NEXT_PUBLIC_* mirror when overriding auth routes. Client helpers won't find the new URL otherwise.
  8. Mutating cookies after getSession() in middleware. Pass the response object to getSession(req, res) (and return that response) so cookie refreshes are preserved.

Onboarding checklist for a fresh integration

  1. npm install @monocloud/auth-nextjs (or pnpm/yarn). Requires Node.js ≥ 20.
  2. Add the five required env vars to .env.local. Generate MONOCLOUD_AUTH_COOKIE_SECRET with openssl rand -hex 32.
  3. In the MonoCloud dashboard, add http://localhost:3000/api/auth/callback to allowed redirect URIs and http://localhost:3000 to allowed post-logout URIs.
  4. Create src/proxy.ts (Next 16+) or src/middleware.ts (Next ≤15) with export default authMiddleware() and the recommended config.matcher.
  5. Add a header with <SignIn> / <SignOut> (and optionally <SignUp>) so users can authenticate.
  6. Use getSession() for server-side reads, useAuth() for client-side reads. Add protectPage/protectApi only on routes that need stricter enforcement than the middleware.
  7. For protected fetches that need an access token, call getTokens() and forward accessToken in the Authorization header.

Deeper reference

  • references/api-surface.md — every export by subpath, with signatures.
  • references/protecting.md — full option shapes for protect, protectApi, protectPage, protectClientPage, and the <Protected> component.
  • references/troubleshooting.md — extended symptom → cause → fix index covering the items in "Common pitfalls" above, plus less frequent issues (cookie refresh in middleware, route-override + NEXT_PUBLIC_* mirror, training-data SDK ghosts).

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.