Require inbox requests to be signed by the activity actor
This commit is contained in:
parent
3c5dfa9a3d
commit
feeea74aea
@ -51,17 +51,21 @@ class PostController
|
|||||||
$object = $results[0];
|
$object = $results[0];
|
||||||
$inboxField = $object->getReferencingField( 'inbox' );
|
$inboxField = $object->getReferencingField( 'inbox' );
|
||||||
if ( $inboxField ) {
|
if ( $inboxField ) {
|
||||||
$actorWithInbox = $inboxField->getObject();
|
$activity = json_decode( $request->getContent(), true );
|
||||||
|
if ( ! $activity || ! array_key_exists( 'actor', $activity ) ) {
|
||||||
|
throw new BadRequestHttpException();
|
||||||
|
}
|
||||||
|
$activityActor = $this->getActivityActor( $activity );
|
||||||
|
if ( ! $activityActor) {
|
||||||
|
throw new BadRequestHttpException();
|
||||||
|
}
|
||||||
if ( ! $request->attributes->has( 'signed' ) ||
|
if ( ! $request->attributes->has( 'signed' ) ||
|
||||||
! $this->authorized( $request, $actorWithInbox ) ) {
|
! $this->authorized( $request, $activityActor ) ) {
|
||||||
throw new UnauthorizedHttpException(
|
throw new UnauthorizedHttpException(
|
||||||
'Signature realm="ActivityPub",headers="(request-target) host date"'
|
'Signature realm="ActivityPub",headers="(request-target) host date"'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$activity = json_decode( $request->getContent(), true );
|
$actorWithInbox = $inboxField->getObject();
|
||||||
if ( ! $activity ) {
|
|
||||||
throw new BadRequestHttpException();
|
|
||||||
}
|
|
||||||
$event = new InboxActivityEvent( $activity, $actorWithInbox, $request );
|
$event = new InboxActivityEvent( $activity, $actorWithInbox, $request );
|
||||||
$this->eventDispatcher->dispatch( InboxActivityEvent::NAME, $event );
|
$this->eventDispatcher->dispatch( InboxActivityEvent::NAME, $event );
|
||||||
return;
|
return;
|
||||||
@ -85,6 +89,17 @@ class PostController
|
|||||||
throw new MethodNotAllowedHttpException( array( Request::METHOD_GET ) );
|
throw new MethodNotAllowedHttpException( array( Request::METHOD_GET ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getActivityActor( array $activity )
|
||||||
|
{
|
||||||
|
xdebug_break();
|
||||||
|
$actor = $activity['actor'];
|
||||||
|
if ( is_array( $actor ) && array_key_exists( 'id', $actor ) ) {
|
||||||
|
return $this->objectsService->dereference( $actor['id'] );
|
||||||
|
} else if ( is_string( $actor ) ) {
|
||||||
|
return $this->objectsService->dereference( $actor );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private function authorized( Request $request, ActivityPubObject $activityActor )
|
private function authorized( Request $request, ActivityPubObject $activityActor )
|
||||||
{
|
{
|
||||||
if ( ! $request->attributes->has( 'actor' ) ) {
|
if ( ! $request->attributes->has( 'actor' ) ) {
|
||||||
|
@ -31,6 +31,9 @@ class PostControllerTest extends TestCase
|
|||||||
'id' => 'https://example.com/actor/1/outbox',
|
'id' => 'https://example.com/actor/1/outbox',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
'https://elsewhere.com/actor/1' => array(
|
||||||
|
'id' => 'https://elsewhere.com/actor/1',
|
||||||
|
),
|
||||||
);
|
);
|
||||||
const REFS = array(
|
const REFS = array(
|
||||||
'https://example.com/actor/1/inbox' => array(
|
'https://example.com/actor/1/inbox' => array(
|
||||||
@ -67,34 +70,46 @@ class PostControllerTest extends TestCase
|
|||||||
}
|
}
|
||||||
} )
|
} )
|
||||||
);
|
);
|
||||||
|
$objectsService->method( 'dereference' )->will(
|
||||||
|
$this->returnCallback( function( $id ) {
|
||||||
|
if ( array_key_exists( $id, self::OBJECTS ) ) {
|
||||||
|
return TestActivityPubObject::fromArray( self::OBJECTS[$id] );
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} )
|
||||||
|
);
|
||||||
$testCases = array(
|
$testCases = array(
|
||||||
array(
|
array(
|
||||||
'id' => 'basicInboxTest',
|
'id' => 'basicInboxTest',
|
||||||
'request' => $this->makeRequest(
|
'request' => $this->makeRequest(
|
||||||
'https://example.com/actor/1/inbox',
|
'https://example.com/actor/1/inbox',
|
||||||
Request::METHOD_POST,
|
Request::METHOD_POST,
|
||||||
'{"type": "Create"}',
|
'{"type": "Create", "actor": "https://elsewhere.com/actor/1"}',
|
||||||
array(
|
array(
|
||||||
'signed' => true,
|
'signed' => true,
|
||||||
'actor' => TestActivityPubObject::fromArray(
|
'actor' => TestActivityPubObject::fromArray(
|
||||||
self::OBJECTS['https://example.com/actor/1']
|
self::OBJECTS['https://elsewhere.com/actor/1']
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
'expectedEventName' => InboxActivityEvent::NAME,
|
'expectedEventName' => InboxActivityEvent::NAME,
|
||||||
'expectedEvent' => new InboxActivityEvent(
|
'expectedEvent' => new InboxActivityEvent(
|
||||||
array( 'type' => 'Create' ),
|
array(
|
||||||
|
'type' => 'Create',
|
||||||
|
'actor' => 'https://elsewhere.com/actor/1'
|
||||||
|
),
|
||||||
TestActivityPubObject::fromArray(
|
TestActivityPubObject::fromArray(
|
||||||
self::OBJECTS['https://example.com/actor/1']
|
self::OBJECTS['https://example.com/actor/1']
|
||||||
),
|
),
|
||||||
$this->makeRequest(
|
$this->makeRequest(
|
||||||
'https://example.com/actor/1/inbox',
|
'https://example.com/actor/1/inbox',
|
||||||
Request::METHOD_POST,
|
Request::METHOD_POST,
|
||||||
'{"type": "Create"}',
|
'{"type": "Create", "actor": "https://elsewhere.com/actor/1"}',
|
||||||
array(
|
array(
|
||||||
'signed' => true,
|
'signed' => true,
|
||||||
'actor' => TestActivityPubObject::fromArray(
|
'actor' => TestActivityPubObject::fromArray(
|
||||||
self::OBJECTS['https://example.com/actor/1']
|
self::OBJECTS['https://elsewhere.com/actor/1']
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -135,10 +150,10 @@ class PostControllerTest extends TestCase
|
|||||||
'request' => $this->makeRequest(
|
'request' => $this->makeRequest(
|
||||||
'https://example.com/actor/1/inbox',
|
'https://example.com/actor/1/inbox',
|
||||||
Request::METHOD_POST,
|
Request::METHOD_POST,
|
||||||
'{"type": "Create"}',
|
'{"type": "Create", "actor": "https://elsewhere.com/actor/1"}',
|
||||||
array(
|
array(
|
||||||
'actor' => TestActivityPubObject::fromArray(
|
'actor' => TestActivityPubObject::fromArray(
|
||||||
self::OBJECTS['https://example.com/actor/1']
|
self::OBJECTS['https://elsewhere.com/actor/1']
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@ -149,7 +164,7 @@ class PostControllerTest extends TestCase
|
|||||||
'request' => $this->makeRequest(
|
'request' => $this->makeRequest(
|
||||||
'https://example.com/actor/1/inbox',
|
'https://example.com/actor/1/inbox',
|
||||||
Request::METHOD_POST,
|
Request::METHOD_POST,
|
||||||
'{"type": "Create"}',
|
'{"type": "Create", "actor": "https://elsewhere.com/actor/1"}',
|
||||||
array()
|
array()
|
||||||
),
|
),
|
||||||
'expectedException' => UnauthorizedHttpException::class,
|
'expectedException' => UnauthorizedHttpException::class,
|
||||||
@ -159,10 +174,11 @@ class PostControllerTest extends TestCase
|
|||||||
'request' => $this->makeRequest(
|
'request' => $this->makeRequest(
|
||||||
'https://example.com/actor/notreal/inbox',
|
'https://example.com/actor/notreal/inbox',
|
||||||
Request::METHOD_POST,
|
Request::METHOD_POST,
|
||||||
'{"type": "Create"}',
|
'{"type": "Create", "actor": "https://elsewhere.com/actor/1"}',
|
||||||
array(
|
array(
|
||||||
|
'signed' => true,
|
||||||
'actor' => TestActivityPubObject::fromArray(
|
'actor' => TestActivityPubObject::fromArray(
|
||||||
self::OBJECTS['https://example.com/actor/1']
|
self::OBJECTS['https://elsewhere.com/actor/1']
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@ -175,8 +191,9 @@ class PostControllerTest extends TestCase
|
|||||||
Request::METHOD_POST,
|
Request::METHOD_POST,
|
||||||
'',
|
'',
|
||||||
array(
|
array(
|
||||||
|
'signed' => true,
|
||||||
'actor' => TestActivityPubObject::fromArray(
|
'actor' => TestActivityPubObject::fromArray(
|
||||||
self::OBJECTS['https://example.com/actor/1']
|
self::OBJECTS['https://elsewhere.com/actor/1']
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@ -189,8 +206,9 @@ class PostControllerTest extends TestCase
|
|||||||
Request::METHOD_POST,
|
Request::METHOD_POST,
|
||||||
'this is not JSON',
|
'this is not JSON',
|
||||||
array(
|
array(
|
||||||
|
'signed' => 'true',
|
||||||
'actor' => TestActivityPubObject::fromArray(
|
'actor' => TestActivityPubObject::fromArray(
|
||||||
self::OBJECTS['https://example.com/actor/1']
|
self::OBJECTS['https://elsewhere.com/actor/1']
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
Loading…
Reference in New Issue
Block a user