Netpress Laravel-inspired backend framework for Node.js
Frameworkv0.1.14 Starterv0.1.12 Docsv1.0.3
Overview Installation Architecture CLI
Features

Authentication

Authentication answers one question:

Who is the current user for this request?

Netpress handles that in core through auth guards. The starter ships with two named guards:

  • web for signed-cookie session auth on server-rendered routes
  • api for JWT bearer tokens on API routes

That split is deliberate. The web guard stays ergonomic for forms and redirects. The API guard stays stateless for clients and mobile apps.

Guard Split

Netpress treats the two guards differently on purpose:

  • web uses encrypted cookies, a lazy session, and CSRF protection
  • api uses Authorization: Bearer <token> only
  • web routes may render pages and redirect with flash data
  • api routes never mount session or CSRF middleware

If you keep that split, auth stays predictable.

Core Guard API

import { Auth } from "@admicaa/netpress";

Auth.extend("admin", adminGuard);

await Auth.user(req);
await Auth.user(req, { guard: "web" });
await Auth.authenticate(req, { guard: "api" });

router.group(Auth.middleware("api"), (router) => {
  router.get("/me", AuthController.me);
});

Core auth gives you:

  • Auth.extend(name, guard) to register a guard
  • Auth.guard(name) to work with one named guard
  • Auth.user(req, { guard }) to resolve the current user
  • Auth.authenticate(req, { guard }) to require authentication
  • Auth.middleware(name) to protect routes
  • Auth.guest(name) for guest-only routes
  • Auth.currentGuard(req) to inspect the active guard

Starter Defaults

The starter keeps auth explicit:

  • app/Providers/AuthServiceProvider.js registers web and api
  • app/Services/Auth/SessionGuard.js powers the web guard
  • app/Services/Auth/JwtGuard.js powers the api guard
  • config/cookies.js controls cookie encryption and XSRF defaults
  • app/Http/Middleware/auth.js is Auth.middleware("api")
  • app/Http/Middleware/resolveWebUser.js resolves the web guard for views

The route stacks are also separate:

  • routes/web.js mounts cookie encryption, session, shared view state, current-user resolution, and CSRF
  • routes/api.js stays stateless

Lazy Sessions

The starter mounts the session middleware on the web route stack only.

  • guest requests do not start a session just because a route is in the web stack
  • the cookie is only parsed when a request actually needs session data
  • flashed view state only loads the session when a session cookie already exists
  • requests that never touch session state do not emit Set-Cookie
  • routes that call req.csrfToken() intentionally start a session because the token is session-backed
  • API routes never receive req.session

That keeps browser auth ergonomic without letting API traffic accidentally turn stateful.

The starter mounts an EncryptCookies-style middleware on the web stack. By default:

  • every cookie is encrypted with APP_KEY
  • normal cookies use httpOnly, sameSite, path, and secure defaults from config/cookies.js
  • XSRF-TOKEN is excluded from encryption so browser JavaScript can read it
  • the web guard session cookie is encrypted automatically

The default config looks like this:

export default {
  encrypt: true,
  except: ["XSRF-TOKEN"],
  httpOnly: true,
  secure: process.env.APP_ENV === "production",
  sameSite: "lax",
  xsrf: {
    enabled: true,
    cookie: "XSRF-TOKEN",
    field: "_token",
    header: "x-xsrf-token",
  },
};

For server-rendered forms:

class SessionsController {
  create(req, res) {
    req.csrfToken();

    return res.render(LoginPage);
  }
}

That gives the view a csrfToken prop and sends the browser-readable XSRF-TOKEN cookie. Forms then post the hidden _token field. JavaScript clients can instead reflect the cookie through the X-XSRF-TOKEN header.

CSRF protection is a web-only concern in the starter. It is not mounted on routes/api.js.

JWT Flow

The starter api guard:

  • verifies bearer tokens against config/auth.js
  • rejects refresh tokens on access-protected routes
  • respects issuer, audience, and clock tolerance when configured
  • checks the cache-based blacklist on logout
  • does not use cookies or sessions
  • ignores browser session cookies entirely

AuthService owns token issuing, refresh-token rotation, and password-reset cleanup so controllers stay thin.

Web Auth Pages

The starter also ships server-rendered auth pages:

  • /login
  • /register
  • /forgot-password
  • /reset-password/:token

To republish them for a different renderer or UI stack:

npm run artisan -- setup:auth
npm run artisan -- setup:auth --web react --ui tailwind
npm run artisan -- setup:auth --web vue --ui bootstrap

setup:auth writes the auth layouts and page components for the selected renderer. setup:rendering can also keep the auth views aligned when you switch the web engine.

Authentication In Views

Server-rendered views receive auth helpers automatically when the web guard is enabled:

  • auth.user
  • auth.guard
  • auth.check
  • csrfToken when the controller requested one through req.csrfToken()
  • Auth.user()
  • Auth.check()
  • can()

Auth.user() is synchronous in the template because the current user was already resolved by middleware. can() is still async because policies or permission checks may hit storage, so resolve permission booleans in the controller when a template needs branching.

Authentication vs Authorization

Authentication identifies the user.

Authorization decides what that user may do.

Use core policies and can() for authorization. If you need roles, permissions, morph assignments, and route middleware similar to Laravel Permission, use NetPress Permissions.

Next, read Authorization.