2024-11-21 09:05:37 +00:00
|
|
|
<?php
|
|
|
|
class Bluesky_Auth {
|
|
|
|
private $identifier;
|
|
|
|
private $password;
|
|
|
|
private $api_domain;
|
|
|
|
|
|
|
|
public function __construct($identifier, $password) {
|
|
|
|
$this->identifier = $identifier;
|
|
|
|
$this->password = $password;
|
|
|
|
|
|
|
|
// Get domain with fallback and force https://
|
|
|
|
$domain = get_option('bluesky_domain', 'https://bsky.social');
|
|
|
|
if (empty($domain)) {
|
|
|
|
$domain = 'https://bsky.social';
|
|
|
|
}
|
|
|
|
if (strpos($domain, 'https://') !== 0) {
|
|
|
|
$domain = 'https://' . $domain;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure proper URL format
|
|
|
|
$this->api_domain = rtrim($domain, '/') . '/';
|
|
|
|
|
2024-12-17 23:00:47 +00:00
|
|
|
// Log configuration details if debugging is enabled
|
|
|
|
$this->log_debug('Auth Configuration', array(
|
|
|
|
'domain_setting' => get_option('bluesky_domain'),
|
|
|
|
'processed_domain' => $this->api_domain,
|
|
|
|
'identifier' => $this->identifier
|
|
|
|
));
|
2024-11-21 09:05:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function get_access_token() {
|
2024-12-17 23:00:47 +00:00
|
|
|
// First check if we have a valid access token
|
|
|
|
$access_token = get_option('bluesky_access_jwt');
|
|
|
|
$token_created = get_option('bluesky_token_created');
|
|
|
|
|
|
|
|
if (!empty($access_token) && $token_created > (time() - 7200)) {
|
|
|
|
$this->log_debug('Using existing valid token');
|
|
|
|
return $access_token;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we have a refresh token, try to use it
|
2024-11-21 09:05:37 +00:00
|
|
|
if ($this->should_refresh_token()) {
|
2024-12-17 23:00:47 +00:00
|
|
|
$refresh_result = $this->refresh_access_token();
|
|
|
|
if (!isset($refresh_result['error'])) {
|
|
|
|
return $refresh_result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we got here, we need to create a new session
|
|
|
|
if (empty($this->identifier) || empty($this->password)) {
|
|
|
|
// Try to get credentials from settings if not provided
|
|
|
|
$settings = get_option('bluesky_connector_settings', array());
|
|
|
|
if (!empty($settings['identifier'])) {
|
|
|
|
$this->identifier = $settings['identifier'];
|
|
|
|
}
|
|
|
|
if (!empty($settings['password'])) {
|
|
|
|
$this->password = $settings['password'];
|
|
|
|
}
|
|
|
|
|
|
|
|
// If still empty, try individual options
|
|
|
|
if (empty($this->identifier)) {
|
|
|
|
$this->identifier = get_option('bluesky_identifier');
|
|
|
|
}
|
|
|
|
if (empty($this->password)) {
|
|
|
|
$this->password = get_option('bluesky_password');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (empty($this->identifier) || empty($this->password)) {
|
|
|
|
$this->log_debug('Missing credentials', array(
|
|
|
|
'has_identifier' => !empty($this->identifier),
|
|
|
|
'has_password' => !empty($this->password)
|
|
|
|
));
|
|
|
|
return array('error' => 'Missing credentials - please check settings');
|
|
|
|
}
|
2024-11-21 09:05:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
$token_url = $this->api_domain . 'xrpc/com.atproto.server.createSession';
|
|
|
|
|
2024-12-17 23:00:47 +00:00
|
|
|
$this->log_debug('Attempting connection', array('url' => $token_url));
|
2024-11-21 09:05:37 +00:00
|
|
|
|
|
|
|
$headers = array(
|
|
|
|
'Content-Type' => 'application/json',
|
|
|
|
);
|
|
|
|
|
2024-12-17 23:00:47 +00:00
|
|
|
$body = wp_json_encode(array(
|
2024-11-21 09:05:37 +00:00
|
|
|
'identifier' => $this->identifier,
|
|
|
|
'password' => $this->password,
|
|
|
|
));
|
|
|
|
|
2024-12-17 23:00:47 +00:00
|
|
|
$this->log_debug('Request prepared', array('body' => str_replace($this->password, '[REDACTED]', $body)));
|
2024-11-21 09:05:37 +00:00
|
|
|
|
|
|
|
$wp_version = get_bloginfo('version');
|
|
|
|
$user_agent = apply_filters('http_headers_useragent', 'WordPress/' . $wp_version . '; ' . get_bloginfo('url'));
|
|
|
|
|
|
|
|
$response = wp_remote_post($token_url, array(
|
|
|
|
'headers' => $headers,
|
|
|
|
'user-agent' => "$user_agent; Bluesky Connector",
|
|
|
|
'body' => $body,
|
2024-12-17 23:00:47 +00:00
|
|
|
'timeout' => 30,
|
2024-11-21 09:05:37 +00:00
|
|
|
));
|
|
|
|
|
|
|
|
if (is_wp_error($response)) {
|
|
|
|
$error_message = $response->get_error_message();
|
2024-12-17 23:00:47 +00:00
|
|
|
$this->log_debug('Auth Error', array('error' => $error_message));
|
2024-11-21 09:05:37 +00:00
|
|
|
return array('error' => $error_message);
|
|
|
|
}
|
|
|
|
|
2024-12-17 23:00:47 +00:00
|
|
|
// Log response details
|
2024-11-21 09:05:37 +00:00
|
|
|
$status_code = wp_remote_retrieve_response_code($response);
|
|
|
|
$response_body = wp_remote_retrieve_body($response);
|
2024-12-17 23:00:47 +00:00
|
|
|
$this->log_debug('Response received', array(
|
|
|
|
'status' => $status_code,
|
|
|
|
'body' => $response_body
|
|
|
|
));
|
2024-11-21 09:05:37 +00:00
|
|
|
|
|
|
|
$data = json_decode($response_body, true);
|
|
|
|
|
|
|
|
if (!empty($data['accessJwt']) && !empty($data['refreshJwt']) && !empty($data['did'])) {
|
2024-12-17 23:00:47 +00:00
|
|
|
// Save credentials in both locations
|
|
|
|
$settings = get_option('bluesky_connector_settings', array());
|
|
|
|
$settings['identifier'] = $this->identifier;
|
|
|
|
update_option('bluesky_connector_settings', $settings);
|
|
|
|
|
|
|
|
// Save all necessary tokens and details
|
|
|
|
update_option('bluesky_identifier', sanitize_text_field($this->identifier));
|
2024-11-21 09:05:37 +00:00
|
|
|
update_option('bluesky_access_jwt', sanitize_text_field($data['accessJwt']));
|
|
|
|
update_option('bluesky_refresh_jwt', sanitize_text_field($data['refreshJwt']));
|
|
|
|
update_option('bluesky_did', sanitize_text_field($data['did']));
|
|
|
|
update_option('bluesky_token_created', time());
|
2024-12-17 23:00:47 +00:00
|
|
|
|
|
|
|
// Store password for reauth
|
|
|
|
update_option('bluesky_password', $this->password);
|
|
|
|
|
|
|
|
$this->log_debug('Authentication successful', array('did' => $data['did']));
|
2024-11-21 09:05:37 +00:00
|
|
|
return $data['accessJwt'];
|
|
|
|
}
|
|
|
|
|
|
|
|
$error_message = isset($data['error']) ? $data['error'] : 'Failed to get access token';
|
|
|
|
if (isset($data['message'])) {
|
|
|
|
$error_message .= ' - ' . $data['message'];
|
|
|
|
}
|
2024-12-17 23:00:47 +00:00
|
|
|
$this->log_debug('Auth Failed', array('error' => $error_message));
|
2024-11-21 09:05:37 +00:00
|
|
|
return array('error' => $error_message);
|
|
|
|
}
|
|
|
|
|
|
|
|
private function should_refresh_token() {
|
|
|
|
$token_created = get_option('bluesky_token_created');
|
|
|
|
$refresh_token = get_option('bluesky_refresh_jwt');
|
|
|
|
|
|
|
|
return !empty($refresh_token) && ($token_created < (time() - 82800));
|
|
|
|
}
|
|
|
|
|
|
|
|
private function refresh_access_token() {
|
|
|
|
$refresh_token = get_option('bluesky_refresh_jwt');
|
|
|
|
if (empty($refresh_token)) {
|
|
|
|
return array('error' => 'No refresh token available');
|
|
|
|
}
|
|
|
|
|
|
|
|
$refresh_url = $this->api_domain . 'xrpc/com.atproto.server.refreshSession';
|
2024-12-17 23:00:47 +00:00
|
|
|
$this->log_debug('Token refresh attempt', array('url' => $refresh_url));
|
2024-11-21 09:05:37 +00:00
|
|
|
|
|
|
|
$wp_version = get_bloginfo('version');
|
|
|
|
$user_agent = apply_filters('http_headers_useragent', 'WordPress/' . $wp_version . '; ' . get_bloginfo('url'));
|
|
|
|
|
|
|
|
$response = wp_remote_post($refresh_url, array(
|
|
|
|
'headers' => array(
|
|
|
|
'Authorization' => 'Bearer ' . $refresh_token,
|
|
|
|
'Content-Type' => 'application/json',
|
|
|
|
),
|
|
|
|
'user-agent' => "$user_agent; Bluesky Connector",
|
|
|
|
'timeout' => 30,
|
|
|
|
));
|
|
|
|
|
|
|
|
if (is_wp_error($response)) {
|
|
|
|
$error_message = $response->get_error_message();
|
2024-12-17 23:00:47 +00:00
|
|
|
$this->log_debug('Token Refresh Error', array('error' => $error_message));
|
2024-11-21 09:05:37 +00:00
|
|
|
return array('error' => $error_message);
|
|
|
|
}
|
|
|
|
|
2024-12-17 23:00:47 +00:00
|
|
|
$data = json_decode(wp_remote_retrieve_body($response), true);
|
2024-11-21 09:05:37 +00:00
|
|
|
|
|
|
|
if (!empty($data['accessJwt']) && !empty($data['refreshJwt'])) {
|
|
|
|
update_option('bluesky_access_jwt', sanitize_text_field($data['accessJwt']));
|
|
|
|
update_option('bluesky_refresh_jwt', sanitize_text_field($data['refreshJwt']));
|
|
|
|
update_option('bluesky_token_created', time());
|
2024-12-17 23:00:47 +00:00
|
|
|
|
|
|
|
$this->log_debug('Token refresh successful');
|
2024-11-21 09:05:37 +00:00
|
|
|
return $data['accessJwt'];
|
|
|
|
}
|
|
|
|
|
|
|
|
$error_message = isset($data['error']) ? $data['error'] : 'Failed to refresh token';
|
|
|
|
if (isset($data['message'])) {
|
|
|
|
$error_message .= ' - ' . $data['message'];
|
|
|
|
}
|
2024-12-17 23:00:47 +00:00
|
|
|
$this->log_debug('Token Refresh Failed', array('error' => $error_message));
|
2024-11-21 09:05:37 +00:00
|
|
|
return array('error' => $error_message);
|
|
|
|
}
|
2024-12-17 23:00:47 +00:00
|
|
|
|
|
|
|
private function log_debug($message, $data = array()) {
|
|
|
|
if (defined('WP_DEBUG') && WP_DEBUG) {
|
|
|
|
$log_message = sprintf(
|
|
|
|
'[Bluesky Connector] %s | Data: %s',
|
|
|
|
$message,
|
|
|
|
wp_json_encode($data, JSON_PRETTY_PRINT)
|
|
|
|
);
|
|
|
|
|
|
|
|
if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) {
|
|
|
|
error_log($log_message);
|
|
|
|
}
|
|
|
|
|
|
|
|
do_action('bluesky_connector_debug', $message, $data);
|
|
|
|
}
|
|
|
|
}
|
2024-11-21 09:05:37 +00:00
|
|
|
}
|