Created
November 26, 2014 16:23
-
-
Save ralphschindler/a585cd74973a97ffee3f to your computer and use it in GitHub Desktop.
A Barebones OAuth2 PHP Client demonstrating the "Password Grant Type"
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 SampleOauth2Client; | |
class Client | |
{ | |
protected $configuration = [ | |
'token_file' => null, // path to a file to store token information | |
'api_authorization_token' => null, // authorization to talk to token service | |
'api_token_url' => null, // url to post to | |
'api_username' => null, // username | |
'api_password' => null, // password | |
'api_scope' => null, // scope to request access for | |
]; | |
public function __construct($configuration) | |
{ | |
$this->configuration = $configuration; | |
} | |
public function getAccessToken($refresh = false) | |
{ | |
if (!isset($this->configuration['token_file'])) { | |
throw new \RuntimeException(__CLASS__ . ' requires a file to store access token information in'); | |
} | |
$tokenDataFile = $this->configuration['token_file']; | |
$tokenData = unserialize(file_get_contents($tokenDataFile)); | |
$tokenIsExpired = (time() > $tokenData['access']['expiration']); | |
if (!$tokenData || $refresh || $tokenIsExpired) { | |
$this->refreshTokens(); | |
} | |
$tokenData = unserialize(file_get_contents($tokenDataFile)); | |
return $tokenData['access']['token']; | |
} | |
protected function refreshTokens() | |
{ | |
$context = stream_context_create([ | |
'http' => [ | |
'method' => 'POST', | |
'header' => "Authorization: Basic {$this->configuration['api_authorization_token']}\r\n" | |
. "Content-Type: application/x-www-form-urlencoded\r\n", | |
'content' => "grant_type=password&username={$this->configuration['api_username']}" | |
. "&password={$this->configuration['api_password']}" | |
. "&scope={$this->configuration['api_scope']}", | |
] | |
]); | |
$content = file_get_contents($this->configuration['api_token_url'], null, $context); | |
if (!strpos($http_response_header[0], '200 OK')) { | |
throw new \RuntimeException('Could not obtain an access token'); | |
} | |
$decoded = json_decode($content, true); | |
$tokenData = [ | |
'access' => [ | |
'token' => $decoded['access_token'], | |
'expiration' => (time() + $decoded['expires_in']) | |
], | |
'refresh' => [ | |
'token' => $decoded['refresh_token'] | |
] | |
]; | |
file_put_contents($this->configuration['token_file'], serialize($tokenData)); | |
} | |
} |
Different goals, that's fair enough.
- How about refreshing access tokens automatically after they are expired when you know the service to be implementing the refresh token grant type (instead of pushing that workflow onto the consumer)?
Guzzle, meh! After months away from zf2 development, I forget about the religious sect FIG in php that believes in the one-true-interface ;)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Yep, so this is a difference in goals.
When you build your own OAuth 2 server, you can interact with it SO easily it hurts, just by throwing a few values at it via HTTP requests.
You are very well versed with the OAuth 2 spec, and that's all gravy, but most providers are either not versed with the spec, or flagrantly ignore it.
Some providers run their token endpoints on GET or POST for instance, which is nutty. Providers help with that.
This package was always aimed to get people working with the popular providers way before worrying about those making their own servers, because this code existed in some form (my old CodeIgniter-OAuth2 package) before either Brett or Alex had built their OAuth 2 servers, and before it seemed reasonable that people would be doing that so often as they are now.
ANYHOO, making it work without having to make your own provider certainly seems like a great goal and me and Ben are both A++ on that. Your #1 is taken care of.
2.) Probably not. We did that for OAuth 2.0 Server and it was just a mess. People want PDO wrappers and Memcache drivers and Eloquent ORM drivers and oh god just do it yourself. :)
3.) I'm gonna go with a big nope on swappable HTTP Clients, as the FIG might be able to make that much easier for us in the future. I regularly use Geocoder as a perfect example of why the FIG needs to keep fighting its fight, and HTTP Message is getting close enough to make a lot of this stuff much easier.
Guzzle is pretty much a defacto standard recently, and although some like streams Guzzle can use streams now too - not that it would make much difference to anyone WHAT its doing under the hood.
So a big yes to 1, nope on 2 and soon on 3. :)