mailn
This commit is contained in:
@@ -0,0 +1,272 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user