br-auth-middleware
Configure Better Route 1.1 authentication with JWT, custom bearer tokens, WordPress Application Passwords, or cookie nonces. Use when protecting routes, mapping verified claims to WordPress users, enforcing scopes, or consuming the shared AuthContext identity.
Install
npx skills add https://github.com/Lonsdale201/wp-agent-skills/tree/main/better-route/br-auth-middleware
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install lonsdale201-wp-agent-skills@llmmart
git clone https://github.com/Lonsdale201/wp-agent-skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole lonsdale201/wp-agent-skills collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Better Route authentication middleware
Select authentication by client type, attach it as middleware, and mark every raw route as middleware-protected. Better Route 1.1 denies every raw route by default, including GET and OPTIONS.
use BetterRoute\Middleware\Jwt\Hs256JwtVerifier;
use BetterRoute\Middleware\Jwt\JwtAuthMiddleware;
$auth = new JwtAuthMiddleware(
verifier: new Hs256JwtVerifier(
secret: MY_PLUGIN_JWT_SECRET,
expectedIssuer: 'https://issuer.example',
expectedAudience: 'my-api',
maxLifetimeSeconds: 3600
),
requiredScopes: ['orders:read']
);
$router->get('/orders/(?P<id>\d+)', $handler)
->middleware([$auth])
->protectedByMiddleware('bearerAuth');
Choose the middleware
- Use
JwtAuthMiddlewarewithHs256JwtVerifierfor first-party HS256 tokens. - Use
BearerTokenAuthMiddlewarewithJwtBearerTokenVerifierAdapterandRs256JwksJwtVerifierfor RS256/ES256 JWKS tokens. Followbr-jwks-jwt-auth. - Use
BearerTokenAuthMiddlewarewith a customBearerTokenVerifierInterfacefor opaque or externally verified bearer tokens. - Use
ApplicationPasswordAuthMiddlewarefor server-to-server WordPress Application Password Basic authentication. - Use
CookieNonceAuthMiddlewarefor same-site browser requests with a logged-in WordPress cookie andX-WP-Nonce. Keep bothrequireNonceandrequireLoggedInenabled unless a separately reviewed design requires otherwise.
protectedByMiddleware() tells the WordPress permission callback to let the request reach the middleware pipeline. It does not add authentication by itself: the authentication middleware must also be attached. The optional name describes the OpenAPI security scheme.
JWT verification rules
expis required by default. Do not disablerequireExpirationfor normal production tokens.- When
maxLifetimeSecondsis set, bothiatandexpare required andexp - iatmust not exceed the limit. - Set
expectedIssuerandexpectedAudiencein production. - Keep
maxTokenLengthbounded; the default is 8192 bytes. - Required-scope wildcards are server-controlled. A token-supplied granted scope ending in
*expands authority only whenallowGrantedScopeWildcards: true; keep that opt-in off unless the issuer contract requires it.
WordPress user mapping
WpClaimsUserMapper defaults to numeric user_id, uid, and wp_user_id claims. It deliberately does not interpret sub as a WordPress user ID and leaves email/login lookup disabled.
Prefer an issuer-scoped custom sub resolver. If email mapping is unavoidable, explicitly pass emailClaims and retain requireEmailVerified: true. Enable login-name mapping only for a fully controlled issuer. A mapped positive user ID becomes the native WordPress current user only during downstream execution (1.1.1).
Native user scope in 1.1.1
JWT, Bearer and Application Password middleware restore the previous WP user in finally, including exceptions. Nested calls unwind in reverse order. A verified JWT/Bearer identity without a positive WP mapping runs downstream as native user 0, never as an unrelated ambient user.
If you supply setCurrentUser, pair it with the appended optional getCurrentUser callback for the same identity store. The default getter calls get_current_user_id() or returns 0 outside WordPress. Previous constructor positions are unchanged.
WordPress permission callbacks run before middleware. Check middleware-established identity inside the downstream pipeline. Later rest_request_after_callbacks, rest_post_dispatch and _embed see the restored caller; use native WordPress request authentication when those phases need an authenticated user. Do not bypass permission checks or leave a global user set.
Shared identity
Successful built-in authentication writes a normalized identity into RequestContext::$attributes['auth'] with provider, userId, subject, and scopes. JWT/bearer claims and useful user fields are exposed through other context attributes. Ownership guards, rate-limit identity selection, and audit enrichment consume this shared contract; do not invent a parallel identity attribute.
Since 1.1.1, AuthContext::withIdentity() always replaces userId, user, claims and scopes, including null/empty values. Do not treat attribute presence alone as proof of a mapped user.
Checks
- Verify mapped/unmapped identities, nested success/exception restoration, and the restored caller in response filters and embedding.
- Test missing, malformed, expired, future, wrong-issuer, wrong-audience, and over-lifetime tokens.
- Test every missing required scope and ensure a token-provided wildcard cannot widen authority unexpectedly.
- Test routes without
protectedByMiddleware()fail closed. - Never log bearer tokens, Basic credentials, cookies, nonces, or complete claims payloads.
Source references: src/Middleware/Jwt/*, src/Middleware/Auth/*, src/Router/RouteBuilder.php.
References
- Official documentation: https://lonsdale201.github.io/better-docs/docs/better-route/agents
Files (wp-agent-skills)
-
agents
-
openai.yaml 271 B
interface: display_name: "Better Route Auth Middleware" short_description: "Configure auth and scoped WordPress user identity." default_prompt: "Use $br-auth-middleware to configure authentication and verify native user restoration and response-filter boundaries."
-
-
SKILL.md 5.6 KB
--- name: br-auth-middleware description: Configure Better Route 1.1 authentication with JWT, custom bearer tokens, WordPress Application Passwords, or cookie nonces. Use when protecting routes, mapping verified claims to WordPress users, enforcing scopes, consuming the shared AuthContext identity, restoring native users after nested dispatch, or diagnosing response-filter/_embed auth boundaries. metadata: wp-skills-author: "Soczó Kristóf" wp-skills-contact: "mailto:lonsdale201@hotmail.com" wp-skills-plugin: "better-route" wp-skills-plugin-version-tested: "1.1.1" wp-skills-php-min: "8.1" wp-skills-last-updated: "2026-09-21" --- # Better Route authentication middleware Select authentication by client type, attach it as middleware, and mark every raw route as middleware-protected. Better Route 1.1 denies every raw route by default, including `GET` and `OPTIONS`. ```php use BetterRoute\Middleware\Jwt\Hs256JwtVerifier; use BetterRoute\Middleware\Jwt\JwtAuthMiddleware; $auth = new JwtAuthMiddleware( verifier: new Hs256JwtVerifier( secret: MY_PLUGIN_JWT_SECRET, expectedIssuer: 'https://issuer.example', expectedAudience: 'my-api', maxLifetimeSeconds: 3600 ), requiredScopes: ['orders:read'] ); $router->get('/orders/(?P<id>\d+)', $handler) ->middleware([$auth]) ->protectedByMiddleware('bearerAuth'); ``` ## Choose the middleware - Use `JwtAuthMiddleware` with `Hs256JwtVerifier` for first-party HS256 tokens. - Use `BearerTokenAuthMiddleware` with `JwtBearerTokenVerifierAdapter` and `Rs256JwksJwtVerifier` for RS256/ES256 JWKS tokens. Follow `br-jwks-jwt-auth`. - Use `BearerTokenAuthMiddleware` with a custom `BearerTokenVerifierInterface` for opaque or externally verified bearer tokens. - Use `ApplicationPasswordAuthMiddleware` for server-to-server WordPress Application Password Basic authentication. - Use `CookieNonceAuthMiddleware` for same-site browser requests with a logged-in WordPress cookie and `X-WP-Nonce`. Keep both `requireNonce` and `requireLoggedIn` enabled unless a separately reviewed design requires otherwise. `protectedByMiddleware()` tells the WordPress permission callback to let the request reach the middleware pipeline. It does not add authentication by itself: the authentication middleware must also be attached. The optional name describes the OpenAPI security scheme. ## JWT verification rules - `exp` is required by default. Do not disable `requireExpiration` for normal production tokens. - When `maxLifetimeSeconds` is set, both `iat` and `exp` are required and `exp - iat` must not exceed the limit. - Set `expectedIssuer` and `expectedAudience` in production. - Keep `maxTokenLength` bounded; the default is 8192 bytes. - Required-scope wildcards are server-controlled. A token-supplied granted scope ending in `*` expands authority only when `allowGrantedScopeWildcards: true`; keep that opt-in off unless the issuer contract requires it. ## WordPress user mapping `WpClaimsUserMapper` defaults to numeric `user_id`, `uid`, and `wp_user_id` claims. It deliberately does not interpret `sub` as a WordPress user ID and leaves email/login lookup disabled. Prefer an issuer-scoped custom `sub` resolver. If email mapping is unavoidable, explicitly pass `emailClaims` and retain `requireEmailVerified: true`. Enable login-name mapping only for a fully controlled issuer. A mapped positive user ID becomes the native WordPress current user only during downstream execution (1.1.1). ## Native user scope in 1.1.1 JWT, Bearer and Application Password middleware restore the previous WP user in `finally`, including exceptions. Nested calls unwind in reverse order. A verified JWT/Bearer identity without a positive WP mapping runs downstream as native user `0`, never as an unrelated ambient user. If you supply `setCurrentUser`, pair it with the appended optional `getCurrentUser` callback for the same identity store. The default getter calls `get_current_user_id()` or returns `0` outside WordPress. Previous constructor positions are unchanged. WordPress permission callbacks run before middleware. Check middleware-established identity inside the downstream pipeline. Later `rest_request_after_callbacks`, `rest_post_dispatch` and `_embed` see the restored caller; use native WordPress request authentication when those phases need an authenticated user. Do not bypass permission checks or leave a global user set. ## Shared identity Successful built-in authentication writes a normalized identity into `RequestContext::$attributes['auth']` with `provider`, `userId`, `subject`, and `scopes`. JWT/bearer claims and useful user fields are exposed through other context attributes. Ownership guards, rate-limit identity selection, and audit enrichment consume this shared contract; do not invent a parallel identity attribute. Since 1.1.1, `AuthContext::withIdentity()` always replaces `userId`, `user`, `claims` and `scopes`, including null/empty values. Do not treat attribute presence alone as proof of a mapped user. ## Checks - Verify mapped/unmapped identities, nested success/exception restoration, and the restored caller in response filters and embedding. - Test missing, malformed, expired, future, wrong-issuer, wrong-audience, and over-lifetime tokens. - Test every missing required scope and ensure a token-provided wildcard cannot widen authority unexpectedly. - Test routes without `protectedByMiddleware()` fail closed. - Never log bearer tokens, Basic credentials, cookies, nonces, or complete claims payloads. Source references: `src/Middleware/Jwt/*`, `src/Middleware/Auth/*`, `src/Router/RouteBuilder.php`. ## References - Official documentation: <https://lonsdale201.github.io/better-docs/docs/better-route/agents>
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.