PluginProbe
Extendify / 3.2.2
Extendify v3.2.2
3.2.2 3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 All 128 releases
extendify / app / Mcp / OAuth / RegistrationEndpoint.php

RegistrationEndpoint.php in Extendify 3.2.2, at app/Mcp/OAuth/RegistrationEndpoint.php

99 lines 3.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * The OAuth dynamic client registration endpoint.
5 */
6
7 namespace Extendify\Mcp\OAuth;
8
9 defined('ABSPATH') || die('No direct access.');
10
11 use Extendify\Config;
12
13 /**
14 * A client that publishes no metadata document registers here first (RFC 7591)
15 * and is handed an id; nothing else about it is verified.
16 */
17 class RegistrationEndpoint
18 {
19 /**
20 * @return void
21 */
22 public static function register()
23 {
24 \add_action('rest_api_init', [self::class, 'registerRoute']);
25 }
26
27 /**
28 * @return void
29 */
30 public static function registerRoute()
31 {
32 \register_rest_route(Config::$slug . '/' . Config::$apiVersion, '/oauth/register', [
33 'methods' => 'POST',
34 'callback' => [self::class, 'handle'],
35 // Registration comes before any credential exists; Clients caps what a stranger can fill.
36 'permission_callback' => '__return_true',
37 'show_in_index' => false,
38 ]);
39 }
40
41 /**
42 * @param \WP_REST_Request $request - The incoming request.
43 * @return \WP_REST_Response
44 */
45 public static function handle(\WP_REST_Request $request)
46 {
47 $sent = $request->get_json_params();
48 if (!is_array($sent)) {
49 return self::answer(400, [
50 'error' => 'invalid_client_metadata',
51 'error_description' => 'The registration must be a JSON object.',
52 ]);
53 }
54
55 $uris = is_array($sent['redirect_uris'] ?? null) ? array_values($sent['redirect_uris']) : [];
56 $acceptable = array_filter($uris, function ($uri) {
57 return is_string($uri) && Clients::acceptableRedirect($uri);
58 });
59 if (!$uris || count($uris) > Clients::MAX_REDIRECTS || count($acceptable) !== count($uris)) {
60 return self::answer(400, [
61 'error' => 'invalid_redirect_uri',
62 'error_description' => sprintf(
63 'Send up to %d redirect URIs, each https or http on a loopback address,'
64 . ' with no fragment and at most %d characters.',
65 Clients::MAX_REDIRECTS,
66 Clients::MAX_REDIRECT_LENGTH
67 ),
68 ]);
69 }
70
71 $name = is_string($sent['client_name'] ?? null) ? $sent['client_name'] : '';
72 $client = Clients::register($name, $uris);
73
74 return self::answer(201, [
75 'client_id' => $client['id'],
76 'client_id_issued_at' => time(),
77 'client_name' => $client['name'],
78 'redirect_uris' => $client['redirectUris'],
79 'token_endpoint_auth_method' => 'none',
80 'grant_types' => ['authorization_code', 'refresh_token'],
81 'response_types' => ['code'],
82 ]);
83 }
84
85 /**
86 * @param integer $status - The HTTP status.
87 * @param array $body - The JSON body.
88 * @return \WP_REST_Response
89 */
90 private static function answer($status, array $body)
91 {
92 $response = new \WP_REST_Response($body, $status);
93 $response->header('Cache-Control', 'no-store');
94 $response->header('Pragma', 'no-cache');
95
96 return $response;
97 }
98 }
99