Skip to content

Commit 0e484ed

Browse files
committed
Added ClosureTokenPersistence for wrapping other cache providers.
1 parent f76ddbc commit 0e484ed

File tree

3 files changed

+134
-1
lines changed

3 files changed

+134
-1
lines changed

README.md

+39-1
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ $response = $client->get('http://somehost/some_secure_url');
143143
echo "Status: ".$response->getStatusCode()."\n";
144144
```
145145

146+
### Authorization Code Example
147+
There is a full example of using the `AuthorizationCode` grant type with a `RefreshToken` in the `examples/` directory.
148+
146149
### Grant Types
147150
The following OAuth grant types are supported directly, and you can always create your own by implementing `kamermans\OAuth2\GrantType\GrantTypeInterface`:
148151
- `AuthorizationCode`
@@ -205,8 +208,9 @@ By default, access tokens are not persisted anywhere. There are some built-in m
205208
- `DoctrineCacheTokenPersistence` Takes a `Doctrine\Common\Cache\Cache` object and optionally a key name (default: `guzzle-oauth2-token`) where the access token will be saved.
206209
- `SimpleCacheTokenPersistence` Takes a PSR-16 SimpleCache and optionally a key name (default: `guzzle-oauth2-token`) where the access token will be saved. This allows any PSR-16 compatible cache to be used.
207210
- `Laravel5CacheTokenPersistence` Takes an `Illuminate\Contracts\Cache\Repository` object and optionally a key name (default: `guzzle-oauth2-token`) where the access token will be saved.
211+
- `ClosureTokenPersistence` Allows you to define a token persistence provider by providing closures to handle the persistence functions.
208212

209-
If you want to use your own persistence layer, you should write your own class that implements `TokenPersistenceInterface`.
213+
If you want to use your own persistence layer, you should write your own class that implements `TokenPersistenceInterface` or use the `ClosureTokenPersistence` provider, which is described at the end of this section.
210214

211215
To enable token persistence, you must use the `OAuth2Middleware::setTokenPersistence()` or `OAuth2Subscriber::setTokenPersistence()` method, like this:
212216

@@ -220,6 +224,40 @@ $grant_type = new ClientCredentials($reauth_client, $reauth_config);
220224
$oauth = new OAuth2Middleware($grant_type);
221225
$oauth->setTokenPersistence($token_persistence);
222226
```
227+
### Closure-Based Token Persistence
228+
There are plenty of cases where you would like to use your own caching layer to store the OAuth2 data, but there is no adapter included that works with your cache provider. The `ClosureTokenPersistence` provider makes this case easier by allowing you to define closures that handle the OAuth2 persistence data, as shown in the example below.
229+
230+
```php
231+
// We'll store everything in an array, but you can use any provider you want
232+
$cache = [];
233+
$cache_key = "foo";
234+
235+
// Returns true if the item exists in cache
236+
$exists = function() use (&$cache, $cache_key) {
237+
return array_key_exists($cache_key, $cache);
238+
};
239+
240+
// Sets the given $value array in cache
241+
$set = function(array $value) use (&$cache, $cache_key) {
242+
$cache[$cache_key] = $value;
243+
};
244+
245+
// Gets the previously-stored value from cache (or null)
246+
$get = function() use (&$cache, $cache_key, $exists) {
247+
return $exists()? $cache[$cache_key]: null;
248+
};
249+
250+
// Deletes the previously-stored value from cache (if exists)
251+
$delete = function() use (&$cache, $cache_key, $exists) {
252+
if ($exists()) {
253+
unset($cache[$cache_key]);
254+
}
255+
};
256+
257+
$persistence = new ClosureTokenPersistence($set, $get, $delete, $exists);
258+
```
259+
260+
> Note: The format of the token data is a PHP associative array. You can flatten the array with `serialize()` or `json_encode()` or whatever else you want before storing it, but remember to decode it back to an array in `get()` before returning it! Also, the above example is not very thread-safe, so if you have a high level of concurrency, you will need to find more atomic ways to handle this logic, or at least wrap things with `try/catch` and handle things gracefully.
223261
224262
Please see the `src/Persistence/` directory for more information on persistence.
225263

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespace kamermans\OAuth2\Persistence;
4+
5+
use Illuminate\Contracts\Cache\Repository;
6+
use kamermans\OAuth2\Token\TokenInterface;
7+
8+
class ClosureTokenPersistence implements TokenPersistenceInterface
9+
{
10+
11+
private $doSaveToken;
12+
private $doRestoreToken;
13+
private $doDeleteToken;
14+
private $doHasToken;
15+
16+
public function __construct(callable $saveToken, callable $restoreToken, callable $deleteToken, callable $hasToken)
17+
{
18+
$this->doSaveToken = $saveToken;
19+
$this->doRestoreToken = $restoreToken;
20+
$this->doDeleteToken = $deleteToken;
21+
$this->doHasToken = $hasToken;
22+
}
23+
24+
public function saveToken(TokenInterface $token)
25+
{
26+
call_user_func($this->doSaveToken, $token->serialize());
27+
}
28+
29+
public function restoreToken(TokenInterface $token)
30+
{
31+
$data = call_user_func($this->doRestoreToken);
32+
33+
if (!is_array($data)) {
34+
return null;
35+
}
36+
37+
return $token->unserialize($data);
38+
}
39+
40+
public function deleteToken()
41+
{
42+
call_user_func($this->doDeleteToken);
43+
}
44+
45+
public function hasToken()
46+
{
47+
return call_user_func($this->doHasToken);
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
namespace kamermans\OAuth2\Tests\Persistence;
4+
5+
use Illuminate\Cache\ArrayStore;
6+
use Illuminate\Cache\Repository;
7+
use kamermans\OAuth2\Persistence\ClosureTokenPersistence;
8+
use kamermans\OAuth2\Token\RawToken;
9+
use kamermans\OAuth2\Token\RawTokenFactory;
10+
11+
class ClosureTokenPersistenceTest extends TokenPersistenceTestBase
12+
{
13+
14+
private $cache = [];
15+
16+
public function setUp()
17+
{
18+
$this->cache = [];
19+
}
20+
21+
public function getInstance()
22+
{
23+
$cache = &$this->cache;
24+
$cache_key = "foo";
25+
26+
$exists = function() use (&$cache, $cache_key) {
27+
return array_key_exists($cache_key, $cache);
28+
};
29+
30+
$set = function(array $value) use (&$cache, $cache_key) {
31+
$cache[$cache_key] = $value;
32+
};
33+
34+
$get = function() use (&$cache, $cache_key, $exists) {
35+
return $exists()? $cache[$cache_key]: null;
36+
};
37+
38+
$delete = function() use (&$cache, $cache_key, $exists) {
39+
if ($exists()) {
40+
unset($cache[$cache_key]);
41+
}
42+
};
43+
44+
return new ClosureTokenPersistence($set, $get, $delete, $exists);
45+
}
46+
}

0 commit comments

Comments
 (0)