PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
16.3 16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 All 508 releases
← All changes | jetpack_vendor/automattic/jetpack-publicize/src/class-keyring-result-handler.php +86 -0 16.2-beta → 16.3 View file →
@@ -1,0 +1,86 @@
1 +<?php
2 +/**
3 + * Same-origin completion handler for the publicize auth_flow=v2 connect flow.
4 + *
5 + * @package automattic/jetpack-publicize
6 + */
7 +
8 +namespace Automattic\Jetpack\Publicize;
9 +
10 +/**
11 + * Handles the popup landing page that public-api redirects back to after a connection is
12 + * verified (auth_flow=v2).
13 + *
14 + * Because Meta/Threads sever `window.opener` via COOP, the popup cannot post its result back
15 + * to the opener tab. Instead public-api redirects the popup to this same-origin admin-post
16 + * endpoint, which broadcasts the request_id over a BroadcastChannel that the opener is
17 + * listening on, then closes itself. The opener then fetches the verified result once.
18 + */
19 +class Keyring_Result_Handler {
20 +
21 + /**
22 + * The admin-post action that the connect popup is redirected back to.
23 + */
24 + const ACTION = 'jetpack_social_keyring_done';
25 +
26 + /**
27 + * The BroadcastChannel name shared with the client.
28 + *
29 + * Must match KEYRING_BROADCAST_CHANNEL in _inc/utils/request-external-access.js.
30 + */
31 + const CHANNEL = 'jetpack-social-keyring';
32 +
33 + /**
34 + * Register the handler.
35 + */
36 + public static function init() {
37 + add_action( 'admin_post_' . self::ACTION, array( __CLASS__, 'handle' ) );
38 + }
39 +
40 + /**
41 + * Output a minimal page that broadcasts the request_id to the opener and closes the popup.
42 + *
43 + * @return never
44 + */
45 + public static function handle() {
46 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only: the request_id is an opaque token reflected back to a same-origin BroadcastChannel; nothing is mutated.
47 + $request_id = isset( $_GET['request_id'] ) ? sanitize_key( wp_unslash( $_GET['request_id'] ) ) : '';
48 +
49 + nocache_headers();
50 +
51 + if ( ! headers_sent() ) {
52 + header( 'Content-Type: text/html; charset=' . get_option( 'blog_charset' ) );
53 + }
54 +
55 + $close_warning = esc_html__( 'You can close this window now.', 'jetpack-publicize-pkg' );
56 + ?>
57 +<!DOCTYPE html>
58 +<html <?php language_attributes(); ?>>
59 +<head>
60 + <meta charset="<?php echo esc_attr( get_option( 'blog_charset' ) ); ?>" />
61 + <title></title>
62 +</head>
63 +<body>
64 + <p><?php echo $close_warning; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- already escaped above. ?></p>
65 + <script>
66 + ( function () {
67 + try {
68 + var channel = new BroadcastChannel( <?php echo wp_json_encode( self::CHANNEL, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ); ?> );
69 + channel.postMessage( {
70 + type: 'keyring-result',
71 + requestId: <?php echo wp_json_encode( $request_id, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ); ?>,
72 + } );
73 + channel.close();
74 + } catch ( e ) {}
75 +
76 + window.setTimeout( function () {
77 + window.close();
78 + }, 50 );
79 + } )();
80 + </script>
81 +</body>
82 +</html>
83 + <?php
84 + exit;
85 + }
86 +}