You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

139 lines
5.1 KiB
PHP

<?php
class OpenID_Connect_Generic_Webhook {
/**
* The settings object instance.
*
* @var OpenID_Connect_Generic_Option_Settings
*/
private $settings;
/**
* Plugin client wrapper instance.
*
* @var OpenID_Connect_Generic_Client_Wrapper
*/
private $client_wrapper;
/**
* The logger object instance.
*
* @var OpenID_Connect_Generic_Option_Logger
*/
private $logger;
public function __construct(OpenID_Connect_Generic_Option_Settings $settings,
OpenID_Connect_Generic_Client_Wrapper $client_wrapper,
OpenID_Connect_Generic_Option_Logger $logger) {
$this->settings = $settings;
$this->client_wrapper = $client_wrapper;
$this->logger = $logger;
}
public static function register(OpenID_Connect_Generic_Option_Settings $settings,
OpenID_Connect_Generic_Client_Wrapper $client_wrapper,
OpenID_Connect_Generic_Option_Logger $logger) {
$webhook = new OpenID_Connect_Generic_Webhook($settings, $client_wrapper, $logger);
add_action('rest_api_init', [$webhook, 'register_rest_api']);
return $webhook;
}
public function register_rest_api() {
register_rest_route('openid-connect/v1', '/webhook/keycloak', [
[
'methods' => ['GET', 'POST'],
'callback' => [$this, 'webhook_keycloak'],
],
'schema' => [$this, 'webhook_keycloak_schema'],
]);
}
public function webhook_keycloak(WP_REST_Request $request) {
if (!$this->settings->enable_webhook) {
$this->logger->log('Webhook is disabled in setting.', 'webhook');
return rest_ensure_response([
'status' => -1,
'code' => 'ERR::WEBHOOK_DISABLED',
'error' => 'Webhook is disabled in setting.'
]);
}
$query = $request->get_query_params();
if (!empty($this->settings->webhook_key) && $query['key'] != $this->settings->webhook_key) {
$this->logger->log('Webhook key is incorrect.', 'webhook');
return rest_ensure_response([
'status' => -1,
'code' => 'ERR::WEBHOOK_KEY_INCORRECT',
'error' => 'Webhook key is incorrect.'
]);
}
$event = $request->get_json_params();
if (is_null($event)) {
$this->logger->log('Event body is empty.', 'webhook');
return rest_ensure_response([
'status' => -1,
'code' => 'ERR::EMPTY_EVENT_BODY',
'error' => 'Event body is empty.',
]);
}
if ($event['realmId'] != $this->settings->realm) {
$this->logger->log("Realm id mismatch: {$event['realmId']}", 'webhook');
return rest_ensure_response([
'status' => 0,
'warning' => "Realm id mismatch: {$event['realmId']}",
]);
}
if (!in_array($event['type'], ['UPDATE_PROFILE', 'UPDATE_EMAIL'])) {
return rest_ensure_response([
'status' => 0,
'warning' => 'Event type ignored',
]);
}
$subject = $event['userId'];
$user = $this->client_wrapper->get_user_by_identity($subject);
if (!$user) {
$this->logger->log("Cannot find user for subject: {$subject}", 'webhook');
return rest_ensure_response([
'status' => 0,
'warning' => "Cannot find user for subject: {$subject}",
]);
}
if (isset($event['userInfo'])) { // Update user profile
$this->client_wrapper->update_user_profile($user, $event['userInfo']);
$this->logger->log("Updated user profile: {$user->user_login}", 'webhook');
}
return rest_ensure_response([
'status' => 1
]);
}
public function webhook_keycloak_schema() {
return [
'$schema' => 'http://json-schema.org/draft-04/schema#',
// The title property marks the identity of the resource.
'title' => 'keycloak-webhook',
'type' => 'object',
'required' => ['type', 'realmId', 'userId', 'userInfo'],
'properties' => [
'type' => [
'description' => esc_html__('Event Type', 'daggerhart-openid-connect-generic'),
'type' => 'string',
],
'realmId' => [
'description' => esc_html__('IDP Realm ID', 'daggerhart-openid-connect-generic'),
'type' => 'string',
],
'userId' => [
'description' => esc_html__('IDP User ID', 'daggerhart-openid-connect-generic'),
'type' => 'string',
],
'userInfo' => [
'description' => esc_html__('IDP User Info', 'daggerhart-openid-connect-generic'),
'type' => 'object',
],
],
];
}
}