273 lines
7.7 KiB
PHP
273 lines
7.7 KiB
PHP
<?php
|
|
/**
|
|
* Flickr OAuth 1.0a Authentication
|
|
* Handles authorization flow to get access tokens for API calls
|
|
*/
|
|
class FlickrOAuth
|
|
{
|
|
private $consumerKey;
|
|
private $consumerSecret;
|
|
private $requestTokenUrl = 'https://www.flickr.com/services/oauth/request_token';
|
|
private $authorizeUrl = 'https://www.flickr.com/services/oauth/authorize';
|
|
private $accessTokenUrl = 'https://www.flickr.com/services/oauth/access_token';
|
|
|
|
private $oauthToken = null;
|
|
private $oauthTokenSecret = null;
|
|
private $tokenFile;
|
|
|
|
public function __construct($consumerKey, $consumerSecret)
|
|
{
|
|
$this->consumerKey = $consumerKey;
|
|
$this->consumerSecret = $consumerSecret;
|
|
$this->tokenFile = __DIR__ . '/../data/oauth_token.json';
|
|
|
|
// Load saved tokens if exist
|
|
$this->loadTokens();
|
|
}
|
|
|
|
/**
|
|
* Check if we have valid access tokens
|
|
*/
|
|
public function isAuthorized()
|
|
{
|
|
return !empty($this->oauthToken) && !empty($this->oauthTokenSecret);
|
|
}
|
|
|
|
/**
|
|
* Get stored OAuth token
|
|
*/
|
|
public function getOAuthToken()
|
|
{
|
|
return $this->oauthToken;
|
|
}
|
|
|
|
/**
|
|
* Get stored OAuth token secret
|
|
*/
|
|
public function getOAuthTokenSecret()
|
|
{
|
|
return $this->oauthTokenSecret;
|
|
}
|
|
|
|
/**
|
|
* Step 1: Get request token and return authorization URL
|
|
*/
|
|
public function getAuthorizationUrl($callbackUrl)
|
|
{
|
|
$params = [
|
|
'oauth_callback' => $callbackUrl,
|
|
'oauth_consumer_key' => $this->consumerKey,
|
|
'oauth_nonce' => $this->generateNonce(),
|
|
'oauth_signature_method' => 'HMAC-SHA1',
|
|
'oauth_timestamp' => time(),
|
|
'oauth_version' => '1.0',
|
|
];
|
|
|
|
$params['oauth_signature'] = $this->generateSignature('GET', $this->requestTokenUrl, $params);
|
|
|
|
$url = $this->requestTokenUrl . '?' . http_build_query($params);
|
|
|
|
$response = $this->httpRequest($url);
|
|
|
|
if (!$response) {
|
|
throw new Exception('Failed to get request token');
|
|
}
|
|
|
|
parse_str($response, $data);
|
|
|
|
if (!isset($data['oauth_token']) || !isset($data['oauth_token_secret'])) {
|
|
throw new Exception('Invalid request token response: ' . $response);
|
|
}
|
|
|
|
// Store request token temporarily (needed for step 2)
|
|
$_SESSION['flickr_request_token'] = $data['oauth_token'];
|
|
$_SESSION['flickr_request_token_secret'] = $data['oauth_token_secret'];
|
|
|
|
// Return URL for user to authorize
|
|
return $this->authorizeUrl . '?oauth_token=' . $data['oauth_token'] . '&perms=read';
|
|
}
|
|
|
|
/**
|
|
* Step 2: Exchange verifier for access token
|
|
*/
|
|
public function handleCallback($oauthToken, $oauthVerifier)
|
|
{
|
|
if (!isset($_SESSION['flickr_request_token_secret'])) {
|
|
throw new Exception('Request token secret not found in session');
|
|
}
|
|
|
|
$requestTokenSecret = $_SESSION['flickr_request_token_secret'];
|
|
|
|
$params = [
|
|
'oauth_consumer_key' => $this->consumerKey,
|
|
'oauth_token' => $oauthToken,
|
|
'oauth_verifier' => $oauthVerifier,
|
|
'oauth_nonce' => $this->generateNonce(),
|
|
'oauth_signature_method' => 'HMAC-SHA1',
|
|
'oauth_timestamp' => time(),
|
|
'oauth_version' => '1.0',
|
|
];
|
|
|
|
$params['oauth_signature'] = $this->generateSignature(
|
|
'GET',
|
|
$this->accessTokenUrl,
|
|
$params,
|
|
$requestTokenSecret
|
|
);
|
|
|
|
$url = $this->accessTokenUrl . '?' . http_build_query($params);
|
|
|
|
$response = $this->httpRequest($url);
|
|
|
|
if (!$response) {
|
|
throw new Exception('Failed to get access token');
|
|
}
|
|
|
|
parse_str($response, $data);
|
|
|
|
if (!isset($data['oauth_token']) || !isset($data['oauth_token_secret'])) {
|
|
throw new Exception('Invalid access token response: ' . $response);
|
|
}
|
|
|
|
// Save access tokens
|
|
$this->oauthToken = $data['oauth_token'];
|
|
$this->oauthTokenSecret = $data['oauth_token_secret'];
|
|
$this->saveTokens($data);
|
|
|
|
// Clean up session
|
|
unset($_SESSION['flickr_request_token']);
|
|
unset($_SESSION['flickr_request_token_secret']);
|
|
|
|
return [
|
|
'oauth_token' => $this->oauthToken,
|
|
'user_nsid' => $data['user_nsid'] ?? null,
|
|
'username' => $data['username'] ?? null,
|
|
'fullname' => $data['fullname'] ?? null,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Sign an API request with OAuth
|
|
*/
|
|
public function signRequest($method, $url, $params = [])
|
|
{
|
|
$oauthParams = [
|
|
'oauth_consumer_key' => $this->consumerKey,
|
|
'oauth_token' => $this->oauthToken,
|
|
'oauth_nonce' => $this->generateNonce(),
|
|
'oauth_signature_method' => 'HMAC-SHA1',
|
|
'oauth_timestamp' => time(),
|
|
'oauth_version' => '1.0',
|
|
];
|
|
|
|
$allParams = array_merge($params, $oauthParams);
|
|
$oauthParams['oauth_signature'] = $this->generateSignature(
|
|
$method,
|
|
$url,
|
|
$allParams,
|
|
$this->oauthTokenSecret
|
|
);
|
|
|
|
return $oauthParams;
|
|
}
|
|
|
|
/**
|
|
* Generate OAuth signature
|
|
*/
|
|
private function generateSignature($method, $url, $params, $tokenSecret = '')
|
|
{
|
|
ksort($params);
|
|
|
|
$paramString = http_build_query($params, '', '&', PHP_QUERY_RFC3986);
|
|
|
|
$baseString = strtoupper($method) . '&'
|
|
. rawurlencode($url) . '&'
|
|
. rawurlencode($paramString);
|
|
|
|
$signingKey = rawurlencode($this->consumerSecret) . '&' . rawurlencode($tokenSecret);
|
|
|
|
return base64_encode(hash_hmac('sha1', $baseString, $signingKey, true));
|
|
}
|
|
|
|
/**
|
|
* Generate random nonce
|
|
*/
|
|
private function generateNonce()
|
|
{
|
|
return md5(uniqid(mt_rand(), true));
|
|
}
|
|
|
|
/**
|
|
* Make HTTP request
|
|
*/
|
|
private function httpRequest($url)
|
|
{
|
|
$ch = curl_init();
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_URL => $url,
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_FOLLOWLOCATION => true,
|
|
CURLOPT_TIMEOUT => 30,
|
|
CURLOPT_SSL_VERIFYPEER => true,
|
|
]);
|
|
|
|
$response = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
if ($httpCode !== 200) {
|
|
return false;
|
|
}
|
|
|
|
return $response;
|
|
}
|
|
|
|
/**
|
|
* Save tokens to file
|
|
*/
|
|
private function saveTokens($data)
|
|
{
|
|
$dir = dirname($this->tokenFile);
|
|
if (!is_dir($dir)) {
|
|
mkdir($dir, 0700, true);
|
|
}
|
|
|
|
$tokenData = [
|
|
'oauth_token' => $data['oauth_token'],
|
|
'oauth_token_secret' => $data['oauth_token_secret'],
|
|
'user_nsid' => $data['user_nsid'] ?? null,
|
|
'username' => $data['username'] ?? null,
|
|
'created_at' => date('Y-m-d H:i:s'),
|
|
];
|
|
|
|
file_put_contents($this->tokenFile, json_encode($tokenData, JSON_PRETTY_PRINT));
|
|
chmod($this->tokenFile, 0600);
|
|
}
|
|
|
|
/**
|
|
* Load tokens from file
|
|
*/
|
|
private function loadTokens()
|
|
{
|
|
if (file_exists($this->tokenFile)) {
|
|
$data = json_decode(file_get_contents($this->tokenFile), true);
|
|
if ($data) {
|
|
$this->oauthToken = $data['oauth_token'] ?? null;
|
|
$this->oauthTokenSecret = $data['oauth_token_secret'] ?? null;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear saved tokens (logout)
|
|
*/
|
|
public function clearTokens()
|
|
{
|
|
$this->oauthToken = null;
|
|
$this->oauthTokenSecret = null;
|
|
if (file_exists($this->tokenFile)) {
|
|
unlink($this->tokenFile);
|
|
}
|
|
}
|
|
}
|