Install
$ agentstack add skill-nexadevapp-nexa-claude-skills-marketplace-setup-web-middleware ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Build Web Middleware
Instructions
Build the Next.js request interception and cross-cutting infrastructure for the project. This skill produces the infrastructure that use case implementations depend on: authentication, authorization, security headers, structured error logging, and server error tracking.
Run this skill after the entity model and Prisma migration exist (so user/role entities are available) and before implementing use cases.
Step 0: Consult Next.js Documentation
Before writing any code, use the context7 MCP server to look up the current Next.js documentation for the project's installed version (read package.json to determine the version). Query for:
- Request interception file convention — the correct file name, export name, runtime,
and configuration format for the request interception entry point (historically middleware.ts, but this may change across versions)
- Runtime constraints — which runtime the request interception layer runs in and what
APIs are available or restricted (e.g. Edge Runtime vs Node.js, Prisma availability, native module support)
- Instrumentation and error tracking — the correct file convention and exports for
global server error tracking (e.g. instrumentation.ts with onRequestError)
- Matcher/config format — how to configure which routes the interception layer applies to
Store these findings and use them throughout the remaining steps. Every file name, export name, runtime constraint, and API choice in the steps below must align with what the documentation says for the installed version — not with hardcoded assumptions.
DO NOT
- Overwrite an existing request interception file without showing the user what will change and asking for confirmation
- Hard-code secrets, tokens, or credentials (use environment variables)
- Install authentication libraries without user confirmation (e.g. next-auth, lucia, clerk) — ask the user which auth approach to use
- Use libraries incompatible with the runtime determined in Step 0
- Import Prisma Client from the request interception entry point if the runtime does not support it
- Add i18n routing unless the requirements explicitly mention internationalization
- Add rate limiting logic inside the request interception layer (use a dedicated service or external provider)
- Create feature-specific logic in the interception layer — keep it generic and cross-cutting
- Skip reading the entity model — the layer must align with the project's user/role structure
- Set security headers in both the interception entry point and
next.config.js— pick one location to avoid duplication and conflicts - Hardcode file names or runtime constraints without checking the documentation first
Nexa Rules Gate
Read and follow ${CLAUDE_PLUGIN_ROOT}/shared/readiness/NEXA_RULES_GATE.md.
Prerequisites
The following must exist before running this skill:
docs/requirements.md(from/requirements) — to identify security and auth NFRsdocs/entity_model.md(from/entity-model) — to understand user/role entitiesprisma/schema.prisma(from/prisma-migration) — to confirm user/role models exist
If any prerequisite is missing, stop and tell the user which /command to run first.
Workflow
Step 1: Gather Context
- Read
docs/requirements.mdand extract:
- Authentication requirements (login, session management, token type)
- Authorization requirements (roles, permissions, RBAC rules)
- Security NFRs (CSRF, headers, HTTPS enforcement)
- Any explicit middleware-related requirements
- Read
docs/entity_model.mdand identify:
- The User entity (or equivalent) and its fields
- Role/Permission entities and their relationship to User
- Session or Token entities if defined
- Read
prisma/schema.prismaand verify the user/role models exist - Read
package.jsonand check for existing auth libraries (next-auth,lucia,@clerk/nextjs,@supabase/ssr, etc.)
Step 2: Retrofit Detection
Check whether the project already has implemented features by scanning for existing pages, API routes, and server actions. This step determines whether the skill runs in greenfield mode (no existing features) or retrofit mode (existing code that will be affected).
2a. Scan for Existing Code
Search the codebase for:
- Pages —
app/**/page.tsxfiles (excludingapp/page.tsxif it's just a landing page) - API routes —
app/api/**/route.tsfiles - Server actions — files containing
"use server"inapp/actions/or colocated with pages - Existing request interception — check if a request interception file already exists at the project root (use the file name determined in Step 0)
- Ad-hoc auth checks — grep for patterns like
getServerSession,getSession,auth(),cookies().get,headers().get('authorization'), or manual token validation in existing code
2b. If Existing Request Interception Found
If a request interception file already exists, show the user its current content and ask:
> An existing request interception file was found. Choose how to proceed: > > 1. Extend — keep existing logic and add auth/security layers around it > 2. Replace — discard the current file and build from scratch > 3. Abort — stop and let me review the existing file first
Wait for the user to choose before proceeding.
2c. If Existing Features Found (Retrofit Mode)
If pages, API routes, or server actions exist, activate retrofit mode.
Impact analysis — for each route protection rule (from Step 3), map it against the existing routes and classify each file:
| File | Current Auth | Will Become | Impact | |-----------------------------|-------------|-----------------|------------| | app/dashboard/page.tsx | None | Authenticated | Breaking — will redirect to login | | app/api/users/route.ts | Manual check | Authenticated | Review — has ad-hoc auth, may conflict | | app/api/health/route.ts | None | Authenticated | Breaking — health check will require auth | | app/about/page.tsx | None | Public | No impact |
Present this table to the user and ask:
> Retrofit impact analysis: > > The following existing routes will be affected: > > [impact table] > > Breaking changes require updates — these routes currently work without auth > and will start redirecting or returning 403 after the interception layer is applied. > > Review items have existing ad-hoc auth that may conflict or duplicate the > new logic. > > Options: > 1. Proceed — I'll adjust the route protection rules to minimize breakage and > generate a migration checklist for the remaining changes > 2. Adjust rules — let me customize which routes stay public before proceeding > 3. Abort — let me review the existing code first
Wait for the user to choose before proceeding.
2d. Ad-hoc Auth Consolidation Plan
If existing code contains ad-hoc auth checks (from 2a), list each file and its current auth pattern:
> Existing ad-hoc auth found in these files: > > | File | Current Pattern | Recommendation | > |----------------------------|------------------------------------------|-------------------------| > | app/api/users/route.ts | getServerSession() + manual role check | Remove — interception layer handles it | > | app/actions/create-post.ts | auth() guard at top of action | Keep — server actions need explicit auth since the interception layer only covers the request | > | app/dashboard/page.tsx | redirect() if no session | Remove — interception layer redirects | > > After the interception layer is built, I will update these files as part of the migration checklist.
Important: Server actions called via fetch or form submission go through the interception layer, but server actions called directly from server components do not. For these, the explicit auth check in the action itself must be kept, not removed. Flag this distinction clearly in the consolidation plan.
2e. Generate Migration Checklist
If in retrofit mode, create a technical task following the standard TT-XXX naming convention:
- Read existing files in
docs/technical_tasks/to determine the next availableTT-XXXID (zero-padded, 3 digits — e.g. ifTT-003.mdis the highest, the next isTT-004) - Create
docs/technical_tasks/TT-XXX-middleware-retrofit.mdusing the template fromnexa-claude-core/skills/technical-task/templates/technical-task.mdwith:
- Task ID:
TT-XXX(the assigned numeric ID) - Task Name: Middleware Retrofit — Consolidate Ad-hoc Auth
- Category: Cleanup
- Goal: Adapt existing routes and server actions to use the new auth layer, removing redundant ad-hoc auth checks and updating tests
- Status: Approved
- Acceptance Criteria: one checklist item per file that needs updating, grouped by change type:
- Remove redundant auth — files where the interception layer now handles what the code did manually
- Keep explicit auth — server actions that need their own auth check
- Update tests — test files that need auth tokens/sessions added to their setup
- Review conflicts — files with auth logic that may conflict with the new behavior
- Affected Areas: every file identified in the retrofit analysis
- Dependencies: None
This checklist becomes the work plan for adapting existing code after the interception layer is in place.
Do not apply the migration changes in this skill. The checklist is implemented via /implement TT-XXX-middleware-retrofit (using the assigned ID) as a follow-up step, so each change can be reviewed individually.
Step 3: Confirm Auth Strategy with User
If an auth library is already installed in package.json, lead with it:
> I found `` in your dependencies. Should I build the interception layer around it? > > If not, choose an alternative:
If no auth library is installed, present options. Use the context7 MCP server to check which auth libraries are compatible with the runtime determined in Step 0, then present:
> Authentication strategy — choose one: > > [list options compatible with the runtime, e.g. session-based, JWT, external provider]
Wait for the user to choose before proceeding.
Step 4: Define Route Protection Rules
Ask the user to confirm or adjust the default route protection rules:
> Route protection rules (adjust as needed): > > | Pattern | Rule | > |---------------------|----------------| > | / | Public | > | /login, /signup | Public (redirect if authenticated) | > | /api/auth/** | Public | > | /dashboard/** | Authenticated | > | /admin/** | Authenticated + Admin role | > | /api/** | Authenticated | > > Should I proceed with these defaults, or do you want to customize them?
Incorporate the user's adjustments.
Step 5: Build the Infrastructure
Create the files below. For every file, use the conventions determined in Step 0 (file names, export names, runtime APIs, matcher format). Consult the context7 MCP server again if you need to clarify any API or convention.
5a. Request Interception Entry Point (project root)
Create the entry point file using the correct file name and export name from Step 0. It must:
- Export the entry function and configuration using the convention from the docs
- Use the matcher/config to exclude static assets and internal Next.js routes
- Wrap the entire function body in a try/catch. On unexpected errors, log the error with full context and fail closed (redirect to login rather than letting the request through)
- Follow this composition pattern:
- Check if the route is public — if so, log at debug level, apply security headers and return
- Validate the session/token (respect runtime constraints — if DB calls are not available, validate statelessly)
- If unauthenticated on a protected route — log a warning with the path and redirect to login
- If authenticated on an auth route (login/signup) — log at debug level and redirect to dashboard
- If route requires a specific role and user lacks it — log a warning with the path, user ID, and required vs. actual roles, then return 403 or redirect
- Apply security headers to the response
- Return the response
5b. lib/auth/middleware.ts
Auth-specific helpers (must respect the runtime constraints from Step 0):
getSessionFromRequest(request)— extract and validate the session/token from the request cookie or Authorization header. Use libraries compatible with the runtime. Must never throw — catch verification errors internally, log them, and returnnullisAuthenticated(session)— check if the session is valid and not expiredhasRole(session, role)— check if the user has the required role
5c. lib/auth/constants.ts
Route and auth constants:
PUBLIC_ROUTES— array of public route patternsAUTH_ROUTES— array of auth-related routes (login, signup) that redirect when authenticatedROLE_PROTECTED_ROUTES— map of route patterns to required roles, supporting multiple roles per routeDEFAULT_LOGIN_REDIRECT— where to redirect after login (e.g./dashboard)LOGIN_PAGE— the login page path
5d. lib/auth/headers.ts
Security headers utility. Set headers only in the interception entry point — not in next.config.js — to avoid duplication and conflicts:
securityHeaders()— returns aHeadersobject with:Content-Security-Policy— start with a restrictive baseline and add a comment noting it should be tuned per projectX-Frame-Options: DENYX-Content-Type-Options: nosniffReferrer-Policy: strict-origin-when-cross-originX-DNS-Prefetch-Control: offPermissions-Policywith sensible defaults (e.g.camera=(), microphone=(), geolocation=())Strict-Transport-Security: max-age=31536000; includeSubDomains(production only — checkprocess.env.NODE_ENV)
5e. lib/auth/logger.ts
Structured logger (must respect the runtime constraints from Step 0 — use only APIs available in the determined runtime):
- Create a logger object with
debug,warn, anderrormethods - Every log message must be a structured JSON string with these fields:
timestamp— ISO 8601level—DEBUG,WARN, orERRORsource— identifies this as the request interception layerpath— the request pathmethod— the HTTP methodmessage— human-readable description of what happened- Additional context fields depending on the event (see below)
debuglevel is only emitted whenprocess.env.NODE_ENV !== 'production'to avoid noise- Define explicit log messages for each decision point:
| Event | Level | Additional Fields | |---------------------------|---------|--------------------------------------------------------| | Public route — allowed | DEBUG | — | | Auth route — redirected | DEBUG | userId, redirectTo | | Token missing | WARN | redirectTo | | Token expired | WARN | userId (if decodable), expiredAt | | Token malformed | WARN | error (the parse error message, not the token value) | | Token signature invalid | ERROR | error | | AUTH_SECRET missing | ERROR | — | | Role check failed | WARN | userId, requiredRoles, actualRoles, redirectTo | | Unexpected error
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: nexadevapp
- Source: nexadevapp/nexa-claude-skills-marketplace
- License: Apache-2.0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.