Fix some signature and application user issues (#410)
* Fix some signature and application user issues * it seems that firefish needs at least an inbox also for application users * prepare domain change * use https * fix PHPDoc * remove image check --------- Co-authored-by: Matt Wiebe <wiebe@automattic.com>
This commit is contained in:
parent
26ad8975d7
commit
2705172b77
7 changed files with 64 additions and 47 deletions
|
@ -26,6 +26,7 @@ class Activity extends Base_Object {
|
||||||
'schema' => 'http://schema.org#',
|
'schema' => 'http://schema.org#',
|
||||||
'pt' => 'https://joinpeertube.org/ns#',
|
'pt' => 'https://joinpeertube.org/ns#',
|
||||||
'toot' => 'http://joinmastodon.org/ns#',
|
'toot' => 'http://joinmastodon.org/ns#',
|
||||||
|
'webfinger' => 'https://webfinger.net/#',
|
||||||
'litepub' => 'http://litepub.social/ns#',
|
'litepub' => 'http://litepub.social/ns#',
|
||||||
'value' => 'schema:value',
|
'value' => 'schema:value',
|
||||||
'Hashtag' => 'as:Hashtag',
|
'Hashtag' => 'as:Hashtag',
|
||||||
|
@ -37,8 +38,13 @@ class Activity extends Base_Object {
|
||||||
'@id' => 'toot:featuredTags',
|
'@id' => 'toot:featuredTags',
|
||||||
'@type' => '@id',
|
'@type' => '@id',
|
||||||
),
|
),
|
||||||
|
'alsoKnownAs' => array(
|
||||||
|
'@id' => 'as:alsoKnownAs',
|
||||||
|
'@type' => '@id',
|
||||||
|
),
|
||||||
'discoverable' => 'toot:discoverable',
|
'discoverable' => 'toot:discoverable',
|
||||||
'sensitive' => 'as:sensitive',
|
'sensitive' => 'as:sensitive',
|
||||||
|
'resource' => 'webfinger:resource',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -162,12 +162,10 @@ class Signature {
|
||||||
$route = '/' . rest_get_url_prefix() . '/' . ltrim( $request->get_route(), '/' );
|
$route = '/' . rest_get_url_prefix() . '/' . ltrim( $request->get_route(), '/' );
|
||||||
}
|
}
|
||||||
$headers = $request->get_headers();
|
$headers = $request->get_headers();
|
||||||
$actor = isset( json_decode( $request->get_body() )->actor ) ? json_decode( $request->get_body() )->actor : '';
|
|
||||||
$headers['(request-target)'][0] = strtolower( $request->get_method() ) . ' ' . $route;
|
$headers['(request-target)'][0] = strtolower( $request->get_method() ) . ' ' . $route;
|
||||||
} else {
|
} else {
|
||||||
$request = self::format_server_request( $request );
|
$request = self::format_server_request( $request );
|
||||||
$headers = $request['headers']; // $_SERVER array
|
$headers = $request['headers']; // $_SERVER array
|
||||||
$actor = null;
|
|
||||||
$headers['(request-target)'][0] = strtolower( $headers['request_method'][0] ) . ' ' . $headers['request_uri'][0];
|
$headers['(request-target)'][0] = strtolower( $headers['request_method'][0] ) . ' ' . $headers['request_uri'][0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,9 +174,9 @@ class Signature {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( array_key_exists( 'signature', $headers ) ) {
|
if ( array_key_exists( 'signature', $headers ) ) {
|
||||||
$signature_block = self::parse_signature_header( $headers['signature'] );
|
$signature_block = self::parse_signature_header( $headers['signature'][0] );
|
||||||
} elseif ( array_key_exists( 'authorization', $headers ) ) {
|
} elseif ( array_key_exists( 'authorization', $headers ) ) {
|
||||||
$signature_block = self::parse_signature_header( $headers['authorization'] );
|
$signature_block = self::parse_signature_header( $headers['authorization'][0] );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! isset( $signature_block ) || ! $signature_block ) {
|
if ( ! isset( $signature_block ) || ! $signature_block ) {
|
||||||
|
@ -217,11 +215,8 @@ class Signature {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $actor ) {
|
|
||||||
$public_key = self::get_remote_key( $actor );
|
|
||||||
} else {
|
|
||||||
$public_key = self::get_remote_key( $signature_block['keyId'] );
|
$public_key = self::get_remote_key( $signature_block['keyId'] );
|
||||||
}
|
|
||||||
if ( \is_wp_error( $public_key ) ) {
|
if ( \is_wp_error( $public_key ) ) {
|
||||||
return $public_key;
|
return $public_key;
|
||||||
}
|
}
|
||||||
|
@ -242,7 +237,7 @@ class Signature {
|
||||||
* @return string The public key.
|
* @return string The public key.
|
||||||
*/
|
*/
|
||||||
public static function get_remote_key( $key_id ) { // phpcs:ignore
|
public static function get_remote_key( $key_id ) { // phpcs:ignore
|
||||||
$actor = get_remote_metadata_by_actor( strtok( strip_fragment_from_url( $key_id ), '?' ) ); // phpcs:ignore
|
$actor = get_remote_metadata_by_actor( strip_fragment_from_url( $key_id ) ); // phpcs:ignore
|
||||||
if ( \is_wp_error( $actor ) ) {
|
if ( \is_wp_error( $actor ) ) {
|
||||||
return $actor;
|
return $actor;
|
||||||
}
|
}
|
||||||
|
@ -274,32 +269,31 @@ class Signature {
|
||||||
/**
|
/**
|
||||||
* Parses the Signature header
|
* Parses the Signature header
|
||||||
*
|
*
|
||||||
* @param array $header The signature header.
|
* @param string $signature The signature header.
|
||||||
*
|
*
|
||||||
* @return array signature parts
|
* @return array signature parts
|
||||||
*/
|
*/
|
||||||
public static function parse_signature_header( $header ) {
|
public static function parse_signature_header( $signature ) {
|
||||||
$parsed_header = array();
|
$parsed_header = array();
|
||||||
$matches = array();
|
$matches = array();
|
||||||
$h_string = \implode( ',', (array) $header[0] );
|
|
||||||
|
|
||||||
if ( \preg_match( '/keyId="(.*?)"/ism', $h_string, $matches ) ) {
|
if ( \preg_match( '/keyId="(.*?)"/ism', $signature, $matches ) ) {
|
||||||
$parsed_header['keyId'] = $matches[1];
|
$parsed_header['keyId'] = trim( $matches[1] );
|
||||||
}
|
}
|
||||||
if ( \preg_match( '/created=([0-9]*)/ism', $h_string, $matches ) ) {
|
if ( \preg_match( '/created=([0-9]*)/ism', $signature, $matches ) ) {
|
||||||
$parsed_header['(created)'] = $matches[1];
|
$parsed_header['(created)'] = trim( $matches[1] );
|
||||||
}
|
}
|
||||||
if ( \preg_match( '/expires=([0-9]*)/ism', $h_string, $matches ) ) {
|
if ( \preg_match( '/expires=([0-9]*)/ism', $signature, $matches ) ) {
|
||||||
$parsed_header['(expires)'] = $matches[1];
|
$parsed_header['(expires)'] = trim( $matches[1] );
|
||||||
}
|
}
|
||||||
if ( \preg_match( '/algorithm="(.*?)"/ism', $h_string, $matches ) ) {
|
if ( \preg_match( '/algorithm="(.*?)"/ism', $signature, $matches ) ) {
|
||||||
$parsed_header['algorithm'] = $matches[1];
|
$parsed_header['algorithm'] = trim( $matches[1] );
|
||||||
}
|
}
|
||||||
if ( \preg_match( '/headers="(.*?)"/ism', $h_string, $matches ) ) {
|
if ( \preg_match( '/headers="(.*?)"/ism', $signature, $matches ) ) {
|
||||||
$parsed_header['headers'] = \explode( ' ', $matches[1] );
|
$parsed_header['headers'] = \explode( ' ', trim( $matches[1] ) );
|
||||||
}
|
}
|
||||||
if ( \preg_match( '/signature="(.*?)"/ism', $h_string, $matches ) ) {
|
if ( \preg_match( '/signature="(.*?)"/ism', $signature, $matches ) ) {
|
||||||
$parsed_header['signature'] = \base64_decode( preg_replace( '/\s+/', '', $matches[1] ) ); // phpcs:ignore
|
$parsed_header['signature'] = \base64_decode( preg_replace( '/\s+/', '', trim( $matches[1] ) ) ); // phpcs:ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ( $parsed_header['signature'] ) && ( $parsed_header['algorithm'] ) && ( ! $parsed_header['headers'] ) ) {
|
if ( ( $parsed_header['signature'] ) && ( $parsed_header['algorithm'] ) && ( ! $parsed_header['headers'] ) ) {
|
||||||
|
@ -312,7 +306,7 @@ class Signature {
|
||||||
/**
|
/**
|
||||||
* Gets the header data from the included pseudo headers
|
* Gets the header data from the included pseudo headers
|
||||||
*
|
*
|
||||||
* @param array $signed_headers
|
* @param array $signed_headers The signed headers.
|
||||||
* @param array $signature_block (pseudo-headers)
|
* @param array $signature_block (pseudo-headers)
|
||||||
* @param array $headers (http headers)
|
* @param array $headers (http headers)
|
||||||
*
|
*
|
||||||
|
|
|
@ -22,6 +22,13 @@ class Application_User extends Blog_User {
|
||||||
*/
|
*/
|
||||||
protected $type = 'Application';
|
protected $type = 'Application';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the User is discoverable.
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
protected $discoverable = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the User-Url.
|
* Get the User-Url.
|
||||||
*
|
*
|
||||||
|
@ -35,7 +42,7 @@ class Application_User extends Blog_User {
|
||||||
return 'application';
|
return 'application';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_username() {
|
public function get_preferred_username() {
|
||||||
return $this::get_name();
|
return $this::get_name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,14 +86,6 @@ class Application_User extends Blog_User {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_inbox() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function get_outbox() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function get_followers() {
|
public function get_followers() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,13 +36,6 @@ class User extends Actor {
|
||||||
*/
|
*/
|
||||||
protected $featured;
|
protected $featured;
|
||||||
|
|
||||||
/**
|
|
||||||
* The Webfinger-style identifier.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $resource;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The User-Type
|
* The User-Type
|
||||||
*
|
*
|
||||||
|
@ -50,6 +43,20 @@ class User extends Actor {
|
||||||
*/
|
*/
|
||||||
protected $type = 'Person';
|
protected $type = 'Person';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the User is discoverable.
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
protected $discoverable = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The WebFinger Resource.
|
||||||
|
*
|
||||||
|
* @var string<url>
|
||||||
|
*/
|
||||||
|
protected $resource;
|
||||||
|
|
||||||
public static function from_wp_user( $user_id ) {
|
public static function from_wp_user( $user_id ) {
|
||||||
if ( is_user_disabled( $user_id ) ) {
|
if ( is_user_disabled( $user_id ) ) {
|
||||||
return new WP_Error(
|
return new WP_Error(
|
||||||
|
|
|
@ -171,6 +171,12 @@ class Inbox {
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ( $users as $user ) {
|
foreach ( $users as $user ) {
|
||||||
|
$user = User_Collection::get_by_various( $user );
|
||||||
|
|
||||||
|
if ( is_wp_error( $user ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$type = \strtolower( $type );
|
$type = \strtolower( $type );
|
||||||
|
|
||||||
\do_action( 'activitypub_inbox', $data, $user->ID, $type );
|
\do_action( 'activitypub_inbox', $data, $user->ID, $type );
|
||||||
|
|
|
@ -46,6 +46,11 @@ class Server {
|
||||||
*/
|
*/
|
||||||
public static function application_actor() {
|
public static function application_actor() {
|
||||||
$user = new Application_User();
|
$user = new Application_User();
|
||||||
|
|
||||||
|
$user->set_context(
|
||||||
|
\Activitypub\Activity\Activity::CONTEXT
|
||||||
|
);
|
||||||
|
|
||||||
$json = $user->to_array();
|
$json = $user->to_array();
|
||||||
|
|
||||||
$response = new WP_REST_Response( $json, 200 );
|
$response = new WP_REST_Response( $json, 200 );
|
||||||
|
@ -80,12 +85,12 @@ class Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
// POST-Requets are always signed
|
// POST-Requets are always signed
|
||||||
if ( 'POST' === $request->get_method() ) {
|
if ( 'post' === \strtolower( $request->get_method() ) ) {
|
||||||
$verified_request = Signature::verify_http_signature( $request );
|
$verified_request = Signature::verify_http_signature( $request );
|
||||||
if ( \is_wp_error( $verified_request ) ) {
|
if ( \is_wp_error( $verified_request ) ) {
|
||||||
return $verified_request;
|
return $verified_request;
|
||||||
}
|
}
|
||||||
} elseif ( 'GET' === $request->get_method() ) { // GET-Requests are only signed in secure mode
|
} elseif ( 'get' === \strtolower( $request->get_method() ) ) { // GET-Requests are only signed in secure mode
|
||||||
if ( ACTIVITYPUB_AUTHORIZED_FETCH ) {
|
if ( ACTIVITYPUB_AUTHORIZED_FETCH ) {
|
||||||
$verified_request = Signature::verify_http_signature( $request );
|
$verified_request = Signature::verify_http_signature( $request );
|
||||||
if ( \is_wp_error( $verified_request ) ) {
|
if ( \is_wp_error( $verified_request ) ) {
|
||||||
|
|
|
@ -39,7 +39,7 @@ class Test_Activitypub_Signature_Verification extends WP_UnitTestCase {
|
||||||
|
|
||||||
// Start verification
|
// Start verification
|
||||||
// parse_signature_header, get_signed_data, get_public_key
|
// parse_signature_header, get_signed_data, get_public_key
|
||||||
$signature_block = Activitypub\Signature::parse_signature_header( $headers['signature'] );
|
$signature_block = Activitypub\Signature::parse_signature_header( $headers['signature'][0] );
|
||||||
$signed_headers = $signature_block['headers'];
|
$signed_headers = $signature_block['headers'];
|
||||||
$signed_data = Activitypub\Signature::get_signed_data( $signed_headers, $signature_block, $headers );
|
$signed_data = Activitypub\Signature::get_signed_data( $signed_headers, $signature_block, $headers );
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue