Skip to content
Draft
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
e41d1c7
Add FAPI (Fediverse Auxiliary Service Provider) support
pfefferle Oct 10, 2025
c56783a
Implement FASP registration and capability management
pfefferle Oct 10, 2025
65dbd85
Update REST route base and endpoint path
pfefferle Oct 10, 2025
6daa9b1
Fix typo in registration endpoint URL
pfefferle Oct 10, 2025
8a4ddb6
Fix REST route to include rest_base in path
pfefferle Oct 10, 2025
6d301f3
Merge branch 'trunk' into fapi
pfefferle Oct 15, 2025
1a731de
Refactor FASP registration and admin classes
pfefferle Oct 15, 2025
1889aa2
Use Activitypub signature verification for provider info
pfefferle Oct 15, 2025
30f98de
Refactor FASP to use Application RSA keypair for signing
pfefferle Oct 15, 2025
ac31c43
Refactor FASP controller to use signature helper
pfefferle Oct 15, 2025
40a1c4a
Change signature base and params methods to private
pfefferle Oct 15, 2025
f338985
Move FASP registrations admin UI to settings tab
pfefferle Oct 29, 2025
87a5dd4
Merge branch 'trunk' into fapi
pfefferle Oct 29, 2025
0e18fe6
Refactor FASP capability auth to use signature verification
pfefferle Oct 29, 2025
71f5a92
Add E2E tests for FASP controller REST API
pfefferle Oct 29, 2025
febf5e1
Enforce FASP public key fingerprint and key matching
pfefferle Oct 29, 2025
cd4e7e6
Update docs/fasp-registration.md
pfefferle Oct 29, 2025
e8995a7
Update docs/fasp-registration.md
pfefferle Oct 29, 2025
bc8f520
Update docs/fasp-registration.md
pfefferle Oct 29, 2025
1f6bcac
Merge branch 'trunk' into fapi
pfefferle Oct 29, 2025
8ce0848
Merge branch 'trunk' into fapi
pfefferle Oct 29, 2025
8ced7d6
Merge branch 'trunk' into fapi
pfefferle Oct 29, 2025
f22a49d
Merge branch 'trunk' into fapi
pfefferle Oct 29, 2025
aad5cd1
Refactor FASP registration handling and admin actions
pfefferle Oct 30, 2025
59ea57c
Update includes/class-fasp.php
pfefferle Oct 30, 2025
3eec684
Add sanitize_callback to REST API registration args
pfefferle Oct 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions activitypub.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ function rest_init() {
( new Rest\Application_Controller() )->register_routes();
( new Rest\Collections_Controller() )->register_routes();
( new Rest\Comments_Controller() )->register_routes();
( new Rest\Fasp_Controller() )->register_routes();
( new Rest\Followers_Controller() )->register_routes();
( new Rest\Following_Controller() )->register_routes();
( new Rest\Inbox_Controller() )->register_routes();
Expand Down Expand Up @@ -74,6 +75,7 @@ function plugin_init() {
\add_action( 'init', array( __NAMESPACE__ . '\Comment', 'init' ) );
\add_action( 'init', array( __NAMESPACE__ . '\Dispatcher', 'init' ) );
\add_action( 'init', array( __NAMESPACE__ . '\Embed', 'init' ) );
\add_action( 'init', array( __NAMESPACE__ . '\Fasp', 'init' ) );
\add_action( 'init', array( __NAMESPACE__ . '\Handler', 'init' ) );
\add_action( 'init', array( __NAMESPACE__ . '\Hashtag', 'init' ) );
\add_action( 'init', array( __NAMESPACE__ . '\Link', 'init' ) );
Expand Down
180 changes: 180 additions & 0 deletions docs/fasp-registration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
# FASP Registration Implementation

This document describes the WordPress ActivityPub plugin's implementation of the FASP registration specification v0.1.

## Overview

The FASP registration implementation allows external FASP providers to register with this WordPress installation to provide auxiliary services. This follows the [FASP registration specification v0.1](https://github.com/mastodon/fediverse_auxiliary_service_provider_specifications/blob/main/general/v0.1/registration.md).

## Architecture

The implementation uses WordPress options instead of custom database tables for simplicity and compatibility:

- **Registration data**: Stored in `activitypub_fasp_registrations` option
- **Capability data**: Stored in `activitypub_fasp_capabilities` option

## Components

### REST API Endpoints

#### Registration Endpoint (`POST /wp-json/activitypub/1.0/fasp/registration`)

Handles registration requests from FASP providers.

**Request format:**
```json
{
"name": "Example FASP",
"baseUrl": "https://fasp.example.com",
"serverId": "b2ks6vm8p23w",
"publicKey": "FbUJDVCftINc9FlgRu2jLagCVvOa7I2Myw8aidvkong="
}
```

**Response format:**
```json
{
"faspId": "dfkl3msw6ps3",
"publicKey": "KvVQVgD4/WcdgbUDWH7EVaYX9W7Jz5fGWt+Wg8h+YvI=",
"registrationCompletionUri": "https://example.com/wp-admin/admin.php?page=activitypub-fasp-registrations&highlight=dfkl3msw6ps3"
}
```

#### Capability Endpoints

- `POST /wp-json/activitypub/1.0/fasp/capabilities/{identifier}/{version}/activation` - Enable capability
- `DELETE /wp-json/activitypub/1.0/fasp/capabilities/{identifier}/{version}/activation` - Disable capability

### Admin Interface

The admin interface is available at **WP Admin > ActivityPub > FASP Registrations**.

Features:
- View pending registration requests
- Approve or reject registrations
- View approved registrations
- Display public key fingerprints for verification
- Manage registered FASPs

### Classes

#### `Fasp_Controller`
- Handles all FASP REST API endpoints (provider info, registration, capability activation)
- Processes registration requests
- Manages capability activation/deactivation

#### `Fasp`
- Manages registration data using WordPress options
- Provides methods for approval/rejection
- Handles capability management
- Adds FASP base URL to nodeinfo metadata

#### `Fasp_Admin`
- WordPress admin interface (in `wp-admin` folder)
- Registration management UI
- Action handlers for approve/reject/delete

## Security Features

### Server Keypair Reuse
- Reuses the application actor's RSA keypair for FASP responses
- Avoids generating per-registration key material
- Never persists private keys inside registration records

### Public Key Fingerprints
- SHA-256 fingerprints of public keys for verification
- Displayed in admin interface for manual verification
- Follows FASP specification requirements

### Nonce Protection
- All admin actions protected with WordPress nonces
- CSRF protection for registration management

## Data Storage

### Registration Data Structure
```php
array(
'fasp_id' => 'unique-fasp-id',
'name' => 'FASP Provider Name',
'base_url' => 'https://fasp.example.com',
'server_id' => 'server-id-from-fasp',
'fasp_public_key' => 'base64-encoded-public-key',
'fasp_public_key_fingerprint' => 'sha256-fingerprint-of-public-key',
'server_public_key' => 'base64-encoded-server-public-key',
'status' => 'pending|approved|rejected',
'requested_at' => 'YYYY-MM-DD HH:MM:SS',
'approved_at' => 'YYYY-MM-DD HH:MM:SS',
'approved_by' => user_id,
)
```

### Capability Data Structure
```php
array(
'fasp_id_capability_vN' => array(
'fasp_id' => 'fasp-id',
'identifier' => 'capability-name',
'version' => 1,
'enabled' => true|false,
'updated_at' => 'YYYY-MM-DD HH:MM:SS',
),
)
```

## Usage Examples

### Testing Registration
```bash
curl -X POST "https://example.com/wp-json/activitypub/1.0/registration" \
-H "Content-Type: application/json" \
-d '{
"name": "Test FASP Provider",
"baseUrl": "https://fasp.example.com",
"serverId": "test-server-123",
"publicKey": "dGVzdC1wdWJsaWMta2V5"
}'
```

### Testing Capability Activation
```bash
# Enable capability
curl -X POST "https://example.com/wp-json/activitypub/1.0/fasp/capabilities/trends/1/activation" \
-H "Authorization: Signature ..."

# Disable capability
curl -X DELETE "https://example.com/wp-json/activitypub/1.0/fasp/capabilities/trends/1/activation" \
-H "Authorization: Signature ..."
```

## Testing

Run FASP tests (including registration):
```bash
./vendor/bin/phpunit tests/phpunit/tests/includes/class-test-fasp.php
```

## Future Enhancements

1. **Ed25519 Signature Verification**: Implement proper Ed25519 signature verification for capability endpoints
2. **Webhook Notifications**: Notify FASPs when registrations are approved/rejected
3. **Capability Discovery**: Auto-discover supported capabilities from FASP providers
4. **Registration Expiry**: Implement registration expiration and renewal
5. **Audit Logging**: Log all registration and capability changes

## Compliance

This implementation follows the FASP registration specification v0.1:
- ✅ Registration endpoint (`/registration`)
- ✅ Capability activation endpoints (`/capabilities/{id}/{version}/activation`)
- ✅ Ed25519 keypair generation
- ✅ Public key fingerprint verification
- ✅ Admin interface for registration management
- ✅ Registration completion URI
- ⚠️ Ed25519 signature verification (placeholder implementation)

## References

- [FASP Registration Specification v0.1](https://github.com/mastodon/fediverse_auxiliary_service_provider_specifications/blob/main/general/v0.1/registration.md)
- [FASP Protocol Basics](https://github.com/mastodon/fediverse_auxiliary_service_provider_specifications/blob/main/general/v0.1/protocol_basics.md)
- [Ed25519 Signature Specification](https://tools.ietf.org/html/rfc8032)
135 changes: 135 additions & 0 deletions docs/fasp-signatures.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# FASP Signature Handling Implementation

## Overview

The FASP controller now implements proper HTTP Message Signatures (RFC-9421) for both request authentication and response signing, matching the existing ActivityPub signature infrastructure.

## Request Authentication

### Implementation
```php
public function authenticate_request( $request ) {
// Use the same signature verification as other ActivityPub endpoints
return \Activitypub\Rest\Server::verify_signature( $request );
}
```

### How it Works
1. **Delegates to Server::verify_signature()** - Uses the same authentication as inbox and other ActivityPub endpoints
2. **Signature Verification** - Validates HTTP Message Signatures using either:
- RFC-9421 (HTTP Message Signatures) - Modern standard
- Draft Cavage signatures - Legacy fallback
3. **Key Lookup** - Retrieves public keys from `Remote_Actors` collection using keyid
4. **Content Validation** - Verifies content-digest headers against request body
5. **Timestamp Checks** - Validates created/expires parameters to prevent replay attacks

### Authentication Flow
```
Request → Server::verify_signature() → Signature::verify_http_signature() →
HTTP_Message_Signature::verify() → Public key lookup → Signature validation
```

## Response Signing

### Implementation
```php
private function sign_response( $response, $content ) {
// Create signature components for response
$components = array(
'"@status"' => (string) $response->get_status(),
'"content-digest"' => $response->get_headers()['Content-Digest'] ?? '',
);

// Sign using blog actor's private key
$signature_base = $this->build_signature_base( $components, $params );
\openssl_sign( $signature_base, $signature, $private_key, \OPENSSL_ALGO_SHA256 );

// Add signature headers
$response->header( 'Signature-Input', 'fasp=(' . $identifiers . ')' . $params );
$response->header( 'Signature', 'fasp=:' . $signature_b64 . ':' );
}
```

### How it Works
1. **Uses Blog Actor** - Signs responses with the blog/application actor's private key
2. **RFC-9421 Components** - Signs `@status` and `content-digest` components
3. **Signature Headers** - Adds proper `Signature-Input` and `Signature` headers
4. **Error Handling** - Gracefully fails without breaking responses

## Signature Verification Process

### Incoming Request Verification
1. **Header Parsing** - Extracts `Signature-Input` and `Signature` headers
2. **Component Extraction** - Gets signed components (@method, @target-uri, content-digest)
3. **Key Retrieval** - Looks up public key using keyid parameter
4. **Signature Base** - Rebuilds signature base string per RFC-9421
5. **Cryptographic Verification** - Uses OpenSSL to verify signature
6. **Timestamp Validation** - Checks created/expires parameters

### Response Signing Process
1. **Component Selection** - Signs @status and content-digest for responses
2. **Key Access** - Uses blog actor's private key for signing
3. **Base String Creation** - Follows RFC-9421 signature base format
4. **Signing** - Uses RSA-SHA256 with OpenSSL
5. **Header Addition** - Adds structured signature headers

## Security Features

### Content Integrity
- **Content-Digest**: SHA-256 hash of request/response body
- **Signature Coverage**: Includes digest in signed components
- **Tamper Detection**: Any modification invalidates signature

### Temporal Security
- **Created Parameter**: Timestamp when signature was created
- **Expires Parameter**: Optional expiration time
- **Clock Skew**: Allows reasonable time drift between servers
- **Replay Protection**: Prevents old signatures from being reused

### Key Management
- **KeyId Parameter**: Identifies which key to use for verification
- **Public Key Lookup**: Retrieves keys from remote actor profiles
- **Key Caching**: Remote actors cached for performance
- **Key Rotation**: Supports key updates through actor profile changes

## FASP Specification Compliance

### Required Features ✅
- **Provider Info Endpoint**: Properly authenticated with signatures
- **Content-Digest Headers**: SHA-256 integrity protection
- **HTTP Message Signatures**: RFC-9421 compliance
- **Response Signing**: Signed responses for integrity

### Implementation Details
- **Signature Label**: Uses "fasp" as signature label for responses
- **Algorithm**: RSA-v1.5-SHA256 (same as other ActivityPub endpoints)
- **Components**: @status and content-digest for responses
- **Fallback**: Graceful degradation if signing fails

## Integration with ActivityPub Infrastructure

### Shared Components
- **Signature Class**: Uses existing `Signature::verify_http_signature()`
- **Actor Management**: Leverages `Actors` and `Remote_Actors` collections
- **HTTP Signature Classes**: Uses `Http_Message_Signature` implementation
- **Server Infrastructure**: Integrates with `Rest\Server::verify_signature()`

### Benefits
- **Consistency**: Same signature handling as inbox/outbox
- **Maintenance**: Uses tested and proven signature code
- **Performance**: Shares cached keys and verification logic
- **Standards**: RFC-9421 and draft signature support

## Testing Coverage

### Authentication Tests
- **Signature Verification**: Tests proper delegation to Server::verify_signature()
- **Error Handling**: Validates proper error responses
- **Integration**: Ensures compatibility with existing auth infrastructure

### Response Tests
- **Content-Digest**: Verifies proper digest header generation
- **Signature Headers**: Validates signature header format
- **Error Recovery**: Tests graceful failure when signing fails

This implementation makes the FASP endpoint secure and compliant with both the FASP specification and ActivityPub security standards.
Loading
Loading