---
title: "@playstack/auth-next"
description: "Next.js Pages and App Router session handoff and server-side protection helpers."
tags: ["package","identity","auth","nextjs","free"]
---

{/* package-access:start */}

> **Free.** MIT licensed. Check preview availability before installing. See [package access](/docs/packages#access-policy).

{/* package-access:end */}

`@playstack/auth-next` provides explicit Pages and App Router session handoff and protection over an application-owned `@playstack/auth` service. Both bindings are structural and import no Next.js runtime.

## Install and compose

```sh
npm install @playstack/auth @playstack/auth-next
```

```ts
import { createAuthNextHelpers } from '@playstack/auth-next/pages'

export const { requireSession, withSession } = createAuthNextHelpers({
  async resolveSession(context) {
    return resolveSafeSessionView(context.req)
  },
})
```

The resolver receives the original structural Pages Router context and may use the application request/response escape hatches. Its result is validated with auth’s exact `AuthSessionView` parser before crossing the SSR boundary.

## Optional and protected pages

```ts
export const getServerSideProps = withSession(async ({ session }) => ({
  props: { title: session ? 'Dashboard' : 'Welcome' },
}))

export const getServerSideProps = requireSession(
  { redirectTo: '/login' },
  async ({ session }) => ({ props: { userId: session.user.id } }),
)
```

`withSession` passes `AuthSessionView | null` to the handler and injects the same value into successful props. `requireSession` provides a non-null session or a non-permanent same-origin redirect. Redirect and not-found results pass through unchanged.

## Configuration and contracts

| Surface                    | Properties                                                |
| -------------------------- | --------------------------------------------------------- |
| `AuthNextOptions`          | `resolveSession(context): Promise<unknown>`.              |
| `RequireSessionOptions`    | `redirectTo`, restricted to a safe same-origin path.      |
| Injected optional context  | Original context plus `session: AuthSessionView \| null`. |
| Injected protected context | Original context plus `session: AuthSessionView`.         |

Handler props may not define their own `session` key. Absolute, protocol-relative, backslash, and header-injection redirect targets are rejected. The ISO-string-only session projection can initialize `PlaystackAuthProvider` without an unauthenticated flash.

## App Router server boundaries

```tsx
import { redirect } from 'next/navigation'

import { createAppRouterAuthHelpers } from '@playstack/auth-next/app'

const auth = createAppRouterAuthHelpers({
  resolveSession: () => resolveSessionViewFromCookies(),
})

export default async function AccountPage() {
  const session = await auth.requireSession({
    redirectTo: '/login',
    onUnauthenticated: (destination) => redirect(destination ?? '/login'),
  })

  return <Account userId={session.user.id} />
}
```

`getSession()` returns a validated optional session. `requireSession()` returns an authenticated session or invokes the supplied unauthenticated policy. `withSession()` and `withRequiredSession()` wrap route handlers while preserving their original request and route-context arguments, including promised dynamic params.

| Surface                                 | Properties                                                                               |
| --------------------------------------- | ---------------------------------------------------------------------------------------- |
| `AppRouterAuthOptions`                  | `resolveSession(...args): unknown \| Promise<unknown>`.                                  |
| `AppRouterRequireSessionOptions`        | Optional same-origin `redirectTo` and an application-owned `onUnauthenticated` callback. |
| `withSession(handler)`                  | Adds `AuthSessionView \| null` before the original handler arguments.                    |
| `withRequiredSession(options, handler)` | Adds `AuthSessionView` or returns the application's unauthenticated response.            |

Without an unauthenticated policy, required access throws the stable `playstack/auth-next/unauthenticated` error. The application continues to own cookies, redirects, middleware, cache behavior, and authorization within server actions and protected operations.

## Boundary

The adapter authenticates nothing by itself and does not replace authorization inside server operations. Its router-specific entrypoints preserve the distinct lifecycle of each router while the application owns request resolution and framework behavior.

{/* package-reference:start */}

## API entry points and requirements

Reference snapshot: `@playstack/auth-next@0.1.0-beta.1`. Import only the entry point your runtime needs. Paths below are relative to the installed package; use **Go to Definition** in your editor to inspect exact parameters, return types and overloads. Do not import the declaration-file paths directly.

| Public entry point | Declaration file |
| --- | --- |
| `@playstack/auth-next` | `./dist/index.d.ts` |
| `@playstack/auth-next/app` | `./dist/app.d.ts` |
| `@playstack/auth-next/pages` | `./dist/pages.d.ts` |
| `@playstack/auth-next/errors` | `./dist/errors.d.ts` |
| `@playstack/auth-next/package.json` | No TypeScript declaration (asset or metadata export). |

Node.js engine requirement: `>=20`. This is not a claim that every entry point works in browsers or Workers.

### Peer dependencies

Keep existing framework versions that satisfy these ranges. Install optional peers only when using the corresponding adapter. The package manager resolves ordinary dependencies separately.

| Peer | Compatible range | When needed |
| --- | --- | --- |
| `@playstack/auth-contracts` | `0.1.0-beta.1` | Required by the package. |
| `@playstack/core` | `0.1.0-beta.1` | Required by the package. |

For a complete first program, start with [Getting started](/docs/getting-started). For API lookup and partial-example conventions, see [Reading the reference](/docs/packages#reading-the-reference). Provider failures, lifecycle requirements and application responsibilities remain described in the guide above; types alone do not establish production safety.

{/* package-reference:end */}
