Skip to content

Commit c39dd02

Browse files
whyisjakeclaude
andcommitted
Expand REST permission callback filter documentation
Significantly enhances the vip_block_data_api__rest_permission_callback documentation with comprehensive authentication examples and best practices. ## New Examples Added 1. **Require Publish Capability** - Using current_user_can('publish_posts') 2. **Application Password Authentication** - WordPress 5.6+ app passwords 3. **API Key Authentication** - Custom API key validation 4. **JWT Token Authentication** - Integration with JWT plugins 5. **Combine Multiple Conditions** - OR logic for auth + IP whitelist 6. **Rate Limiting for Public Access** - Throttle public requests 7. **Time-Based Access Control** - Business hours example ## Additional Content - Client-side usage examples for Application Passwords - Client-side usage examples for API Key authentication - Important caching warning callout for authenticated requests - Practical code examples for headless WordPress applications ## Key Features Covered - Application Passwords (WordPress 5.6+) - Custom API key validation - JWT token authentication - IP whitelisting - Combined authentication methods - Rate limiting strategies - Time-based access control - Caching implications on WordPress VIP These examples provide production-ready code for securing the Block Data API in various scenarios from simple authentication to complex multi-condition access. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 1abeb35 commit c39dd02

File tree

1 file changed

+167
-1
lines changed

1 file changed

+167
-1
lines changed

docs/docs/hooks/filters.md

Lines changed: 167 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,10 @@ Control who can access the REST API endpoint globally.
276276

277277
**Returns:** *(bool)* - Whether to allow access to the API
278278

279+
:::warning Important: Caching Implications
280+
Authenticated requests to the Block Data API will bypass WordPress VIP's built-in REST API caching. This can impact performance. Consider your caching strategy when requiring authentication.
281+
:::
282+
279283
**Example: Require Authentication**
280284

281285
```php
@@ -285,7 +289,17 @@ add_filter( 'vip_block_data_api__rest_permission_callback', function( $is_permit
285289
} );
286290
```
287291

288-
**Example: Require Specific Capability**
292+
**Example: Require Publish Capability**
293+
294+
```php
295+
add_filter( 'vip_block_data_api__rest_permission_callback', function( $is_permitted ) {
296+
// Require authenticated user access with 'publish_posts' permission
297+
// This is useful when combining with draft/preview access
298+
return current_user_can( 'publish_posts' );
299+
} );
300+
```
301+
302+
**Example: Require Editor or Administrator Role**
289303

290304
```php
291305
add_filter( 'vip_block_data_api__rest_permission_callback', function( $is_permitted ) {
@@ -294,17 +308,169 @@ add_filter( 'vip_block_data_api__rest_permission_callback', function( $is_permit
294308
} );
295309
```
296310

311+
**Example: Application Password Authentication**
312+
313+
```php
314+
add_filter( 'vip_block_data_api__rest_permission_callback', function( $is_permitted ) {
315+
// Requires WordPress 5.6+ with Application Passwords
316+
// Users authenticate with: username + application password
317+
318+
// Check if user is authenticated (via Application Password or cookie)
319+
if ( ! is_user_logged_in() ) {
320+
return false;
321+
}
322+
323+
// Optionally require specific capability
324+
return current_user_can( 'edit_posts' );
325+
} );
326+
```
327+
328+
**Client-Side Usage with Application Passwords:**
329+
330+
```javascript
331+
// Using Application Passwords for authentication
332+
const username = 'your-username';
333+
const applicationPassword = 'xxxx xxxx xxxx xxxx xxxx xxxx';
334+
335+
const response = await fetch(
336+
'https://example.com/wp-json/vip-block-data-api/v1/posts/123/blocks',
337+
{
338+
headers: {
339+
'Authorization': 'Basic ' + btoa(`${username}:${applicationPassword}`)
340+
}
341+
}
342+
);
343+
```
344+
345+
**Example: API Key Authentication**
346+
347+
```php
348+
add_filter( 'vip_block_data_api__rest_permission_callback', function( $is_permitted ) {
349+
// Custom API key authentication
350+
$api_key = $_SERVER['HTTP_X_API_KEY'] ?? '';
351+
352+
if ( empty( $api_key ) ) {
353+
return false;
354+
}
355+
356+
// Validate against stored keys
357+
$valid_keys = get_option( 'vip_block_api_keys', [] );
358+
359+
return in_array( $api_key, $valid_keys, true );
360+
} );
361+
```
362+
363+
**Client-Side Usage with API Key:**
364+
365+
```javascript
366+
const response = await fetch(
367+
'https://example.com/wp-json/vip-block-data-api/v1/posts/123/blocks',
368+
{
369+
headers: {
370+
'X-API-Key': 'your-api-key-here'
371+
}
372+
}
373+
);
374+
```
375+
376+
**Example: JWT Token Authentication**
377+
378+
```php
379+
add_filter( 'vip_block_data_api__rest_permission_callback', function( $is_permitted ) {
380+
// Requires JWT authentication plugin
381+
// Example: https://github.com/WP-API/jwt-authentication
382+
383+
$token = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
384+
385+
if ( empty( $token ) ) {
386+
return false;
387+
}
388+
389+
// JWT plugin handles validation
390+
// If user is authenticated via JWT, WordPress will recognize them
391+
return is_user_logged_in();
392+
} );
393+
```
394+
297395
**Example: IP Whitelist**
298396

