Security
Authentication
Introduction
JCC Express MVC authentication is cookie + JWT based, centered on the Authentication class and middleware exports:
auth(web/session-like protected routes)apiAuth(API bearer/cookie token protection)guest(guest-only routes)
Exported from jcc-express-mvc:
Login flow
Typical controller/login handler usage:
Auth.attempt(next):
- resolves user by
email,phone, orusername - verifies password with
verifyHash(...) - on success issues:
auth_tokencookie (access token, ~1 hour)refresh_tokencookie (~7 days)
- on failure throws
ValidationException(Invalid credentials) and forwards tonext(error)
Auth middleware behavior
auth
- reads
auth_tokencookie - verifies token type/payload
- loads user and attaches
req.user - sets
res.locals.Auth = user - if invalid/missing: clears auth cookies, stores redirect target in session, redirects to
/login
apiAuth
- reads
Authorization: Bearer <token>first, thenauth_tokencookie fallback - verifies JWT signature and access-token rules (
typmust not berefresh) - strips
exp,iat, andtypfrom the payload, then reloads the user using the remaining claims as a database lookup (for example{ id: 1 }or{ email: "user@example.com" }) - returns
401 { message: "Not authorized" }on failure - sets
req.userandreq.idon success
This pairs with model-issued tokens from User.createToken() — see Defining Model.
guest
- blocks authenticated users from guest routes
- generally redirects back/previous if token exists
Refresh and logout
Refresh
Auth.refreshToken(req, res, next) validates/rotates refresh token (jti store), reissues cookies, and rehydrates req.user.
On failure it clears cookies and returns 401.
Logout
- revokes refresh token jti if present
- clears
auth_tokenandrefresh_token - redirects to
/login
Auth helper methods
Auth.check()-> whether access cookie is valid and usableAuth.user()-> current user from requestAuth.id()-> current user id (idor_id)Auth.socialLogin(userId)-> issues auth cookies after OAuth/social flow
Route examples
API token login (apiAttempt)
For stateless API clients, use auth().apiAttempt() to validate credentials and issue a bearer token in one step:
apiAttempt options:
| Field | Default | Description |
|---|---|---|
field | "email" | Request input key to match (email, phone, username, etc.) |
model | "User" | Model name resolved via getModel() |
The request body must include the credential field and password. On success, returns { success: true, token, user, message }. On failure, returns { success: false, token: null, user: null, message: "Invalid credentials" }.
The model must have protected hasToken = true. User lookup and password verification are shared with session login via findUserForAuth().
Manual token login (createToken)
You can also issue a token manually after your own credential check:
Full createToken details: Defining Model.
Summary
- Authentication uses JWT cookies with rotating refresh tokens.
- Use
Auth.attempt(next)for cookie login,auth().apiAttempt()for API email/password + bearer token, andauth/apiAuthmiddleware for protection. - For manual API tokens, enable
hasTokenon the model and callcreateToken()—apiAuthreloads the user from JWT claims. Auth.logout()clears auth state and redirects to login.