-
Notifications
You must be signed in to change notification settings - Fork 83
Add HTTP signatures to WebFinger requests #2594
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Some ActivityPub implementations like GoToSocial require HTTP signatures for all requests, including WebFinger lookups. Previously, WebFinger requests were made without signatures, causing 401 Unauthorized errors when trying to resolve mentions for users on these platforms. This updates Webfinger::get_data() to use Http::get() which includes HTTP signature authentication, while using a filter to override the Accept header to the WebFinger-appropriate application/jrd+json. Fixes #2593.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds HTTP signature support to WebFinger requests to ensure compatibility with ActivityPub implementations like GoToSocial that require signed HTTP requests for all endpoints. Previously, unsigned WebFinger requests resulted in 401 Unauthorized errors when resolving mentions on these platforms.
Key Changes:
- Replaced
wp_safe_remote_get()withHttp::get()to enable HTTP signatures on WebFinger requests - Implemented
http_request_argsfilter to set the Accept header toapplication/jrd+json - Simplified error handling by removing the HTTP status code check
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| includes/class-webfinger.php | Updates WebFinger request mechanism to use signed HTTP requests via Http::get() and adds Accept header through filter |
| .github/changelog/2594-from-description | Adds changelog entry documenting the bug fix for mention compatibility |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| \remove_filter( 'http_request_args', $set_accept_header ); | ||
|
|
||
| if ( \is_wp_error( $response ) || \wp_remote_retrieve_response_code( $response ) >= 400 ) { | ||
| if ( \is_wp_error( $response ) ) { |
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The removal of the HTTP status code check || \wp_remote_retrieve_response_code( $response ) >= 400 means that 4xx and 5xx HTTP errors will no longer be caught and converted to WP_Error. This could allow invalid responses (like 404 or 500) to proceed to parsing, potentially causing downstream errors. The status code validation should be retained alongside the WP_Error check.
| if ( \is_wp_error( $response ) ) { | |
| if ( \is_wp_error( $response ) || \wp_remote_retrieve_response_code( $response ) >= 400 ) { |
| ) | ||
| ); | ||
| $set_accept_header = function ( $args ) { | ||
| $args['headers']['Accept'] = 'application/jrd+json'; |
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The filter function directly assigns to $args['headers']['Accept'] without checking if the 'headers' key exists. If $args['headers'] is not set, this will create it, but it's safer to check or use array merging to avoid potential issues with existing header configurations.
| $args['headers']['Accept'] = 'application/jrd+json'; | |
| if ( ! isset( $args['headers'] ) || ! is_array( $args['headers'] ) ) { | |
| $args['headers'] = array(); | |
| } | |
| $args['headers'] = array_merge( $args['headers'], array( 'Accept' => 'application/jrd+json' ) ); |
| $set_accept_header = function ( $args ) { | ||
| $args['headers']['Accept'] = 'application/jrd+json'; | ||
| return $args; | ||
| }; | ||
|
|
||
| \add_filter( 'http_request_args', $set_accept_header ); | ||
| $response = Http::get( $webfinger_url ); | ||
| \remove_filter( 'http_request_args', $set_accept_header ); | ||
|
|
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using a global filter for a single HTTP request creates a potential race condition in concurrent scenarios and affects all HTTP requests during execution. Consider passing headers directly to Http::get() if the method supports it, or use a more specific filter with priority to minimize side effects.
| $set_accept_header = function ( $args ) { | |
| $args['headers']['Accept'] = 'application/jrd+json'; | |
| return $args; | |
| }; | |
| \add_filter( 'http_request_args', $set_accept_header ); | |
| $response = Http::get( $webfinger_url ); | |
| \remove_filter( 'http_request_args', $set_accept_header ); | |
| // Set Accept header directly in the request arguments to avoid global filter side effects. | |
| $response = Http::get( $webfinger_url, array( | |
| 'headers' => array( | |
| 'Accept' => 'application/jrd+json', | |
| ), | |
| ) ); |
|
I don't think this is needed after all. |
Fixes #2593
Proposed changes:
Webfinger::get_data()to useHttp::get()for signed HTTP requests.http_request_argsfilter to override the Accept header toapplication/jrd+json.Some ActivityPub implementations like GoToSocial require HTTP signatures for all requests, including WebFinger lookups. Previously, WebFinger requests were made without signatures, causing 401 Unauthorized errors when trying to resolve mentions for users on these platforms.
Other information:
Testing instructions:
npm run env-test -- --filter=Webfinger.Changelog entry
Changelog Entry Details
Significance
Type
Message
Mentions now work with GoToSocial and other platforms that require signed requests.