299397
```php
300398
add_filter( 'vip_block_data_api__rest_permission_callback', function( $is_permitted ) {
399+
// Useful for internal tools or specific integrations
301400
$allowed_ips = [ '192.168.1.1', '10.0.0.1' ];
302401
$client_ip = $_SERVER['REMOTE_ADDR'] ?? '';
303402

304403
return in_array( $client_ip, $allowed_ips, true );
305404
} );
306405
```
307406

407+
**Example: Combine Multiple Conditions**
408+
409+
```php
410+
add_filter( 'vip_block_data_api__rest_permission_callback', function( $is_permitted ) {
411+
// Allow access if:
412+
// 1. User is authenticated with proper capability, OR
413+
// 2. Request comes from whitelisted IP
414+
415+
// Check for authenticated user
416+
if ( is_user_logged_in() && current_user_can( 'edit_posts' ) ) {
417+
return true;
418+
}
419+
420+
// Check for whitelisted IP
421+
$allowed_ips = [ '192.168.1.1', '10.0.0.1' ];
422+
$client_ip = $_SERVER['REMOTE_ADDR'] ?? '';
423+
424+
if ( in_array( $client_ip, $allowed_ips, true ) ) {
425+
return true;
426+
}
427+
428+
return false;
429+
} );
430+
```
431+
432+
**Example: Rate Limiting for Public Access**
433+
434+
```php
435+
add_filter( 'vip_block_data_api__rest_permission_callback', function( $is_permitted ) {
436+
// Authenticated users bypass rate limiting
437+
if ( is_user_logged_in() ) {
438+
return true;
439+
}
440+
441+
// Rate limit public requests
442+
$ip = $_SERVER['REMOTE_ADDR'] ?? '';
443+
$rate_key = "block_api_rate_{$ip}";
444+
$requests = (int) get_transient( $rate_key );
445+
446+
// Allow 100 requests per hour for public access
447+
if ( $requests >= 100 ) {
448+
return false;
449+
}
450+
451+
set_transient( $rate_key, $requests + 1, HOUR_IN_SECONDS );
452+
453+
return true;
454+
} );
455+
```
456+
457+
**Example: Time-Based Access Control**
458+
459+
```php
460+
add_filter( 'vip_block_data_api__rest_permission_callback', function( $is_permitted ) {
461+
// Only allow API access during business hours (9 AM - 5 PM EST)
462+
$hour = (int) current_time( 'H' );
463+
464+
if ( $hour < 9 || $hour >= 17 ) {
465+
// Outside business hours, require authentication
466+
return is_user_logged_in() && current_user_can( 'edit_posts' );
467+
}
468+
469+
// During business hours, allow public access
470+
return true;
471+
} );
472+
```
473+
308474
---
309475

310476
## Block Filtering

0 commit comments

Comments
 (0)