permission-core Auth integration
This page explains how to bridge permission-core to VextJS Auth and its prerequisites. The external-package snippets are integration references after compatibility is confirmed, not a verified installation tutorial for the current framework. For a runnable auth flow, use the complete example in Authentication and security.
Vext separates authentication from route authorization:
auth()parses a Bearer token and fillsreq.auth.permission-coredecides authorization for resources such asinvoke + api:GET:/api/posts.- Each route keeps its final
RouteOptions.authinline or in a same-fileconst, so build indexing, runtime guards, and OpenAPI read one contract.
1. Confirm dependency compatibility first
The npm release permission-core@3.0.4, checked on 2026-09-25, declares
vextjs: 0.3.26 and monsqlize: 3.1.0 as peers; this repository uses
Vext 2.0.0 and MonSQLize 3.3.0. The upstream main branch's version
declarations are not the npm release's declarations. These numbers record a
compatibility check; they do not instruct users to pin an old Vext install.
In the application directory, check the versions actually resolved:
Only when a published upstream package declares compatible dependencies and the application's integration tests pass should you use the ordinary install command:
Do not force an install to hide a peer conflict. This page does not claim
that the conflict is resolved or that current Vext and the older
permission-core database combination has been fully verified. The security
guide provides immediately runnable identity and role protection. An external
authorization system can connect through the can returned by
auth().verify.
The current upstream API accepts a host-connected MonSQLize instance and
uses MongoDB with transaction support. It does not use the old
MemoryAdapter integration. See Database for database
preparation and the
published package information
for upstream lifecycle and API details.
2. Initialize and prepare authorization data
Use these snippets only after compatibility is confirmed. Enable the
database first and ensure app.db is available, then initialize the
authorization core. Vext owns the database connection; closing the
authorization core must not also close the host connection.
Create authorization data in an administrative workflow, not on every app
startup. The following is one-time preparation using an already initialized
core. The administrative identity and tenant come from a trusted server:
Handle administrative write results and failures according to the upstream API. Viewer only receives GET permission; POST/DELETE are not granted. Admin and editor roles also require creation and grants through an administrative workflow. Listing a role in a token does not grant it automatically. Keep resource strings identical across authorization data, routes, and dynamic checks.
3. Bridge auth() to permission-core
Fixed tokens only demonstrate identity mapping and are not JWT. A production
application must verify real credentials and obtain the tenant from trusted
identity. Providing can preserves the distinction between denial and a
provider failure.
Register the middleware name and enable OpenAPI in src/config/default.ts.
Merge this into the existing database config:
4. Declare statically projectable route guards
The route index does not execute imported or local helper functions. Keep each final guard shape in the route file as a same-file const; this makes the complete middleware, permission, security, and docs contract visible before runtime:
Keep related route constants together in their route module. Shared runtime behavior remains centralized in the permission-core-auth middleware and permission provider; the route contract itself stays statically visible.
5. Protect routes with the final option constants
Combine the two route snippets in one file. Its directory supplies the
/api/posts prefix. These handlers return authorization success only; they
do not implement post CRUD. The middleware listed in config runs only when
a route references it.
RouteOptions.auth remains the guard contract. Route-options helper calls are rejected by the finite static grammar; use an inline final object or a same-file final const. The older openapi.guardSecurityMap fallback still exists only for legacy middleware-only routes.
6. Call assert() directly in a handler
Only use an explicit handler check when an object-level dynamic decision is
needed. Put this route in the same defineRoutes callback above. The
application also needs permission data for api:GET:/api/posts/<id>:
This example's assert explicitly throws 403 when can returns false.
Provider failures continue to propagate; catching all failures and rewriting
them as denial would hide outages. A direct handler call to assert does
not pass through the Auth guard's exception conversion. If the Guard has
only an upstream assert and no can, it treats every exception as
denial; keep can when failures need to remain distinct.
7. Verify
First verify the complete application in the security guide. Then, after
dependency compatibility is confirmed and the database and authorization data
are prepared, run npm run build -- --typecheck and npm start in the
integration project. For the default port 3000:
Also verify that the request context identity snapshot excludes token,
can, and assert functions, along with cross-tenant denial, role changes,
and revocation. These are application and upstream integration checks; passing
Vext Auth tests alone does not prove them.
Related documentation
- Authentication and security: runnable Vext identity and role protection.
- Route definition: auth, static declarations, and OpenAPI contract.
- Plugins and Database: initialization, type extension, and resource ownership.
- Security and resources specification: responsibilities for authentication, authorization, and business operations.