Last active
June 14, 2018 00:52
-
-
Save joeswann/ca2ead84b983c6cd535a to your computer and use it in GitHub Desktop.
[oauth2.php] Oauth 2 example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
//install | |
$app->match('/install/{state}', function($state) use ($app) { | |
return json_encode($app['vend_oauth']->install($state)); | |
}); | |
$app->post('/wombat/add_order', function() use ($app) { | |
$oauth = $app['vend_oauth']->getOrCreateToken(); | |
if(isset($oauth['token'])) { | |
$app['vend']->initAPI($oauth['token']); | |
$response = $app['vend']->wombatAddOrder($app['settings']); | |
return new Response( | |
json_encode($response), | |
200, | |
['Content-Type' => 'application/json'] | |
); | |
} else { | |
return json_encode($oauth); | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace JoeSwann; | |
class VendBase { | |
public function __construct(&$app, $settings = array()) { | |
$this->app = $app; | |
$this->settings = $settings; | |
$this->db = $this->app['db']; | |
$this->spree_api = new SpreeAPI($app, $settings); | |
$this->model = new VendModel($app, $settings); | |
} | |
public function initAPI($token) { | |
$url = 'https://' . $this->settings['oauth']['domain_prefix'] . '.vendhq.com'; | |
$token_type = 'Bearer'; | |
$access_token = $token['access_token']; | |
$this->vend_api = new \VendAPI\VendAPI($url,$token_type, $access_token); | |
$this->api = new VendAPI($this->app, $this->vend_api,$this->settings); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace JoeSwann; | |
class VendOauth extends VendBase { | |
function install($state) { | |
$session = &$this->app['session']; | |
//Unpack our saved parameters out of database for use with getProvider | |
$settings = $this->db->fetchAssoc('select * from install where state = ?', [$state]); | |
if($settings == false) die('no records found'); | |
//Send settings to provider | |
$provider = $this->getProvider($settings); | |
$auth_url = $settings['auth_url']; | |
$state = $settings['state']; | |
// Add our provided state to session | |
$session->set('oauth2state', $state); | |
//Redirect | |
header('Location: '.$auth_url); | |
exit; | |
} | |
function getOrCreateToken($state = false) { | |
$session = &$this->app['session']; | |
$request = &$this->app['request']; | |
//if we are installing we won't have oauth details as part of request | |
if($state) { | |
//Unpack our saved parameters out of database for use with getProvider | |
$oauth = $this->db->fetchAssoc('select * from install where state = ? limit 1', [$state]); | |
if($oauth == false) die('no records found'); | |
$domain_prefix = $oauth['domain_prefix']; | |
} else { | |
$oauth = $this->settings['oauth']; | |
$domain_prefix = $this->settings['oauth']['domain_prefix']; | |
} | |
//See if we already have a valid token | |
$token = $this->getToken($domain_prefix); | |
//If the token has expired then we should refresh it | |
if($token) { | |
// Check expiry | |
if($this->hasExpired($token)) { | |
//The latest token doesn't have refresh | |
$token = $this->db->fetchAssoc('select * from token where retailer = ? order by expires asc', [$domain_prefix]); | |
$token = $this->refreshToken($token, $oauth); | |
return [ | |
'action' => 'refresh token', | |
'token' => $token | |
]; | |
} else { | |
return [ | |
'action' => 'existing token', | |
'token' => $token | |
]; | |
} | |
} else { | |
//Go ahead and install fresh | |
$provider = $this->getProvider($oauth); | |
$session_state = $session->get('oauth2state', false); | |
$request_code = $request->get('code', false); | |
$request_state = $request->get('state'); | |
// If we don't have an authorization code then we haven't installed yet | |
if ($request_code == false) { | |
// Generate a state and save it + settings to database | |
$auth_url = $provider->getAuthorizationUrl(); | |
$state = $provider->state; | |
// save installation settings using state as identifier | |
$install = []; | |
foreach($oauth as $key => $setting) { | |
$install[$key] = $setting; | |
} | |
$install['state'] = $state; | |
$install['auth_url'] = $auth_url; | |
$this->db->insert('install', $install); | |
return [ | |
'action' => 'install application', | |
'auth_url' => "http://{$_SERVER[HTTP_HOST]}/install/{$state}" | |
]; | |
// Check given state against previously stored one to mitigate CSRF attack | |
} elseif (empty($session_state) || $session_state !== $request_state) { | |
$session->remove('oauth2state'); | |
return [ | |
'action' => 'reject state' | |
]; | |
} else { | |
// Try to get an access token (using the authorization code grant) | |
$token_data = $provider->getAccessToken('authorization_code', [ | |
'code' => $request_code | |
]); | |
$token = $this->saveToken($token_data, $oauth); | |
return [ | |
'action' => 'save token', | |
'token' => $token | |
]; | |
} | |
} | |
} | |
function refreshToken($token_data, $oauth) { | |
$grant = new \League\OAuth2\Client\Grant\RefreshToken(); | |
$provider = $this->getProvider($oauth); | |
$token_data = $provider->getAccessToken($grant, ['refresh_token' => $token_data['refresh_token']]); | |
$token = $this->saveToken($token_data, $oauth); | |
return $token; | |
} | |
function hasExpired($token) { | |
//Compare current time against tokens expiry date - an hour (to avoid complications) | |
//hopefully requesting a new token before expiry isn't complicated | |
return (int)$token['expires'] < time(); | |
} | |
function getToken($domain_prefix) { | |
//Just return the latest token assigned to the current retailer | |
$token = $this->db->fetchAssoc('select * from token where retailer = ? ORDER BY expires DESC', [$domain_prefix]); | |
return $token; | |
} | |
function saveToken($access_token,$oauth) { | |
//Is this a refresh token? | |
$retailer = $oauth['domain_prefix']; | |
$has_refresh = isset($access_token->refreshToken); | |
$token = []; | |
$token['retailer'] = $retailer; | |
$token['access_token'] = $access_token->accessToken; | |
$token['expires'] = $access_token->expires; | |
$token['has_refresh'] = $has_refresh; | |
if($has_refresh) { | |
$token['refresh_token'] = $access_token->refreshToken; | |
} | |
$this->db->insert('token', $token); | |
return $token; | |
} | |
function getProvider($oauth) { | |
return new \Wheniwork\OAuth2\Client\Provider\Vend([ | |
'clientId' => $oauth['client_id'], | |
'clientSecret' => $oauth['client_secret'], | |
'domainPrefix' => $oauth['domain_prefix'], | |
'redirectUri' => $oauth['redirect_uri'] | |
]); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment