Compare commits

..

164 Commits
0.3.3 ... 1.0.0

Author SHA1 Message Date
Alex Bilbie
8fc0cadae4 Updated composer.json 2013-02-15 17:10:31 +00:00
Alex Bilbie
52bdc79f79 Merge branch 'release/1.0.0' 2013-02-15 17:09:24 +00:00
Alex Bilbie
4c46dd222e Added changelog 2013-02-15 17:08:41 +00:00
Alex Bilbie
6a81bcbefc Updated composer.json 2013-02-15 17:08:27 +00:00
Alex Bilbie
f42f45e42e Updated README 2013-02-15 17:08:21 +00:00
Alex Bilbie
333ce37c97 Removed authserver.md - going to be in docs instead 2013-02-15 16:56:54 +00:00
Alex Bilbie
645fc7210e Removed sillyness 2013-02-15 16:35:28 +00:00
Alex Bilbie
ff37850fea Pretty print github-style codeblocks 2013-02-15 16:33:18 +00:00
Alex Bilbie
57c24953be First draft of auth server docs 2013-02-15 16:30:32 +00:00
Alex Bilbie
92d9435bba Added method to get the exception type 2013-02-15 16:29:00 +00:00
Alex Bilbie
9f6bd64100 Renamed database.sql to mysql.sql 2013-02-15 15:05:40 +00:00
Alex Bilbie
e86d5cb3f1 Broke up grants into their own tests 2013-02-13 20:12:51 +00:00
Alex Bilbie
f818bdf40e Updated docblocks 2013-02-13 19:59:08 +00:00
Alex Bilbie
246732153c Updated grantTypes to use AuthServer::getParam() 2013-02-13 19:39:43 +00:00
Alex Bilbie
92ce378a93 Added more files+folders to ignore 2013-02-13 19:37:40 +00:00
Alex Bilbie
4506037bda Docblock updates 2013-02-13 19:36:56 +00:00
Alex Bilbie
d99002ef2f Renamed variable as $authParams is no longer used 2013-02-13 19:36:10 +00:00
Alex Bilbie
a98dcea6fe Fixed missing fields in oauth_sessions table 2013-02-13 19:35:42 +00:00
Alex Bilbie
1e2d2b3d25 Added AuthServer::getParam() function to reduce repetitive code 2013-02-13 18:25:10 +00:00
Alex Bilbie
0f4546db47 Changed 'oauth_token' to 'access_token' 2013-02-13 17:10:44 +00:00
Alex Bilbie
d0b1034f35 Ignore vendor/phpunit 2013-02-12 20:33:40 +00:00
Alex Bilbie
1cfe10105a Updated docblocks for the two main classes 2013-02-12 20:33:23 +00:00
Alex Bilbie
7739923273 Updated database 2013-02-12 20:33:03 +00:00
Alex Bilbie
e771099568 Removed unnecessary functions 2013-02-12 17:22:15 +00:00
Alex Bilbie
a361fbab14 Finished unit tests for AuthServer 2013-02-12 16:45:45 +00:00
Alex Bilbie
61d1685e84 Minor fixes to password grant 2013-02-12 16:45:33 +00:00
Alex Bilbie
d2267dbd24 Added Password grant 2013-02-12 16:22:14 +00:00
Alex Bilbie
87186d73b7 Removed old client code which can be now be found at lncd/oauth2-client 2013-02-12 16:01:02 +00:00
Alex Bilbie
e76111c2b7 Fixed silliness with access token verification 2013-02-08 11:45:51 +00:00
Alex Bilbie
60b2caf41d Various fixes and tweaks 2013-02-08 11:40:33 +00:00
Alex Bilbie
89f3c35466 Authorization header fixes 2013-02-07 16:16:09 +00:00
Alex Bilbie
55d68bd105 Import namespace for util\request 2013-02-07 14:54:56 +00:00
Alex Bilbie
7293d47234 Merge branch 'feature/reorg' into develop 2013-02-05 16:27:01 +00:00
Alex Bilbie
49e0088f72 Removed old unit tests 2013-02-05 16:26:55 +00:00
Alex Bilbie
37331c4dc8 Added resource server tests 2013-02-05 16:20:56 +00:00
Alex Bilbie
562c257596 Various bug fixes 2013-02-05 16:20:45 +00:00
Alex Bilbie
f481a9baeb Bug fix 2013-02-05 15:59:44 +00:00
Alex Bilbie
322eb15bb5 Revert "Removed unnecessary code"
This reverts commit c89a2346a8.
2013-02-05 15:57:24 +00:00
Alex Bilbie
6b4e51b3a3 Removed unnecessary interfaces 2013-02-05 15:56:03 +00:00
Alex Bilbie
daa352d126 Added resource server tests 2013-02-05 15:55:48 +00:00
Alex Bilbie
e903cbee68 Update request class namespace 2013-02-05 15:55:38 +00:00
Alex Bilbie
920fd9344f Moved request class to util folder 2013-02-05 15:55:04 +00:00
Alex Bilbie
463803f74d Added client credentials grant function 2013-02-05 14:48:10 +00:00
Alex Bilbie
7a646d3a84 Renamed client get function 2013-02-05 14:47:54 +00:00
Alex Bilbie
14a7142ad7 Lots more tests 2013-02-05 10:07:45 +00:00
Alex Bilbie
66bea97e8c Bug fixes based on previous code changes 2013-02-05 10:07:36 +00:00
Alex Bilbie
7214101cfc Ensure Travis installs Mockery 2013-02-04 19:47:11 +00:00
Alex Bilbie
81f3dc9a2b Added new auth server unit tests 2013-02-04 19:46:37 +00:00
Alex Bilbie
c7e9235db3 Added util unit tests 2013-02-04 19:46:29 +00:00
Alex Bilbie
2f010584ef Removed old auth server unit tests 2013-02-04 19:46:21 +00:00
Alex Bilbie
4a50af333d Added code coverage blocks 2013-02-04 19:46:06 +00:00
Alex Bilbie
c89a2346a8 Removed unnecessary code 2013-02-04 19:45:58 +00:00
Alex Bilbie
22f793a16f Fixed getClient call 2013-02-04 19:45:47 +00:00
Alex Bilbie
6edd486b4c Added code coverage ignore blocks to getRequest method 2013-02-04 19:45:34 +00:00
Alex Bilbie
8a6823b78d Removed resource tests, added util tests 2013-02-04 19:45:19 +00:00
Alex Bilbie
d80b2935fc Require mockery for unit tests 2013-02-04 19:45:03 +00:00
Alex Bilbie
d5ae471d94 Throw root exception 2013-02-04 18:58:26 +00:00
Alex Bilbie
9a265f7956 Fixed bad ternary statement. Added missing semicolon 2013-02-04 18:58:17 +00:00
Alex Bilbie
04b8394009 Updated method calls to reflect naming changes 2013-02-04 18:44:19 +00:00
Alex Bilbie
6ae4db460e $request parameter is static 2013-02-04 18:31:13 +00:00
Alex Bilbie
768dfb369c Renamed getCurrentGrantType to getGrantType 2013-02-04 18:30:56 +00:00
Alex Bilbie
0d173d4c35 Renamed methods to prevent ORM conflict 2013-02-04 17:10:30 +00:00
Alex Bilbie
4b8bc76622 Removed properties from Interface 2013-02-04 15:32:33 +00:00
Alex Bilbie
1a1bfd9348 Fix $expiresIn call as static 2013-02-04 15:32:21 +00:00
Alex Bilbie
91bf8cc241 Removed old Authentication folder 2013-02-04 14:42:14 +00:00
Alex Bilbie
3c7fe00130 Renamed some session methods to avoid conflicts with ORM methods 2013-02-04 14:41:40 +00:00
Alex Bilbie
5f8ca89772 Added docblocks to the grant interface 2013-02-04 13:59:34 +00:00
Alex Bilbie
f855b572e8 First commit of new refresh token grant 2013-02-01 16:50:59 +00:00
Alex Bilbie
5e365bb974 Function name fix 2013-02-01 16:02:38 +00:00
Alex Bilbie
85c42db355 Variable name fix 2013-02-01 16:02:04 +00:00
Alex Bilbie
a81c486e0e Spelling fix 2013-02-01 16:00:00 +00:00
Alex Bilbie
e8d43f2087 Anal restyle 2013-02-01 15:59:50 +00:00
Alex Bilbie
5abb84eda0 Validate all client credentials 2013-02-01 15:59:43 +00:00
Alex Bilbie
9fd7ccc137 Added ClientCredentials grant 2013-02-01 15:51:51 +00:00
Alex Bilbie
a3a617171a $grantTypes static access 2013-02-01 15:28:40 +00:00
Alex Bilbie
47731ce901 $expiresIn now static 2013-02-01 15:28:25 +00:00
Alex Bilbie
fcf57abbb2 Removed guzzle dependancy 2013-02-01 15:24:01 +00:00
Alex Bilbie
3aa8465640 Made $grantTypes static to fix ref bug 2013-02-01 15:23:04 +00:00
Alex Bilbie
2a8688b54e Update getRequest calls to static requests 2013-02-01 15:09:15 +00:00
Alex Bilbie
aec9aa908c Made getRequest static 2013-02-01 15:07:47 +00:00
Alex Bilbie
8de2cdb1d9 < PHP5.4 array syntax 2013-02-01 15:02:36 +00:00
Alex Bilbie
2c1dedfe8a Updated grantTypeInterface 2013-02-01 14:56:36 +00:00
Alex Bilbie
d732778f65 Finished AuthCode grant 2013-02-01 14:41:52 +00:00
Alex Bilbie
6eb5db0239 Lots of bug fixes. Some methods and variables made static so they can be accessed by grant classes. 2013-02-01 14:41:10 +00:00
Alex Bilbie
7a851084c6 Initial commit of AuthCode grant type 2013-02-01 10:50:39 +00:00
Alex Bilbie
9b6a92c506 Updated namespace use for Util\SecureKey 2013-01-29 16:53:39 +00:00
Alex Bilbie
781bf985c3 Renamed checkClientAuthoriseParams method to checkAuthoriseParams 2013-01-29 16:25:14 +00:00
Alex Bilbie
87a142cc30 Updated getCurrentGrantType method 2013-01-29 16:24:48 +00:00
Alex Bilbie
4fa37bb356 Updated issueAccessToken method 2013-01-29 16:24:28 +00:00
Alex Bilbie
514aabb838 Updated newAuthoriseRequest method 2013-01-29 16:23:41 +00:00
Alex Bilbie
3cb53448c5 Anal style fix 2013-01-29 16:21:53 +00:00
Alex Bilbie
8ae0dbcf46 Default to 40 characters (as that is what the DB table columns are set to) 2013-01-29 16:21:39 +00:00
Alex Bilbie
ffcad85d95 Renamed functions, changed some doc terms 2013-01-29 16:21:21 +00:00
Alex Bilbie
14b680f6be Moved GrantTypeInterface 2013-01-29 16:18:45 +00:00
Alex Bilbie
74f48d28a4 Added ClientException 2013-01-29 16:18:23 +00:00
Alex Bilbie
cab721923a Set relationship to scope_id 2013-01-29 16:17:30 +00:00
Alex Bilbie
dcd1026a98 Use scope_id instead of the scope name 2013-01-29 16:15:45 +00:00
Alex Bilbie
31c3b495bf Re-added checkClientAuthoriseParams() function 2013-01-29 14:56:17 +00:00
Alex Bilbie
a8b6389092 Updated SessionInterface 2013-01-29 14:55:50 +00:00
Alex Bilbie
5e91b95cb3 Updated ScopeInterface with get method 2013-01-29 14:25:49 +00:00
Alex Bilbie
1ed4c27420 Update ClientInterface with get() method 2013-01-29 14:23:28 +00:00
Alex Bilbie
57f825b0a8 Added exception codes and messages 2013-01-29 14:19:23 +00:00
Alex Bilbie
846a008c76 Explanation of the scope delimiter parameter 2013-01-29 14:18:13 +00:00
Alex Bilbie
a189156f26 Response types are now generated from grants that are injected in 2013-01-29 14:17:56 +00:00
Alex Bilbie
d63c0ea262 Added model variable storage 2013-01-29 14:16:47 +00:00
Alex Bilbie
f74a35074a Added getResponseType parameter 2013-01-29 14:15:05 +00:00
Alex Bilbie
9a41ab8bfc Removed unnecessary column from the table 2013-01-29 14:14:50 +00:00
Alex Bilbie
e415e0051a Version bump 2013-01-24 15:44:07 +00:00
Daniel Horrigan
945d60bd5d Renaming Server and Resource to AuthServer and ResourceServer to be less confusing. 2013-01-22 11:33:09 -05:00
Daniel Horrigan
892ae3a0d3 Started adding some Server methods, adding some Util classes and adding a way to get the token from the Resource 2013-01-22 11:25:51 -05:00
Daniel Horrigan
2727ba0078 Adding a few Getters to the Resource, moving Exceptions and adding some new ones. 2013-01-17 15:19:01 -05:00
Daniel Horrigan
c12472857b Changed Case of Oauth2 namespace to OAuth2 namespace 2013-01-08 16:35:29 -05:00
Daniel Horrigan
385111a1f2 Merge branch 'cleanup' of github.com:dandoescode/OAuth2 into feature/reorg
Conflicts:
	src/OAuth2/Authentication/Server.php
	src/Oauth2/Resource/Server.php
2013-01-08 16:26:17 -05:00
Nick Jackson
608bcb767b Bearer token now correctly base64 decoding 2013-01-08 15:52:17 +00:00
Daniel Horrigan
89e89a73dc Changing 'user_credentials' to password 2013-01-07 10:31:28 -05:00
Daniel Horrigan
2fecadd2a6 Fixing Resource bugs and moving the Request dep to a setter. 2013-01-04 17:21:24 -05:00
Daniel Horrigan
373ddf9f34 Changing Case in namespaces 2013-01-04 14:55:13 -05:00
Daniel Horrigan
a3fd22b3dd Changing Case 2013-01-04 14:44:58 -05:00
Alex Bilbie
e5e132f67a Merge branch 'release/0.4.1' into develop 2013-01-02 22:37:24 +00:00
Alex Bilbie
b4e8c27618 Merge branch 'release/0.4.1' 2013-01-02 22:36:48 +00:00
Alex Bilbie
d65cdaf028 Version bump 2013-01-02 22:36:41 +00:00
Alex Bilbie
5f1779c4e7 Autoload dependencies with autoloader in bootstrap.php 2013-01-02 22:32:49 +00:00
Alex Bilbie
b10613c5e3 Composer install 2013-01-02 21:31:33 +00:00
Alex Bilbie
1c3b319aa6 Altered the script parameter of .travis.yml 2013-01-02 21:22:09 +00:00
Alex Bilbie
1069507ab4 Revert require_once statements 2013-01-02 21:13:32 +00:00
Alex Bilbie
5ca63c921a Updated PHPUnit.xml 2013-01-02 21:13:12 +00:00
Alex Bilbie
943fc1cc82 Possible fix for Travis? 2013-01-02 20:34:09 +00:00
Alex Bilbie
a158883aed Another attempt to fix paths for travis 2013-01-02 20:32:38 +00:00
Alex Bilbie
8aba2b29b8 Better travis debugging 2013-01-02 20:24:45 +00:00
Alex Bilbie
b5e8f9206b Fool. 2013-01-02 20:21:25 +00:00
Alex Bilbie
755a753cb5 Test include path on travis 2013-01-02 20:19:26 +00:00
Alex Bilbie
e99211db31 Moved require_once statement outside of setUp tests method 2013-01-02 20:13:02 +00:00
Alex Bilbie
1142f8d86b Merge branch 'release/0.4' into develop 2013-01-02 19:17:12 +00:00
Alex Bilbie
5772a2f12f Merge branch 'release/0.4' 2013-01-02 19:17:01 +00:00
Alex Bilbie
f351cea442 Version bump 2013-01-02 19:16:51 +00:00
Alex Bilbie
2e1f1c05cf Updated README 2013-01-02 19:16:16 +00:00
Alex Bilbie
7279c8675b Merge branch 'feature/grants' into develop 2013-01-02 19:14:33 +00:00
Alex Bilbie
94945ec49e Added support for refresh tokens, user credentials and client credentials grant. 100% unit test code coverage for authentication. Fixes #2 2013-01-02 19:14:22 +00:00
Alex Bilbie
2b8a27ef47 Ignore code coverage in ../tests folder 2013-01-02 19:12:53 +00:00
Alex Bilbie
7d1aa28087 Added .travis.yml 2012-12-30 21:31:19 +00:00
Daniel Horrigan
31b36f23e7 Starting the reorganization 2012-12-28 15:12:16 -05:00
Alex Bilbie
0fcbeb8158 PSR fixes 2012-12-23 22:13:22 +00:00
Alex Bilbie
0876fd9ad3 Spacing fixes 2012-12-23 22:12:51 +00:00
Alex Bilbie
2545ea7dc1 Added refresh token params and examples 2012-12-23 22:12:44 +00:00
Alex Bilbie
6eeb7e13e4 Updated unit tests 2012-12-23 22:11:33 +00:00
Alex Bilbie
38c50c00b0 PSR fixes 2012-12-23 21:39:42 +00:00
Alex Bilbie
df85c98e53 PSR fixes 2012-12-23 21:36:30 +00:00
Alex Bilbie
0f30b2a803 Removed lots of unnecessary if/else blocks.
Removed null value of expires/expiresIn parameter
2012-12-23 21:21:37 +00:00
Alex Bilbie
f2dc89cdf3 Merge remote-tracking branch 'dhorrigan/master' into feature/grants 2012-12-23 20:34:21 +00:00
Alex Bilbie
c676ba9857 Merge remote-tracking branch 'origin/develop' into develop 2012-12-23 20:33:42 +00:00
Alex Bilbie
d99e871e11 Set a default token ttl of one hour 2012-12-23 20:31:16 +00:00
Daniel Horrigan
0f6f5e2939 Added the user_credentials and refresh_token grants. Fixed expires_in so it is inline with the spec, but added expires for the old usage of expires_in. Made redirect_uri in oauth_sessions ALLOW NULL since user_credential grants don't have a redirect 2012-12-19 16:12:48 -05:00
Alex Bilbie
9fd6f309df Merge branch 'release/0.3.5' into develop 2012-12-12 11:45:07 +00:00
Alex Bilbie
41d8a1efa3 Merge branch 'release/0.3.5' 2012-12-12 11:44:56 +00:00
Alex Bilbie
4928221b49 Version bump 2012-12-12 11:44:51 +00:00
Alex Bilbie
8131d5be90 Merge branch 'hotfix/resourceConfig' into develop 2012-12-12 11:44:04 +00:00
Alex Bilbie
a948335e45 Merge branch 'hotfix/resourceConfig' 2012-12-12 11:43:11 +00:00
Alex Bilbie
aa978d3581 Fix variable name 2012-12-12 11:43:01 +00:00
Alex Bilbie
b1d91f33cf Merge branch 'release/0.3.4' into develop 2012-12-11 15:33:20 +00:00
Alex Bilbie
1be25955d6 Merge branch 'release/0.3.4' 2012-12-11 15:33:05 +00:00
Alex Bilbie
3365953257 Version bump 2012-12-11 15:32:27 +00:00
Alex Bilbie
302bf1f70d Clean trailing whitespace 2012-12-11 15:31:42 +00:00
Alex Bilbie
6553fb3f22 Return client details 2012-12-11 12:09:56 +00:00
Alex Bilbie
1b29c0f1a0 Merge branch 'release/0.3.2' into develop 2012-11-20 15:30:02 +00:00
60 changed files with 3583 additions and 3149 deletions

4
.gitignore vendored
View File

@@ -3,4 +3,6 @@
/docs/build/ /docs/build/
/build/logs/ /build/logs/
/build/coverage/ /build/coverage/
test test
/docs/
/testing/

8
.travis.yml Normal file
View File

@@ -0,0 +1,8 @@
language: php
php:
- 5.3
- 5.4
before_script: composer install --dev
script: phpunit -c build/phpunit.xml

5
CHANGELOG.md Normal file
View File

@@ -0,0 +1,5 @@
# Changelog
## 1.0.0 (released 2012-02-15)
* First release

View File

@@ -1,6 +1,6 @@
# PHP OAuth Framework # PHP OAuth Framework
The goal of this project is to develop a standards compliant [OAuth 2](http://tools.ietf.org/wg/oauth/draft-ietf-oauth-v2/) authentication server, resource server and client library with support for a major OAuth 2 providers. The goal of this project is to develop a standards compliant [OAuth 2](http://tools.ietf.org/wg/oauth/draft-ietf-oauth-v2/) authentication server and resource server.
## Package Installation ## Package Installation
@@ -8,29 +8,31 @@ The framework is provided as a Composer package which can be installed by adding
```javascript ```javascript
{ {
"require": { "require": {
"lncd\Oauth2": "*" "lncd\OAuth2": "*"
} }
} }
``` ```
## Package Integration ---
Check out the [wiki](https://github.com/lncd/OAuth2/wiki) The library features 100% unit test code coverage. To run the tests yourself run `phpunit -c build/phpunit.xml`.
## Current Features ## Current Features
### Authentication Server ### Authentication Server
The authentication server is a flexible class that supports the standard authorization code grant. The authentication server is a flexible class and following core specification grants are implemented:
* authentication code ([section 4.1](http://tools.ietf.org/html/rfc6749#section-4.1))
* refresh token ([section 6](http://tools.ietf.org/html/rfc6749#section-6))
* client credentials ([section 2.3.1](http://tools.ietf.org/html/rfc6749#section-2.3.1))
* password (user credentials) ([section 4.3](http://tools.ietf.org/html/rfc6749#section-4.3))
### Resource Server ### Resource Server
The resource server allows you to secure your API endpoints by checking for a valid OAuth access token in the request and ensuring the token has the correct permission to access resources. The resource server allows you to secure your API endpoints by checking for a valid OAuth access token in the request and ensuring the token has the correct permission to access resources.
## Future Goals ## Future Goals
### Authentication Server ### Authentication Server
@@ -38,10 +40,13 @@ The resource server allows you to secure your API endpoints by checking for a va
* Support for [JSON web tokens](http://tools.ietf.org/wg/oauth/draft-ietf-oauth-json-web-token/). * Support for [JSON web tokens](http://tools.ietf.org/wg/oauth/draft-ietf-oauth-json-web-token/).
* Support for [SAML assertions](http://tools.ietf.org/wg/oauth/draft-ietf-oauth-saml2-bearer/). * Support for [SAML assertions](http://tools.ietf.org/wg/oauth/draft-ietf-oauth-saml2-bearer/).
### Client support
* Merge in https://github.com/philsturgeon/codeigniter-oauth2
--- ---
This code will be developed as part of the [Linkey](http://linkey.blogs.lincoln.ac.uk) project which has been funded by [JISC](http://jisc.ac.uk) under the Access and Identity Management programme. This code will be developed as part of the [Linkey](http://linkey.blogs.lincoln.ac.uk) project which has been funded by [JISC](http://jisc.ac.uk) under the Access and Identity Management programme.
This code was principally developed by [Alex Bilbie](http://alexbilbie.com/) ([Twitter](https://twitter.com/alexbilbie)|[Github](https://github.com/alexbilbie)).
Valuable contribtions have been made by the following:
* [Dan Horrigan](http://dandoescode.com) ([Twitter](https://twitter.com/dandoescode)|[Github](https://github.com/dandoescode))
* [Nick Jackson](http://nickjackson.me) ([Twitter](https://twitter.com/jacksonj04)|[Github](https://github.com/jacksonj04))

View File

@@ -1,11 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" stopOnError="false" stopOnFailure="false" stopOnIncomplete="false" stopOnSkipped="false"> <phpunit colors="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" stopOnError="false" stopOnFailure="false" stopOnIncomplete="false" stopOnSkipped="false" bootstrap="../tests/Bootstrap.php">
<testsuites> <testsuites>
<testsuite name="Authentication Server"> <testsuite name="Authentication Server">
<directory suffix="test.php">../tests/authentication</directory> <directory suffix="Test.php">../tests/authentication</directory>
</testsuite> </testsuite>
<testsuite name="Resource Server"> <testsuite name="Resource Server">
<directory suffix="test.php">../tests/resource</directory> <directory suffix="Test.php">../tests/resource</directory>
</testsuite>
<testsuite name="Utility Methods">
<directory suffix="Test.php">../tests/util</directory>
</testsuite> </testsuite>
</testsuites> </testsuites>
<filter> <filter>
@@ -13,10 +16,15 @@
<directory suffix=".php">PEAR_INSTALL_DIR</directory> <directory suffix=".php">PEAR_INSTALL_DIR</directory>
<directory suffix=".php">PHP_LIBDIR</directory> <directory suffix=".php">PHP_LIBDIR</directory>
<directory suffix=".php">../vendor/composer</directory> <directory suffix=".php">../vendor/composer</directory>
<directory suffix=".php">../vendor/mockery</directory>
<directory suffix=".php">../vendor/phpunit</directory>
<directory suffix=".php">../tests</directory>
<directory suffix=".php">../testing</directory>
</blacklist> </blacklist>
</filter> </filter>
<logging> <logging>
<log type="coverage-html" target="coverage" title="lncd/OAuth" charset="UTF-8" yui="true" highlight="true" lowUpperBound="35" highLowerBound="70"/> <log type="coverage-html" target="coverage" title="lncd/OAuth" charset="UTF-8" yui="true" highlight="true" lowUpperBound="50" highLowerBound="90"/>
<log type="coverage-text" target="php://stdout" title="lncd/OAuth" charset="UTF-8" yui="true" highlight="true" lowUpperBound="50" highLowerBound="90"/>
<log type="coverage-clover" target="logs/clover.xml"/> <log type="coverage-clover" target="logs/clover.xml"/>
<log type="junit" target="logs/junit.xml" logIncompleteSkipped="false"/> <log type="junit" target="logs/junit.xml" logIncompleteSkipped="false"/>
</logging> </logging>

View File

@@ -1,15 +1,15 @@
{ {
"name": "lncd/oauth2", "name": "lncd/oauth2",
"description": "OAuth 2.0 Framework", "description": "OAuth 2.0 Framework",
"version": "0.3.3", "version": "1.0.0",
"homepage": "https://github.com/lncd/OAuth2", "homepage": "https://github.com/lncd/OAuth2",
"license": "MIT", "license": "MIT",
"require": { "require": {
"php": ">=5.3.0", "php": ">=5.3.0"
"guzzle/guzzle": "*"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "*" "phpunit/phpunit": "*",
"mockery/mockery": ">=0.7.2"
}, },
"repositories": [ "repositories": [
{ {
@@ -23,7 +23,8 @@
"server", "server",
"authorization", "authorization",
"authentication", "authentication",
"resource" "resource",
"api"
], ],
"authors": [ "authors": [
{ {
@@ -35,10 +36,8 @@
], ],
"autoload": { "autoload": {
"psr-0": { "psr-0": {
"Oauth2": "src/" "OAuth2": "src/"
} }
}, },
"suggest": { "suggest": {}
"lncd/oauth2-facebook": "Adds support for Facebook as an IDP" }
}
}

View File

@@ -1,5 +1,13 @@
-- Create syntax for TABLE 'clients' CREATE TABLE `oauth_client_endpoints` (
CREATE TABLE `clients` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`client_id` varchar(40) NOT NULL DEFAULT '',
`redirect_uri` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `client_id` (`client_id`),
CONSTRAINT `oauth_client_endpoints_ibfk_1` FOREIGN KEY (`client_id`) REFERENCES `oauth_clients` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `oauth_clients` (
`id` varchar(40) NOT NULL DEFAULT '', `id` varchar(40) NOT NULL DEFAULT '',
`secret` varchar(40) NOT NULL DEFAULT '', `secret` varchar(40) NOT NULL DEFAULT '',
`name` varchar(255) NOT NULL DEFAULT '', `name` varchar(255) NOT NULL DEFAULT '',
@@ -7,25 +15,26 @@ CREATE TABLE `clients` (
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Create syntax for TABLE 'client_endpoints' CREATE TABLE `oauth_session_scopes` (
CREATE TABLE `client_endpoints` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT, `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`client_id` varchar(40) NOT NULL DEFAULT '', `session_id` int(11) unsigned NOT NULL,
`redirect_uri` varchar(255) DEFAULT NULL, `scope_id` int(11) unsigned NOT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `client_id` (`client_id`), KEY `session_id` (`session_id`),
CONSTRAINT `client_endpoints_ibfk_1` FOREIGN KEY (`client_id`) REFERENCES `clients` (`id`) ON DELETE CASCADE ON UPDATE CASCADE KEY `scope_id` (`scope_id`),
CONSTRAINT `oauth_session_scopes_ibfk_5` FOREIGN KEY (`scope_id`) REFERENCES `oauth_scopes` (`id`) ON DELETE CASCADE,
CONSTRAINT `oauth_session_scopes_ibfk_4` FOREIGN KEY (`session_id`) REFERENCES `oauth_sessions` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Create syntax for TABLE 'oauth_sessions'
CREATE TABLE `oauth_sessions` ( CREATE TABLE `oauth_sessions` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT, `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`client_id` varchar(40) NOT NULL DEFAULT '', `client_id` varchar(40) NOT NULL DEFAULT '',
`redirect_uri` varchar(250) NOT NULL DEFAULT '', `redirect_uri` varchar(250) DEFAULT '',
`owner_type` enum('user','client') NOT NULL DEFAULT 'user', `owner_type` enum('user','client') NOT NULL DEFAULT 'user',
`owner_id` varchar(255) DEFAULT NULL, `owner_id` varchar(255) DEFAULT '',
`auth_code` varchar(40) DEFAULT '', `auth_code` varchar(40) DEFAULT '',
`access_token` varchar(40) DEFAULT '', `access_token` varchar(40) DEFAULT '',
`refresh_token` varchar(40) DEFAULT '',
`access_token_expires` int(10) DEFAULT NULL, `access_token_expires` int(10) DEFAULT NULL,
`stage` enum('requested','granted') NOT NULL DEFAULT 'requested', `stage` enum('requested','granted') NOT NULL DEFAULT 'requested',
`first_requested` int(10) unsigned NOT NULL, `first_requested` int(10) unsigned NOT NULL,
@@ -34,26 +43,11 @@ CREATE TABLE `oauth_sessions` (
KEY `client_id` (`client_id`) KEY `client_id` (`client_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Create syntax for TABLE 'scopes' CREATE TABLE `oauth_scopes` (
CREATE TABLE `scopes` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT, `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`scope` varchar(255) NOT NULL DEFAULT '', `scope` varchar(255) NOT NULL DEFAULT '',
`name` varchar(255) NOT NULL DEFAULT '', `name` varchar(255) NOT NULL DEFAULT '',
`description` varchar(255) DEFAULT '', `description` varchar(255) DEFAULT '',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `scope` (`scope`) UNIQUE KEY `scope` (`scope`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Create syntax for TABLE 'oauth_session_scopes'
CREATE TABLE `oauth_session_scopes` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`session_id` int(11) unsigned NOT NULL,
`access_token` varchar(40) NOT NULL DEFAULT '',
`scope` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `session_id` (`session_id`),
KEY `access_token` (`access_token`),
KEY `scope` (`scope`),
CONSTRAINT `oauth_session_scopes_ibfk_3` FOREIGN KEY (`scope`) REFERENCES `scopes` (`scope`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `oauth_session_scopes_ibfk_4` FOREIGN KEY (`session_id`) REFERENCES `oauth_sessions` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

408
src/OAuth2/AuthServer.php Normal file
View File

@@ -0,0 +1,408 @@
<?php
/**
* OAuth 2.0 Authentication Server
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2;
use OAuth2\Util\Request;
use OAuth2\Util\SecureKey;
use OAuth2\Storage\SessionInterface;
use OAuth2\Storage\ClientInterface;
use OAuth2\Storage\ScopeInterface;
use OAuth2\Grant\GrantTypeInterface;
/**
* OAuth 2.0 authentication server class
*/
class AuthServer
{
/**
* The delimeter between scopes specified in the scope query string parameter
*
* The OAuth 2 specification states it should be a space but that is stupid
* and everyone excepted Google use a comma instead.
*
* @var string
*/
protected $scopeDelimeter = ',';
/**
* The TTL (time to live) of an access token in seconds (default: 3600)
* @var integer
*/
static protected $expiresIn = 3600;
/**
* The registered grant response types
* @var array
*/
protected $responseTypes = array();
/**
* The client, scope and session storage classes
* @var array
*/
static protected $storages = array();
/**
* The registered grant types
* @var array
*/
static protected $grantTypes = array();
/**
* The request object
* @var Util\RequestInterface
*/
static protected $request = null;
/**
* Exception error codes
* @var array
*/
protected static $exceptionCodes = array(
0 => 'invalid_request',
1 => 'unauthorized_client',
2 => 'access_denied',
3 => 'unsupported_response_type',
4 => 'invalid_scope',
5 => 'server_error',
6 => 'temporarily_unavailable',
7 => 'unsupported_grant_type',
8 => 'invalid_client',
9 => 'invalid_grant'
);
/**
* Exception error messages
* @var array
*/
static protected $exceptionMessages = array(
'invalid_request' => 'The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Check the "%s" parameter.',
'unauthorized_client' => 'The client is not authorized to request an access token using this method.',
'access_denied' => 'The resource owner or authorization server denied the request.',
'unsupported_response_type' => 'The authorization server does not support obtaining an access token using this method.',
'invalid_scope' => 'The requested scope is invalid, unknown, or malformed. Check the "%s" scope.',
'server_error' => 'The authorization server encountered an unexpected condition which prevented it from fulfilling the request.',
'temporarily_unavailable' => 'The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.',
'unsupported_grant_type' => 'The authorization grant type "%s" is not supported by the authorization server',
'invalid_client' => 'Client authentication failed',
'invalid_grant' => 'The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client. Check the "%s" parameter.',
'invalid_credentials' => 'The user credentials were incorrect.',
'invalid_refresh' => 'The refresh token is invalid.',
);
/**
* Get an exception message
*
* @param string $error The error message key
* @return string The error message
*/
public static function getExceptionMessage($error = '')
{
return self::$exceptionMessages[$error];
}
/**
* Get an exception code
*
* @param integer $code The exception code
* @return string The exception code type
*/
public static function getExceptionType($code = 0)
{
return self::$exceptionCodes[$code];
}
/**
* Create a new OAuth2 authentication server
*
* @param ClientInterface $client A class which inherits from Storage/ClientInterface
* @param SessionInterface $session A class which inherits from Storage/SessionInterface
* @param ScopeInterface $scope A class which inherits from Storage/ScopeInterface
*/
public function __construct(ClientInterface $client, SessionInterface $session, ScopeInterface $scope)
{
self::$storages = array(
'client' => $client,
'session' => $session,
'scope' => $scope
);
}
/**
* Enable support for a grant
* @param GrantTypeInterface $grantType A grant class which conforms to Interface/GrantTypeInterface
* @param null|string $identifier An identifier for the grant (autodetected if not passed)
*/
public function addGrantType(GrantTypeInterface $grantType, $identifier = null)
{
if (is_null($identifier)) {
$identifier = $grantType->getIdentifier();
}
self::$grantTypes[$identifier] = $grantType;
if ( ! is_null($grantType->getResponseType())) {
$this->responseTypes[] = $grantType->getResponseType();
}
}
/**
* Check if a grant type has been enabled
* @param string $identifier The grant type identifier
* @return boolean Returns "true" if enabled, "false" if not
*/
public static function hasGrantType($identifier)
{
return (array_key_exists($identifier, self::$grantTypes));
}
/**
* Get the scope delimeter
*
* @return string The scope delimiter (default: ",")
*/
public function getScopeDelimeter()
{
return $this->scopeDelimeter;
}
/**
* Set the scope delimiter
*
* @param string $scopeDelimeter
*/
public function setScopeDelimeter($scopeDelimeter)
{
$this->scopeDelimeter = $scopeDelimeter;
}
/**
* Get the TTL for an access token
* @return int The TTL
*/
public static function getExpiresIn()
{
return self::$expiresIn;
}
/**
* Set the TTL for an access token
* @param int $expiresIn The new TTL
*/
public function setExpiresIn($expiresIn)
{
self::$expiresIn = $expiresIn;
}
/**
* Sets the Request Object
*
* @param Util\RequestInterface The Request Object
*/
public function setRequest(Util\RequestInterface $request)
{
self::$request = $request;
}
/**
* Gets the Request object. It will create one from the globals if one is not set.
*
* @return Util\RequestInterface
*/
public static function getRequest()
{
if (self::$request === null) {
// @codeCoverageIgnoreStart
self::$request = Request::buildFromGlobals();
}
// @codeCoverageIgnoreEnd
return self::$request;
}
/**
* Return a storage class
* @param string $obj The class required
* @return Storage\ClientInterface|Storage\ScopeInterface|Storage\SessionInterface
*/
public static function getStorage($obj)
{
return self::$storages[$obj];
}
/**
* Check authorise parameters
*
* @param array $inputParams Optional array of parsed $_GET keys
* @throws \OAuth2\Exception\ClientException
* @return array Authorise request parameters
*/
public function checkAuthoriseParams($inputParams = array())
{
$authParams = array();
// Client ID
$authParams['client_id'] = (isset($inputParams['client_id'])) ?
$inputParams['client_id'] :
self::getRequest()->get('client_id');
if (is_null($authParams['client_id'])) {
throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_request'], 'client_id'), 0);
}
// Redirect URI
$authParams['redirect_uri'] = (isset($inputParams['redirect_uri'])) ?
$inputParams['redirect_uri'] :
self::getRequest()->get('redirect_uri');
if (is_null($authParams['redirect_uri'])) {
throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_request'], 'redirect_uri'), 0);
}
// Validate client ID and redirect URI
$clientDetails = self::getStorage('client')->getClient($authParams['client_id'], null, $authParams['redirect_uri']);
if ($clientDetails === false) {
throw new Exception\ClientException(self::$exceptionMessages['invalid_client'], 8);
}
$authParams['client_details'] = $clientDetails;
// Response type
$authParams['response_type'] = (isset($inputParams['response_type'])) ?
$inputParams['response_type'] :
self::getRequest()->get('response_type');
if (is_null($authParams['response_type'])) {
throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_request'], 'response_type'), 0);
}
// Ensure response type is one that is recognised
if ( ! in_array($authParams['response_type'], $this->responseTypes)) {
throw new Exception\ClientException(self::$exceptionMessages['unsupported_response_type'], 3);
}
// Get and validate scopes
$scopes = (isset($inputParams['scope'])) ?
$inputParams['scope'] :
self::getRequest()->get('scope', '');
$scopes = explode($this->scopeDelimeter, $scopes);
for ($i = 0; $i < count($scopes); $i++) {
$scopes[$i] = trim($scopes[$i]);
if ($scopes[$i] === '') unset($scopes[$i]); // Remove any junk scopes
}
if (count($scopes) === 0) {
throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_request'], 'scope'), 0);
}
$authParams['scopes'] = array();
foreach ($scopes as $scope) {
$scopeDetails = self::getStorage('scope')->getScope($scope);
if ($scopeDetails === false) {
throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_scope'], $scope), 4);
}
$authParams['scopes'][] = $scopeDetails;
}
return $authParams;
}
/**
* Parse a new authorise request
*
* @param string $type The session owner's type
* @param string $typeId The session owner's ID
* @param array $authParams The authorise request $_GET parameters
* @return string An authorisation code
*/
public function newAuthoriseRequest($type, $typeId, $authParams = array())
{
// Generate an auth code
$authCode = SecureKey::make();
// Remove any old sessions the user might have
self::getStorage('session')->deleteSession($authParams['client_id'], $type, $typeId);
// Create a new session
$sessionId = self::getStorage('session')->createSession($authParams['client_id'], $authParams['redirect_uri'], $type, $typeId, $authCode);
// Associate scopes with the new session
foreach ($authParams['scopes'] as $scope)
{
self::getStorage('session')->associateScope($sessionId, $scope['id']);
}
return $authCode;
}
/**
* Issue an access token
*
* @param array $inputParams Optional array of parsed $_POST keys
* @return array Authorise request parameters
*/
public function issueAccessToken($inputParams = array())
{
$grantType = (isset($inputParams['grant_type'])) ?
$inputParams['grant_type'] :
self::getRequest()->post('grant_type');
if (is_null($grantType)) {
throw new Exception\ClientException(sprintf(self::$exceptionMessages['invalid_request'], 'grant_type'), 0);
}
// Ensure grant type is one that is recognised and is enabled
if ( ! in_array($grantType, array_keys(self::$grantTypes))) {
throw new Exception\ClientException(sprintf(self::$exceptionMessages['unsupported_grant_type'], $grantType), 7);
}
// Complete the flow
return $this->getGrantType($grantType)->completeFlow($inputParams);
}
/**
* Return a grant type class
* @param string $grantType The grant type identifer
* @return class
*/
protected function getGrantType($grantType)
{
return self::$grantTypes[$grantType];
}
/**
* Get a parameter from passed input parameters or the Request class
* @param string|array $param Requried parameter
* @param string $method Get/put/post/delete
* @param array $inputParams Passed input parameters
* @return mixed 'Null' if parameter is missing
*/
public static function getParam($param = '', $method = 'get', $inputParams = array())
{
if (is_string($param)) {
return (isset($inputParams[$param])) ? $inputParams['client_id'] : self::getRequest()->{$method}($param);
} else {
$response = array();
foreach ($param as $p) {
$response[$p] = self::getParam($p, $method, $inputParams);
}
return $response;
}
}
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* OAuth 2.0 Client Exception
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2\Exception;
/**
* ClientException Exception
*/
class ClientException extends OAuth2Exception
{
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* OAuth 2.0 Invalid Access Token Exception
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2\Exception;
/**
* InvalidAccessToken Exception
*/
class InvalidAccessTokenException extends OAuth2Exception
{
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* OAuth 2.0 Invalid Grant Type Exception
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2\Exception;
/**
* InvalidGrantTypeException Exception
*/
class InvalidGrantTypeException extends OAuth2Exception
{
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* OAuth 2.0 Base Exception
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2\Exception;
/**
* Exception class
*/
class OAuth2Exception extends \Exception
{
}

View File

@@ -0,0 +1,132 @@
<?php
/**
* OAuth 2.0 Auth code grant
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2\Grant;
use OAuth2\Request;
use OAuth2\AuthServer;
use OAuth2\Exception;
use OAuth2\Util\SecureKey;
use OAuth2\Storage\SessionInterface;
use OAuth2\Storage\ClientInterface;
use OAuth2\Storage\ScopeInterface;
/**
* Auth code grant class
*/
class AuthCode implements GrantTypeInterface {
/**
* Grant identifier
* @var string
*/
protected $identifier = 'authorization_code';
/**
* Response type
* @var string
*/
protected $responseType = 'code';
/**
* Return the identifier
* @return string
*/
public function getIdentifier()
{
return $this->identifier;
}
/**
* Return the response type
* @return string
*/
public function getResponseType()
{
return $this->responseType;
}
/**
* Complete the auth code grant
* @param null|array $inputParams
* @return array
*/
public function completeFlow($inputParams = null)
{
// Get the required params
$authParams = AuthServer::getParam(array('client_id', 'client_secret', 'redirect_uri', 'code'), 'post', $inputParams);
if (is_null($authParams['client_id'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_id'), 0);
}
if (is_null($authParams['client_secret'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_secret'), 0);
}
if (is_null($authParams['redirect_uri'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'redirect_uri'), 0);
}
// Validate client ID and redirect URI
$clientDetails = AuthServer::getStorage('client')->getClient($authParams['client_id'], $authParams['client_secret'], $authParams['redirect_uri']);
if ($clientDetails === false) {
throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_client'), 8);
}
$authParams['client_details'] = $clientDetails;
// Validate the authorization code
if (is_null($authParams['code'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'code'), 0);
}
// Verify the authorization code matches the client_id and the request_uri
$session = AuthServer::getStorage('session')->validateAuthCode($authParams['client_id'], $authParams['redirect_uri'], $authParams['code']);
if ( ! $session) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_grant'), 'code'), 9);
}
// A session ID was returned so update it with an access token,
// remove the authorisation code, change the stage to 'granted'
$accessToken = SecureKey::make();
$refreshToken = (AuthServer::hasGrantType('refresh_token')) ? SecureKey::make() : null;
$accessTokenExpires = time() + AuthServer::getExpiresIn();
$accessTokenExpiresIn = AuthServer::getExpiresIn();
AuthServer::getStorage('session')->updateSession(
$session['id'],
null,
$accessToken,
$refreshToken,
$accessTokenExpires,
'granted'
);
$response = array(
'access_token' => $accessToken,
'token_type' => 'bearer',
'expires' => $accessTokenExpires,
'expires_in' => $accessTokenExpiresIn
);
if (AuthServer::hasGrantType('refresh_token')) {
$response['refresh_token'] = $refreshToken;
}
return $response;
}
}

View File

@@ -0,0 +1,121 @@
<?php
/**
* OAuth 2.0 Auth code grant
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2\Grant;
use OAuth2\Request;
use OAuth2\AuthServer;
use OAuth2\Exception;
use OAuth2\Util\SecureKey;
use OAuth2\Storage\SessionInterface;
use OAuth2\Storage\ClientInterface;
use OAuth2\Storage\ScopeInterface;
/**
* Client credentials grant class
*/
class ClientCredentials implements GrantTypeInterface {
/**
* Grant identifier
* @var string
*/
protected $identifier = 'client_credentials';
/**
* Response type
* @var string
*/
protected $responseType = null;
/**
* Return the identifier
* @return string
*/
public function getIdentifier()
{
return $this->identifier;
}
/**
* Return the response type
* @return string
*/
public function getResponseType()
{
return $this->responseType;
}
/**
* Complete the client credentials grant
* @param null|array $inputParams
* @return array
*/
public function completeFlow($inputParams = null)
{
// Get the required params
$authParams = AuthServer::getParam(array('client_id', 'client_secret'), 'post', $inputParams);
if (is_null($authParams['client_id'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_id'), 0);
}
if (is_null($authParams['client_secret'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_secret'), 0);
}
// Validate client ID and client secret
$clientDetails = AuthServer::getStorage('client')->getClient($authParams['client_id'], $authParams['client_secret']);
if ($clientDetails === false) {
throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_client'), 8);
}
$authParams['client_details'] = $clientDetails;
// Generate an access token
$accessToken = SecureKey::make();
$refreshToken = (AuthServer::hasGrantType('refresh_token')) ? SecureKey::make() : null;
$accessTokenExpires = time() + AuthServer::getExpiresIn();
$accessTokenExpiresIn = AuthServer::getExpiresIn();
// Delete any existing sessions just to be sure
AuthServer::getStorage('session')->deleteSession($authParams['client_id'], 'client', $authParams['client_id']);
// Create a new session
AuthServer::getStorage('session')->createSession(
$authParams['client_id'],
null,
'client',
$authParams['client_id'],
null,
$accessToken,
$refreshToken,
$accessTokenExpires,
'granted'
);
$response = array(
'access_token' => $accessToken,
'token_type' => 'bearer',
'expires' => $accessTokenExpires,
'expires_in' => $accessTokenExpiresIn
);
if (AuthServer::hasGrantType('refresh_token')) {
$response['refresh_token'] = $refreshToken;
}
return $response;
}
}

View File

@@ -0,0 +1,54 @@
<?php
/**
* OAuth 2.0 Grant type interface
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2\Grant;
use OAuth2\Request;
use OAuth2\AuthServer;
use OAuth2\Exception;
use OAuth2\Util\SecureKey;
use OAuth2\Storage\SessionInterface;
use OAuth2\Storage\ClientInterface;
use OAuth2\Storage\ScopeInterface;
interface GrantTypeInterface
{
/**
* Returns the grant identifier (used to validate grant_type in OAuth2\AuthServer\issueAccessToken())
* @return string
*/
public function getIdentifier();
/**
* Returns the response type (used to validate response_type in OAuth2\AuthServer\checkAuthoriseParams())
* @return null|string
*/
public function getResponseType();
/**
* Complete the grant flow
*
* Example response:
* <code>
* array(
* 'access_token' => (string), // The access token
* 'refresh_token' => (string), // The refresh token (only set if the refresh token grant is enabled)
* 'token_type' => 'bearer', // Almost always "bearer" (exceptions: JWT, SAML)
* 'expires' => (int), // The timestamp of when the access token will expire
* 'expires_in' => (int) // The number of seconds before the access token will expire
* )
* </code>
*
* @param null|array $inputParams Null unless the input parameters have been manually set
* @return array An array of parameters to be passed back to the client
*/
public function completeFlow($inputParams = null);
}

View File

@@ -0,0 +1,164 @@
<?php
/**
* OAuth 2.0 Password grant
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2\Grant;
use OAuth2\Request;
use OAuth2\AuthServer;
use OAuth2\Exception;
use OAuth2\Util\SecureKey;
use OAuth2\Storage\SessionInterface;
use OAuth2\Storage\ClientInterface;
use OAuth2\Storage\ScopeInterface;
/**
* Password grant class
*/
class Password implements GrantTypeInterface {
/**
* Grant identifier
* @var string
*/
protected $identifier = 'password';
/**
* Response type
* @var string
*/
protected $responseType = null;
/**
* Callback to authenticate a user's name and password
* @var function
*/
protected $callback = null;
/**
* Return the identifier
* @return string
*/
public function getIdentifier()
{
return $this->identifier;
}
/**
* Return the response type
* @return string
*/
public function getResponseType()
{
return $this->responseType;
}
/**
* Set the callback to verify a user's username and password
* @param function $callback The callback function
*/
public function setVerifyCredentialsCallback($callback)
{
$this->callback = $callback;
}
/**
* Return the callback function
* @return function
*/
protected function getVerifyCredentialsCallback()
{
if (is_null($this->callback) || ! is_callable($this->callback)) {
throw new Exception\InvalidGrantTypeException('Null or non-callable callback set');
}
return $this->callback;
}
/**
* Complete the password grant
* @param null|array $inputParams
* @return array
*/
public function completeFlow($inputParams = null)
{
// Get the required params
$authParams = AuthServer::getParam(array('client_id', 'client_secret', 'username', 'password'), 'post', $inputParams);
if (is_null($authParams['client_id'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_id'), 0);
}
if (is_null($authParams['client_secret'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_secret'), 0);
}
// Validate client ID and redirect URI
$clientDetails = AuthServer::getStorage('client')->getClient($authParams['client_id'], $authParams['client_secret']);
if ($clientDetails === false) {
throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_client'), 8);
}
$authParams['client_details'] = $clientDetails;
if (is_null($authParams['username'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'username'), 0);
}
if (is_null($authParams['password'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'password'), 0);
}
// Check if user's username and password are correct
$userId = call_user_func($this->getVerifyCredentialsCallback(), $authParams['username'], $authParams['password']);
if ($userId === false) {
throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_credentials'), 0);
}
// Generate an access token
$accessToken = SecureKey::make();
$refreshToken = (AuthServer::hasGrantType('refresh_token')) ? SecureKey::make() : null;
$accessTokenExpires = time() + AuthServer::getExpiresIn();
$accessTokenExpiresIn = AuthServer::getExpiresIn();
// Delete any existing sessions just to be sure
AuthServer::getStorage('session')->deleteSession($authParams['client_id'], 'user', $userId);
// Create a new session
AuthServer::getStorage('session')->createSession(
$authParams['client_id'],
null,
'user',
$userId,
null,
$accessToken,
$refreshToken,
$accessTokenExpires,
'granted'
);
$response = array(
'access_token' => $accessToken,
'token_type' => 'bearer',
'expires' => $accessTokenExpires,
'expires_in' => $accessTokenExpiresIn
);
if (AuthServer::hasGrantType('refresh_token')) {
$response['refresh_token'] = $refreshToken;
}
return $response;
}
}

View File

@@ -0,0 +1,116 @@
<?php
/**
* OAuth 2.0 Refresh token grant
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2\Grant;
use OAuth2\Request;
use OAuth2\AuthServer;
use OAuth2\Exception;
use OAuth2\Util\SecureKey;
use OAuth2\Storage\SessionInterface;
use OAuth2\Storage\ClientInterface;
use OAuth2\Storage\ScopeInterface;
/**
* Referesh token grant
*/
class RefreshToken implements GrantTypeInterface {
/**
* Grant identifier
* @var string
*/
protected $identifier = 'refresh_token';
/**
* Response type
* @var string
*/
protected $responseType = null;
/**
* Return the identifier
* @return string
*/
public function getIdentifier()
{
return $this->identifier;
}
/**
* Return the response type
* @return string
*/
public function getResponseType()
{
return $this->responseType;
}
/**
* Complete the refresh token grant
* @param null|array $inputParams
* @return array
*/
public function completeFlow($inputParams = null)
{
// Get the required params
$authParams = AuthServer::getParam(array('client_id', 'client_secret', 'refresh_token'), 'post', $inputParams);
if (is_null($authParams['client_id'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_id'), 0);
}
if (is_null($authParams['client_secret'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'client_secret'), 0);
}
// Validate client ID and client secret
$clientDetails = AuthServer::getStorage('client')->getClient($authParams['client_id'], $authParams['client_secret']);
if ($clientDetails === false) {
throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_client'), 8);
}
$authParams['client_details'] = $clientDetails;
if (is_null($authParams['refresh_token'])) {
throw new Exception\ClientException(sprintf(AuthServer::getExceptionMessage('invalid_request'), 'refresh_token'), 0);
}
// Validate refresh token
$sessionId = AuthServer::getStorage('client')->validateRefreshToken(
$authParams['refresh_token'],
$authParams['client_id']
);
if ($sessionId === false) {
throw new Exception\ClientException(AuthServer::getExceptionMessage('invalid_refresh'), 0);
}
// Generate new tokens
$accessToken = SecureKey::make();
$refreshToken = (AuthServer::hasGrantType('refresh_token')) ? SecureKey::make() : null;
$accessTokenExpires = time() + AuthServer::getExpiresIn();
$accessTokenExpiresIn = AuthServer::getExpiresIn();
AuthServer::getStorage('session')->updateRefreshToken($sessionId, $accessToken, $refreshToken, $accessTokenExpires);
return array(
'access_token' => $accessToken,
'refresh_token' => $refreshToken,
'token_type' => 'bearer',
'expires' => $accessTokenExpires,
'expires_in' => $accessTokenExpiresIn
);
}
}

View File

@@ -0,0 +1,232 @@
<?php
/**
* OAuth 2.0 Resource Server
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2;
use OutOfBoundsException;
use OAuth2\Storage\SessionInterface;
use OAuth2\Storage\SessionScopeInterface;
use OAuth2\Util\RequestInterface;
use OAuth2\Util\Request;
/**
* OAuth 2.0 Resource Server
*/
class ResourceServer
{
/**
* The access token
* @var string
*/
protected $accessToken = null;
/**
* The session ID
* @var string
*/
protected $sessionId = null;
/**
* The type of the owner of the access token
* @var string
*/
protected $ownerType = null;
/**
* The ID of the owner of the access token
* @var string
*/
protected $ownerId = null;
/**
* The scopes associated with the access token
* @var array
*/
protected $sessionScopes = array();
/**
* The client, scope and session storage classes
* @var array
*/
protected $storages = array();
/**
* The request object
* @var Util\RequestInterface
*/
protected $request = null;
/**
* The query string key which is used by clients to present the access token (default: access_token)
* @var string
*/
protected $tokenKey = 'access_token';
/**
* Sets up the Resource
*
* @param SessionInterface The Session Storage Object
*/
public function __construct(SessionInterface $session)
{
$this->storages['session'] = $session;
}
/**
* Sets the Request Object
*
* @param RequestInterface The Request Object
*/
public function setRequest(RequestInterface $request)
{
$this->request = $request;
}
/**
* Gets the Request object. It will create one from the globals if one is not set.
*
* @return Util\RequestInterface
*/
public function getRequest()
{
if ($this->request === null) {
// @codeCoverageIgnoreStart
$this->request = Request::buildFromGlobals();
}
// @codeCoverageIgnoreEnd
return $this->request;
}
/**
* Returns the query string key for the access token.
*
* @return string
*/
public function getTokenKey()
{
return $this->tokenKey;
}
/**
* Sets the query string key for the access token.
*
* @param $key The new query string key
*/
public function setTokenKey($key)
{
$this->tokenKey = $key;
}
/**
* Gets the access token owner ID.
*
* @return string
*/
public function getOwnerId()
{
return $this->ownerId;
}
/**
* Gets the owner type.
*
* @return string
*/
public function getOwnerType()
{
return $this->ownerType;
}
/**
* Gets the access token.
*
* @return string
*/
public function getAccessToken()
{
return $this->accessToken;
}
/**
* Checks if the access token is valid or not.
*
* @throws Exception\InvalidAccessTokenException Thrown if the presented access token is not valid
* @return bool
*/
public function isValid()
{
$access_token = $this->determineAccessToken();
$result = $this->storages['session']->validateAccessToken($access_token);
if ( ! $result) {
throw new Exception\InvalidAccessTokenException('Access token is not valid');
}
$this->accessToken = $access_token;
$this->sessionId = $result['id'];
$this->ownerType = $result['owner_type'];
$this->ownerId = $result['owner_id'];
$this->sessionScopes = $this->storages['session']->getScopes($this->sessionId);
return true;
}
/**
* Checks if the presented access token has the given scope(s).
*
* @param array|string An array of scopes or a single scope as a string
* @return bool Returns bool if all scopes are found, false if any fail
*/
public function hasScope($scopes)
{
if (is_string($scopes)) {
if (in_array($scopes, $this->sessionScopes)) {
return true;
}
return false;
} elseif (is_array($scopes)) {
foreach ($scopes as $scope) {
if ( ! in_array($scope, $this->sessionScopes)) {
return false;
}
}
return true;
}
return false;
}
/**
* Reads in the access token from the headers.
*
* @throws Exception\MissingAccessTokenException Thrown if there is no access token presented
* @return string
*/
protected function determineAccessToken()
{
if ($header = $this->getRequest()->header('Authorization')) {
$access_token = base64_decode(trim(str_replace('Bearer', '', $header)));
} else {
$method = $this->getRequest()->server('REQUEST_METHOD');
$access_token = $this->getRequest()->{$method}($this->tokenKey);
}
if (empty($access_token)) {
throw new Exception\InvalidAccessTokenException('Access token is missing');
}
return $access_token;
}
}

View File

@@ -0,0 +1,56 @@
<?php
/**
* OAuth 2.0 Client storage interface
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2\Storage;
interface ClientInterface
{
/**
* Validate a client
*
* Example SQL query:
*
* <code>
* # Client ID + redirect URI
* SELECT clients.id FROM clients LEFT JOIN client_endpoints ON
* client_endpoints.client_id = clients.id WHERE clients.id = $clientId AND
* client_endpoints.redirect_uri = $redirectUri
*
* # Client ID + client secret
* SELECT clients.id FROM clients WHERE clients.id = $clientId AND
* clients.secret = $clientSecret
*
* # Client ID + client secret + redirect URI
* SELECT clients.id FROM clients LEFT JOIN client_endpoints ON
* client_endpoints.client_id = clients.id WHERE clients.id = $clientId AND
* clients.secret = $clientSecret AND client_endpoints.redirect_uri =
* $redirectUri
* </code>
*
* Response:
*
* <code>
* Array
* (
* [client_id] => (string) The client ID
* [client secret] => (string) The client secret
* [redirect_uri] => (string) The redirect URI used in this request
* [name] => (string) The name of the client
* )
* </code>
*
* @param string $clientId The client's ID
* @param string $clientSecret The client's secret (default = "null")
* @param string $redirectUri The client's redirect URI (default = "null")
* @return bool|array Returns false if the validation fails, array on success
*/
public function getClient($clientId = null, $clientSecret = null, $redirectUri = null);
}

View File

@@ -0,0 +1,41 @@
<?php
/**
* OAuth 2.0 Scope storage interface
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2\Storage;
interface ScopeInterface
{
/**
* Return information about a scope
*
* Example SQL query:
*
* <code>
* SELECT * FROM scopes WHERE scope = $scope
* </code>
*
* Response:
*
* <code>
* Array
* (
* [id] => (int) The scope's ID
* [scope] => (string) The scope itself
* [name] => (string) The scope's name
* [description] => (string) The scope's description
* )
* </code>
*
* @param string $scope The scope
* @return bool|array If the scope doesn't exist return false
*/
public function getScope($scope);
}

View File

@@ -0,0 +1,251 @@
<?php
/**
* OAuth 2.0 Session storage interface
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2\Storage;
interface SessionInterface
{
/**
* Create a new OAuth session
*
* Example SQL query:
*
* <code>
* INSERT INTO oauth_sessions (client_id, redirect_uri, owner_type,
* owner_id, auth_code, access_token, refresh_token, stage, first_requested,
* last_updated) VALUES ($clientId, $redirectUri, $type, $typeId, $authCode,
* $accessToken, $stage, UNIX_TIMESTAMP(NOW()), UNIX_TIMESTAMP(NOW()))
* </code>
*
* @param string $clientId The client ID
* @param string $redirectUri The redirect URI
* @param string $type The session owner's type (default = "user")
* @param string $typeId The session owner's ID (default = "null")
* @param string $authCode The authorisation code (default = "null")
* @param string $accessToken The access token (default = "null")
* @param string $refreshToken The refresh token (default = "null")
* @param int $accessTokenExpire The expiry time of an access token as a unix timestamp
* @param string $stage The stage of the session (default ="request")
* @return int The session ID
*/
public function createSession(
$clientId,
$redirectUri,
$type = 'user',
$typeId = null,
$authCode = null,
$accessToken = null,
$refreshToken = null,
$accessTokenExpire = null,
$stage = 'requested'
);
/**
* Update an OAuth session
*
* Example SQL query:
*
* <code>
* UPDATE oauth_sessions SET auth_code = $authCode, access_token =
* $accessToken, stage = $stage, last_updated = UNIX_TIMESTAMP(NOW()) WHERE
* id = $sessionId
* </code>
*
* @param string $sessionId The session ID
* @param string $authCode The authorisation code (default = "null")
* @param string $accessToken The access token (default = "null")
* @param string $refreshToken The refresh token (default = "null")
* @param int $accessTokenExpire The expiry time of an access token as a unix timestamp
* @param string $stage The stage of the session (default ="request")
* @return void
*/
public function updateSession(
$sessionId,
$authCode = null,
$accessToken = null,
$refreshToken = null,
$accessTokenExpire = null,
$stage = 'requested'
);
/**
* Delete an OAuth session
*
* <code>
* DELETE FROM oauth_sessions WHERE client_id = $clientId AND owner_type =
* $type AND owner_id = $typeId
* </code>
*
* @param string $clientId The client ID
* @param string $type The session owner's type
* @param string $typeId The session owner's ID
* @return void
*/
public function deleteSession(
$clientId,
$type,
$typeId
);
/**
* Validate that an authorisation code is valid
*
* Example SQL query:
*
* <code>
* SELECT id FROM oauth_sessions WHERE client_id = $clientID AND
* redirect_uri = $redirectUri AND auth_code = $authCode
* </code>
*
* Response:
*
* <code>
* Array
* (
* [id] => (int) The session ID
* [client_id] => (string) The client ID
* [redirect_uri] => (string) The redirect URI
* [owner_type] => (string) The session owner type
* [owner_id] => (string) The session owner's ID
* [auth_code] => (string) The authorisation code
* [stage] => (string) The session's stage
* [first_requested] => (int) Unix timestamp of the time the session was
* first generated
* [last_updated] => (int) Unix timestamp of the time the session was
* last updated
* )
* </code>
*
* @param string $clientId The client ID
* @param string $redirectUri The redirect URI
* @param string $authCode The authorisation code
* @return int|bool Returns the session ID if the auth code
* is valid otherwise returns false
*/
public function validateAuthCode(
$clientId,
$redirectUri,
$authCode
);
/**
* Validate an access token
*
* Example SQL query:
*
* <code>
* SELECT id, owner_id, owner_type FROM oauth_sessions WHERE access_token = $accessToken
* </code>
*
* Response:
*
* <code>
* Array
* (
* [id] => (int) The session ID
* [owner_type] => (string) The owner type
* [owner_id] => (string) The owner ID
* )
* </code>
*
* @param [type] $accessToken [description]
* @return [type] [description]
*/
public function validateAccessToken($accessToken);
/**
* Return the access token for a given session
*
* Example SQL query:
*
* <code>
* SELECT access_token FROM oauth_sessions WHERE id = $sessionId
* </code>
*
* @param int $sessionId The OAuth session ID
* @return string|null Returns the access token as a string if
* found otherwise returns null
*/
public function getAccessToken($sessionId);
/**
* Validate a refresh token
* @param string $refreshToken The refresh token
* @param string $clientId The client ID
* @return int The session ID
*/
public function validateRefreshToken($refreshToken, $clientId);
/**
* Update the refresh token
*
* Example SQL query:
*
* <code>
* UPDATE oauth_sessions SET access_token = $newAccessToken, refresh_token =
* $newRefreshToken, access_toke_expires = $accessTokenExpires, last_updated = UNIX_TIMESTAMP(NOW()) WHERE
* id = $sessionId
* </code>
*
* @param string $sessionId The session ID
* @param string $newAccessToken The new access token for this session
* @param string $newRefreshToken The new refresh token for the session
* @param int $accessTokenExpires The UNIX timestamp of when the new token expires
* @return void
*/
public function updateRefreshToken($sessionId, $newAccessToken, $newRefreshToken, $accessTokenExpires);
/**
* Associates a session with a scope
*
* Example SQL query:
*
* <code>
* INSERT INTO oauth_session_scopes (session_id, scope_id) VALUE ($sessionId,
* $scopeId)
* </code>
*
* @param int $sessionId The session ID
* @param string $scopeId The scope ID
* @return void
*/
public function associateScope($sessionId, $scopeId);
/**
* Return the scopes associated with an access token
*
* Example SQL query:
*
* <code>
* SELECT scopes.scope, scopes.name, scopes.description FROM
* oauth_session_scopes JOIN scopes ON oauth_session_scopes.scope =
* scopes.scope WHERE access_token = $accessToken
* </code>
*
* Response:
*
* <code>
* Array
* (
* [0] => Array
* (
* [scope] => (string) The scope
* [name] => (string) The scope's name
* [description] => (string) The scope's description
* )
* )
* </code>
*
* @param string $accessToken The access token
* @return array
*/
public function getScopes($accessToken);
}

View File

@@ -0,0 +1,31 @@
<?php
/**
* OAuth 2.0 Redirect URI generator
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2\Util;
/**
* RedirectUri class
*/
class RedirectUri
{
/**
* Generate a new redirect uri
* @param string $uri The base URI
* @param array $params The query string parameters
* @param string $queryDelimeter The query string delimeter (default: "?")
* @return string The updated URI
*/
public static function make($uri, $params = array(), $queryDelimeter = '?')
{
$uri .= (strstr($uri, $queryDelimeter) === false) ? $queryDelimeter : '&';
return $uri.http_build_query($params);
}
}

100
src/OAuth2/Util/Request.php Normal file
View File

@@ -0,0 +1,100 @@
<?php
namespace OAuth2\Util;
use OutOfBoundsException;
use InvalidMethodCallException;
use InvalidArgumentException;
class Request implements RequestInterface
{
protected $get = array();
protected $post = array();
protected $cookies = array();
protected $files = array();
protected $server = array();
protected $headers = array();
public static function buildFromGlobals()
{
return new static($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER);
}
public function __construct(array $get = array(), array $post = array(), array $cookies = array(), array $files = array(), array $server = array(), $headers = array())
{
$this->get = $get;
$this->post = $post;
$this->cookies = $cookies;
$this->files = $files;
$this->server = $server;
if (empty($headers)) {
$this->headers = $this->readHeaders();
}
}
public function get($index = null, $default = null)
{
return $this->getPropertyValue('get', $index, $default);
}
public function post($index = null, $default = null)
{
return $this->getPropertyValue('post', $index, $default);
}
public function file($index = null, $default = null)
{
return $this->getPropertyValue('files', $index, $default);
}
public function cookie($index = null, $default = null)
{
return $this->getPropertyValue('cookies', $index, $default);
}
public function server($index = null, $default = null)
{
return $this->getPropertyValue('server', $index, $default);
}
public function header($index = null, $default = null)
{
return $this->getPropertyValue('headers', $index, $default);
}
protected function readHeaders()
{
if (function_exists('getallheaders')) {
// @codeCoverageIgnoreStart
$headers = getallheaders();
} else {
// @codeCoverageIgnoreEnd
$headers = array();
foreach ($this->server() as $name => $value) {
if (substr($name, 0, 5) == 'HTTP_') {
$name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))));
$headers[$name] = $value;
}
}
}
return $headers;
}
protected function getPropertyValue($property, $index = null, $default = null)
{
if ( ! isset($this->{$property})) {
throw new InvalidArgumentException("Property '$property' does not exist.");
}
if (is_null($index)) {
return $this->{$property};
}
if ( ! array_key_exists($index, $this->{$property})) {
return $default;
}
return $this->{$property}[$index];
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace OAuth2\Util;
interface RequestInterface
{
public static function buildFromGlobals();
public function __construct(array $get = array(), array $post = array(), array $cookies = array(), array $files = array(), array $server = array(), $headers = array());
public function get($index = null);
public function post($index = null);
public function cookie($index = null);
public function file($index = null);
public function server($index = null);
public function header($index = null);
}

View File

@@ -0,0 +1,40 @@
<?php
/**
* OAuth 2.0 Secure key generator
*
* @package lncd/oauth2
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) 2013 University of Lincoln
* @license http://mit-license.org/
* @link http://github.com/lncd/oauth2
*/
namespace OAuth2\Util;
/**
* SecureKey class
*/
class SecureKey
{
/**
* Generate a new unique code
* @param integer $len Length of the generated code
* @return string
*/
public static function make($len = 40)
{
// We generate twice as many bytes here because we want to ensure we have
// enough after we base64 encode it to get the length we need because we
// take out the "/", "+", and "=" characters.
$bytes = openssl_random_pseudo_bytes($len * 2, $strong);
// We want to stop execution if the key fails because, well, that is bad.
if ($bytes === false || $strong === false) {
// @codeCoverageIgnoreStart
throw new \Exception('Error Generating Key');
// @codeCoverageIgnoreEnd
}
return substr(str_replace(array('/', '+', '='), '', base64_encode($bytes)), 0, $len);
}
}

View File

@@ -1,332 +0,0 @@
<?php
namespace Oauth2\Authentication;
interface Database
{
/**
* Validate a client
*
* Database query:
*
* <code>
* # Client ID + redirect URI
* SELECT clients.id FROM clients LEFT JOIN client_endpoints ON
* client_endpoints.client_id = clients.id WHERE clients.id = $clientId AND
* client_endpoints.redirect_uri = $redirectUri
*
* # Client ID + client secret
* SELECT clients.id FROM clients WHERE clients.id = $clientId AND
* clients.secret = $clientSecret
*
* # Client ID + client secret + redirect URI
* SELECT clients.id FROM clients LEFT JOIN client_endpoints ON
* client_endpoints.client_id = clients.id WHERE clients.id = $clientId AND
* clients.secret = $clientSecret AND client_endpoints.redirect_uri =
* $redirectUri
* </code>
*
* Response:
*
* <code>
* Array
* (
* [client_id] => (string) The client ID
* [client secret] => (string) The client secret
* [redirect_uri] => (string) The redirect URI used in this request
* [name] => (string) The name of the client
* )
* </code>
*
* @param string $clientId The client's ID
* @param string $clientSecret The client's secret (default = "null")
* @param string $redirectUri The client's redirect URI (default = "null")
* @return bool|array Returns false if the validation fails, array on success
*/
public function validateClient(
$clientId,
$clientSecret = null,
$redirectUri = null
);
/**
* Create a new OAuth session
*
* Database query:
*
* <code>
* INSERT INTO oauth_sessions (client_id, redirect_uri, owner_type,
* owner_id, auth_code, access_token, stage, first_requested, last_updated)
* VALUES ($clientId, $redirectUri, $type, $typeId, $authCode,
* $accessToken, $stage, UNIX_TIMESTAMP(NOW()), UNIX_TIMESTAMP(NOW()))
* </code>
*
* @param string $clientId The client ID
* @param string $redirectUri The redirect URI
* @param string $type The session owner's type (default = "user")
* @param string $typeId The session owner's ID (default = "null")
* @param string $authCode The authorisation code (default = "null")
* @param string $accessToken The access token (default = "null")
* @param string $stage The stage of the session (default ="request")
* @return int The session ID
*/
public function newSession(
$clientId,
$redirectUri,
$type = 'user',
$typeId = null,
$authCode = null,
$accessToken = null,
$accessTokenExpire = null,
$stage = 'requested'
);
/**
* Update an OAuth session
*
* Database query:
*
* <code>
* UPDATE oauth_sessions SET auth_code = $authCode, access_token =
* $accessToken, stage = $stage, last_updated = UNIX_TIMESTAMP(NOW()) WHERE
* id = $sessionId
* </code>
*
* @param string $sessionId The session ID
* @param string $authCode The authorisation code (default = "null")
* @param string $accessToken The access token (default = "null")
* @param string $stage The stage of the session (default ="request")
* @return void
*/
public function updateSession(
$sessionId,
$authCode = null,
$accessToken = null,
$accessTokenExpire = null,
$stage = 'requested'
);
/**
* Delete an OAuth session
*
* <code>
* DELETE FROM oauth_sessions WHERE client_id = $clientId AND owner_type =
* $type AND owner_id = $typeId
* </code>
*
* @param string $clientId The client ID
* @param string $type The session owner's type
* @param string $typeId The session owner's ID
* @return void
*/
public function deleteSession(
$clientId,
$type,
$typeId
);
/**
* Validate that an authorisation code is valid
*
* Database query:
*
* <code>
* SELECT id FROM oauth_sessions WHERE client_id = $clientID AND
* redirect_uri = $redirectUri AND auth_code = $authCode
* </code>
*
* Response:
*
* <code>
* Array
* (
* [id] => (int) The session ID
* [client_id] => (string) The client ID
* [redirect_uri] => (string) The redirect URI
* [owner_type] => (string) The session owner type
* [owner_id] => (string) The session owner's ID
* [auth_code] => (string) The authorisation code
* [stage] => (string) The session's stage
* [first_requested] => (int) Unix timestamp of the time the session was
* first generated
* [last_updated] => (int) Unix timestamp of the time the session was
* last updated
* )
* </code>
*
* @param string $clientId The client ID
* @param string $redirectUri The redirect URI
* @param string $authCode The authorisation code
* @return int|bool Returns the session ID if the auth code
* is valid otherwise returns false
*/
public function validateAuthCode(
$clientId,
$redirectUri,
$authCode
);
/**
* Return the session ID for a given session owner and client combination
*
* Database query:
*
* <code>
* SELECT id FROM oauth_sessions WHERE client_id = $clientId
* AND owner_type = $type AND owner_id = $typeId
* </code>
*
* @param string $type The session owner's type
* @param string $typeId The session owner's ID
* @param string $clientId The client ID
* @return string|null Return the session ID as an integer if
* found otherwise returns false
*/
public function hasSession(
$type,
$typeId,
$clientId
);
/**
* Return the access token for a given session
*
* Database query:
*
* <code>
* SELECT access_token FROM oauth_sessions WHERE id = $sessionId
* </code>
*
* @param int $sessionId The OAuth session ID
* @return string|null Returns the access token as a string if
* found otherwise returns null
*/
public function getAccessToken($sessionId);
/**
* Removes an authorisation code associated with a session
*
* Database query:
*
* <code>
* UPDATE oauth_sessions SET auth_code = NULL WHERE id = $sessionId
* </code>
*
* @param int $sessionId The OAuth session ID
* @return void
*/
public function removeAuthCode($sessionId);
/**
* Sets a sessions access token
*
* Database query:
*
* <code>
* UPDATE oauth_sessions SET access_token = $accessToken WHERE id =
* $sessionId
* </code>
*
* @param int $sessionId The OAuth session ID
* @param string $accessToken The access token
* @return void
*/
public function setAccessToken(
$sessionId,
$accessToken
);
/**
* Associates a session with a scope
*
* Database query:
*
* <code>
* INSERT INTO oauth_session_scopes (session_id, scope) VALUE ($sessionId,
* $scope)
* </code>
*
* @param int $sessionId The session ID
* @param string $scope The scope
* @return void
*/
public function addSessionScope(
$sessionId,
$scope
);
/**
* Return information about a scope
*
* Database query:
*
* <code>
* SELECT * FROM scopes WHERE scope = $scope
* </code>
*
* Response:
*
* <code>
* Array
* (
* [id] => (int) The scope's ID
* [scope] => (string) The scope itself
* [name] => (string) The scope's name
* [description] => (string) The scope's description
* )
* </code>
*
* @param string $scope The scope
* @return array
*/
public function getScope($scope);
/**
* Associate a session's scopes with an access token
*
* Database query:
*
* <code>
* UPDATE oauth_session_scopes SET access_token = $accessToken WHERE
* session_id = $sessionId
* </code>
*
* @param int $sessionId The session ID
* @param string $accessToken The access token
* @return void
*/
public function updateSessionScopeAccessToken(
$sessionId,
$accessToken
);
/**
* Return the scopes associated with an access token
*
* Database query:
*
* <code>
* SELECT scopes.scope, scopes.name, scopes.description FROM
* oauth_session_scopes JOIN scopes ON oauth_session_scopes.scope =
* scopes.scope WHERE access_token = $accessToken
* </code>
*
* Response:
*
* <code>
* Array
* (
* [0] => Array
* (
* [scope] => (string) The scope
* [name] => (string) The scope's name
* [description] => (string) The scope's description
* )
* )
* </code>
*
* @param string $accessToken The access token
* @return array
*/
public function accessTokenScopes($accessToken);
}

View File

@@ -1,557 +0,0 @@
<?php
namespace Oauth2\Authentication;
class ClientException extends \Exception
{
}
class UserException extends \Exception
{
}
class ServerException extends \Exception
{
}
class Server
{
/**
* Reference to the database abstractor
* @var object
*/
private $_db = null;
/**
* Server configuration
* @var array
*/
private $_config = array(
'scope_delimeter' => ',',
'access_token_ttl' => null
);
/**
* Supported response types
* @var array
*/
private $_responseTypes = array(
'code'
);
/**
* Supported grant types
* @var array
*/
private $_grantTypes = array(
'authorization_code'
);
/**
* Exception error codes
* @var array
*/
public $exceptionCodes = array(
0 => 'invalid_request',
1 => 'unauthorized_client',
2 => 'access_denied',
3 => 'unsupported_response_type',
4 => 'invalid_scope',
5 => 'server_error',
6 => 'temporarily_unavailable',
7 => 'unsupported_grant_type',
8 => 'invalid_client',
9 => 'invalid_grant'
);
/**
* Error codes.
*
* To provide i8ln errors just overwrite the keys
*
* @var array
*/
public $errors = array(
'invalid_request' => 'The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Check the "%s" parameter.',
'unauthorized_client' => 'The client is not authorized to request an access token using this method.',
'access_denied' => 'The resource owner or authorization server denied the request.',
'unsupported_response_type' => 'The authorization server does not support obtaining an access token using this method.',
'invalid_scope' => 'The requested scope is invalid, unknown, or malformed. Check the "%s" scope.',
'server_error' => 'The authorization server encountered an unexpected condition which prevented it from fulfilling the request.',
'temporarily_unavailable' => 'The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.',
'unsupported_grant_type' => 'The authorization grant type is not supported by the authorization server',
'invalid_client' => 'Client authentication failed',
'invalid_grant' => 'The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client. Check the "%s" parameter.'
);
/**
* Constructor
*
* @access public
* @param array $options Optional list of options to overwrite the defaults
* @return void
*/
public function __construct($options = null)
{
if ($options !== null) {
$this->options = array_merge($this->_config, $options);
}
}
/**
* Register a database abstrator class
*
* @access public
* @param object $db A class that implements OAuth2ServerDatabase
* @return void
*/
public function registerDbAbstractor($db)
{
$this->_db = $db;
}
/**
* Check client authorise parameters
*
* @access public
* @param array $authParams Optional array of parsed $_GET keys
* @return array Authorise request parameters
*/
public function checkClientAuthoriseParams($authParams = null)
{
$params = array();
// Client ID
if ( ! isset($authParams['client_id']) && ! isset($_GET['client_id'])) {
throw new ClientException(sprintf($this->errors['invalid_request'], 'client_id'), 0);
} else {
$params['client_id'] = (isset($authParams['client_id'])) ?
$authParams['client_id'] :
$_GET['client_id'];
}
// Redirect URI
if ( ! isset($authParams['redirect_uri']) && ! isset($_GET['redirect_uri'])) {
throw new ClientException(sprintf($this->errors['invalid_request'], 'redirect_uri'), 0);
} else {
$params['redirect_uri'] = (isset($authParams['redirect_uri'])) ?
$authParams['redirect_uri'] :
$_GET['redirect_uri'];
}
// Validate client ID and redirect URI
$clientDetails = $this->_dbCall(
'validateClient',
$params['client_id'],
null,
$params['redirect_uri']
);
if ($clientDetails === false) {
throw new ClientException($this->errors['invalid_client'], 8);
}
// Response type
if ( ! isset($authParams['response_type']) && ! isset($_GET['response_type'])) {
throw new ClientException(sprintf($this->errors['invalid_request'], 'response_type'), 0);
} else {
$params['response_type'] = (isset($authParams['response_type'])) ?
$authParams['response_type'] :
$_GET['response_type'];
// Ensure response type is one that is recognised
if ( ! in_array($params['response_type'], $this->_responseTypes)) {
throw new ClientException($this->errors['unsupported_response_type'], 3);
}
}
// Get and validate scopes
if (isset($authParams['scope']) || isset($_GET['scope'])) {
$scopes = (isset($_GET['scope'])) ?
$_GET['scope'] :
$authParams['scope'];
$scopes = explode($this->_config['scope_delimeter'], $scopes);
// Remove any junk scopes
for ($i = 0; $i < count($scopes); $i++) {
$scopes[$i] = trim($scopes[$i]);
if ($scopes[$i] === '') {
unset($scopes[$i]);
}
}
if (count($scopes) === 0) {
throw new ClientException(sprintf($this->errors['invalid_request'], 'scope'), 0);
}
$params['scopes'] = array();
foreach ($scopes as $scope) {
$scopeDetails = $this->_dbCall(
'getScope',
$scope
);
if ($scopeDetails === false) {
throw new ClientException(sprintf($this->errors['invalid_scope'], $scope), 4);
}
$params['scopes'][] = $scopeDetails;
}
}
return $params;
}
/**
* Parse a new authorise request
*
* @param string $type The session owner's type
* @param string $typeId The session owner's ID
* @param array $authoriseParams The authorise request $_GET parameters
* @return string An authorisation code
*/
public function newAuthoriseRequest($type, $typeId, $authoriseParams)
{
// Remove any old sessions the user might have
$this->_dbCall(
'deleteSession',
$authoriseParams['client_id'],
$type,
$typeId
);
// Create the new auth code
$authCode = $this->newAuthCode(
$authoriseParams['client_id'],
'user',
$typeId,
$authoriseParams['redirect_uri'],
$authoriseParams['scopes']
);
return $authCode;
}
/**
* Generate a unique code
*
* Generate a unique code for an authorisation code, or token
*
* @return string A unique code
*/
private function generateCode()
{
return sha1(uniqid(microtime()));
}
/**
* Create a new authorisation code
*
* @param string $clientId The client ID
* @param string $type The type of the owner of the session
* @param string $typeId The session owner's ID
* @param string $redirectUri The redirect URI
* @param array $scopes The requested scopes
* @param string $accessToken The access token (default = null)
* @return string An authorisation code
*/
private function newAuthCode($clientId, $type, $typeId, $redirectUri, $scopes = array(), $accessToken = null)
{
$authCode = $this->generateCode();
// If an access token exists then update the existing session with the
// new authorisation code otherwise create a new session
if ($accessToken !== null) {
$this->_dbCall(
'updateSession',
$clientId,
$type,
$typeId,
$authCode,
$accessToken,
'requested'
);
} else {
// Delete any existing sessions just to be sure
$this->_dbCall('deleteSession', $clientId, $type, $typeId);
// Create a new session
$sessionId = $this->_dbCall(
'newSession',
$clientId,
$redirectUri,
$type,
$typeId,
$authCode,
null,
null,
'requested'
);
// Add the scopes
foreach ($scopes as $key => $scope) {
$this->_dbCall(
'addSessionScope',
$sessionId,
$scope['scope']
);
}
}
return $authCode;
}
/**
* Issue an access token
*
* @access public
*
* @param array $authParams Optional array of parsed $_POST keys
*
* @return array Authorise request parameters
*/
public function issueAccessToken($authParams = null)
{
$params = array();
if ( ! isset($authParams['grant_type']) && ! isset($_POST['grant_type'])) {
throw new ClientException(sprintf($this->errors['invalid_request'], 'grant_type'), 0);
} else {
$params['grant_type'] = (isset($authParams['grant_type'])) ?
$authParams['grant_type'] :
$_POST['grant_type'];
// Ensure grant type is one that is recognised
if ( ! in_array($params['grant_type'], $this->_grantTypes)) {
throw new ClientException($this->errors['unsupported_grant_type'], 7);
}
}
switch ($params['grant_type'])
{
case 'authorization_code': // Authorization code grant
return $this->completeAuthCodeGrant($authParams, $params);
break;
case 'refresh_token': // Refresh token
case 'password': // Resource owner password credentials grant
case 'client_credentials': // Client credentials grant
default: // Unsupported
throw new ServerException($this->errors['server_error'] . 'Tried to process an unsuppported grant type.', 5);
break;
}
}
/**
* Complete the authorisation code grant
*
* @access private
*
* @param array $authParams Array of parsed $_POST keys
* @param array $params Generated parameters from issueAccessToken()
*
* @return array Authorise request parameters
*/
private function completeAuthCodeGrant($authParams = array(), $params = array())
{
// Client ID
if ( ! isset($authParams['client_id']) && ! isset($_POST['client_id'])) {
throw new ClientException(sprintf($this->errors['invalid_request'], 'client_id'), 0);
} else {
$params['client_id'] = (isset($authParams['client_id'])) ?
$authParams['client_id'] :
$_POST['client_id'];
}
// Client secret
if ( ! isset($authParams['client_secret']) && ! isset($_POST['client_secret'])) {
throw new ClientException(sprintf($this->errors['invalid_request'], 'client_secret'), 0);
} else {
$params['client_secret'] = (isset($authParams['client_secret'])) ?
$authParams['client_secret'] :
$_POST['client_secret'];
}
// Redirect URI
if ( ! isset($authParams['redirect_uri']) && ! isset($_POST['redirect_uri'])) {
throw new ClientException(sprintf($this->errors['invalid_request'], 'redirect_uri'), 0);
} else {
$params['redirect_uri'] = (isset($authParams['redirect_uri'])) ?
$authParams['redirect_uri'] :
$_POST['redirect_uri'];
}
// Validate client ID and redirect URI
$clientDetails = $this->_dbCall(
'validateClient',
$params['client_id'],
$params['client_secret'],
$params['redirect_uri']
);
if ($clientDetails === false) {
throw new ClientException($this->errors['invalid_client'], 8);
}
// The authorization code
if ( ! isset($authParams['code']) && ! isset($_POST['code'])) {
throw new ClientException(sprintf($this->errors['invalid_request'], 'code'), 0);
} else {
$params['code'] = (isset($authParams['code'])) ?
$authParams['code'] :
$_POST['code'];
}
// Verify the authorization code matches the client_id and the
// request_uri
$session = $this->_dbCall(
'validateAuthCode',
$params['client_id'],
$params['redirect_uri'],
$params['code']
);
if ( ! $session) {
throw new ClientException(sprintf($this->errors['invalid_grant'], 'code'), 9);
} else {
// A session ID was returned so update it with an access token,
// remove the authorisation code, change the stage to 'granted'
$accessToken = $this->generateCode();
$accessTokenExpires = ($this->_config['access_token_ttl'] === null) ?
null :
time() + $this->_config['access_token_ttl'];
$this->_dbCall(
'updateSession',
$session['id'],
null,
$accessToken,
$accessTokenExpires,
'granted'
);
// Update the session's scopes to reference the access token
$this->_dbCall(
'updateSessionScopeAccessToken',
$session['id'],
$accessToken
);
return array(
'access_token' => $accessToken,
'token_type' => 'bearer',
'expires_in' => $this->_config['access_token_ttl']
);
}
}
/**
* Generates the redirect uri with appended params
*
* @param string $redirectUri The redirect URI
* @param array $params The parameters to be appended to the URL
* @param string $query_delimeter The query string delimiter (default: ?)
*
* @return string The updated redirect URI
*/
public function redirectUri($redirectUri, $params = array(), $queryDelimeter = '?')
{
if (strstr($redirectUri, $queryDelimeter)) {
$redirectUri = $redirectUri . '&' . http_build_query($params);
} else {
$redirectUri = $redirectUri . $queryDelimeter . http_build_query($params);
}
return $redirectUri;
}
/**
* Call database methods from the abstractor
*
* @return mixed The query result
*/
private function _dbCall()
{
if ($this->_db === null) {
throw new ServerException('No registered database abstractor');
}
if ( ! $this->_db instanceof Database) {
throw new ServerException('Registered database abstractor is not an instance of Oauth2\Authentication\Database');
}
$args = func_get_args();
$method = $args[0];
unset($args[0]);
$params = array_values($args);
return call_user_func_array(array($this->_db, $method), $params);
}
}

View File

@@ -1,230 +0,0 @@
<?php
namespace OAuth2\Client;
use Guzzle\Service\Client as GuzzleClient;
class IDPException extends \Exception
{
protected $result;
public function __construct($result)
{
$this->result = $result;
$code = isset($result['code']) ? $result['code'] : 0;
if (isset($result['error'])) {
// OAuth 2.0 Draft 10 style
$message = $result['error'];
} elseif (isset($result['message'])) {
// cURL style
$message = $result['message'];
} else {
$message = 'Unknown Error.';
}
parent::__construct($message['message'], $message['code']);
}
public function getType()
{
if (isset($this->result['error'])) {
$message = $this->result['error'];
if (is_string($message)) {
// OAuth 2.0 Draft 10 style
return $message;
}
}
return 'Exception';
}
/**
* To make debugging easier.
*
* @returns
* The string representation of the error.
*/
public function __toString()
{
$str = $this->getType() . ': ';
if ($this->code != 0) {
$str .= $this->code . ': ';
}
return $str . $this->message;
}
}
abstract class IDP {
public $clientId = '';
public $clientSecret = '';
public $redirectUri = '';
public $name;
public $uidKey = 'uid';
public $scopes = array();
public $method = 'post';
public $scopeSeperator = ',';
public $responseType = 'json';
public function __construct($options)
{
foreach ($options as $option => $value) {
if (isset($this->{$option})) {
$this->{$option} = $value;
}
}
}
abstract public function urlAuthorize();
abstract public function urlAccessToken();
abstract public function urlUserDetails(\Oauth2\Client\Token\Access $token);
abstract public function userDetails($response, \Oauth2\Client\Token\Access $token);
public function authorize($options = array())
{
$state = md5(uniqid(rand(), TRUE));
setcookie($this->name.'_authorize_state', $state);
$params = array(
'client_id' => $this->clientId,
'redirect_uri' => $this->redirectUri,
'state' => $state,
'scope' => is_array($this->scope) ? implode($this->scopeSeperator, $this->scope) : $this->scope,
'response_type' => isset($options['response_type']) ? $options['response_type'] : 'code',
'approval_prompt' => 'force' // - google force-recheck
);
header('Location: ' . $this->urlAuthorize().'?'.http_build_query($params));
exit;
}
public function getAccessToken($code = NULL, $options = array())
{
if ($code === NULL) {
throw new \BadMethodCallException('Missing authorization code');
}
$params = array(
'client_id' => $this->clientId,
'client_secret' => $this->clientSecret,
'grant_type' => isset($options['grantType']) ? $options['grantType'] : 'authorization_code',
);
switch ($params['grant_type']) {
case 'authorization_code':
$params['code'] = $code;
$params['redirect_uri'] = isset($options['redirectUri']) ? $options['redirectUri'] : $this->redirectUri;
break;
case 'refresh_token':
$params['refresh_token'] = $code;
break;
}
try {
switch ($this->method) {
case 'get':
$client = new GuzzleClient($this->urlAccessToken() . '?' . http_build_query($params));
$request = $client->send();
$response = $request->getBody();
break;
case 'post':
$client = new GuzzleClient($this->urlAccessToken());
$request = $client->post(null, null, $params)->send();
$response = $request->getBody();
break;
}
}
catch (\Guzzle\Http\Exception\BadResponseException $e)
{
$raw_response = explode("\n", $e->getResponse());
$response = end($raw_response);
}
switch ($this->responseType) {
case 'json':
$result = json_decode($response, true);
break;
case 'string':
parse_str($response, $result);
break;
}
if (isset($result['error']) && ! empty($result['error'])) {
throw new \Oauth2\Client\IDPException($result);
}
switch ($params['grant_type']) {
case 'authorization_code':
return \Oauth2\Client\Token::factory('access', $result);
break;
case 'refresh_token':
return \Oauth2\Client\Token::factory('refresh', $result);
break;
}
}
public function getUserDetails(\Oauth2\Client\Token\Access $token)
{
$url = $this->urlUserDetails($token);
try {
$client = new GuzzleClient($url);
$request = $client->get()->send();
$response = $request->getBody();
return $this->userDetails(json_decode($response), $token);
}
catch (\Guzzle\Http\Exception\BadResponseException $e)
{
$raw_response = explode("\n", $e->getResponse());
throw new \Oauth2\Client\IDPException(end($raw_response));
}
}
}

View File

@@ -1,19 +0,0 @@
<?php
namespace OAuth2\Client;
class Provider
{
private function __constuct() {}
public static function factory($name, array $options = null)
{
if ( ! class_exists($name)) {
throw new OAuth2\Client\Exception('There is no identity provider called: '.$name);
}
return new $name($options);
}
}

View File

@@ -1,42 +0,0 @@
<?php
class Blooie extends Oauth2\Client\IDP
{
public $scope = array('user.profile', 'user.picture');
public $method = 'POST';
public function urlAuthorize()
{
return 'https://bloo.ie/oauth';
}
public function urlAccessToken()
{
return 'https://bloo.ie/oauth/access_token';
}
public function getUserInfo(Oauth2\Token\Access $token)
{
$url = 'https://graph.facebook.com/me?'.http_build_query(array(
'access_token' => $token->access_token,
));
$user = json_decode(file_get_contents($url));
return array(
'uid' => $user->id,
'nickname' => $user->username,
'name' => $user->name,
'first_name' => $user->first_name,
'last_name' => $user->last_name,
'email' => isset($user->email) ? $user->email : null,
'location' => isset($user->hometown->name) ? $user->hometown->name : null,
'description' => isset($user->bio) ? $user->bio : null,
'image' => 'https://graph.facebook.com/me/picture?type=normal&access_token='.$token->access_token,
'urls' => array(
'Facebook' => $user->link,
),
);
}
}

View File

@@ -1,49 +0,0 @@
<?php
/**
* Facebook OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Phil Sturgeon
* @copyright (c) 2012 HappyNinjas Ltd
* @license http://philsturgeon.co.uk/code/dbad-license
*/
class Facebook extends Oauth2\Client\IDP
{
protected $scope = array('offline_access', 'email', 'read_stream');
public function urlAuthorize()
{
return 'https://www.facebook.com/dialog/oauth';
}
public function urlAccessToken()
{
return 'https://graph.facebook.com/oauth/access_token';
}
public function getUserInfo(Oauth2\Token\Access $token)
{
$url = 'https://graph.facebook.com/me?'.http_build_query(array(
'access_token' => $token->access_token,
));
$user = json_decode(file_get_contents($url));
return array(
'uid' => $user->id,
'nickname' => isset($user->username) ? $user->username : null,
'name' => $user->name,
'first_name' => $user->first_name,
'last_name' => $user->last_name,
'email' => isset($user->email) ? $user->email : null,
'location' => isset($user->hometown->name) ? $user->hometown->name : null,
'description' => isset($user->bio) ? $user->bio : null,
'image' => 'https://graph.facebook.com/me/picture?type=normal&access_token='.$token->access_token,
'urls' => array(
'Facebook' => $user->link,
),
);
}
}

View File

@@ -1,45 +0,0 @@
<?php
/**
* Foursquare OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Phil Sturgeon
* @copyright (c) 2012 HappyNinjas Ltd
* @license http://philsturgeon.co.uk/code/dbad-license
*/
class Foursquare extends Oauth2\Client\IDP
{
public $method = 'POST';
public function urlAuthorize()
{
return 'https://foursquare.com/oauth2/authenticate';
}
public function urlAccessToken()
{
return 'https://foursquare.com/oauth2/access_token';
}
public function getUserInfo(Oauth2\Token\Access $token)
{
$url = 'https://api.foursquare.com/v2/users/self?'.http_build_query(array(
'oauth_token' => $token->access_token,
));
$response = json_decode(file_get_contents($url));
$user = $response->response->user;
// Create a response from the request
return array(
'uid' => $user->id,
'name' => sprintf('%s %s', $user->firstName, $user->lastName),
'email' => $user->contact->email,
'image' => $user->photo,
'location' => $user->homeCity,
);
}
}

View File

@@ -1,43 +0,0 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* GitHub OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Phil Sturgeon
* @copyright (c) 2012 HappyNinjas Ltd
* @license http://philsturgeon.co.uk/code/dbad-license
*/
class OAuth2_Provider_Github extends Oauth2\Client\IDP
{
public function urlAuthorize()
{
return 'https://github.com/login/oauth/authorize';
}
public function urlAccessToken()
{
return 'https://github.com/login/oauth/access_token';
}
public function getUserInfo(Oauth\Token\Access $token)
{
$url = 'https://api.github.com/user?'.http_build_query(array(
'access_token' => $token->access_token,
));
$user = json_decode(file_get_contents($url));
return array(
'uid' => $user->id,
'nickname' => $user->login,
'name' => $user->name,
'email' => $user->email,
'urls' => array(
'GitHub' => 'http://github.com/'.$user->login,
'Blog' => $user->blog,
),
);
}
}

View File

@@ -1,84 +0,0 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Google OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Phil Sturgeon
* @copyright (c) 2012 HappyNinjas Ltd
* @license http://philsturgeon.co.uk/code/dbad-license
*/
class OAuth2_Provider_Google extends OAuth2_Provider
{
/**
* @var string the method to use when requesting tokens
*/
public $method = 'POST';
/**
* @var string scope separator, most use "," but some like Google are spaces
*/
public $scope_seperator = ' ';
public function url_authorize()
{
return 'https://accounts.google.com/o/oauth2/auth';
}
public function url_access_token()
{
return 'https://accounts.google.com/o/oauth2/token';
}
public function __construct(array $options = array())
{
// Now make sure we have the default scope to get user data
empty($options['scope']) and $options['scope'] = array(
'https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/userinfo.email'
);
// Array it if its string
$options['scope'] = (array) $options['scope'];
parent::__construct($options);
}
/*
* Get access to the API
*
* @param string The access code
* @return object Success or failure along with the response details
*/
public function access($code, $options = array())
{
if ($code === null)
{
throw new OAuth2_Exception(array('message' => 'Expected Authorization Code from '.ucfirst($this->name).' is missing'));
}
return parent::access($code, $options);
}
public function get_user_info(OAuth2_Token_Access $token)
{
$url = 'https://www.googleapis.com/oauth2/v1/userinfo?alt=json&'.http_build_query(array(
'access_token' => $token->access_token,
));
$user = json_decode(file_get_contents($url), true);
return array(
'uid' => $user['id'],
'nickname' => url_title($user['name'], '_', true),
'name' => $user['name'],
'first_name' => $user['given_name'],
'last_name' => $user['family_name'],
'email' => $user['email'],
'location' => null,
'image' => (isset($user['picture'])) ? $user['picture'] : null,
'description' => null,
'urls' => array(),
);
}
}

View File

@@ -1,48 +0,0 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Instagram OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Phil Sturgeon
* @copyright (c) 2012 HappyNinjas Ltd
* @license http://philsturgeon.co.uk/code/dbad-license
*/
class OAuth2_Provider_Instagram extends OAuth2_Provider
{
/**
* @var string scope separator, most use "," but some like Google are spaces
*/
public $scope_seperator = '+';
/**
* @var string the method to use when requesting tokens
*/
public $method = 'POST';
public function url_authorize()
{
return 'https://api.instagram.com/oauth/authorize';
}
public function url_access_token()
{
return 'https://api.instagram.com/oauth/access_token';
}
public function get_user_info(OAuth2_Token_Access $token)
{
$user = $token->user;
return array(
'uid' => $user->id,
'nickname' => $user->username,
'name' => $user->full_name,
'image' => $user->profile_picture,
'urls' => array(
'website' => $user->website,
),
);
}
}

View File

@@ -1,36 +0,0 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Mailchimp OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Phil Sturgeon
* @copyright (c) 2012 HappyNinjas Ltd
* @license http://philsturgeon.co.uk/code/dbad-license
*/
class OAuth2_Provider_Mailchimp extends OAuth2_Provider
{
/**
* @var string the method to use when requesting tokens
*/
protected $method = 'POST';
public function url_authorize()
{
return 'https://login.mailchimp.com/oauth2/authorize';
}
public function url_access_token()
{
return 'https://login.mailchimp.com/oauth2/token';
}
public function get_user_info(OAuth2_Token_Access $token)
{
// Create a response from the request
return array(
'uid' => $token->access_token,
);
}
}

View File

@@ -1,73 +0,0 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Mailru OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Lavr Lyndin
*/
class OAuth2_Provider_Mailru extends OAuth2_Provider
{
public $method = 'POST';
public function url_authorize()
{
return 'https://connect.mail.ru/oauth/authorize';
}
public function url_access_token()
{
return 'https://connect.mail.ru/oauth/token';
}
protected function sign_server_server(array $request_params, $secret_key)
{
ksort($request_params);
$params = '';
foreach ($request_params as $key => $value) {
$params .= "$key=$value";
}
return md5($params . $secret_key);
}
public function get_user_info(OAuth2_Token_Access $token)
{
$request_params = array(
'app_id' => $this->client_id,
'method' => 'users.getInfo',
'uids' => $token->uid,
'access_token' => $token->access_token,
'secure' => 1
);
$sig = $this->sign_server_server($request_params,$this->client_secret);
$url = 'http://www.appsmail.ru/platform/api?'.http_build_query($request_params).'&sig='.$sig;
$user = json_decode(file_get_contents($url));
return array(
'uid' => $user[0]->uid,
'nickname' => $user[0]->nick,
'name' => $user[0]->first_name.' '.$user[0]->last_name,
'first_name' => $user[0]->first_name,
'last_name' => $user[0]->last_name,
'email' => isset($user[0]->email) ? $user[0]->email : null,
'image' => isset($user[0]->pic_big) ? $user[0]->pic_big : null,
);
}
public function authorize($options = array())
{
$state = md5(uniqid(rand(), TRUE));
get_instance()->session->set_userdata('state', $state);
$params = array(
'client_id' => $this->client_id,
'redirect_uri' => isset($options['redirect_uri']) ? $options['redirect_uri'] : $this->redirect_uri,
'response_type' => 'code',
);
redirect($this->url_authorize().'?'.http_build_query($params));
}
}

View File

@@ -1,59 +0,0 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* PayPal OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Phil Sturgeon
* @copyright (c) 2012 HappyNinjas Ltd
* @license http://philsturgeon.co.uk/code/dbad-license
*/
class OAuth2_Provider_Paypal extends OAuth2_Provider
{
/**
* @var string default scope (useful if a scope is required for user info)
*/
protected $scope = array('https://identity.x.com/xidentity/resources/profile/me');
/**
* @var string the method to use when requesting tokens
*/
protected $method = 'POST';
public function url_authorize()
{
return 'https://identity.x.com/xidentity/resources/authorize';
}
public function url_access_token()
{
return 'https://identity.x.com/xidentity/oauthtokenservice';
}
public function get_user_info(OAuth2_Token_Access $token)
{
$url = 'https://identity.x.com/xidentity/resources/profile/me?' . http_build_query(array(
'oauth_token' => $token->access_token
));
$user = json_decode(file_get_contents($url));
$user = $user->identity;
return array(
'uid' => $user['userId'],
'nickname' => url_title($user['fullName'], '_', true),
'name' => $user['fullName'],
'first_name' => $user['firstName'],
'last_name' => $user['lastName'],
'email' => $user['emails'][0],
'location' => $user->addresses[0],
'image' => null,
'description' => null,
'urls' => array(
'PayPal' => null
)
);
}
}

View File

@@ -1,51 +0,0 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Soundcloud OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Phil Sturgeon
* @copyright (c) 2012 HappyNinjas Ltd
* @license http://philsturgeon.co.uk/code/dbad-license
*/
class OAuth2_Provider_Soundcloud extends OAuth2_Provider
{
/**
* @var string the method to use when requesting tokens
*/
protected $method = 'POST';
public function url_authorize()
{
return 'https://soundcloud.com/connect';
}
public function url_access_token()
{
return 'https://api.soundcloud.com/oauth2/token';
}
public function get_user_info(OAuth2_Token_Access $token)
{
$url = 'https://api.soundcloud.com/me.json?'.http_build_query(array(
'oauth_token' => $token->access_token,
));
$user = json_decode(file_get_contents($url));
// Create a response from the request
return array(
'uid' => $user->id,
'nickname' => $user->username,
'name' => $user->full_name,
'location' => $user->country.' ,'.$user->country,
'description' => $user->description,
'image' => $user->avatar_url,
'urls' => array(
'MySpace' => $user->myspace_name,
'Website' => $user->website,
),
);
}
}

View File

@@ -1,54 +0,0 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Vkontakte OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Lavr Lyndin
*/
class OAuth2_Provider_Vkontakte extends OAuth2_Provider
{
protected $method = 'POST';
public $uid_key = 'user_id';
public function url_authorize()
{
return 'http://oauth.vk.com/authorize';
}
public function url_access_token()
{
return 'https://oauth.vk.com/access_token';
}
public function get_user_info(OAuth2_Token_Access $token)
{
$scope = array('nickname', 'screen_name','photo_big');
$url = 'https://api.vk.com/method/users.get?'.http_build_query(array(
'uids' => $token->uid,
'fields' => implode(",",$scope),
'access_token' => $token->access_token,
));
$user = json_decode(file_get_contents($url))->response;
if(sizeof($user)==0)
return null;
else
$user = $user[0];
return array(
'uid' => $user->uid,
'nickname' => isset($user->nickname) ? $user->nickname : null,
'name' => isset($user->name) ? $user->name : null,
'first_name' => isset($user->first_name) ? $user->first_name : null,
'last_name' => isset($user->last_name) ? $user->last_name : null,
'email' => null,
'location' => null,
'description' => null,
'image' => isset($user->photo_big) ? $user->photo_big : null,
'urls' => array(),
);
}
}

View File

@@ -1,60 +0,0 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Windows Live OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Phil Sturgeon
* @copyright (c) 2012 HappyNinjas Ltd
* @license http://philsturgeon.co.uk/code/dbad-license
*/
class OAuth2_Provider_Windowslive extends OAuth2_Provider
{
protected $scope = array('wl.basic', 'wl.emails');
/**
* @var string the method to use when requesting tokens
*/
protected $method = 'POST';
// authorise url
public function url_authorize()
{
return 'https://oauth.live.com/authorize';
}
// access token url
public function url_access_token()
{
return 'https://oauth.live.com/token';
}
// get basic user information
/********************************
** this can be extended through the
** use of scopes, check out the document at
** http://msdn.microsoft.com/en-gb/library/hh243648.aspx#user
*********************************/
public function get_user_info(OAuth2_Token_Access $token)
{
// define the get user information token
$url = 'https://apis.live.net/v5.0/me?'.http_build_query(array(
'access_token' => $token->access_token,
));
// perform network request
$user = json_decode(file_get_contents($url));
// create a response from the request and return it
return array(
'uid' => $user->id,
'name' => $user->name,
'nickname' => url_title($user->name, '_', true),
// 'location' => $user[''], # scope wl.postal_addresses is required
# but won't be implemented by default
'locale' => $user->locale,
'urls' => array('Windows Live' => $user->link),
);
}
}

View File

@@ -1,115 +0,0 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Yandex OAuth2 Provider
*
* @package CodeIgniter/OAuth2
* @category Provider
* @author Lavr Lyndin
*/
class OAuth2_Provider_Yandex extends OAuth2_Provider
{
public $method = 'POST';
public function url_authorize()
{
return 'https://oauth.yandex.ru/authorize';
}
public function url_access_token()
{
return 'https://oauth.yandex.ru/token';
}
public function get_user_info(OAuth2_Token_Access $token)
{
$opts = array(
'http' => array(
'method' => 'GET',
'header' => 'Authorization: OAuth '.$token->access_token
)
);
$_default_opts = stream_context_get_params(stream_context_get_default());
$opts = array_merge_recursive($_default_opts['options'], $opts);
$context = stream_context_create($opts);
$url = 'http://api-yaru.yandex.ru/me/?format=json';
$user = json_decode(file_get_contents($url,false,$context));
preg_match("/\d+$/",$user->id,$uid);
return array(
'uid' => $uid[0],
'nickname' => isset($user->name) ? $user->name : null,
'name' => isset($user->name) ? $user->name : null,
'first_name' => isset($user->first_name) ? $user->first_name : null,
'last_name' => isset($user->last_name) ? $user->last_name : null,
'email' => isset($user->email) ? $user->email : null,
'location' => isset($user->hometown->name) ? $user->hometown->name : null,
'description' => isset($user->bio) ? $user->bio : null,
'image' => $user->links->userpic,
);
}
public function access($code, $options = array())
{
$params = array(
'client_id' => $this->client_id,
'client_secret' => $this->client_secret,
'grant_type' => isset($options['grant_type']) ? $options['grant_type'] : 'authorization_code',
);
switch ($params['grant_type'])
{
case 'authorization_code':
$params['code'] = $code;
$params['redirect_uri'] = isset($options['redirect_uri']) ? $options['redirect_uri'] : $this->redirect_uri;
break;
case 'refresh_token':
$params['refresh_token'] = $code;
break;
}
$response = null;
$url = $this->url_access_token();
$curl = curl_init($url);
$headers[] = 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8;';
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
// curl_setopt($curl, CURLOPT_USERAGENT, 'yamolib-php');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($curl, CURLOPT_TIMEOUT, 80);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($params));
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
// curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
// curl_setopt($curl, CURLOPT_CAINFO, dirname(__FILE__) . '/../data/ca-certificate.crt');
$response = curl_exec($curl);
curl_close($curl);
$return = json_decode($response, true);
if ( ! empty($return['error']))
{
throw new OAuth2_Exception($return);
}
switch ($params['grant_type'])
{
case 'authorization_code':
return OAuth2_Token::factory('access', $return);
break;
case 'refresh_token':
return OAuth2_Token::factory('refresh', $return);
break;
}
}
}

View File

@@ -1,46 +0,0 @@
<?php
namespace Oauth2\Client;
abstract class Token
{
/**
* Create a new token object.
*
* @param string token type
* @param array token options
* @return Token
*/
public static function factory($name = 'access', array $options = null)
{
include_once 'Token/'.ucfirst(strtolower($name)).'.php';
$class = 'Oauth2\Client\Token\\'.ucfirst($name);
return new $class($options);
}
/**
* Return the value of any protected class variable.
*
* @param string variable name
* @return mixed
*/
public function __get($key)
{
return $this->$key;
}
/**
* Return a boolean if the property is set
*
* @param string variable name
* @return bool
*/
public function __isset($key)
{
return isset($this->$key);
}
} // End Token

View File

@@ -1,79 +0,0 @@
<?php
namespace Oauth2\Client\Token;
/**
* OAuth2 Token
*
* @package OAuth2
* @category Token
* @author Phil Sturgeon
* @copyright (c) 2011 HappyNinjas Ltd
*/
class Access extends \Oauth2\Client\Token
{
/**
* @var string accessToken
*/
protected $accessToken;
/**
* @var int expires
*/
protected $expires;
/**
* @var string refreshToken
*/
protected $refreshToken;
/**
* @var string uid
*/
protected $uid;
/**
* Sets the token, expiry, etc values.
*
* @param array token options
* @return void
*/
public function __construct(array $options = null)
{
if ( ! isset($options['access_token'])) {
throw new \BadMethodCallException('Required option not passed: access_token'.PHP_EOL.print_r($options, true));
}
$this->accessToken = $options['access_token'];
// Some providers (not many) give the uid here, so lets take it
isset($options['uid']) and $this->uid = $options['uid'];
//Vkontakte uses user_id instead of uid
isset($options['user_id']) and $this->uid = $options['user_id'];
//Mailru uses x_mailru_vid instead of uid
isset($options['x_mailru_vid']) and $this->uid = $options['x_mailru_vid'];
// We need to know when the token expires, add num. seconds to current time
isset($options['expires_in']) and $this->expires = time() + ((int) $options['expires_in']);
// Facebook is just being a spec ignoring jerk
isset($options['expires']) and $this->expires = time() + ((int) $options['expires']);
// Grab a refresh token so we can update access tokens when they expires
isset($options['refresh_token']) and $this->refreshToken = $options['refresh_token'];
}
/**
* Returns the token key.
*
* @return string
*/
public function __toString()
{
return (string) $this->accessToken;
}
}

View File

@@ -1,55 +0,0 @@
<?php
/**
* OAuth2 Token
*
* @package OAuth2
* @category Token
* @author Phil Sturgeon
* @copyright (c) 2011 HappyNinjas Ltd
*/
class Authorize extends \Oauth2\Client\Token
{
/**
* @var string code
*/
protected $code;
/**
* @var string redirect_uri
*/
protected $redirectUri;
/**
* Sets the token, expiry, etc values.
*
* @param array token options
* @return void
*/
public function __construct(array $options)
{
if ( ! isset($options['code'])) {
throw new Exception('Required option not passed: code');
} elseif ( ! isset($options['redirect_uri'])) {
throw new Exception('Required option not passed: redirect_uri');
}
$this->code = $options['code'];
$this->redirectUri = $options['redirect_uri'];
}
/**
* Returns the token key.
*
* @return string
*/
public function __toString()
{
return (string) $this->code;
}
}

View File

@@ -1,59 +0,0 @@
<?php
namespace Oauth2\Resource;
interface Database
{
/**
* Validate an access token and return the session details.
*
* Database query:
*
* <code>
* SELECT id, owner_type, owner_id FROM oauth_sessions WHERE access_token =
* $accessToken AND stage = 'granted' AND
* access_token_expires > UNIX_TIMESTAMP(now())
* </code>
*
* Response:
*
* <code>
* Array
* (
* [id] => (int) The session ID
* [owner_type] => (string) The session owner type
* [owner_id] => (string) The session owner's ID
* )
* </code>
*
* @param string $accessToken The access token
* @return array|bool Return an array on success or false on failure
*/
public function validateAccessToken($accessToken);
/**
* Returns the scopes that the session is authorised with.
*
* Database query:
*
* <code>
* SELECT scope FROM oauth_session_scopes WHERE session_id =
* $sessionId
* </code>
*
* Response:
*
* <code>
* Array
* (
* [0] => (string) A scope
* [1] => (string) Another scope
* ...
* )
* </code>
*
* @param int $sessionId The session ID
* @return array A list of scopes
*/
public function sessionScopes($sessionId);
}

View File

@@ -1,253 +0,0 @@
<?php
namespace Oauth2\Resource;
class ServerException extends \Exception
{
}
class ClientException extends \Exception
{
}
class Server
{
/**
* Reference to the database abstractor
* @var object
*/
private $_db = null;
/**
* The access token.
* @access private
*/
private $_accessToken = null;
/**
* The scopes the access token has access to.
* @access private
*/
private $_scopes = array();
/**
* The type of owner of the access token.
* @access private
*/
private $_type = null;
/**
* The ID of the owner of the access token.
* @access private
*/
private $_typeId = null;
/**
* Server configuration
* @var array
*/
private $_config = array(
'token_key' => 'oauth_token'
);
/**
* Error codes.
*
* To provide i8ln errors just overwrite the keys
*
* @var array
*/
public $errors = array(
'missing_access_token' => 'An access token was not presented with the request',
'invalid_access_token' => 'The access token is not registered with the resource server',
'missing_access_token_details' => 'The registered database abstractor did not return a valid access token details response',
'invalid_access_token_scopes' => 'The registered database abstractor did not return a valid access token scopes response',
);
/**
* Constructor
*
* @access public
* @return void
*/
public function __construct($options = null)
{
if ($options !== null) {
$this->config = array_merge($this->config, $options);
}
}
/**
* Magic method to test if access token represents a particular owner type
* @param string $method The method name
* @param mixed $arguements The method arguements
* @return bool If method is valid, and access token is owned by the requested party then true,
*/
public function __call($method, $arguements = null)
{
if (substr($method, 0, 2) === 'is') {
if ($this->_type === strtolower(substr($method, 2))) {
return $this->_typeId;
}
return false;
}
trigger_error('Call to undefined function ' . $method . '()');
}
/**
* Register a database abstrator class
*
* @access public
* @param object $db A class that implements OAuth2ServerDatabase
* @return void
*/
public function registerDbAbstractor($db)
{
$this->_db = $db;
}
/**
* Init function
*
* @access public
* @return void
*/
public function init()
{
$accessToken = null;
$_SERVER['REQUEST_METHOD'] = isset($_SERVER['REQUEST_METHOD']) ?
$_SERVER['REQUEST_METHOD'] :
null;
// Try and get the access token via an access_token or oauth_token parameter
switch ($_SERVER['REQUEST_METHOD'])
{
case 'POST':
$accessToken = isset($_POST[$this->_config['token_key']]) ?
$_POST[$this->_config['token_key']] :
null;
break;
default:
$accessToken = isset($_GET[$this->_config['token_key']]) ?
$_GET[$this->_config['token_key']] :
null;
break;
}
// Try and get an access token from the auth header
if (function_exists('getallheaders')) {
$headers = getallheaders();
if (isset($headers['Authorization'])) {
$rawToken = trim(str_replace('Bearer', '', $headers['Authorization']));
if ( ! empty($rawToken)) {
$accessToken = $rawToken;
}
}
}
if ($accessToken) {
$result = $this->_dbCall('validateAccessToken', $accessToken);
if ($result === false) {
throw new ClientException($this->errors['invalid_access_token']);
} else {
if ( ! array_key_exists('id', $result) ||
! array_key_exists('owner_id', $result) ||
! array_key_exists('owner_type', $result)) {
throw new ServerException($this->errors['missing_access_token_details']);
}
$this->_accessToken = $accessToken;
$this->_type = $result['owner_type'];
$this->_typeId = $result['owner_id'];
// Get the scopes
$scopes = $this->_dbCall('sessionScopes', $result['id']);
if ( ! is_array($scopes))
{
throw new ServerException($this->errors['invalid_access_token_scopes']);
}
$this->_scopes = $scopes;
}
} else {
throw new ClientException($this->errors['missing_access_token']);
}
}
/**
* Test if the access token has a specific scope
*
* @param mixed $scopes Scope(s) to check
*
* @access public
* @return string|bool
*/
public function hasScope($scopes)
{
if (is_string($scopes)) {
if (in_array($scopes, $this->_scopes)) {
return true;
}
return false;
} elseif (is_array($scopes)) {
foreach ($scopes as $scope) {
if ( ! in_array($scope, $this->_scopes)) {
return false;
}
}
return true;
}
return false;
}
/**
* Call database methods from the abstractor
*
* @return mixed The query result
*/
private function _dbCall()
{
if ($this->_db === null) {
throw new ServerException('No registered database abstractor');
}
if ( ! $this->_db instanceof Database) {
throw new ServerException('The registered database abstractor is not an instance of Oauth2\Resource\Database');
}
$args = func_get_args();
$method = $args[0];
unset($args[0]);
$params = array_values($args);
return call_user_func_array(array($this->_db, $method), $params);
}
}

6
tests/Bootstrap.php Normal file
View File

@@ -0,0 +1,6 @@
<?php
if ( ! @include_once __DIR__ . '/../vendor/autoload.php')
{
exit("You must set up the project dependencies, run the following commands:\n> wget http://getcomposer.org/composer.phar\n> php composer.phar install\n");
}

View File

@@ -0,0 +1,606 @@
<?php
use \Mockery as m;
class Authentication_Server_test extends PHPUnit_Framework_TestCase
{
private $client;
private $session;
private $scope;
public function setUp()
{
$this->client = M::mock('OAuth2\Storage\ClientInterface');
$this->session = M::mock('OAuth2\Storage\SessionInterface');
$this->scope = M::mock('OAuth2\Storage\ScopeInterface');
}
private function returnDefault()
{
return new OAuth2\AuthServer($this->client, $this->session, $this->scope);
}
/**
* @expectedException PHPUnit_Framework_Error
*/
public function test__construct_NoStorage()
{
$a = new OAuth2\AuthServer;
}
public function test__contruct_WithStorage()
{
$a = $this->returnDefault();
}
public function test_getExceptionMessage()
{
$m = OAuth2\AuthServer::getExceptionMessage('access_denied');
$reflector = new ReflectionClass($this->returnDefault());
$exceptionMessages = $reflector->getProperty('exceptionMessages');
$exceptionMessages->setAccessible(true);
$v = $exceptionMessages->getValue();
$this->assertEquals($v['access_denied'], $m);
}
public function test_getExceptionCode()
{
$this->assertEquals('access_denied', OAuth2\AuthServer::getExceptionType(2));
}
public function test_hasGrantType()
{
$this->assertFalse(OAuth2\AuthServer::hasGrantType('test'));
}
public function test_addGrantType()
{
$a = $this->returnDefault();
$grant = M::mock('OAuth2\Grant\GrantTypeInterface');
$grant->shouldReceive('getResponseType')->andReturn('test');
$a->addGrantType($grant, 'test');
$this->assertTrue(OAuth2\AuthServer::hasGrantType('test'));
}
public function test_addGrantType_noIdentifier()
{
$a = $this->returnDefault();
$grant = M::mock('OAuth2\Grant\GrantTypeInterface');
$grant->shouldReceive('getIdentifier')->andReturn('test');
$grant->shouldReceive('getResponseType')->andReturn('test');
$a->addGrantType($grant);
$this->assertTrue(OAuth2\AuthServer::hasGrantType('test'));
}
public function test_getScopeDelimeter()
{
$a = $this->returnDefault();
$this->assertEquals(',', $a->getScopeDelimeter());
}
public function test_setScopeDelimeter()
{
$a = $this->returnDefault();
$a->setScopeDelimeter(';');
$this->assertEquals(';', $a->getScopeDelimeter());
}
public function test_getExpiresIn()
{
$a = $this->returnDefault();
$a->setExpiresIn(7200);
$this->assertEquals(7200, $a::getExpiresIn());
}
public function test_setExpiresIn()
{
$a = $this->returnDefault();
$a->setScopeDelimeter(';');
$this->assertEquals(';', $a->getScopeDelimeter());
}
public function test_setRequest()
{
$a = $this->returnDefault();
$request = new OAuth2\Util\Request();
$a->setRequest($request);
$reflector = new ReflectionClass($a);
$requestProperty = $reflector->getProperty('request');
$requestProperty->setAccessible(true);
$v = $requestProperty->getValue();
$this->assertTrue($v instanceof OAuth2\Util\RequestInterface);
}
public function test_getRequest()
{
$a = $this->returnDefault();
$request = new OAuth2\Util\Request();
$a->setRequest($request);
$v = $a::getRequest();
$this->assertTrue($v instanceof OAuth2\Util\RequestInterface);
}
public function test_getStorage()
{
$a = $this->returnDefault();
$this->assertTrue($a->getStorage('session') instanceof OAuth2\Storage\SessionInterface);
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_checkAuthoriseParams_noClientId()
{
$a = $this->returnDefault();
$a->checkAuthoriseParams();
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_checkAuthoriseParams_noRedirectUri()
{
$a = $this->returnDefault();
$a->checkAuthoriseParams(array(
'client_id' => 1234
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 8
*/
public function test_checkAuthoriseParams_badClient()
{
$this->client->shouldReceive('getClient')->andReturn(false);
$a = $this->returnDefault();
$a->checkAuthoriseParams(array(
'client_id' => 1234,
'redirect_uri' => 'http://foo/redirect'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_checkAuthoriseParams_missingResponseType()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$a = $this->returnDefault();
$a->checkAuthoriseParams(array(
'client_id' => 1234,
'redirect_uri' => 'http://foo/redirect'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 3
*/
public function test_checkAuthoriseParams_badResponseType()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$a = $this->returnDefault();
$a->checkAuthoriseParams(array(
'client_id' => 1234,
'redirect_uri' => 'http://foo/redirect',
'response_type' => 'foo'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_checkAuthoriseParams_missingScopes()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$a->checkAuthoriseParams(array(
'client_id' => 1234,
'redirect_uri' => 'http://foo/redirect',
'response_type' => 'code',
'scope' => ''
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 4
*/
public function test_checkAuthoriseParams_badScopes()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->scope->shouldReceive('getScope')->andReturn(false);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$a->checkAuthoriseParams(array(
'client_id' => 1234,
'redirect_uri' => 'http://foo/redirect',
'response_type' => 'code',
'scope' => 'foo'
));
}
public function test_checkAuthoriseParams_passedInput()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->scope->shouldReceive('getScope')->andReturn(array(
'id' => 1,
'scope' => 'foo',
'name' => 'Foo Name',
'description' => 'Foo Name Description'
));
$v = $a->checkAuthoriseParams(array(
'client_id' => 1234,
'redirect_uri' => 'http://foo/redirect',
'response_type' => 'code',
'scope' => 'foo'
));
$this->assertEquals(array(
'client_id' => 1234,
'redirect_uri' => 'http://foo/redirect',
'client_details' => array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
),
'response_type' => 'code',
'scopes' => array(
array(
'id' => 1,
'scope' => 'foo',
'name' => 'Foo Name',
'description' => 'Foo Name Description'
)
)
), $v);
}
public function test_checkAuthoriseParams()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->scope->shouldReceive('getScope')->andReturn(array(
'id' => 1,
'scope' => 'foo',
'name' => 'Foo Name',
'description' => 'Foo Name Description'
));
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$_GET['client_id'] = 1234;
$_GET['redirect_uri'] = 'http://foo/redirect';
$_GET['response_type'] = 'code';
$_GET['scope'] = 'foo';
$request = new OAuth2\Util\Request($_GET);
$a->setRequest($request);
$v = $a->checkAuthoriseParams();
$this->assertEquals(array(
'client_id' => 1234,
'redirect_uri' => 'http://foo/redirect',
'client_details' => array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
),
'response_type' => 'code',
'scopes' => array(
array(
'id' => 1,
'scope' => 'foo',
'name' => 'Foo Name',
'description' => 'Foo Name Description'
)
)
), $v);
}
function test_newAuthoriseRequest()
{
$this->session->shouldReceive('deleteSession')->andReturn(null);
$this->session->shouldReceive('createSession')->andReturn(1);
$this->session->shouldReceive('associateScope')->andReturn(null);
$a = $this->returnDefault();
$params = array(
'client_id' => 1234,
'redirect_uri' => 'http://foo/redirect',
'client_details' => array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
),
'response_type' => 'code',
'scopes' => array(
array(
'id' => 1,
'scope' => 'foo',
'name' => 'Foo Name',
'description' => 'Foo Name Description'
)
)
);
$v = $a->newAuthoriseRequest('user', 123, $params);
$this->assertEquals(40, strlen($v));
}
public function test_getGrantType()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$reflector = new ReflectionClass($a);
$method = $reflector->getMethod('getGrantType');
$method->setAccessible(true);
$result = $method->invoke($a, 'authorization_code');
$this->assertTrue($result instanceof OAuth2\Grant\GrantTypeInterface);
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_missingGrantType()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$v = $a->issueAccessToken();
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 7
*/
public function test_issueAccessToken_badGrantType()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$v = $a->issueAccessToken(array('grant_type' => 'foo'));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_missingClientId()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$v = $a->issueAccessToken(array(
'grant_type' => 'authorization_code'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_missingClientSecret()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$v = $a->issueAccessToken(array(
'grant_type' => 'authorization_code',
'client_id' => 1234
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_missingRedirectUri()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$v = $a->issueAccessToken(array(
'grant_type' => 'authorization_code',
'client_id' => 1234,
'client_secret' => 5678
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 8
*/
public function test_issueAccessToken_badClient()
{
$this->client->shouldReceive('getClient')->andReturn(false);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$v = $a->issueAccessToken(array(
'grant_type' => 'authorization_code',
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_missingCode()
{
$this->client->shouldReceive('getClient')->andReturn(array());
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$v = $a->issueAccessToken(array(
'grant_type' => 'authorization_code',
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 9
*/
public function test_issueAccessToken_badCode()
{
$this->client->shouldReceive('getClient')->andReturn(array());
$this->session->shouldReceive('validateAuthCode')->andReturn(false);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$v = $a->issueAccessToken(array(
'grant_type' => 'authorization_code',
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'code' => 'foobar'
));
}
public function test_issueAccessToken_passedInput()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->session->shouldReceive('validateAuthCode')->andReturn(1);
$this->session->shouldReceive('updateSession')->andReturn(null);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$v = $a->issueAccessToken(array(
'grant_type' => 'authorization_code',
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'code' => 'foobar'
));
$this->assertArrayHasKey('access_token', $v);
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
$this->assertArrayHasKey('expires_in', $v);
$this->assertEquals($a::getExpiresIn(), $v['expires_in']);
$this->assertEquals(time()+$a::getExpiresIn(), $v['expires']);
}
public function test_issueAccessToken()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->session->shouldReceive('validateAuthCode')->andReturn(1);
$this->session->shouldReceive('updateSession')->andReturn(null);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$_POST['grant_type'] = 'authorization_code';
$_POST['client_id'] = 1234;
$_POST['client_secret'] = 5678;
$_POST['redirect_uri'] = 'http://foo/redirect';
$_POST['code'] = 'foobar';
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken();
$this->assertArrayHasKey('access_token', $v);
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
$this->assertArrayHasKey('expires_in', $v);
$this->assertEquals($a::getExpiresIn(), $v['expires_in']);
$this->assertEquals(time()+$a::getExpiresIn(), $v['expires']);
}
public function tearDown() {
M::close();
}
}

View File

@@ -0,0 +1,189 @@
<?php
use \Mockery as m;
class Client_Credentials_Grant_Test extends PHPUnit_Framework_TestCase
{
private $client;
private $session;
private $scope;
public function setUp()
{
$this->client = M::mock('OAuth2\Storage\ClientInterface');
$this->session = M::mock('OAuth2\Storage\SessionInterface');
$this->scope = M::mock('OAuth2\Storage\ScopeInterface');
}
private function returnDefault()
{
return new OAuth2\AuthServer($this->client, $this->session, $this->scope);
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_clientCredentialsGrant_missingClientId()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\ClientCredentials());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'client_credentials'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_clientCredentialsGrant_missingClientPassword()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\ClientCredentials());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'client_credentials',
'client_id' => 1234
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 8
*/
public function test_issueAccessToken_clientCredentialsGrant_badClient()
{
$this->client->shouldReceive('getClient')->andReturn(false);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\ClientCredentials());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'client_credentials',
'client_id' => 1234,
'client_secret' => 5678
));
}
function test_issueAccessToken_clientCredentialsGrant_passedInput()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->client->shouldReceive('validateRefreshToken')->andReturn(1);
$this->session->shouldReceive('validateAuthCode')->andReturn(1);
$this->session->shouldReceive('createSession')->andReturn(1);
$this->session->shouldReceive('deleteSession')->andReturn(null);
$this->session->shouldReceive('updateRefreshToken')->andReturn(null);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\ClientCredentials());
$v = $a->issueAccessToken(array(
'grant_type' => 'client_credentials',
'client_id' => 1234,
'client_secret' => 5678
));
$this->assertArrayHasKey('access_token', $v);
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
$this->assertArrayHasKey('expires_in', $v);
$this->assertEquals($a::getExpiresIn(), $v['expires_in']);
$this->assertEquals(time()+$a::getExpiresIn(), $v['expires']);
}
function test_issueAccessToken_clientCredentialsGrant()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->client->shouldReceive('validateRefreshToken')->andReturn(1);
$this->session->shouldReceive('validateAuthCode')->andReturn(1);
$this->session->shouldReceive('createSession')->andReturn(1);
$this->session->shouldReceive('deleteSession')->andReturn(null);
$this->session->shouldReceive('updateRefreshToken')->andReturn(null);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\ClientCredentials());
$_POST['grant_type'] = 'client_credentials';
$_POST['client_id'] = 1234;
$_POST['client_secret'] = 5678;
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken();
$this->assertArrayHasKey('access_token', $v);
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
$this->assertArrayHasKey('expires_in', $v);
$this->assertEquals($a::getExpiresIn(), $v['expires_in']);
$this->assertEquals(time()+$a::getExpiresIn(), $v['expires']);
}
function test_issueAccessToken_clientCredentialsGrant_withRefreshToken()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->client->shouldReceive('validateRefreshToken')->andReturn(1);
$this->session->shouldReceive('validateAuthCode')->andReturn(1);
$this->session->shouldReceive('createSession')->andReturn(1);
$this->session->shouldReceive('deleteSession')->andReturn(null);
$this->session->shouldReceive('updateRefreshToken')->andReturn(null);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\ClientCredentials());
$a->addGrantType(new OAuth2\Grant\RefreshToken());
$_POST['grant_type'] = 'client_credentials';
$_POST['client_id'] = 1234;
$_POST['client_secret'] = 5678;
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken();
$this->assertArrayHasKey('access_token', $v);
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
$this->assertArrayHasKey('expires_in', $v);
$this->assertArrayHasKey('refresh_token', $v);
$this->assertEquals($a::getExpiresIn(), $v['expires_in']);
$this->assertEquals(time()+$a::getExpiresIn(), $v['expires']);
}
}

View File

@@ -0,0 +1,347 @@
<?php
use \Mockery as m;
class Password_Grant_Test extends PHPUnit_Framework_TestCase
{
private $client;
private $session;
private $scope;
public function setUp()
{
$this->client = M::mock('OAuth2\Storage\ClientInterface');
$this->session = M::mock('OAuth2\Storage\SessionInterface');
$this->scope = M::mock('OAuth2\Storage\ScopeInterface');
}
private function returnDefault()
{
return new OAuth2\AuthServer($this->client, $this->session, $this->scope);
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_passwordGrant_missingClientId()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\Password());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'password'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_passwordGrant_missingClientPassword()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\Password());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'password',
'client_id' => 1234
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 8
*/
public function test_issueAccessToken_passwordGrant_badClient()
{
$this->client->shouldReceive('getClient')->andReturn(false);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\Password());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'password',
'client_id' => 1234,
'client_secret' => 5678
));
}
/**
* @expectedException OAuth2\Exception\InvalidGrantTypeException
*/
function test_issueAccessToken_passwordGrant_invalidCallback()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->client->shouldReceive('validateRefreshToken')->andReturn(1);
$this->session->shouldReceive('validateAuthCode')->andReturn(1);
$this->session->shouldReceive('createSession')->andReturn(1);
$this->session->shouldReceive('deleteSession')->andReturn(null);
$this->session->shouldReceive('updateRefreshToken')->andReturn(null);
$testCredentials = null;
$a = $this->returnDefault();
$pgrant = new OAuth2\Grant\Password();
$pgrant->setVerifyCredentialsCallback($testCredentials);
$a->addGrantType($pgrant);
$v = $a->issueAccessToken(array(
'grant_type' => 'password',
'client_id' => 1234,
'client_secret' => 5678,
'username' => 'foo',
'password' => 'bar'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
function test_issueAccessToken_passwordGrant_missingUsername()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->client->shouldReceive('validateRefreshToken')->andReturn(1);
$this->session->shouldReceive('validateAuthCode')->andReturn(1);
$this->session->shouldReceive('createSession')->andReturn(1);
$this->session->shouldReceive('deleteSession')->andReturn(null);
$this->session->shouldReceive('updateRefreshToken')->andReturn(null);
$testCredentials = function($u, $p) { return false; };
$a = $this->returnDefault();
$pgrant = new OAuth2\Grant\Password();
$pgrant->setVerifyCredentialsCallback($testCredentials);
$a->addGrantType($pgrant);
$v = $a->issueAccessToken(array(
'grant_type' => 'password',
'client_id' => 1234,
'client_secret' => 5678
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
function test_issueAccessToken_passwordGrant_missingPassword()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->client->shouldReceive('validateRefreshToken')->andReturn(1);
$this->session->shouldReceive('validateAuthCode')->andReturn(1);
$this->session->shouldReceive('createSession')->andReturn(1);
$this->session->shouldReceive('deleteSession')->andReturn(null);
$this->session->shouldReceive('updateRefreshToken')->andReturn(null);
$testCredentials = function($u, $p) { return false; };
$a = $this->returnDefault();
$pgrant = new OAuth2\Grant\Password();
$pgrant->setVerifyCredentialsCallback($testCredentials);
$a->addGrantType($pgrant);
$v = $a->issueAccessToken(array(
'grant_type' => 'password',
'client_id' => 1234,
'client_secret' => 5678,
'username' => 'foo'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
function test_issueAccessToken_passwordGrant_badCredentials()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->client->shouldReceive('validateRefreshToken')->andReturn(1);
$this->session->shouldReceive('validateAuthCode')->andReturn(1);
$this->session->shouldReceive('createSession')->andReturn(1);
$this->session->shouldReceive('deleteSession')->andReturn(null);
$this->session->shouldReceive('updateRefreshToken')->andReturn(null);
$testCredentials = function($u, $p) { return false; };
$a = $this->returnDefault();
$pgrant = new OAuth2\Grant\Password();
$pgrant->setVerifyCredentialsCallback($testCredentials);
$a->addGrantType($pgrant);
$v = $a->issueAccessToken(array(
'grant_type' => 'password',
'client_id' => 1234,
'client_secret' => 5678,
'username' => 'foo',
'password' => 'bar'
));
}
function test_issueAccessToken_passwordGrant_passedInput()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->client->shouldReceive('validateRefreshToken')->andReturn(1);
$this->session->shouldReceive('validateAuthCode')->andReturn(1);
$this->session->shouldReceive('createSession')->andReturn(1);
$this->session->shouldReceive('deleteSession')->andReturn(null);
$this->session->shouldReceive('updateRefreshToken')->andReturn(null);
$testCredentials = function($u, $p) { return 1; };
$a = $this->returnDefault();
$pgrant = new OAuth2\Grant\Password();
$pgrant->setVerifyCredentialsCallback($testCredentials);
$a->addGrantType($pgrant);
$v = $a->issueAccessToken(array(
'grant_type' => 'password',
'client_id' => 1234,
'client_secret' => 5678,
'username' => 'foo',
'password' => 'bar'
));
$this->assertArrayHasKey('access_token', $v);
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
$this->assertArrayHasKey('expires_in', $v);
$this->assertEquals($a::getExpiresIn(), $v['expires_in']);
$this->assertEquals(time()+$a::getExpiresIn(), $v['expires']);
}
function test_issueAccessToken_passwordGrant()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->client->shouldReceive('validateRefreshToken')->andReturn(1);
$this->session->shouldReceive('validateAuthCode')->andReturn(1);
$this->session->shouldReceive('createSession')->andReturn(1);
$this->session->shouldReceive('deleteSession')->andReturn(null);
$this->session->shouldReceive('updateRefreshToken')->andReturn(null);
$testCredentials = function($u, $p) { return 1; };
$a = $this->returnDefault();
$pgrant = new OAuth2\Grant\Password();
$pgrant->setVerifyCredentialsCallback($testCredentials);
$a->addGrantType($pgrant);
$_POST['grant_type'] = 'password';
$_POST['client_id'] = 1234;
$_POST['client_secret'] = 5678;
$_POST['username'] = 'foo';
$_POST['password'] = 'bar';
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken();
$this->assertArrayHasKey('access_token', $v);
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
$this->assertArrayHasKey('expires_in', $v);
$this->assertEquals($a::getExpiresIn(), $v['expires_in']);
$this->assertEquals(time()+$a::getExpiresIn(), $v['expires']);
}
function test_issueAccessToken_passwordGrant_withRefreshToken()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->client->shouldReceive('validateRefreshToken')->andReturn(1);
$this->session->shouldReceive('validateAuthCode')->andReturn(1);
$this->session->shouldReceive('createSession')->andReturn(1);
$this->session->shouldReceive('deleteSession')->andReturn(null);
$this->session->shouldReceive('updateRefreshToken')->andReturn(null);
$testCredentials = function($u, $p) { return 1; };
$a = $this->returnDefault();
$pgrant = new OAuth2\Grant\Password();
$pgrant->setVerifyCredentialsCallback($testCredentials);
$a->addGrantType($pgrant);
$a->addGrantType(new OAuth2\Grant\RefreshToken());
$_POST['grant_type'] = 'password';
$_POST['client_id'] = 1234;
$_POST['client_secret'] = 5678;
$_POST['username'] = 'foo';
$_POST['password'] = 'bar';
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken();
$this->assertArrayHasKey('access_token', $v);
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
$this->assertArrayHasKey('expires_in', $v);
$this->assertArrayHasKey('refresh_token', $v);
$this->assertEquals($a::getExpiresIn(), $v['expires_in']);
$this->assertEquals(time()+$a::getExpiresIn(), $v['expires']);
}
}

View File

@@ -0,0 +1,233 @@
<?php
use \Mockery as m;
class Refresh_Token_test extends PHPUnit_Framework_TestCase
{
private $client;
private $session;
private $scope;
public function setUp()
{
$this->client = M::mock('OAuth2\Storage\ClientInterface');
$this->session = M::mock('OAuth2\Storage\SessionInterface');
$this->scope = M::mock('OAuth2\Storage\ScopeInterface');
}
private function returnDefault()
{
return new OAuth2\AuthServer($this->client, $this->session, $this->scope);
}
public function test_issueAccessToken_with_refresh_token()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->session->shouldReceive('validateAuthCode')->andReturn(1);
$this->session->shouldReceive('updateSession')->andReturn(null);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\AuthCode());
$a->addGrantType(new OAuth2\Grant\RefreshToken());
$_POST['grant_type'] = 'authorization_code';
$_POST['client_id'] = 1234;
$_POST['client_secret'] = 5678;
$_POST['redirect_uri'] = 'http://foo/redirect';
$_POST['code'] = 'foobar';
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken();
$this->assertArrayHasKey('access_token', $v);
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
$this->assertArrayHasKey('expires_in', $v);
$this->assertArrayHasKey('refresh_token', $v);
$this->assertEquals($a::getExpiresIn(), $v['expires_in']);
$this->assertEquals(time()+$a::getExpiresIn(), $v['expires']);
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_refreshTokenGrant_missingClientId()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\RefreshToken());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'refresh_token'
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_refreshTokenGrant_missingClientSecret()
{
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\RefreshToken());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'refresh_token',
'client_id' => 1234
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 8
*/
public function test_issueAccessToken_refreshTokenGrant_badClient()
{
$this->client->shouldReceive('getClient')->andReturn(false);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\RefreshToken());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'refresh_token',
'client_id' => 1234,
'client_secret' => 5678
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_refreshTokenGrant_missingRefreshToken()
{
$this->client->shouldReceive('getClient')->andReturn(array());
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\RefreshToken());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'refresh_token',
'client_id' => 1234,
'client_secret' => 5678,
//'refresh_token' =>
));
}
/**
* @expectedException OAuth2\Exception\ClientException
* @expectedExceptionCode 0
*/
public function test_issueAccessToken_refreshTokenGrant_badRefreshToken()
{
$this->client->shouldReceive('getClient')->andReturn(array());
$this->client->shouldReceive('validateRefreshToken')->andReturn(false);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\RefreshToken());
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken(array(
'grant_type' => 'refresh_token',
'client_id' => 1234,
'client_secret' => 5678,
'refresh_token' => 'abcdef'
));
}
public function test_issueAccessToken_refreshTokenGrant_passedInput()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->client->shouldReceive('validateRefreshToken')->andReturn(1);
$this->session->shouldReceive('validateAuthCode')->andReturn(1);
$this->session->shouldReceive('updateSession')->andReturn(null);
$this->session->shouldReceive('updateRefreshToken')->andReturn(null);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\RefreshToken());
$_POST['grant_type'] = 'refresh_token';
$_POST['client_id'] = 1234;
$_POST['client_secret'] = 5678;
$_POST['refresh_token'] = 'abcdef';
$request = new OAuth2\Util\Request(array(), $_POST);
$a->setRequest($request);
$v = $a->issueAccessToken();
$this->assertArrayHasKey('access_token', $v);
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
$this->assertArrayHasKey('expires_in', $v);
$this->assertArrayHasKey('refresh_token', $v);
$this->assertEquals($a::getExpiresIn(), $v['expires_in']);
$this->assertEquals(time()+$a::getExpiresIn(), $v['expires']);
}
public function test_issueAccessToken_refreshTokenGrant()
{
$this->client->shouldReceive('getClient')->andReturn(array(
'client_id' => 1234,
'client_secret' => 5678,
'redirect_uri' => 'http://foo/redirect',
'name' => 'Example Client'
));
$this->client->shouldReceive('validateRefreshToken')->andReturn(1);
$this->session->shouldReceive('validateAuthCode')->andReturn(1);
$this->session->shouldReceive('updateSession')->andReturn(null);
$this->session->shouldReceive('updateRefreshToken')->andReturn(null);
$a = $this->returnDefault();
$a->addGrantType(new OAuth2\Grant\RefreshToken());
$v = $a->issueAccessToken(array(
'grant_type' => 'refresh_token',
'client_id' => 1234,
'client_secret' => 5678,
'refresh_token' => 'abcdef',
));
$this->assertArrayHasKey('access_token', $v);
$this->assertArrayHasKey('token_type', $v);
$this->assertArrayHasKey('expires', $v);
$this->assertArrayHasKey('expires_in', $v);
$this->assertArrayHasKey('refresh_token', $v);
$this->assertEquals($a::getExpiresIn(), $v['expires_in']);
$this->assertEquals(time()+$a::getExpiresIn(), $v['expires']);
}
}

View File

@@ -1,154 +0,0 @@
<?php
use Oauth2\Authentication\Database;
class OAuthdb implements Database
{
private $sessions = array();
private $sessions_client_type_id = array();
private $sessions_code = array();
private $session_scopes = array();
private $clients = array(0 => array(
'client_id' => 'test',
'client_secret' => 'test',
'redirect_uri' => 'http://example.com/test',
'name' => 'Test Client'
));
private $scopes = array('test' => array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
));
public function validateClient($clientId, $clientSecret = null, $redirectUri = null)
{
if ($clientId !== $this->clients[0]['client_id'])
{
return false;
}
if ($clientSecret !== null && $clientSecret !== $this->clients[0]['client_secret'])
{
return false;
}
if ($redirectUri !== null && $redirectUri !== $this->clients[0]['redirect_uri'])
{
return false;
}
return $this->clients[0];
}
public function newSession($clientId, $redirectUri, $type = 'user', $typeId = null, $authCode = null, $accessToken = null, $accessTokenExpire = null, $stage = 'requested')
{
$id = count($this->sessions);
$this->sessions[$id] = array(
'id' => $id,
'client_id' => $clientId,
'redirect_uri' => $redirectUri,
'owner_type' => $type,
'owner_id' => $typeId,
'auth_code' => $authCode,
'access_token' => $accessToken,
'access_token_expire' => $accessTokenExpire,
'stage' => $stage
);
$this->sessions_client_type_id[$clientId . ':' . $type . ':' . $typeId] = $id;
$this->sessions_code[$clientId . ':' . $redirectUri . ':' . $authCode] = $id;
return $id;
}
public function updateSession($sessionId, $authCode = null, $accessToken = null, $accessTokenExpire = null, $stage = 'requested')
{
$this->sessions[$sessionId]['auth_code'] = $authCode;
$this->sessions[$sessionId]['access_token'] = $accessToken;
$this->sessions[$sessionId]['access_token_expire'] = $accessTokenExpire;
$this->sessions[$sessionId]['stage'] = $stage;
return true;
}
public function deleteSession($clientId, $type, $typeId)
{
$key = $clientId . ':' . $type . ':' . $typeId;
if (isset($this->sessions_client_type_id[$key]))
{
unset($this->sessions[$this->sessions_client_type_id[$key]]);
}
return true;
}
public function validateAuthCode($clientId, $redirectUri, $authCode)
{
$key = $clientId . ':' . $redirectUri . ':' . $authCode;
if (isset($this->sessions_code[$key]))
{
return $this->sessions[$this->sessions_code[$key]];
}
return false;
}
public function hasSession($type, $typeId, $clientId)
{
die('not implemented hasSession');
}
public function getAccessToken($sessionId)
{
die('not implemented getAccessToken');
}
public function removeAuthCode($sessionId)
{
die('not implemented removeAuthCode');
}
public function setAccessToken(
$sessionId,
$accessToken
)
{
die('not implemented setAccessToken');
}
public function addSessionScope($sessionId, $scope)
{
if ( ! isset($this->session_scopes[$sessionId]))
{
$this->session_scopes[$sessionId] = array();
}
$this->session_scopes[$sessionId][] = $scope;
return true;
}
public function getScope($scope)
{
if ( ! isset($this->scopes[$scope]))
{
return false;
}
return $this->scopes[$scope];
}
public function updateSessionScopeAccessToken($sessionId, $accessToken)
{
return true;
}
public function accessTokenScopes($accessToken)
{
die('not implemented accessTokenScopes');
}
}

View File

@@ -1,398 +0,0 @@
<?php
class Authentication_Server_test extends PHPUnit_Framework_TestCase {
function setUp()
{
$this->oauth = new Oauth2\Authentication\Server();
require_once('database_mock.php');
$this->oauthdb = new OAuthdb();
$this->assertInstanceOf('Oauth2\Authentication\Database', $this->oauthdb);
$this->oauth->registerDbAbstractor($this->oauthdb);
}
function test_generateCode()
{
$reflector = new ReflectionClass($this->oauth);
$method = $reflector->getMethod('generateCode');
$method->setAccessible(true);
$result = $method->invoke($this->oauth);
$result2 = $method->invoke($this->oauth);
$this->assertEquals(40, strlen($result));
$this->assertNotEquals($result, $result2);
}
function test_redirectUri()
{
$result1 = $this->oauth->redirectUri('http://example.com/foo');
$result2 = $this->oauth->redirectUri('http://example.com/foo', array('foo' => 'bar'));
$result3 = $this->oauth->redirectUri('http://example.com/foo', array('foo' => 'bar'), '#');
$this->assertEquals('http://example.com/foo?', $result1);
$this->assertEquals('http://example.com/foo?foo=bar', $result2);
$this->assertEquals('http://example.com/foo#foo=bar', $result3);
}
function test_checkClientAuthoriseParams_GET()
{
$_GET['client_id'] = 'test';
$_GET['redirect_uri'] = 'http://example.com/test';
$_GET['response_type'] = 'code';
$_GET['scope'] = 'test';
$expect = array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'response_type' => 'code',
'scopes' => array(
0 => array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
)
)
);
$result = $this->oauth->checkClientAuthoriseParams();
$this->assertEquals($expect, $result);
}
function test_checkClientAuthoriseParams_PassedParams()
{
unset($_GET['client_id']);
unset($_GET['redirect_uri']);
unset($_GET['response_type']);
unset($_GET['scope']);
$params = array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'response_type' => 'code',
'scope' => 'test'
);
$this->assertEquals(array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'response_type' => 'code',
'scopes' => array(0 => array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
))
), $this->oauth->checkClientAuthoriseParams($params));
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
function test_checkClientAuthoriseParams_missingClientId()
{
$this->oauth->checkClientAuthoriseParams();
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
function test_checkClientAuthoriseParams_missingRedirectUri()
{
$_GET['client_id'] = 'test';
$this->oauth->checkClientAuthoriseParams();
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
function test_checkClientAuthoriseParams_missingResponseType()
{
$_GET['client_id'] = 'test';
$_GET['redirect_uri'] = 'http://example.com/test';
$this->oauth->checkClientAuthoriseParams();
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
function test_checkClientAuthoriseParams_missingScopes()
{
$_GET['client_id'] = 'test';
$_GET['redirect_uri'] = 'http://example.com/test';
$_GET['response_type'] = 'code';
$_GET['scope'] = ' ';
$this->oauth->checkClientAuthoriseParams();
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 4
*/
function test_checkClientAuthoriseParams_invalidScopes()
{
$_GET['client_id'] = 'test';
$_GET['redirect_uri'] = 'http://example.com/test';
$_GET['response_type'] = 'code';
$_GET['scope'] = 'blah';
$this->oauth->checkClientAuthoriseParams();
}
function test_newAuthoriseRequest()
{
$result = $this->oauth->newAuthoriseRequest('user', '123', array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'scopes' => array(array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
))
));
$this->assertEquals(40, strlen($result));
}
function test_newAuthoriseRequest_isUnique()
{
$result1 = $this->oauth->newAuthoriseRequest('user', '123', array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'scopes' => array(array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
))
));
$result2 = $this->oauth->newAuthoriseRequest('user', '123', array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'scopes' => array(array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
))
));
$this->assertNotEquals($result1, $result2);
}
function test_issueAccessToken_POST()
{
$auth_code = $this->oauth->newAuthoriseRequest('user', '123', array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'scopes' => array(array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
))
));
$_POST['client_id'] = 'test';
$_POST['client_secret'] = 'test';
$_POST['redirect_uri'] = 'http://example.com/test';
$_POST['grant_type'] = 'authorization_code';
$_POST['code'] = $auth_code;
$result = $this->oauth->issueAccessToken();
$this->assertCount(3, $result);
$this->assertArrayHasKey('access_token', $result);
$this->assertArrayHasKey('token_type', $result);
$this->assertArrayHasKey('expires_in', $result);
}
function test_issueAccessToken_PassedParams()
{
$auth_code = $this->oauth->newAuthoriseRequest('user', '123', array(
'client_id' => 'test',
'redirect_uri' => 'http://example.com/test',
'scopes' => array(array(
'id' => 1,
'scope' => 'test',
'name' => 'test',
'description' => 'test'
))
));
$params['client_id'] = 'test';
$params['client_secret'] = 'test';
$params['redirect_uri'] = 'http://example.com/test';
$params['grant_type'] = 'authorization_code';
$params['code'] = $auth_code;
$result = $this->oauth->issueAccessToken($params);
$this->assertCount(3, $result);
$this->assertArrayHasKey('access_token', $result);
$this->assertArrayHasKey('token_type', $result);
$this->assertArrayHasKey('expires_in', $result);
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
function test_issueAccessToken_missingGrantType()
{
$this->oauth->issueAccessToken();
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 7
*/
function test_issueAccessToken_unsupportedGrantType()
{
$params['grant_type'] = 'blah';
$this->oauth->issueAccessToken($params);
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
function test_completeAuthCodeGrant_missingClientId()
{
$reflector = new ReflectionClass($this->oauth);
$method = $reflector->getMethod('completeAuthCodeGrant');
$method->setAccessible(true);
$method->invoke($this->oauth);
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
function test_completeAuthCodeGrant_missingClientSecret()
{
$reflector = new ReflectionClass($this->oauth);
$method = $reflector->getMethod('completeAuthCodeGrant');
$method->setAccessible(true);
$authParams['client_id'] = 'test';
$method->invoke($this->oauth, $authParams);
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
function test_completeAuthCodeGrant_missingRedirectUri()
{
$reflector = new ReflectionClass($this->oauth);
$method = $reflector->getMethod('completeAuthCodeGrant');
$method->setAccessible(true);
$authParams['client_id'] = 'test';
$authParams['client_secret'] = 'test';
$method->invoke($this->oauth, $authParams);
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 8
*/
function test_completeAuthCodeGrant_invalidClient()
{
$reflector = new ReflectionClass($this->oauth);
$method = $reflector->getMethod('completeAuthCodeGrant');
$method->setAccessible(true);
$authParams['client_id'] = 'test';
$authParams['client_secret'] = 'test123';
$authParams['redirect_uri'] = 'http://example.com/test';
$method->invoke($this->oauth, $authParams);
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 0
*/
function test_completeAuthCodeGrant_missingCode()
{
$reflector = new ReflectionClass($this->oauth);
$method = $reflector->getMethod('completeAuthCodeGrant');
$method->setAccessible(true);
$authParams['client_id'] = 'test';
$authParams['client_secret'] = 'test';
$authParams['redirect_uri'] = 'http://example.com/test';
$method->invoke($this->oauth, $authParams);
}
/**
* @expectedException Oauth2\Authentication\ClientException
* @expectedExceptionCode 9
*/
function test_completeAuthCodeGrant_invalidCode()
{
$reflector = new ReflectionClass($this->oauth);
$method = $reflector->getMethod('completeAuthCodeGrant');
$method->setAccessible(true);
$authParams['client_id'] = 'test';
$authParams['client_secret'] = 'test';
$authParams['redirect_uri'] = 'http://example.com/test';
$authParams['code'] = 'blah';
$method->invoke($this->oauth, $authParams);
}
/**
* @expectedException Oauth2\Authentication\ServerException
* @expectedExceptionMessage No registered database abstractor
*/
function test_noRegisteredDatabaseAbstractor()
{
$reflector = new ReflectionClass($this->oauth);
$method = $reflector->getMethod('_dbCall');
$method->setAccessible(true);
$dbAbstractor = $reflector->getProperty('_db');
$dbAbstractor->setAccessible(true);
$dbAbstractor->setValue($this->oauth, null);
$result = $method->invoke($this->oauth);
}
/**
* @expectedException Oauth2\Authentication\ServerException
* @expectedExceptionMessage Registered database abstractor is not an instance of Oauth2\Authentication\Database
*/
function test_invalidRegisteredDatabaseAbstractor()
{
$fake = new stdClass;
$this->oauth->registerDbAbstractor($fake);
$reflector = new ReflectionClass($this->oauth);
$method = $reflector->getMethod('_dbCall');
$method->setAccessible(true);
$result = $method->invoke($this->oauth);
}
}

View File

@@ -0,0 +1,172 @@
<?php
use \Mockery as m;
class Resource_Server_test extends PHPUnit_Framework_TestCase
{
private $session;
public function setUp()
{
$this->session = M::mock('OAuth2\Storage\SessionInterface');
}
private function returnDefault()
{
return new OAuth2\ResourceServer($this->session);
}
public function test_setRequest()
{
$s = $this->returnDefault();
$request = new OAuth2\Util\Request();
$s->setRequest($request);
$reflector = new ReflectionClass($s);
$requestProperty = $reflector->getProperty('request');
$requestProperty->setAccessible(true);
$v = $requestProperty->getValue($s);
$this->assertTrue($v instanceof OAuth2\Util\RequestInterface);
}
public function test_getRequest()
{
$s = $this->returnDefault();
$request = new OAuth2\Util\Request();
$s->setRequest($request);
$v = $s->getRequest();
$this->assertTrue($v instanceof OAuth2\Util\RequestInterface);
}
public function test_getTokenKey()
{
$s = $this->returnDefault();
$this->assertEquals('access_token', $s->getTokenKey());
}
public function test_setTokenKey()
{
$s = $this->returnDefault();
$s->setTokenKey('oauth_token');
$reflector = new ReflectionClass($s);
$requestProperty = $reflector->getProperty('tokenKey');
$requestProperty->setAccessible(true);
$v = $requestProperty->getValue($s);
$this->assertEquals('oauth_token', $v);
}
/**
* @expectedException OAuth2\Exception\InvalidAccessTokenException
*/
public function test_determineAccessToken_missingToken()
{
$_SERVER['HTTP_AUTHORIZATION'] = 'Bearer';
$request = new OAuth2\Util\Request(array(), array(), array(), array(), $_SERVER);
$s = $this->returnDefault();
$s->setRequest($request);
$reflector = new ReflectionClass($s);
$method = $reflector->getMethod('determineAccessToken');
$method->setAccessible(true);
$result = $method->invoke($s);
}
public function test_determineAccessToken_fromHeader()
{
$request = new OAuth2\Util\Request();
$requestReflector = new ReflectionClass($request);
$param = $requestReflector->getProperty('headers');
$param->setAccessible(true);
$param->setValue($request, array(
'Authorization' => 'Bearer YWJjZGVm'
));
$s = $this->returnDefault();
$s->setRequest($request);
$reflector = new ReflectionClass($s);
$method = $reflector->getMethod('determineAccessToken');
$method->setAccessible(true);
$result = $method->invoke($s);
$this->assertEquals('abcdef', $result);
}
public function test_determineAccessToken_fromMethod()
{
$s = $this->returnDefault();
$_GET[$s->getTokenKey()] = 'abcdef';
$_SERVER['REQUEST_METHOD'] = 'get';
$request = new OAuth2\Util\Request($_GET, array(), array(), array(), $_SERVER);
$s->setRequest($request);
$reflector = new ReflectionClass($s);
$method = $reflector->getMethod('determineAccessToken');
$method->setAccessible(true);
$result = $method->invoke($s);
$this->assertEquals('abcdef', $result);
}
/**
* @expectedException OAuth2\Exception\InvalidAccessTokenException
*/
public function test_isValid_notValid()
{
$this->session->shouldReceive('validateAccessToken')->andReturn(false);
$request = new OAuth2\Util\Request();
$requestReflector = new ReflectionClass($request);
$param = $requestReflector->getProperty('headers');
$param->setAccessible(true);
$param->setValue($request, array(
'Authorization' => 'Bearer YWJjZGVm'
));
$s = $this->returnDefault();
$s->setRequest($request);
$s->isValid();
}
public function test_isValid_valid()
{
$this->session->shouldReceive('validateAccessToken')->andReturn(array(
'id' => 1,
'owner_type' => 'user',
'owner_id' => 123
));
$this->session->shouldReceive('getScopes')->andReturn(array('foo', 'bar'));
$request = new OAuth2\Util\Request();
$requestReflector = new ReflectionClass($request);
$param = $requestReflector->getProperty('headers');
$param->setAccessible(true);
$param->setValue($request, array(
'Authorization' => 'Bearer YWJjZGVm'
));
$s = $this->returnDefault();
$s->setRequest($request);
$this->assertTrue($s->isValid());
$this->assertEquals(123, $s->getOwnerId());
$this->assertEquals('user', $s->getOwnerType());
$this->assertEquals('abcdef', $s->getAccessToken());
$this->assertTrue($s->hasScope('foo'));
$this->assertTrue($s->hasScope('bar'));
$this->assertTrue($s->hasScope(array('foo', 'bar')));
$this->assertFalse($s->hasScope(array('foobar')));
$this->assertFalse($s->hasScope('foobar'));
$this->assertFalse($s->hasScope(new StdClass));
}
}

View File

@@ -1,31 +0,0 @@
<?php
use Oauth2\Resource\Database;
class ResourceDB implements Database
{
private $accessTokens = array(
'test12345' => array(
'id' => 1,
'owner_type' => 'user',
'owner_id' => 123
)
);
private $sessionScopes = array(
1 => array(
'foo',
'bar'
)
);
public function validateAccessToken($accessToken)
{
return (isset($this->accessTokens[$accessToken])) ? $this->accessTokens[$accessToken] : false;
}
public function sessionScopes($sessionId)
{
return (isset($this->sessionScopes[$sessionId])) ? $this->sessionScopes[$sessionId] : array();
}
}

View File

@@ -1,121 +0,0 @@
<?php
class Resource_Server_test extends PHPUnit_Framework_TestCase {
function setUp()
{
require_once('database_mock.php');
$this->server = new Oauth2\Resource\Server();
$this->db = new ResourceDB();
$this->assertInstanceOf('Oauth2\Resource\Database', $this->db);
$this->server->registerDbAbstractor($this->db);
}
function test_init_POST()
{
$_SERVER['REQUEST_METHOD'] = 'POST';
$_POST['oauth_token'] = 'test12345';
$this->server->init();
$reflector = new ReflectionClass($this->server);
$_accessToken = $reflector->getProperty('_accessToken');
$_accessToken->setAccessible(true);
$_type = $reflector->getProperty('_type');
$_type->setAccessible(true);
$_typeId = $reflector->getProperty('_typeId');
$_typeId->setAccessible(true);
$_scopes = $reflector->getProperty('_scopes');
$_scopes->setAccessible(true);
$this->assertEquals($_accessToken->getValue($this->server), $_POST['oauth_token']);
$this->assertEquals($_type->getValue($this->server), 'user');
$this->assertEquals($_typeId->getValue($this->server), 123);
$this->assertEquals($_scopes->getValue($this->server), array('foo', 'bar'));
}
function test_init_GET()
{
$_GET['oauth_token'] = 'test12345';
$this->server->init();
$reflector = new ReflectionClass($this->server);
$_accessToken = $reflector->getProperty('_accessToken');
$_accessToken->setAccessible(true);
$_type = $reflector->getProperty('_type');
$_type->setAccessible(true);
$_typeId = $reflector->getProperty('_typeId');
$_typeId->setAccessible(true);
$_scopes = $reflector->getProperty('_scopes');
$_scopes->setAccessible(true);
$this->assertEquals($_accessToken->getValue($this->server), $_GET['oauth_token']);
$this->assertEquals($_type->getValue($this->server), 'user');
$this->assertEquals($_typeId->getValue($this->server), 123);
$this->assertEquals($_scopes->getValue($this->server), array('foo', 'bar'));
}
function test_init_header()
{
// Test with authorisation header
$this->markTestIncomplete('Authorisation header test has not been implemented yet.');
}
/**
* @expectedException \Oauth2\Resource\ClientException
* @expectedExceptionMessage An access token was not presented with the request
*/
function test_init_missingToken()
{
$this->server->init();
}
/**
* @expectedException \Oauth2\Resource\ClientException
* @expectedExceptionMessage The access token is not registered with the resource server
*/
function test_init_wrongToken()
{
$_POST['oauth_token'] = 'blah';
$_SERVER['REQUEST_METHOD'] = 'POST';
$this->server->init();
}
function test_hasScope()
{
$_POST['oauth_token'] = 'test12345';
$_SERVER['REQUEST_METHOD'] = 'POST';
$this->server->init();
$this->assertEquals(true, $this->server->hasScope('foo'));
$this->assertEquals(true, $this->server->hasScope('bar'));
$this->assertEquals(true, $this->server->hasScope(array('foo', 'bar')));
$this->assertEquals(false, $this->server->hasScope('foobar'));
$this->assertEquals(false, $this->server->hasScope(array('foobar')));
}
function test___call()
{
$_POST['oauth_token'] = 'test12345';
$_SERVER['REQUEST_METHOD'] = 'POST';
$this->server->init();
$this->assertEquals(123, $this->server->isUser());
$this->assertEquals(false, $this->server->isMachine());
}
}

View File

@@ -0,0 +1,15 @@
<?php
class RedirectUri_test extends PHPUnit_Framework_TestCase
{
function test_make()
{
$v1 = OAuth2\Util\RedirectUri::make('https://foobar/', array('foo'=>'bar'));
$v2 = OAuth2\Util\RedirectUri::make('https://foobar/', array('foo'=>'bar'), '#');
$v3 = OAuth2\Util\RedirectUri::make('https://foobar/', array('foo'=>'bar', 'bar' => 'foo'));
$this->assertEquals('https://foobar/?foo=bar', $v1);
$this->assertEquals('https://foobar/#foo=bar', $v2);
$this->assertEquals('https://foobar/?foo=bar&bar=foo', $v3);
}
}

View File

@@ -0,0 +1,73 @@
<?php
class Request_test extends PHPUnit_Framework_TestCase
{
private $request;
function setUp()
{
$this->request = new OAuth2\Util\Request(
array('foo' => 'bar'),
array('foo' => 'bar'),
array('foo' => 'bar'),
array('foo' => 'bar'),
array('HTTP_HOST' => 'foobar.com')
);
}
function test_buildFromIndex()
{
$r = new OAuth2\Util\Request();
$r->buildFromGlobals();
$this->assertTrue($r instanceof OAuth2\Util\Request);
}
function test_get()
{
$this->assertEquals('bar', $this->request->get('foo'));
$this->assertEquals(array('foo' => 'bar'), $this->request->get());
}
function test_post()
{
$this->assertEquals('bar', $this->request->post('foo'));
$this->assertEquals(array('foo' => 'bar'), $this->request->post());
}
function test_file()
{
$this->assertEquals('bar', $this->request->file('foo'));
$this->assertEquals(array('foo' => 'bar'), $this->request->file());
}
function test_cookie()
{
$this->assertEquals('bar', $this->request->cookie('foo'));
$this->assertEquals(array('foo' => 'bar'), $this->request->cookie());
}
function test_server()
{
$this->assertEquals('foobar.com', $this->request->server('HTTP_HOST'));
$this->assertEquals(array('HTTP_HOST' => 'foobar.com'), $this->request->server());
}
function test_header()
{
$this->assertEquals('foobar.com', $this->request->header('Host'));
$this->assertEquals(array('Host' => 'foobar.com'), $this->request->header());
}
/**
* @expectedException InvalidArgumentException
*/
function test_unknownProperty()
{
$reflector = new ReflectionClass($this->request);
$method = $reflector->getMethod('getPropertyValue');
$method->setAccessible(true);
$result = $method->invoke($this->request, 'blah');
}
}

View File

@@ -0,0 +1,15 @@
<?php
class Secure_Key_test extends PHPUnit_Framework_TestCase
{
function test_make()
{
$v1 = OAuth2\Util\SecureKey::make();
$v2 = OAuth2\Util\SecureKey::make();
$v3 = OAuth2\Util\SecureKey::make(50);
$this->assertEquals(40, strlen($v1));
$this->assertTrue($v1 !== $v2);
$this->assertEquals(50, strlen($v3));
}
}