najm-auth 3.1.0 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -830,6 +830,85 @@ const session = await serverAuth.requireRole(['admin', 'operator']);
|
|
|
830
830
|
non-React consumers of `najm-auth` are unaffected. Importing it from a Client
|
|
831
831
|
Component or the Edge runtime fails at build time.
|
|
832
832
|
|
|
833
|
+
### `auth.ts` and `session.ts` cannot be merged
|
|
834
|
+
|
|
835
|
+
Two files looks like one too many until you try it. Both directions fail, for
|
|
836
|
+
the same reason in mirror image:
|
|
837
|
+
|
|
838
|
+
| Module | Must be reachable from | Must never be reachable from |
|
|
839
|
+
|---|---|---|
|
|
840
|
+
| the `defineAuth()` module | browser, Edge, server | — |
|
|
841
|
+
| the `createReactServerAuth()` module | server only | browser, Edge |
|
|
842
|
+
|
|
843
|
+
`auth.client` and `auth.api` are what Client Components call, and
|
|
844
|
+
`auth.middleware` is what the Edge proxy calls, so the `defineAuth()` module is
|
|
845
|
+
always in the browser and Edge graphs. The adapter must never be. Putting both
|
|
846
|
+
in one file puts the adapter everywhere `auth` already is, and the `browser`
|
|
847
|
+
export condition — which exists precisely to catch this — resolves to a module
|
|
848
|
+
that throws:
|
|
849
|
+
|
|
850
|
+
```text
|
|
851
|
+
The export createReactServerAuth was not found in module
|
|
852
|
+
…/najm-auth/dist/client/server/reactClientGuard.js [app-client]
|
|
853
|
+
|
|
854
|
+
Import traces:
|
|
855
|
+
Middleware: ./src/lib/auth.ts → ./src/proxy.ts
|
|
856
|
+
Client Component Browser: ./src/lib/auth.ts → … → ./src/app/dashboard/page.tsx
|
|
857
|
+
Client Component SSR: ./src/lib/auth.ts → … → ./src/app/dashboard/page.tsx
|
|
858
|
+
Server Component: ./src/lib/auth.ts → ./src/lib/session.ts → layout.tsx
|
|
859
|
+
```
|
|
860
|
+
|
|
861
|
+
Renaming the files changes nothing; there simply have to be two. This is a
|
|
862
|
+
property of the runtime boundary, not of the package.
|
|
863
|
+
|
|
864
|
+
### Protected trees must opt out of prerendering
|
|
865
|
+
|
|
866
|
+
`requireSession()` reads a per-request cookie. A route Next.js tries to
|
|
867
|
+
prerender has no request, so the read fails and the guard reports a
|
|
868
|
+
configuration error — correct behavior, wrong context. Mark the protected
|
|
869
|
+
segment dynamic:
|
|
870
|
+
|
|
871
|
+
```tsx
|
|
872
|
+
// src/app/(dashboard)/layout.tsx
|
|
873
|
+
export const dynamic = 'force-dynamic';
|
|
874
|
+
|
|
875
|
+
export default async function DashboardLayout({ children }) {
|
|
876
|
+
await serverAuth.requireSession();
|
|
877
|
+
return <Shell>{children}</Shell>;
|
|
878
|
+
}
|
|
879
|
+
```
|
|
880
|
+
|
|
881
|
+
`getSession()` needs no such opt-out — it returns `null` rather than throwing,
|
|
882
|
+
so a prerendered public page renders anonymous. Do not "fix" a prerender failure
|
|
883
|
+
by wrapping a strict guard in `.catch(() => null)`; that turns a real outage
|
|
884
|
+
into a silently anonymous page.
|
|
885
|
+
|
|
886
|
+
### What the app owns, what the package owns
|
|
887
|
+
|
|
888
|
+
| App, via `defineAuth()` | Package |
|
|
889
|
+
|---|---|
|
|
890
|
+
| `loginRoute`, `forbiddenRoute`, route matchers, `roleRoutes` | when to redirect where |
|
|
891
|
+
| cookie names, `apiBaseURL`, `authPrefix`, recovery URL | request memoization |
|
|
892
|
+
| `refreshThreshold`, `tabSync`, `verifyAlways` | strict vs optional semantics |
|
|
893
|
+
| — | `session.roles` / `user.role` fallback |
|
|
894
|
+
| — | error classification |
|
|
895
|
+
|
|
896
|
+
If a new app has to copy anything beyond the three files above, that logic
|
|
897
|
+
belongs in the package instead.
|
|
898
|
+
|
|
899
|
+
### What a new app must prove
|
|
900
|
+
|
|
901
|
+
At its real Next.js production boundary, not with mocks:
|
|
902
|
+
|
|
903
|
+
- two concurrent renders never observe each other's session;
|
|
904
|
+
- root layout, nested layout, and page resolve once per render — measurable by
|
|
905
|
+
counting recovery round trips;
|
|
906
|
+
- anonymous navigation to a protected route redirects to `loginRoute`;
|
|
907
|
+
- an authenticated role mismatch reaches `forbiddenRoute` without a login loop;
|
|
908
|
+
- an unset session secret or an unreachable recovery endpoint stays a visible
|
|
909
|
+
failure rather than a login redirect;
|
|
910
|
+
- the Edge/proxy bundle builds without pulling in React.
|
|
911
|
+
|
|
833
912
|
---
|
|
834
913
|
|
|
835
914
|
## TypeScript Types
|