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:
webfor signed-cookie session auth on server-rendered routesapifor 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:
webuses encrypted cookies, a lazy session, and CSRF protectionapiusesAuthorization: Bearer <token>onlywebroutes may render pages and redirect with flash dataapiroutes 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 guardAuth.guard(name)to work with one named guardAuth.user(req, { guard })to resolve the current userAuth.authenticate(req, { guard })to require authenticationAuth.middleware(name)to protect routesAuth.guest(name)for guest-only routesAuth.currentGuard(req)to inspect the active guard
Starter Defaults
The starter keeps auth explicit:
app/Providers/AuthServiceProvider.jsregisterswebandapiapp/Services/Auth/SessionGuard.jspowers thewebguardapp/Services/Auth/JwtGuard.jspowers theapiguardconfig/cookies.jscontrols cookie encryption and XSRF defaultsapp/Http/Middleware/auth.jsisAuth.middleware("api")app/Http/Middleware/resolveWebUser.jsresolves thewebguard for views
The route stacks are also separate:
routes/web.jsmounts cookie encryption, session, shared view state, current-user resolution, and CSRFroutes/api.jsstays 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.
Cookie Encryption And XSRF
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, andsecuredefaults fromconfig/cookies.js XSRF-TOKENis excluded from encryption so browser JavaScript can read it- the
webguard 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.userauth.guardauth.checkcsrfTokenwhen the controller requested one throughreq.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.