Compare commits

...

420 Commits

Author SHA1 Message Date
Alex Bilbie
9533595394 Added 5.0.0-RC1 release notes 2016-03-24 19:37:07 +00:00
Alex Bilbie
5b977b1495 Updated changelog from master 2016-03-24 19:34:26 +00:00
Alex Bilbie
1c47ec51f8 Merge pull request #494 from frederikbosch/double_persis
prevent double persist of token when doing refresh grant
2016-03-24 17:34:47 +00:00
Frederik Bosch
fbf4388b01 prevent double persist of token when doing refresh grant 2016-03-24 17:24:17 +01:00
Alex Bilbie
a867fdd891 Merge pull request #492 from thephpleague/analysis-Xaj1EZ
Applied fixes from StyleCI
2016-03-24 15:28:56 +00:00
Alex Bilbie
1041a39d08 Applied fixes from StyleCI 2016-03-24 11:28:05 -04:00
Alex Bilbie
e23570535f Added API example 2016-03-24 15:27:55 +00:00
Alex Bilbie
b1cf6a8436 Fix for bad hint 2016-03-24 14:51:44 +00:00
Alex Bilbie
fe0ed765a5 Added setTemplateRenderer method 2016-03-24 13:56:31 +00:00
Alex Bilbie
7ce31bda87 Merge pull request #488 from thephpleague/analysis-ze7lN9
Applied fixes from StyleCI
2016-03-24 10:10:44 +00:00
Alex Bilbie
630a92b45f Applied fixes from StyleCI 2016-03-24 06:07:20 -04:00
Alex Bilbie
2b76e2bf6e Fix for broken test which wasn't actually broken but was 2016-03-24 10:07:09 +00:00
Alex Bilbie
115237bc1a Added missing return statement 2016-03-24 10:04:48 +00:00
Alex Bilbie
6383a58755 Updated scope validation 2016-03-24 10:04:15 +00:00
Alex Bilbie
614fbde56e Updated composer.lock 2016-03-24 10:01:49 +00:00
Alex Bilbie
0fbe109e20 Merge pull request #486 from thephpleague/analysis-864Kdo
Applied fixes from StyleCI
2016-03-23 18:59:01 +00:00
Alex Bilbie
57216984e9 Merge pull request #487 from thephpleague/analysis-z4xV5G
Applied fixes from StyleCI
2016-03-23 18:58:35 +00:00
Alex Bilbie
267bd3c5d4 Applied fixes from StyleCI 2016-03-23 14:50:27 -04:00
Alex Bilbie
a18b8c57b2 Fix broken tests 2016-03-23 18:50:14 +00:00
Alex Bilbie
cca401e66e Applied fixes from StyleCI 2016-03-23 14:37:07 -04:00
Alex Bilbie
55ff59edf4 Merge branch 'V5-WIP' of github.com:thephpleague/oauth2-server into V5-WIP 2016-03-23 18:36:49 +00:00
Alex Bilbie
a49c762683 Remove injected array of scopes 2016-03-23 18:36:43 +00:00
Alex Bilbie
b5b5d9f347 Added finalizeScopes method to ScopeRepositoryInterface 2016-03-23 18:36:23 +00:00
Alex Bilbie
07b2758cba Merge pull request #484 from thephpleague/analysis-qvQODv
Applied fixes from StyleCI
2016-03-23 13:12:24 +00:00
Alex Bilbie
864a27f2c8 Applied fixes from StyleCI 2016-03-23 08:54:30 -04:00
Alex Bilbie
a698a4da7e Added RequestEvent 2016-03-23 12:54:17 +00:00
Alex Bilbie
95cdaae17f Removed unused method 2016-03-22 17:07:30 +00:00
Alex Bilbie
61986db5ee Merge branch 'V5-WIP' of github.com:thephpleague/oauth2-server into V5-WIP 2016-03-22 16:29:08 +00:00
Alex Bilbie
878afeb9f9 ClientRepository implementations are now responsible for dealing with client secret 2016-03-22 16:29:04 +00:00
Alex Bilbie
e9dd1478c4 Merge pull request #482 from thephpleague/analysis-ze73j2
Applied fixes from StyleCI
2016-03-22 15:15:41 +00:00
Alex Bilbie
945731cb39 Applied fixes from StyleCI 2016-03-22 11:11:39 -04:00
Alex Bilbie
f688401f63 Merge branch 'V5-WIP' of github.com:thephpleague/oauth2-server into V5-WIP 2016-03-22 15:11:31 +00:00
Alex Bilbie
09770dc537 Inject client into getUserEntityByUserCredentials method 2016-03-22 15:11:20 +00:00
Alex Bilbie
dcf3f50b87 Merge pull request #481 from thephpleague/analysis-qBM7DW
Applied fixes from StyleCI
2016-03-22 14:57:26 +00:00
Alex Bilbie
59e8785f50 Applied fixes from StyleCI 2016-03-22 10:45:28 -04:00
Alex Bilbie
ca54a387c8 Merge branch 'V5-WIP' of github.com:thephpleague/oauth2-server into V5-WIP 2016-03-22 14:45:14 +00:00
Alex Bilbie
6fea054381 Update examples/composer.lock 2016-03-22 14:44:58 +00:00
Alex Bilbie
ed17b6540e Add additional repository 2016-03-22 14:44:39 +00:00
Alex Bilbie
e27b13ee7d Accept scopes as reference 2016-03-22 14:44:21 +00:00
Alex Bilbie
67f835a606 Merge pull request #480 from thephpleague/analysis-Xajx5Z
Applied fixes from StyleCI
2016-03-22 14:19:10 +00:00
Alex Bilbie
8685006743 Applied fixes from StyleCI 2016-03-22 10:18:21 -04:00
Alex Bilbie
400eae153b Added grant and scopes to UserRepository getUserEntityByUserCredentials method 2016-03-22 14:18:02 +00:00
Alex Bilbie
c880d5c1ec Merge pull request #476 from juliangut/fixes
Fixes
2016-03-18 11:04:43 +01:00
Julián Gutiérrez
9ee2e7271f require-dev zend-diactoros 2016-03-18 00:41:38 +01:00
Julián Gutiérrez
b629b5e53f styleCI request 2016-03-18 00:38:37 +01:00
Julián Gutiérrez
4b775fe241 include CryptTrait tests, allow Server::respondToRequest trhow exceptions and fix ResposeType tests 2016-03-18 00:25:32 +01:00
Julián Gutiérrez
8196f5c832 code against interface 2016-03-17 21:33:04 +01:00
Julián Gutiérrez
890fdeba16 CryptTrait tests 2016-03-17 21:18:28 +01:00
Alex Bilbie
c2e83ff359 Merge pull request #475 from thephpleague/analysis-zYjdLv
Applied fixes from StyleCI
2016-03-17 15:38:10 +01:00
Alex Bilbie
51a1a75d37 Applied fixes from StyleCI 2016-03-17 10:37:48 -04:00
Alex Bilbie
251190d828 Fix #468 and #473 2016-03-17 14:37:21 +00:00
Alex Bilbie
a350705a01 Merge branch 'V5-WIP' of github.com:thephpleague/oauth2-server into V5-WIP 2016-03-17 11:49:20 +00:00
Alex Bilbie
7293ff9e9d Updated zendframework/zend-diactoros from ~1.1 to ^1.1 2016-03-17 11:49:05 +00:00
Alex Bilbie
c207addf87 Merge pull request #474 from thephpleague/analysis-XlKDLQ
Applied fixes from StyleCI
2016-03-17 12:23:30 +01:00
Alex Bilbie
3af75729b8 Applied fixes from StyleCI 2016-03-17 07:22:59 -04:00
Alex Bilbie
7b8d9c9af3 Added missing RendererInterface 2016-03-17 11:22:04 +00:00
Alex Bilbie
15b6506644 No need to use Zend\Diactoros\Stream 2016-03-17 11:21:53 +00:00
Alex Bilbie
bd12c8b1a9 Fix exception usage 2016-03-17 11:18:59 +00:00
Alex Bilbie
c3c49c83f9 Merge pull request #472 from juliangut/templating
V5 - Template renderer holds template related information
2016-03-17 10:49:14 +01:00
Alex Bilbie
2f459b6470 Merge pull request #470 from juliangut/clarify
V5 - Clarify names and return types
2016-03-16 17:35:39 +01:00
Julián Gutiérrez
ee91072455 template renderer holds template related information 2016-03-16 12:32:21 +01:00
Alex Bilbie
25f93071ea Merge pull request #467 from thephpleague/analysis-z4xMPE
Applied fixes from StyleCI
2016-03-15 22:55:33 +01:00
Alex Bilbie
079ed0040a Applied fixes from StyleCI 2016-03-15 17:54:45 -04:00
Alex Bilbie
5bbf703711 Fixes for examples 2016-03-15 21:54:36 +00:00
Alex Bilbie
d635b3484b Fix broken code 2016-03-15 21:30:18 +00:00
Alex Bilbie
3365f3d733 Moved client secret validation to abstract grant. Fixes #460 2016-03-15 21:30:13 +00:00
Alex Bilbie
9e828f8f3c Updated stub client entity 2016-03-15 21:29:45 +00:00
Alex Bilbie
c7a5a57304 Added getSecret method to ClientEntityInterface 2016-03-15 21:29:35 +00:00
Julián Gutiérrez
ae0edc40aa clarify names and return types 2016-03-15 22:25:28 +01:00
Alex Bilbie
264bc7b625 Merge pull request #466 from thephpleague/analysis-8641PP
Applied fixes from StyleCI
2016-03-15 22:21:49 +01:00
Alex Bilbie
7159352108 Applied fixes from StyleCI 2016-03-15 17:21:21 -04:00
Alex Bilbie
a70bc2360a Merge branch 'V5-WIP' of github.com:thephpleague/oauth2-server into V5-WIP 2016-03-15 21:21:08 +00:00
Alex Bilbie
472ec68bbe Removed validateAccessToken from abstract response type 2016-03-15 21:20:59 +00:00
Alex Bilbie
e946c1e106 Remove old MAC output type 2016-03-15 21:20:46 +00:00
Alex Bilbie
4c392db673 Merge pull request #465 from juliangut/repositories_visibility
normalize repositories visibility
2016-03-15 21:30:48 +01:00
Julián Gutiérrez
66e473b1f0 clean use statment 2016-03-15 20:57:32 +01:00
Julián Gutiérrez
91c8daeb99 normalize repositories visibility 2016-03-15 20:54:59 +01:00
Alex Bilbie
9ffe806112 Merge pull request #464 from juliangut/scopes_from_repository
V5 - Always extract scopes from repository
2016-03-15 19:44:32 +01:00
Julián Gutiérrez
9e04da01de unused use statements 2016-03-15 01:18:54 +01:00
Julián Gutiérrez
592f60de70 allways extract scopes from repository 2016-03-15 01:10:47 +01:00
Alex Bilbie
5ae9827d67 Merge pull request #461 from juliangut/extract_scopes
V5 - scopes extraction from querystring on auth_code and implicit grants
2016-03-14 12:36:17 +01:00
Alex Bilbie
5e8d2fe0f5 Merge pull request #462 from juliangut/jwt_to_string
V5 - Convert JWT to string for http_build_query
2016-03-14 12:35:39 +01:00
Julián Gutiérrez
9b665f494f convert JWT to string for http_build_query 2016-03-14 01:00:06 +01:00
Julián Gutiérrez
ced63e2051 allow scopes extraction on GET requests for auth_code and implicit grants 2016-03-14 00:12:14 +01:00
Alex Bilbie
c3ffed2daf Merge pull request #459 from juliangut/throw_instead_of_return
V5 - Throw exception instead of return Response
2016-03-11 07:49:57 +00:00
Julián Gutiérrez
ecad2b98ae update invalid grant type test 2016-03-11 00:23:29 +01:00
Julián Gutiérrez
a0402f1994 throw exception instead of return Response 2016-03-11 00:01:19 +01:00
Alex Bilbie
6e74de50e5 Test fixes 2016-03-10 19:01:57 +00:00
Alex Bilbie
4ab9c52767 Merge pull request #448 from juliangut/validate_authenticated_request
V5 - rename validateRequest
2016-03-10 17:47:28 +00:00
Alex Bilbie
2b2d4a3df7 Merge pull request #444 from juliangut/secure_body_params_access
V5 - Secure access to body params
2016-03-10 17:47:20 +00:00
Alex Bilbie
0ae8863322 Ignore TemplateRenderer method 2016-03-10 17:45:31 +00:00
Alex Bilbie
4c55b6879d Merge pull request #457 from juliangut/renderer
V5 - Allow different template engines
2016-03-10 17:43:20 +00:00
Alex Bilbie
9590550799 Merge pull request #458 from thephpleague/analysis-XWN3Ry
Applied fixes from StyleCI
2016-03-10 17:41:28 +00:00
Alex Bilbie
c40a10a071 Applied fixes from StyleCI 2016-03-10 12:40:28 -05:00
Alex Bilbie
f7f3cdee24 Use client->setName method 2016-03-10 17:34:36 +00:00
Alex Bilbie
edf0ee8622 Removed unused code 2016-03-10 17:34:25 +00:00
Alex Bilbie
c490cd4ef2 Added middleware tests 2016-03-10 17:22:48 +00:00
Alex Bilbie
a716a08be6 Completed stub response 2016-03-10 17:22:38 +00:00
Alex Bilbie
3b4a8cf5f3 Added code coverage ignore comments 2016-03-10 17:22:10 +00:00
Alex Bilbie
8f0cb0e78c Updated server test 2016-03-10 16:34:32 +00:00
Alex Bilbie
fb1fa71b5d Improved BearerResponseType test 2016-03-10 16:34:21 +00:00
Alex Bilbie
0216638903 Added BearerResponseType test 2016-03-10 15:50:17 +00:00
Alex Bilbie
5074ad9a6c Fixed request attribute 2016-03-10 15:50:04 +00:00
Alex Bilbie
721a31534e Added implicit grant test 2016-03-10 15:10:08 +00:00
Alex Bilbie
01517bb57a Added missing namespace 2016-03-10 15:09:56 +00:00
Alex Bilbie
0f2c6e7f4e Merge pull request #446 from juliangut/unify_examples
V5 - unify examples
2016-03-10 14:32:10 +00:00
Julián Gutiérrez
320d9e65d5 StyleCI always watching upon us 2016-03-09 12:44:47 +01:00
Julián Gutiérrez
1218cede79 allow different template engines 2016-03-09 12:32:01 +01:00
Julián Gutiérrez
8ff0cb6495 include implicit grant example 2016-03-08 22:17:56 +01:00
Julián Gutiérrez
1bdeb71efb make StyleCI happy 2016-03-08 21:59:10 +01:00
Julián Gutiérrez
1632b80631 Merge branch 'V5-WIP' into secure_body_params_access 2016-03-08 21:57:43 +01:00
Julián Gutiérrez
5760450854 satisfy StyleCI 2016-03-08 21:49:05 +01:00
Julián Gutiérrez
9c66688d19 Merge branch 'V5-WIP' into unify_examples 2016-03-08 21:47:02 +01:00
Alex Bilbie
da53067e63 Updated README 2016-02-22 11:04:03 +00:00
Alex Bilbie
84172c0d29 Merge pull request #454 from thephpleague/analysis-z9myNn
Applied fixes from StyleCI
2016-02-22 08:01:14 +00:00
Alex Bilbie
997d390f3d Applied fixes from StyleCI 2016-02-22 03:00:50 -05:00
Alex Bilbie
e2794c47af First commit of the implicit grant 2016-02-22 07:59:17 +00:00
Alex Bilbie
0d0aaa8764 Use the new access token covertToJWT method 2016-02-22 07:58:59 +00:00
Alex Bilbie
ad270f7d9d Redirect either with query string parameters or fragment parameters 2016-02-22 07:58:44 +00:00
Alex Bilbie
a1bdaae9a9 Access token can now return a JWT from itself 2016-02-22 07:58:25 +00:00
Alex Bilbie
e08669d50c Doc improvements 2016-02-22 07:58:12 +00:00
Alex Bilbie
d02437dd73 Improved testing 2016-02-21 18:13:39 +00:00
Alex Bilbie
cee4147688 PHP 5.5 doesn't support phpunit 5 2016-02-21 17:11:58 +00:00
Alex Bilbie
eedcfe115c Bug fixes 2016-02-21 17:09:12 +00:00
Alex Bilbie
f06adb38cd Require dev league/plates 2016-02-21 17:09:04 +00:00
Alex Bilbie
9675dff220 Added AuthCodeGrant tests 2016-02-21 17:08:57 +00:00
Alex Bilbie
2488cbd55d Bug fixes 2016-02-21 17:08:49 +00:00
Alex Bilbie
27d4441d1d Updated to phpunit 5 2016-02-21 16:40:29 +00:00
Alex Bilbie
bc82f5badd Improved RefreshTokenGrant tests 2016-02-21 16:40:16 +00:00
Alex Bilbie
7f539f8736 Removed unused exception parameters 2016-02-21 16:40:01 +00:00
Alex Bilbie
a4b65241ad Updated PasswordGrant test 2016-02-21 16:09:39 +00:00
Alex Bilbie
8b601d79b9 First commit of AuthCodeGrant test 2016-02-21 14:32:27 +00:00
Alex Bilbie
d0878300d0 Bug fix for AuthCodeGrant 2016-02-21 14:32:16 +00:00
Alex Bilbie
97c138bb0b Removed unused SecureKey class 2016-02-20 10:05:15 +00:00
Alex Bilbie
937d425e4c Merge pull request #451 from thephpleague/analysis-XlKgE9
Applied fixes from StyleCI
2016-02-19 23:10:14 +00:00
Alex Bilbie
ff5ea52ccd Merge pull request #450 from thephpleague/styleCI
Create .styleci.yml
2016-02-19 23:10:00 +00:00
Alex Bilbie
a2460886f6 Applied fixes from StyleCI 2016-02-19 18:09:39 -05:00
Alex Bilbie
65bcc97fc3 Create .styleci.yml 2016-02-19 23:08:32 +00:00
Alex Bilbie
60c45ab8fe Merge pull request #447 from juliangut/move_identifier_generation
V5 - move token identifier generation
2016-02-18 18:27:08 +00:00
Julián Gutiérrez
a644eacea7 Merge branch 'V5-WIP' into move_identifier_generation 2016-02-18 18:14:59 +01:00
Alex Bilbie
13baa0bb26 Updated tests 2016-02-18 12:07:50 +00:00
Alex Bilbie
e8a01c3bcd Fix for logic 2016-02-18 12:07:36 +00:00
Alex Bilbie
064eb85f4e AbstractGrant now handles persisting tokens 2016-02-18 12:07:23 +00:00
Alex Bilbie
ad5b242d10 Updated AbstractGrantTest 2016-02-18 11:36:20 +00:00
Alex Bilbie
704e114568 Updated AuthCodeGrant 2016-02-18 10:49:39 +00:00
Alex Bilbie
73cd377c4b Added client credentials grant test 2016-02-18 10:49:13 +00:00
Alex Bilbie
3b36ae9000 Rewrote validateClient method to progressively test client secret and redirect URI 2016-02-18 10:49:05 +00:00
Alex Bilbie
7f67000d53 Provided implementation of new client entity methods 2016-02-18 10:48:23 +00:00
Alex Bilbie
de000b72a4 Updated ClientEntityInterface with additional methods 2016-02-18 10:48:12 +00:00
Alex Bilbie
e808528cc8 Added test stubs 2016-02-18 10:47:59 +00:00
Alex Bilbie
fb77a78fb3 Added Password Grant test 2016-02-18 10:47:52 +00:00
Alex Bilbie
0d8cb0d06f Fixes for RefreshTokenGrant 2016-02-18 10:47:30 +00:00
Alex Bilbie
fc53d636f5 Updated getClientEntity now just requires the client ID and the grant type 2016-02-18 10:47:06 +00:00
Julián Gutiérrez
dbcaaa1f35 rename determineAccessTokenInHeader 2016-02-13 14:38:23 +01:00
Julián Gutiérrez
5d6634aa9f Merge branch 'V5-WIP' into move_identifier_generation 2016-02-13 14:11:38 +01:00
Julián Gutiérrez
099c9ce41b move token identifier generation 2016-02-13 14:07:09 +01:00
Alex Bilbie
186853390a Updated phpunit.xml.dist 2016-02-12 18:08:35 +00:00
Alex Bilbie
335630f150 Added code coverage ignore docblocks 2016-02-12 18:08:27 +00:00
Alex Bilbie
de13e14cdd Added test/Utils 2016-02-12 18:08:13 +00:00
Julián Gutiérrez
2bd45f2a6b unify examples 2016-02-12 19:06:31 +01:00
Alex Bilbie
e20c529f39 Added isExpired method to refresh token 2016-02-12 17:53:42 +00:00
Alex Bilbie
08ad67e401 Updated phpunit tests 2016-02-12 17:53:07 +00:00
Alex Bilbie
7f2fd69d0a Removed respondsWith from interface 2016-02-12 17:52:37 +00:00
Alex Bilbie
29068dd84c Removed responseWith method 2016-02-12 17:51:59 +00:00
Alex Bilbie
174ae490fc Updated .gitignore / .gitattributes files 2016-02-12 17:51:28 +00:00
Alex Bilbie
fa3fb36ed8 Updated .travis.yml 2016-02-12 17:51:16 +00:00
Alex Bilbie
21e2ccd0fb Removed codeception 2016-02-12 17:51:10 +00:00
Alex Bilbie
aa0570c932 Ignore build folder 2016-02-12 17:46:42 +00:00
Alex Bilbie
9a8b7ec898 Removed old codecept tests 2016-02-12 17:46:30 +00:00
Julián Gutiérrez
1f6bb40952 correcting param access mistake 2016-02-12 18:45:47 +01:00
Julián Gutiérrez
2f914a0aa3 secure params access on authcode grant 2016-02-12 18:32:09 +01:00
Julián Gutiérrez
95e3c1d1a2 Merge branch 'V5-WIP' into secure_body_params_access 2016-02-12 17:10:52 +01:00
Alex Bilbie
64d4c4a38a Removed old tests 2016-02-12 15:44:34 +00:00
Alex Bilbie
655f6b9771 Merge pull request #445 from juliangut/abstract_token_validation
V5 - Abstract access token validation
2016-02-12 14:31:18 +00:00
Alex Bilbie
d95958bae4 Small fixes 2016-02-12 14:28:24 +00:00
Alex Bilbie
85b9412813 Multiple fixes 2016-02-12 14:18:52 +00:00
Alex Bilbie
1a5030200a The response may be a PSR response which is valid 2016-02-12 14:18:45 +00:00
Alex Bilbie
796106b6c1 Fix for non-imported namespace 2016-02-12 14:18:34 +00:00
Alex Bilbie
4234b69f3a Fix for method calls 2016-02-12 14:18:10 +00:00
Alex Bilbie
6dd4caf056 Fix for redirect_uri 2016-02-12 14:17:58 +00:00
Alex Bilbie
f6cc8bbb42 Import namespace 2016-02-12 14:17:49 +00:00
Alex Bilbie
0115c41eea Numerous bug fixes 2016-02-12 13:32:58 +00:00
Julián Gutiérrez
f314154216 abstract access token validation 2016-02-12 14:19:47 +01:00
Alex Bilbie
9b97778618 Removed unused dependency 2016-02-12 13:02:26 +00:00
Alex Bilbie
5e326d9e45 First commit of respondToAccessTokenRequest 2016-02-12 13:01:25 +00:00
Julián Gutiérrez
d2760e4ec7 secure access to body params 2016-02-12 13:56:14 +01:00
Alex Bilbie
2025749fa4 Updated respondToAuthorizationRequest to use Plates templates instead of custom ResponseType 2016-02-12 11:55:41 +00:00
Alex Bilbie
1c913fe75e Added default basic HTML login + authorise templates 2016-02-12 11:32:09 +00:00
Alex Bilbie
556c9fa782 Require league/plates in the examples composer.json 2016-02-12 11:31:46 +00:00
Alex Bilbie
c5bc63027f Suggest league/plates 2016-02-12 11:31:19 +00:00
Alex Bilbie
ac9955b393 Removed response type interfaces for auth code login + authorize because they were a stupid idea 2016-02-12 11:30:59 +00:00
Alex Bilbie
fccb06ed67 First commit of updated AuthCodeGrant with respondToAuthorizationRequest method completed 2016-02-12 10:01:15 +00:00
Alex Bilbie
f29703ea24 Updated Docblock 2016-02-12 10:00:41 +00:00
Alex Bilbie
dcc3f5d856 First commit of new ResponseTypes 2016-02-12 10:00:32 +00:00
Alex Bilbie
264eba9f20 Updated AuthCodeRepositoryInterface 2016-02-12 10:00:22 +00:00
Alex Bilbie
c2c199cf98 Added issueAuthCode method 2016-02-12 10:00:10 +00:00
Alex Bilbie
0b6bcad9fb Added getCookieParameter method 2016-02-12 09:59:59 +00:00
Alex Bilbie
38a7e53cb5 Added optional redirectUri parameter to accessDenied method 2016-02-12 09:59:47 +00:00
Alex Bilbie
f4b83baf74 Fix getClientEntity method call 2016-02-12 09:09:39 +00:00
Alex Bilbie
5a08a0cbe2 Merge branch 'V5-WIP' into V5-AuthCode
# Conflicts:
#	src/Grant/AbstractGrant.php
2016-02-12 09:06:28 +00:00
Alex Bilbie
7a628409db Validate client can now optionally validate secret + redirectUri, and actually validate the redirectUri 2016-02-12 09:03:35 +00:00
Alex Bilbie
c6d806d3f7 Docblock updates 2016-02-12 09:02:33 +00:00
Alex Bilbie
bfcf7af4d8 Added getQueryStringParameter method 2016-02-12 09:02:17 +00:00
Alex Bilbie
d96f57d27f Got rid of mystery $identifier class property, moved it to the getIdentifier method 2016-02-12 08:33:59 +00:00
Alex Bilbie
95919a688e Merge pull request #436 from juliangut/minor
V5 - Minor improvements and documentation fixes
2016-02-12 08:32:14 +00:00
Julián Gutiérrez
8b185e0580 Merge branch 'V5-WIP' into minor_merge 2016-02-12 00:12:56 +01:00
Alex Bilbie
ca776e83a2 Fix for header writing 2016-02-11 17:58:35 +00:00
Alex Bilbie
ddf3f1b890 Merge branch 'V5-WIP' into V5-AuthCode 2016-02-11 17:50:08 +00:00
Alex Bilbie
a40ac5d77b Minor fixes 2016-02-11 17:49:41 +00:00
Alex Bilbie
4bc89f3fc2 Removed unused import 2016-02-11 17:49:31 +00:00
Alex Bilbie
11d25eb5a1 Removed old exceptions 2016-02-11 17:49:24 +00:00
Alex Bilbie
770bda8f10 Merge pull request #431 from juliangut/redirectUri
V5 - use Psr\Http\Message\UriInterface
2016-02-11 17:35:33 +00:00
Alex Bilbie
7a8c92b3d9 Merge pull request #435 from juliangut/exception_middleware
V5 - Exception based access token check
2016-02-11 17:34:31 +00:00
Alex Bilbie
96620c8b3b Merge pull request #437 from juliangut/refresh_ttl
V5 - Allow refresh token TTL assign
2016-02-11 17:33:10 +00:00
Alex Bilbie
92a101f263 First commit of AuthCode rewrite 2016-02-11 17:30:01 +00:00
Julián Gutiérrez
b85f81c429 configurable refresh token TTL per grant 2016-01-21 18:11:53 +01:00
Julián Gutiérrez
8fb64041df client secret can be null 2016-01-20 12:50:23 +01:00
Julián Gutiérrez
44155a8efc allow refresh token ttl assign 2016-01-20 12:21:44 +01:00
Julián Gutiérrez
b7b1f56d0c stream write fix 2016-01-20 10:58:45 +01:00
Julián Gutiérrez
3e5889e93b minor improvements and documentation fixes 2016-01-20 10:36:16 +01:00
Julián Gutiérrez
ef5904ab1a exception based determineAccessTokenInHeader 2016-01-20 00:32:59 +01:00
Julián Gutiérrez
94cc7c2bc7 fix server reference 2016-01-20 00:16:12 +01:00
Alex Bilbie
1e1043c04f Merge pull request #432 from juliangut/middleware
V5 - authentication middleware
2016-01-17 19:33:38 +00:00
Julián Gutiérrez
8591fc7686 moved to authentication middleware 2016-01-17 18:40:26 +01:00
Alex Bilbie
86b75edca0 Merge pull request #430 from juliangut/scopedelimiter
V5 - remove scopedelimiter parameter
2016-01-17 16:40:55 +00:00
Alex Bilbie
13ddec3283 Fix for PasswordGrant 2016-01-17 16:38:25 +00:00
Alex Bilbie
322caa77af Fixes for RefreshTokenGrant 2016-01-17 16:35:52 +00:00
Julián Gutiérrez
95634fb390 compound redirect uri with Psr\Http\Message\UriInterface 2016-01-17 17:28:27 +01:00
Alex Bilbie
6beb8d42ff Replaced SecureKey::generate with random_bytes method 2016-01-17 16:16:01 +00:00
Julián Gutiérrez
6cffbfe33b remove scopedelimiter parameter 2016-01-17 17:01:08 +01:00
Alex Bilbie
5fcb47d66a Merge pull request #425 from juliangut/scopes_extraction
V5 - normalize validatescopes
2016-01-17 14:59:37 +00:00
Alex Bilbie
cbd45cc5ab Added protected API example 2016-01-17 14:56:51 +00:00
Alex Bilbie
8566a128c8 Pass errors back up the chain 2016-01-17 14:56:42 +00:00
Alex Bilbie
419cb6d149 Use first array result 2016-01-17 14:56:35 +00:00
Alex Bilbie
f1d06e7c33 Use the error returned from the response type 2016-01-17 14:56:06 +00:00
Alex Bilbie
212938d1e2 Fixed call to static 2016-01-17 14:55:48 +00:00
Alex Bilbie
cd19f11799 Fixed conversion to response object 2016-01-17 14:55:36 +00:00
Julián Gutiérrez
4862ca7d60 fix conflicts 2016-01-17 15:49:55 +01:00
Alex Bilbie
660378c7b3 Added MAC auth scheme to 401 header 2016-01-17 14:28:13 +00:00
Alex Bilbie
06ee612bb1 Updated composer.lock in example 2016-01-17 14:25:54 +00:00
Alex Bilbie
3c4347e385 Updated refresh token example 2016-01-17 14:25:44 +00:00
Alex Bilbie
168e7640c6 Updated examples to use new API 2016-01-17 14:23:42 +00:00
Alex Bilbie
3d08051cbb Removed default wording as there is no override 2016-01-17 14:23:18 +00:00
Alex Bilbie
0486d93fa3 Removed default wording as there are no overrides 2016-01-17 14:23:02 +00:00
Alex Bilbie
5a8659471c Public key is set in abstract grant now 2016-01-17 14:21:53 +00:00
Alex Bilbie
f6664c6917 Private and public key paths are injected into grants now 2016-01-17 14:21:35 +00:00
Alex Bilbie
5f22ead287 Updated access denied hint 2016-01-17 14:11:21 +00:00
Alex Bilbie
19b12cda8e Made getDefaultResponseType public 2016-01-17 14:08:53 +00:00
Alex Bilbie
6c787c374c First commit of ResourceServerMiddleware 2016-01-17 14:08:42 +00:00
Alex Bilbie
cd68103267 New server constructor 2016-01-17 14:03:41 +00:00
Alex Bilbie
6332ecfa0b Removed default overrides 2016-01-17 14:03:33 +00:00
Alex Bilbie
e43d95415b Inject required params into grant type 2016-01-17 14:03:07 +00:00
Alex Bilbie
d755a8c01d Updated the validation to BearerTokenResponse 2016-01-17 13:57:07 +00:00
Alex Bilbie
c7a904ca40 Added access token repository and public key path as required params to response type constructor 2016-01-17 13:56:46 +00:00
Alex Bilbie
8ee4dc7eb9 Fixed docblock 2016-01-17 13:56:14 +00:00
Alex Bilbie
645f719ee9 Added new repository setter methods to GrantTypeInterface 2016-01-17 13:55:12 +00:00
Alex Bilbie
0cc13630cc Cody tidy 2016-01-17 13:54:55 +00:00
Alex Bilbie
e21a13c82c Access token TTL is now configured on a per grant basis 2016-01-17 13:54:39 +00:00
Alex Bilbie
a4ce1e510e Scope delimiter string is no longer configurable 2016-01-17 13:53:18 +00:00
Alex Bilbie
ad05a5cae6 Scope delimiter is no longer a required parameter 2016-01-17 13:51:56 +00:00
Alex Bilbie
e6cc6c35ec Scope delimiter string is now a constant 2016-01-17 13:49:53 +00:00
Alex Bilbie
f74bca33ab Removed parameters that are no longer required 2016-01-17 13:48:40 +00:00
Alex Bilbie
90d9d7bdd6 Required repositories are now set by the server 2016-01-17 13:47:44 +00:00
Julián Gutiérrez
8d8dbaea0c normalize validatescopes 2016-01-17 14:35:43 +01:00
Alex Bilbie
03391e9630 Removed old access denied exception 2016-01-17 12:58:15 +00:00
Alex Bilbie
7242a8db31 Added access denied exception 2016-01-17 12:58:00 +00:00
Alex Bilbie
f44b618531 Docblock tidy 2016-01-17 12:57:50 +00:00
Alex Bilbie
9e4fd82763 Rewrote RefreshTokenGrant to understand encrypted tokens 2016-01-17 12:56:52 +00:00
Alex Bilbie
0744d8e926 Tidy up 2016-01-17 12:43:20 +00:00
Alex Bilbie
3efe7b3c0a Merge pull request #424 from juliangut/grants_abstract
V5 - abstract common grant tasks
2016-01-17 12:18:53 +00:00
Julián Gutiérrez
44ff8692dc abstract common grants tasks 2016-01-17 00:41:55 +01:00
Alex Bilbie
6108c06e34 Updated examples/composer.lock 2016-01-15 18:43:08 +00:00
Alex Bilbie
dce1620f60 Removed unused imports 2016-01-15 18:37:46 +00:00
Alex Bilbie
bcd84320da Updated docblocks 2016-01-15 18:37:26 +00:00
Alex Bilbie
a40374e6ec Merge branch 'V5-WIP' of github.com:thephpleague/oauth2-server into V5-WIP 2016-01-15 18:36:38 +00:00
Alex Bilbie
748ae15376 Updated docblock 2016-01-15 18:36:34 +00:00
Alex Bilbie
7811721d28 Merge pull request #421 from juliangut/deferred_creation
V5 - deferred default objects creation
2016-01-15 18:35:49 +00:00
Alex Bilbie
c5e5ae5555 Merge pull request #423 from hannesvdvreken/patch-1
Fix markdown syntax
2016-01-15 18:34:15 +00:00
Alex Bilbie
8f724bb720 Fix immutability issues 2016-01-15 18:32:53 +00:00
Alex Bilbie
e9f8e7ac19 Merge pull request #422 from juliangut/middleware
V5 - allow middleware use
2016-01-15 18:30:53 +00:00
Hannes Van De Vreken
c4830608a2 Fix markdown syntax 2016-01-15 16:08:10 +01:00
Julián Gutiérrez
65d981ad32 allow middleware use 2016-01-15 14:02:47 +01:00
Julián Gutiérrez
3de1b5917a deferred default objects creation 2016-01-15 12:41:48 +01:00
Alex Bilbie
0fbe447862 Removed old exceptions 2016-01-15 00:17:13 +00:00
Alex Bilbie
84a9802a67 Removed ServerAwareTrait 2016-01-15 00:14:41 +00:00
Alex Bilbie
f7b3c018c5 Removed old authorization server 2016-01-15 00:05:59 +00:00
Alex Bilbie
a88c30cb53 Added invalid refresh token exception 2016-01-14 23:47:49 +00:00
Alex Bilbie
5e6f0fc6a3 Code tidy 2016-01-14 23:47:41 +00:00
Alex Bilbie
b57b497cb7 Revoke both refresh token and access token 2016-01-14 23:47:19 +00:00
Alex Bilbie
0b061e3086 Refresh token is encrypted payload now instead of JWT 2016-01-14 23:47:06 +00:00
Alex Bilbie
304ea2baf4 Encrypt refresh token parameters instead of using JWT 2016-01-14 23:46:24 +00:00
Alex Bilbie
56060b2c16 Code tidy 2016-01-14 23:45:36 +00:00
Alex Bilbie
633746b02e Added KeyCrypt class 2016-01-14 23:44:39 +00:00
Alex Bilbie
94b221c8a1 Updated examples 2016-01-13 00:47:41 +00:00
Alex Bilbie
20ad5d251c Updated link to OAuth 2 spec 2016-01-13 00:47:27 +00:00
Alex Bilbie
e95a228128 Added code of conduct 2016-01-13 00:46:18 +00:00
Alex Bilbie
dc2919710c Updated README 2016-01-13 00:46:08 +00:00
Alex Bilbie
936b8f93ec Addititonal refresh token validation 2016-01-13 00:38:23 +00:00
Alex Bilbie
c1d15aa15c Uset sub instead of uid 2016-01-13 00:38:08 +00:00
Alex Bilbie
70e9d7b699 Updated examples 2016-01-13 00:28:52 +00:00
Alex Bilbie
79791e5848 Code tidy 2016-01-13 00:13:34 +00:00
Alex Bilbie
0efa7cd7ea Set the uid on the refresh token 2016-01-13 00:13:16 +00:00
Alex Bilbie
eef5cf39d4 Fixes to refresh grant 2016-01-13 00:12:10 +00:00
Alex Bilbie
6fb3fb5110 Updated refresh token grant 2016-01-12 23:53:03 +00:00
Alex Bilbie
a2bbb17483 Updated repository method names 2016-01-12 23:52:08 +00:00
Alex Bilbie
3135f1796e Generate a refresh token in password grant 2016-01-12 23:05:19 +00:00
Alex Bilbie
d565665ccb Code tidy 2016-01-12 23:05:07 +00:00
Alex Bilbie
13a1ea6db8 Updated token interface to drop owner concept for simple user identifier 2016-01-12 23:04:33 +00:00
Alex Bilbie
6358be90c2 Token is now linked to a user identifier instead of owner concept 2016-01-12 23:04:03 +00:00
Alex Bilbie
de89a6bc89 Code tidy 2016-01-12 23:03:38 +00:00
Alex Bilbie
e03ad0d52f Server constructor expects path to private key 2016-01-12 23:03:24 +00:00
Alex Bilbie
2a20de991b Docblock update 2016-01-12 23:02:54 +00:00
Alex Bilbie
b8732a2f83 BearerTokenResponse now outputs JWTs. Fixes #209 2016-01-12 23:02:45 +00:00
Alex Bilbie
1bdad3ad14 Updated AbstractResponseType with interface methods 2016-01-12 23:01:55 +00:00
Alex Bilbie
fd47712060 Removed unused methods 2016-01-12 23:01:19 +00:00
Alex Bilbie
6339524c86 Updated RefreshToken methods 2016-01-12 23:00:05 +00:00
Alex Bilbie
5f9feda80c ScopeEntity is JsonSerializable 2016-01-12 22:59:33 +00:00
Alex Bilbie
9958e1bf80 Added serverError exception 2016-01-12 22:59:14 +00:00
Alex Bilbie
758471ec16 Fixed docblock 2016-01-12 22:59:00 +00:00
Alex Bilbie
3fcba9339d Updated composer.json 2016-01-12 22:58:45 +00:00
Alex Bilbie
f9c0cb08e0 Removed unused code 2016-01-12 22:58:25 +00:00
Alex Bilbie
a9313e76d4 Removed old JsonWebTokenType response as all tokens are JWTs now 2016-01-12 22:56:10 +00:00
Alex Bilbie
59080a8319 New dependencies 2016-01-10 13:15:58 +00:00
Alex Bilbie
524f04c78c Made generate-crypto-key executable 2016-01-10 13:15:43 +00:00
Alex Bilbie
8e04868320 Added bin/generate-crypto-key 2016-01-10 13:15:17 +00:00
Alex Bilbie
fa3dc4e055 Merge pull request #401 from vinkla/patch-1
Add branch alias for version 5.0
2015-12-22 13:40:04 +00:00
Alex Bilbie
f9b2441c41 Merge pull request #408 from vinkla/license
Rename license file
2015-12-22 13:25:00 +00:00
Alex Bilbie
09f1d0fbb1 Merge pull request #409 from vinkla/phpunit
Rename phpunit.xml file
2015-12-22 13:24:42 +00:00
Vincent Klaiber
5ab91d7345 Rename phpunit.xml file 2015-12-03 14:33:05 +01:00
Vincent Klaiber
6c054dbf35 Rename license file 2015-12-03 14:30:37 +01:00
Alex Bilbie
530cdb02f0 Merge pull request #405 from vinkla/patch-2
Add files to attributes
2015-12-03 13:23:22 +00:00
Vincent Klaiber
0a2d4c1649 Add files to attributes
Added more files to the .gitattributes file.
2015-12-02 17:02:54 +01:00
Alex Bilbie
bb17abfe26 Updated password grant example 2015-11-16 12:58:50 +00:00
Alex Bilbie
e7e4892408 Fixed method parameter name 2015-11-16 12:58:38 +00:00
Alex Bilbie
46648f3e80 Updated password grant 2015-11-16 12:58:11 +00:00
Alex Bilbie
6f2e2a0071 Updated exceptions 2015-11-16 12:57:59 +00:00
Vincent Klaiber
b7ba593856 Add branch alias for version 5.0
To let us start testing this version for Laravel OAuth server package.
2015-11-16 12:36:23 +01:00
Alex Bilbie
c0bdd22154 Updated exception reference 2015-11-16 09:27:49 +00:00
Alex Bilbie
32b451aa21 Updates 2015-11-13 17:41:05 +00:00
Alex Bilbie
96a0c34d41 Updated example repositories to match updated interfaces 2015-11-13 17:40:53 +00:00
Alex Bilbie
b95780022a Updated client credentials example 2015-11-13 17:40:39 +00:00
Alex Bilbie
c0823c464e Tidy 2015-11-13 17:40:29 +00:00
Alex Bilbie
cc43a31ca6 Updated examples composer 2015-11-13 17:40:22 +00:00
Alex Bilbie
da8efa20cd Updated repository method names to be more explicit 2015-11-13 17:39:07 +00:00
Alex Bilbie
03e4ac7ea6 Removed service providers 2015-11-13 17:38:48 +00:00
Alex Bilbie
1442842da9 TokenType -> ResponseType 2015-11-13 17:38:23 +00:00
Alex Bilbie
0a602cb022 We don't support PHP 5.4 anymore 2015-11-13 17:37:53 +00:00
Alex Bilbie
b479cb7912 New OAuthServerException class 2015-11-13 17:37:37 +00:00
Alex Bilbie
41c7a6e731 Removed old exceptions 2015-11-13 17:37:28 +00:00
Alex Bilbie
82413513e8 Checkin 2015-10-14 09:51:53 +01:00
Alex Bilbie
18b104d0ac Run codecept build to generate test files 2015-04-06 08:34:50 +01:00
Alex Bilbie
2e3c6b4f3a Refactored constructor to set defaults, added new setter methods for default token TTL and default token type 2015-04-06 08:32:44 +01:00
Alex Bilbie
8e9b12fefd Code readability 2015-04-06 08:23:35 +01:00
Alex Bilbie
95a2308ff6 Added @todo 2015-04-06 08:23:24 +01:00
Alex Bilbie
9985f3eee2 Fixed docblock 2015-04-06 08:23:18 +01:00
Alex Bilbie
39df4ff9b1 Clarified docblock 2015-04-06 08:21:25 +01:00
Alex Bilbie
90d18c553d Broke expiration DateTime out into seperate variable for readability 2015-04-06 08:13:41 +01:00
Alex Bilbie
385b03db6f Import DateTime instead of using root namespace 2015-04-06 08:08:18 +01:00
Alex Bilbie
a15995c126 First commit of updated auth code grant 2015-04-05 21:57:29 +01:00
Alex Bilbie
f4cfd37745 Added isExpired method 2015-04-05 21:57:17 +01:00
Alex Bilbie
a0d5d5817b Updated AuthCodeEntity 2015-04-05 21:57:04 +01:00
Alex Bilbie
d468cbf600 Updated AuthCodeRepositoryInterface 2015-04-05 21:56:42 +01:00
Alex Bilbie
be14b3a2df Updated namespace 2015-04-05 21:14:22 +01:00
Alex Bilbie
1f1f0d8f15 Added PasswordGrantProvider to container 2015-04-05 21:14:06 +01:00
Alex Bilbie
8fcf93c489 Removed unused method 2015-04-05 21:13:53 +01:00
Alex Bilbie
bdd71743cd Added knowledge of UserRepository 2015-04-05 21:13:45 +01:00
Alex Bilbie
77b5282b46 Namespace updates 2015-04-05 21:13:15 +01:00
Alex Bilbie
e88d802918 Added UserEntityInterface 2015-04-05 21:13:04 +01:00
Alex Bilbie
61ab070692 Renamed ClientCredentialsGrantServerProvider to ClientCredentialsGrantProvider 2015-04-05 21:12:55 +01:00
Alex Bilbie
d3ed454881 Added PasswordGrantProvider 2015-04-05 21:12:26 +01:00
Alex Bilbie
b5bbf8332f Added JsonWebTokenType 2015-04-05 21:12:05 +01:00
Alex Bilbie
110d5ce76f Respond with json content-type header 2015-04-05 21:11:51 +01:00
Alex Bilbie
bf1c46d62f Added firebase/php-jwt to composer.json 2015-04-05 21:11:35 +01:00
Alex Bilbie
5840ace38f Updated examples 2015-04-05 21:11:10 +01:00
Alex Bilbie
eabcf82268 Added UserRepositoryInterface 2015-04-05 21:10:50 +01:00
Alex Bilbie
6a78d53d03 Updated grants 2015-04-05 21:10:41 +01:00
Alex Bilbie
b831d19f8d Renamed interface 2015-04-05 21:10:18 +01:00
Alex Bilbie
721e52c5d9 Renamed response types to token types 2015-04-05 21:10:06 +01:00
Alex Bilbie
6e73099d8c Ignore hhvm failures for now 2015-04-05 18:51:46 +01:00
Alex Bilbie
784af67367 Code tidy 2015-04-05 18:42:24 +01:00
Alex Bilbie
4f053bb63a Added ircmaxell/password-compat so tests pass on < PHP 5.5 2015-04-05 18:42:18 +01:00
Alex Bilbie
5211d1902c Fixed .travis.yml 2015-04-05 18:35:26 +01:00
Alex Bilbie
ffc8823e4f Move out of directory 2015-04-05 18:28:07 +01:00
Alex Bilbie
f912f60a59 Added .travis.yml before_script 2015-04-05 18:26:09 +01:00
Alex Bilbie
476b8d81c1 Build v5 branch 2015-04-05 18:21:57 +01:00
Alex Bilbie
2b2067e162 Updated .travis.yml 2015-04-05 18:19:37 +01:00
Alex Bilbie
9048617e35 Updated client credentials example 2015-04-05 18:18:28 +01:00
Alex Bilbie
775d42115a More client credentials test 2015-04-05 18:18:09 +01:00
Alex Bilbie
f3705865a3 Ignore codeception output 2015-04-05 18:17:36 +01:00
Alex Bilbie
15cef6ba16 Code tidy 2015-04-05 18:16:26 +01:00
Alex Bilbie
72b741d7c9 Added generateHttpResponse method to exception 2015-04-05 18:16:21 +01:00
Alex Bilbie
26c1abdd3c Remove client secret propety on entity 2015-04-05 17:13:55 +01:00
Alex Bilbie
56f6df11a8 Updated .gitignore 2015-04-05 17:07:10 +01:00
Alex Bilbie
997d4f2eb7 Updated .gitignore 2015-04-05 17:06:05 +01:00
Alex Bilbie
d63efc8dbf Updated grant type interface 2015-04-05 17:05:57 +01:00
Alex Bilbie
7a3670523d First commit of Codeception files 2015-04-05 17:05:49 +01:00
Alex Bilbie
1e39f1d84a Updated abstract server 2015-04-05 17:03:13 +01:00
Alex Bilbie
0b66fd1948 First commit of new server class 2015-04-05 17:03:06 +01:00
Alex Bilbie
164de644e9 First commit of new examples 2015-04-05 17:02:43 +01:00
Alex Bilbie
f1da0d2943 Added ClientCredentialsGrantServerProvider 2015-04-05 17:01:41 +01:00
Alex Bilbie
f964fd2962 Updated abstract grant and client credentials grant 2015-04-05 17:01:19 +01:00
Alex Bilbie
36a1a430b5 Updated response types 2015-04-05 17:01:00 +01:00
Alex Bilbie
3721ecb40a Updated repository interfaces 2015-04-05 17:00:43 +01:00
Alex Bilbie
5fcf01f4c8 Updated composer dev requirements 2015-04-05 17:00:01 +01:00
Alex Bilbie
a16a1dbb7d Removed old examples 2015-04-05 14:07:24 +01:00
Alex Bilbie
f357602090 Removed old traits 2015-04-05 14:03:34 +01:00
Alex Bilbie
a48630c837 New entities, traits and interfaces 2015-04-05 14:03:25 +01:00
Alex Bilbie
171be1c422 Updated .gitignore and .gitattributes 2015-04-05 13:59:38 +01:00
Alex Bilbie
324b6db5e6 Added league/container to dependencies 2015-04-04 15:42:26 +01:00
Alex Bilbie
a73322fb43 Renamed namespace Util > Utils 2015-04-04 15:42:12 +01:00
Alex Bilbie
027971776b Namespace renamed TokenType > TokenTypes 2015-04-04 15:41:53 +01:00
Alex Bilbie
7c57310b67 Removed old fuzz tests 2015-04-04 15:41:31 +01:00
Alex Bilbie
5d7eeb0512 Spelling fix 2015-03-01 21:29:52 +00:00
Alex Bilbie
742b51c2cd Removed domain events 2015-03-01 21:29:47 +00:00
Alex Bilbie
cc7596f3b3 Renamed storage to repository 2015-02-22 19:44:26 +00:00
Alex Bilbie
7da7484008 Added security section 2015-02-05 16:14:59 +00:00
Alex Bilbie
b42ba4af17 Merge pull request #303 from hannesvdvreken/fix/consistent-use-and-fqcn
Boyscouting the php docs to always use FQCNs
2015-01-23 10:47:26 +00:00
Hannes Van De Vreken
dd795a82f4 Changed the order and added missing throws 2015-01-23 11:21:12 +01:00
Hannes Van De Vreken
166362d3cd Boyscouting the php docs to always use FQCNs 2015-01-23 11:17:19 +01:00
Alex Bilbie
ea6edf572a Changelog update 2015-01-01 12:56:20 +00:00
190 changed files with 8443 additions and 9153 deletions

18
.gitattributes vendored
View File

@@ -1,5 +1,13 @@
tests/ export-ignore
phpunit.xml export-ignore
build.xml export-ignore
test export-ignore
.travis.yml export-ignore
* text=auto
/examples export-ignore
/tests export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/.travis.yml export-ignore
.travis.yml export-ignore
.scrutinizer.yml export-ignore
/phpunit.xml.dist export-ignore
/CHANGELOG.md export-ignore
/CONTRIBUTING.md export-ignore
/README.md export-ignore

19
.gitignore vendored
View File

@@ -1,15 +1,8 @@
/vendor
/composer.lock
/build
/docs
/testing
/examples/relational/vendor
/examples/relational/config/oauth2.sqlite3
/examples/nosql/vendor
/examples/nosql/config/oauth2.sqlite3
/examples/relational/composer.lock
/tests/codecept/tests/_log
oauth2-server.paw
/output_*/
/_site
.idea
phpunit.xml
.idea
/examples/vendor
examples/public.key
examples/private.key
build

53
.styleci.yml Normal file
View File

@@ -0,0 +1,53 @@
preset: psr2
enabled:
- binary_operator_spaces
- blank_line_before_return
- concat_with_spaces
- function_typehint_space
- hash_to_slash_comment
- include
- lowercase_cast
- method_separation
- native_function_casing
- no_blank_lines_after_class_opening
- no_blank_lines_between_uses
- no_duplicate_semicolons
- no_leading_import_slash
- no_leading_namespace_whitespace
- no_multiline_whitespace_before_semicolons
- no_php4_constructor
- no_short_bool_cast
- no_singleline_whitespace_before_semicolons
- no_trailing_comma_in_singleline_array
- no_unreachable_default_argument_value
- no_unused_imports
- no_whitespace_before_comma_in_array
- ordered_imports
- phpdoc_align
- phpdoc_indent
- phpdoc_inline_tag
- phpdoc_no_access
- phpdoc_no_simplified_null_return
- phpdoc_order
- phpdoc_property
- phpdoc_scalar
- phpdoc_separation
- phpdoc_to_comment
- phpdoc_trim
- phpdoc_type_to_var
- phpdoc_types
- phpdoc_var_without_name
- print_to_echo
- short_array_syntax
- short_scalar_cast
- simplified_null_return
- single_quote
- spaces_cast
- standardize_not_equal
- ternary_operator_spaces
- trailing_comma_in_multiline_array
- trim_array_spaces
- unary_operator_spaces
- whitespace_after_comma_in_array
- whitespacy_lines

View File

@@ -1,44 +1,24 @@
language: php
sudo: false
cache:
directories:
- vendor
php:
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
install:
- travis_retry composer install --no-interaction --prefer-source
script:
- mkdir -p build/logs
- phpunit --coverage-text --verbose --coverage-clover=coverage.clover --coverage-html coverage
- vendor/bin/phpunit
after_script:
- wget https://scrutinizer-ci.com/ocular.phar
- php ocular.phar code-coverage:upload --format=php-clover coverage.clover
- git config --global user.email "travis@travis-ci.org"
- git config --global user.name "TravisCI"
- cp -R coverage ${HOME}/coverage
- cd ${HOME}
- git clone --quiet --branch=gh-pages https://${GITHUBTOKEN}@github.com/thephpleague/oauth2-server.git gh-pages > /dev/null
- cd gh-pages
- mkdir ${TRAVIS_BRANCH}
- cd ${TRAVIS_BRANCH}
- cp -Rf $HOME/coverage/* .
- git add -f .
- git commit -m "Travis pushed coverage of ${TRAVIS_COMMIT}@${TRAVIS_BRANCH} to gh-pages"
- git push -fq origin gh-pages > /dev/null
branches:
only:
- master
env:
global:
secure: "C4wD/BQefKSu9W594iyLp+IBCjlM8kKlmp+nXKXnZGi0L8IkV3m4mmNOb8PExxGMhZ3mlev5DnU4Uoh4oJaUxnkR1FpX4dSEpyzU3VknUzSE2yZOlL+bdCw3o85TGoCcp/+ReJCOw5sncxTskJKHlW1YMa33FznaXwLNoImpjTg="
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/7de0ca12596cd5268f30
on_success: always # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: false # default: false
- V5-WIP

View File

@@ -1,5 +1,65 @@
# Changelog
## 5.0.0-RC1 (release 2016-03-24)
Version 5 is a complete code rewrite.
* JWT support
* PSR-7 support
* Improved exception errors
* Replace all occurrences of the term "Storage" with "Repository"
* Simplify repositories
* Entities conform to interfaces and use traits
* Auth code grant updated
* Allow support for public clients
* Add support for #439
* Client credentials grant updated
* Password grant updated
* Allow support for public clients
* Refresh token grant updated
* Implement Implicit grant
* Bearer token output type
* Remove MAC token output type
* Authorization server rewrite
* Resource server class moved to PSR-7 middleware
* Tests
* Much much better documentation
## 4.1.5 (released 2016-01-04)
* Enable Symfony 3.0 support (#412)
## 4.1.4 (released 2015-11-13)
* Fix for determining access token in header (Issue #328)
* Refresh tokens are now returned for MAC responses (Issue #356)
* Added integration list to readme (Issue #341)
* Expose parameter passed to exceptions (Issue #345)
* Removed duplicate routing setup code (Issue #346)
* Docs fix (Issues #347, #360, #380)
* Examples fix (Issues #348, #358)
* Fix typo in docblock (Issue #352)
* Improved timeouts for MAC tokens (Issue #364)
* `hash_hmac()` should output raw binary data, not hexits (Issue #370)
* Improved regex for matching all Base64 characters (Issue #371)
* Fix incorrect signature parameter (Issue #372)
* AuthCodeGrant and RefreshTokenGrant don't require client_secret (Issue #377)
* Added priority argument to event listener (Issue #388)
## 4.1.3 (released 2015-03-22)
* Docblock, namespace and inconsistency fixes (Issue #303)
* Docblock type fix (Issue #310)
* Example bug fix (Issue #300)
* Updated league/event to ~2.1 (Issue #311)
* Fixed missing session scope (Issue #319)
* Updated interface docs (Issue #323)
* `.travis.yml` updates
## 4.1.2 (released 2015-01-01)
* Remove side-effects in hash_equals() implementation (Issue #290)
## 4.1.1 (released 2014-12-31)
* Changed `symfony/http-foundation` dependency version to `~2.4` so package can be installed in Laravel `4.1.*`
@@ -124,7 +184,7 @@
* Included a PDO driver which implements the storage interfaces so the library is more "get up and go"
* Further normalised the database structure so all sessions no longer contain infomation related to authorization grant (which may or may not be enabled)
* A session can have multiple associated access tokens
* Induvidual grants can have custom expire times for access tokens
* Individual grants can have custom expire times for access tokens
* Authorization codes now have a TTL of 10 minutes by default (can be manually set)
* Refresh tokens now have a TTL of one week by default (can be manually set)
* The client credentials grant will no longer gives out refresh tokens as per the specification

22
CONDUCT.md Normal file
View File

@@ -0,0 +1,22 @@
# Contributor Code of Conduct
As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing other's private information, such as physical or electronic addresses, without explicit permission
* Other unethical or unprofessional conduct.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.
This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community in a direct capacity. Personal views, beliefs and values of individuals do not necessarily reflect those of the organisation or affiliated individuals and organisations.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)

View File

@@ -5,43 +5,40 @@
[![Build Status](https://img.shields.io/travis/thephpleague/oauth2-server/master.svg?style=flat-square)](https://travis-ci.org/thephpleague/oauth2-server)
[![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/thephpleague/oauth2-server.svg?style=flat-square)](https://scrutinizer-ci.com/g/thephpleague/oauth2-server/code-structure)
[![Quality Score](https://img.shields.io/scrutinizer/g/thephpleague/oauth2-server.svg?style=flat-square)](https://scrutinizer-ci.com/g/thephpleague/oauth2-server)
[![Total Downloads](https://img.shields.io/packagist/dt/league/oauth2-server.svg?style=flat-square)](https://packagist.org/packages/league/oauth2-server) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/thephpleague/oauth2-server?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Total Downloads](https://img.shields.io/packagist/dt/league/oauth2-server.svg?style=flat-square)](https://packagist.org/packages/league/oauth2-server)
A standards compliant [OAuth 2.0](http://tools.ietf.org/wg/oauth/draft-ietf-oauth-v2/) authorization server and resource server written in PHP which makes working with OAuth 2.0 trivial. You can easily configure an OAuth 2.0 server to protect your API with access tokens, or allow clients to request new access tokens and refresh them.
`league/oauth2-server` is a a standards compliant implementation of an [OAuth 2.0](https://tools.ietf.org/html/rfc6749) authorization server written in PHP which makes working with OAuth 2.0 trivial. You can easily configure an OAuth 2.0 server to protect your API with access tokens, or allow clients to request new access tokens and refresh them.
It supports out of the box the following grants:
* Authorization code grant
* Implicit grant
* Client credentials grant
* Resource owner password credentials grant
* Refresh grant
You can also define your own grants.
You can also easily define your own grants.
In addition it supports the following token types:
In addition it supports the following token response types:
* Bearer tokens
* Bearer (JWT) tokens
* MAC tokens
* JSON web tokens (coming soon)
You can also create you own tokens.
## Requirements
The following versions of PHP are supported:
* PHP 5.4
* PHP 5.5
* PHP 5.5 (>=5.5.9)
* PHP 5.6
* PHP 7.0
* HHVM
## Documentation
This library has [full documentation](http://oauth2.thephpleague.com), powered by [Jekyll](http://jekyllrb.com/).
Contribute to this documentation in the [gh-pages branch](https://github.com/thephpleague/oauth2-server/tree/gh-pages/).
The library documentation can be found at [http://oauth2.thephpleague.com](http://oauth2.thephpleague.com).
You can contribute to this documentation in the [gh-pages branch](https://github.com/thephpleague/oauth2-server/tree/gh-pages/).
## Changelog
@@ -49,11 +46,17 @@ Contribute to this documentation in the [gh-pages branch](https://github.com/the
## Contributing
Please see [CONTRIBUTING](https://github.com/thephpleague/oauth2-server/blob/master/CONTRIBUTING.md) for details.
Please see [CONTRIBUTING.md](https://github.com/thephpleague/oauth2-server/blob/master/CONTRIBUTING.md) and [CONDUCT.md](https://github.com/thephpleague/oauth2-server/blob/master/CONDUCT.md) for details.
## Support
Bugs and feature request are tracked on [GitHub](https://github.com/thephpleague/oauth2-server/issues)
Bugs and feature request are tracked on [GitHub](https://github.com/thephpleague/oauth2-server/issues).
If you have any questions about OAuth _please_ open a ticket here; please **don't** email the address below.
## Security
If you discover any security related issues, please email hello@alexbilbie.com instead of using the issue tracker.
## License
@@ -63,12 +66,6 @@ This package is released under the MIT License. See the bundled [LICENSE](https:
This code is principally developed and maintained by [Alex Bilbie](https://twitter.com/alexbilbie).
Special thanks to:
* [Dan Horrigan](https://github.com/dandoescode)
* [Nick Jackson](https://github.com/jacksonj04)
* [Michael Gooden](https://github.com/MichaelGooden)
* [Phil Sturgeon](https://github.com/philsturgeon)
* [and all the other contributors](https://github.com/thephpleague/oauth2-server/contributors)
Special thanks to [all of these awesome contributors](https://github.com/thephpleague/oauth2-server/contributors)
The initial code was developed as part of the [Linkey](http://linkey.blogs.lincoln.ac.uk) project which was funded by [JISC](http://jisc.ac.uk) under the Access and Identity Management programme.

View File

@@ -1,59 +1,73 @@
{
"name": "league/oauth2-server",
"description": "A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.",
"homepage": "http://oauth2.thephpleague.com/",
"license": "MIT",
"require": {
"php": ">=5.4.0",
"symfony/http-foundation": "~2.4",
"league/event": "1.0.*"
},
"require-dev": {
"phpunit/phpunit": "4.3.*",
"mockery/mockery": "0.9.*"
},
"repositories": [
{
"type": "git",
"url": "https://github.com/thephpleague/oauth2-server.git"
}
],
"keywords": [
"oauth",
"oauth2",
"oauth 2",
"oauth 2.0",
"server",
"auth",
"authorization",
"authorisation",
"authentication",
"resource",
"api",
"auth",
"protect",
"secure"
],
"authors": [
{
"name": "Alex Bilbie",
"email": "hello@alexbilbie.com",
"homepage": "http://www.alexbilbie.com",
"role": "Developer"
}
],
"replace": {
"lncd/oauth2": "*",
"league/oauth2server": "*"
},
"autoload": {
"psr-4": {
"League\\OAuth2\\Server\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"LeagueTests\\": "tests/unit/"
}
}
"name": "league/oauth2-server",
"description": "A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.",
"homepage": "http://oauth2.thephpleague.com/",
"license": "MIT",
"require": {
"php": ">=5.5.9",
"league/event": "^2.1",
"lcobucci/jwt": "^3.1",
"paragonie/random_compat": "^1.1",
"psr/http-message": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8",
"league/plates": "^3.1",
"zendframework/zend-diactoros": "^1.0"
},
"repositories": [
{
"type": "git",
"url": "https://github.com/thephpleague/oauth2-server.git"
}
],
"keywords": [
"oauth",
"oauth2",
"oauth 2",
"oauth 2.0",
"server",
"auth",
"authorization",
"authorisation",
"authentication",
"resource",
"api",
"auth",
"protect",
"secure"
],
"authors": [
{
"name": "Alex Bilbie",
"email": "hello@alexbilbie.com",
"homepage": "http://www.alexbilbie.com",
"role": "Developer"
}
],
"replace": {
"lncd/oauth2": "*",
"league/oauth2server": "*"
},
"autoload": {
"psr-4": {
"League\\OAuth2\\Server\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"LeagueTests\\": "tests/"
}
},
"extra": {
"branch-alias": {
"dev-V5-WIP": "5.0-dev"
}
},
"suggest": {
"league/plates": "Used for parsing authorization code templates",
"twig/twig": "Used for parsing authorization code templates",
"smarty/smarty": "Used for parsing authorization code templates",
"mustache/mustache": "Used for parsing authorization code templates"
}
}

53
examples/README.md Normal file
View File

@@ -0,0 +1,53 @@
# Example implementations
## Installation
0. Run `composer install --no-dev` in this directory to install dependencies
0. Create a private key `openssl genrsa -out private.key 1024`
0. Create a public key `openssl rsa -in private.key -pubout > public.key`
0. `cd` into the public directory
0. Start a PHP server `php -S localhost:4444`
## Testing the client credentials grant example
Send the following cURL request:
```
curl -X "POST" "http://localhost:4444/client_credentials.php/access_token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Accept: 1.0" \
--data-urlencode "grant_type=client_credentials" \
--data-urlencode "client_id=myawesomeapp" \
--data-urlencode "client_secret=abc123" \
--data-urlencode "scope=basic email"
```
## Testing the password grant example
Send the following cURL request:
```
curl -X "POST" "http://localhost:4444/password.php/access_token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Accept: 1.0" \
--data-urlencode "grant_type=password" \
--data-urlencode "client_id=myawesomeapp" \
--data-urlencode "client_secret=abc123" \
--data-urlencode "username=alex" \
--data-urlencode "password=whisky" \
--data-urlencode "scope=basic email"
```
## Testing the refresh token grant example
Send the following cURL request. Replace `{{REFRESH_TOKEN}}` with a refresh token from another grant above:
```
curl -X "POST" "http://localhost:4444/refresh_token.php/access_token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Accept: 1.0" \
--data-urlencode "grant_type=refresh_token" \
--data-urlencode "client_id=myawesomeapp" \
--data-urlencode "client_secret=abc123" \
--data-urlencode "refresh_token={{REFRESH_TOKEN}}"
```

18
examples/composer.json Normal file
View File

@@ -0,0 +1,18 @@
{
"repositories": [
{
"type": "path",
"url": ".."
}
],
"require": {
"slim/slim": "3.0.*",
"league/oauth2-server": "dev-V5-WIP",
"league/plates": "^3.1"
},
"autoload": {
"psr-4": {
"OAuth2ServerExamples\\": "src/"
}
}
}

537
examples/composer.lock generated Normal file
View File

@@ -0,0 +1,537 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "143453cc35e7f499b130b6460222dc5a",
"content-hash": "1ea46581fb6db25f323a37a45ef74f95",
"packages": [
{
"name": "container-interop/container-interop",
"version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/container-interop/container-interop.git",
"reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/container-interop/container-interop/zipball/fc08354828f8fd3245f77a66b9e23a6bca48297e",
"reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e",
"shasum": ""
},
"type": "library",
"autoload": {
"psr-4": {
"Interop\\Container\\": "src/Interop/Container/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
"time": "2014-12-30 15:22:37"
},
{
"name": "lcobucci/jwt",
"version": "3.1.0",
"source": {
"type": "git",
"url": "https://github.com/lcobucci/jwt.git",
"reference": "31499db4e692b343cec7ff345932899f98fde1cf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lcobucci/jwt/zipball/31499db4e692b343cec7ff345932899f98fde1cf",
"reference": "31499db4e692b343cec7ff345932899f98fde1cf",
"shasum": ""
},
"require": {
"ext-openssl": "*",
"php": ">=5.5"
},
"require-dev": {
"mdanter/ecc": "~0.3",
"mikey179/vfsstream": "~1.5",
"phpmd/phpmd": "~2.2",
"phpunit/php-invoker": "~1.1",
"phpunit/phpunit": "~4.5",
"squizlabs/php_codesniffer": "~2.3"
},
"suggest": {
"mdanter/ecc": "Required to use Elliptic Curves based algorithms."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"psr-4": {
"Lcobucci\\JWT\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Luís Otávio Cobucci Oblonczyk",
"email": "lcobucci@gmail.com",
"role": "Developer"
}
],
"description": "A simple library to work with JSON Web Token and JSON Web Signature",
"keywords": [
"JWS",
"jwt"
],
"time": "2015-11-15 01:42:47"
},
{
"name": "league/event",
"version": "2.1.2",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/event.git",
"reference": "e4bfc88dbcb60c8d8a2939a71f9813e141bbe4cd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/event/zipball/e4bfc88dbcb60c8d8a2939a71f9813e141bbe4cd",
"reference": "e4bfc88dbcb60c8d8a2939a71f9813e141bbe4cd",
"shasum": ""
},
"require": {
"php": ">=5.4.0"
},
"require-dev": {
"henrikbjorn/phpspec-code-coverage": "~1.0.1",
"phpspec/phpspec": "~2.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.2-dev"
}
},
"autoload": {
"psr-4": {
"League\\Event\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Frank de Jonge",
"email": "info@frenky.net"
}
],
"description": "Event package",
"keywords": [
"emitter",
"event",
"listener"
],
"time": "2015-05-21 12:24:47"
},
{
"name": "league/oauth2-server",
"version": "dev-V5-WIP",
"dist": {
"type": "path",
"url": "../",
"reference": "0fbe109e2004c71feac2bd14fd85aff97704b2e5",
"shasum": null
},
"require": {
"lcobucci/jwt": "^3.1",
"league/event": "^2.1",
"paragonie/random_compat": "^1.1",
"php": ">=5.5.9",
"psr/http-message": "^1.0"
},
"replace": {
"league/oauth2server": "*",
"lncd/oauth2": "*"
},
"require-dev": {
"league/plates": "^3.1",
"phpunit/phpunit": "^4.8",
"zendframework/zend-diactoros": "^1.0"
},
"suggest": {
"league/plates": "Used for parsing authorization code templates",
"mustache/mustache": "Used for parsing authorization code templates",
"smarty/smarty": "Used for parsing authorization code templates",
"twig/twig": "Used for parsing authorization code templates"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-V5-WIP": "5.0-dev"
}
},
"autoload": {
"psr-4": {
"League\\OAuth2\\Server\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"LeagueTests\\": "tests/"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Alex Bilbie",
"email": "hello@alexbilbie.com",
"homepage": "http://www.alexbilbie.com",
"role": "Developer"
}
],
"description": "A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.",
"homepage": "http://oauth2.thephpleague.com/",
"keywords": [
"api",
"auth",
"auth",
"authentication",
"authorisation",
"authorization",
"oauth",
"oauth 2",
"oauth 2.0",
"oauth2",
"protect",
"resource",
"secure",
"server"
]
},
{
"name": "league/plates",
"version": "3.1.1",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/plates.git",
"reference": "2d8569e9f140a70d6a05db38006926f7547cb802"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/plates/zipball/2d8569e9f140a70d6a05db38006926f7547cb802",
"reference": "2d8569e9f140a70d6a05db38006926f7547cb802",
"shasum": ""
},
"require-dev": {
"mikey179/vfsstream": "~1.4.0",
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "~1.5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"psr-4": {
"League\\Plates\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jonathan Reinink",
"email": "jonathan@reinink.ca",
"role": "Developer"
}
],
"description": "Plates, the native PHP template system that's fast, easy to use and easy to extend.",
"homepage": "http://platesphp.com",
"keywords": [
"league",
"package",
"templates",
"templating",
"views"
],
"time": "2015-07-09 02:14:40"
},
{
"name": "nikic/fast-route",
"version": "v0.6.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/FastRoute.git",
"reference": "31fa86924556b80735f98b294a7ffdfb26789f22"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/FastRoute/zipball/31fa86924556b80735f98b294a7ffdfb26789f22",
"reference": "31fa86924556b80735f98b294a7ffdfb26789f22",
"shasum": ""
},
"require": {
"php": ">=5.4.0"
},
"type": "library",
"autoload": {
"psr-4": {
"FastRoute\\": "src/"
},
"files": [
"src/functions.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Nikita Popov",
"email": "nikic@php.net"
}
],
"description": "Fast request router for PHP",
"keywords": [
"router",
"routing"
],
"time": "2015-06-18 19:15:47"
},
{
"name": "paragonie/random_compat",
"version": "v1.4.1",
"source": {
"type": "git",
"url": "https://github.com/paragonie/random_compat.git",
"reference": "c7e26a21ba357863de030f0b9e701c7d04593774"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/c7e26a21ba357863de030f0b9e701c7d04593774",
"reference": "c7e26a21ba357863de030f0b9e701c7d04593774",
"shasum": ""
},
"require": {
"php": ">=5.2.0"
},
"require-dev": {
"phpunit/phpunit": "4.*|5.*"
},
"suggest": {
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
},
"type": "library",
"autoload": {
"files": [
"lib/random.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Paragon Initiative Enterprises",
"email": "security@paragonie.com",
"homepage": "https://paragonie.com"
}
],
"description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
"keywords": [
"csprng",
"pseudorandom",
"random"
],
"time": "2016-03-18 20:34:03"
},
{
"name": "pimple/pimple",
"version": "v3.0.2",
"source": {
"type": "git",
"url": "https://github.com/silexphp/Pimple.git",
"reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/silexphp/Pimple/zipball/a30f7d6e57565a2e1a316e1baf2a483f788b258a",
"reference": "a30f7d6e57565a2e1a316e1baf2a483f788b258a",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0.x-dev"
}
},
"autoload": {
"psr-0": {
"Pimple": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
}
],
"description": "Pimple, a simple Dependency Injection Container",
"homepage": "http://pimple.sensiolabs.org",
"keywords": [
"container",
"dependency injection"
],
"time": "2015-09-11 15:10:35"
},
{
"name": "psr/http-message",
"version": "1.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298",
"reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"time": "2015-05-04 20:22:00"
},
{
"name": "slim/slim",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/slimphp/Slim.git",
"reference": "3b06f0f2d84dabbe81b6cea46ace46a3e883253e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slimphp/Slim/zipball/3b06f0f2d84dabbe81b6cea46ace46a3e883253e",
"reference": "3b06f0f2d84dabbe81b6cea46ace46a3e883253e",
"shasum": ""
},
"require": {
"container-interop/container-interop": "^1.1",
"nikic/fast-route": "^0.6",
"php": ">=5.5.0",
"pimple/pimple": "^3.0",
"psr/http-message": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Slim\\": "Slim"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Rob Allen",
"email": "rob@akrabat.com",
"homepage": "http://akrabat.com"
},
{
"name": "Josh Lockhart",
"email": "hello@joshlockhart.com",
"homepage": "https://joshlockhart.com"
},
{
"name": "Gabriel Manricks",
"email": "gmanricks@me.com",
"homepage": "http://gabrielmanricks.com"
},
{
"name": "Andrew Smith",
"email": "a.smith@silentworks.co.uk",
"homepage": "http://silentworks.co.uk"
}
],
"description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs",
"homepage": "http://slimframework.com",
"keywords": [
"api",
"framework",
"micro",
"router"
],
"time": "2015-12-07 14:11:09"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
"league/oauth2-server": 20
},
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
}

74
examples/public/api.php Normal file
View File

@@ -0,0 +1,74 @@
<?php
use League\OAuth2\Server\Server;
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
use OAuth2ServerExamples\Repositories\ClientRepository;
use OAuth2ServerExamples\Repositories\ScopeRepository;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\App;
include __DIR__ . '/../vendor/autoload.php';
$app = new App([
'settings' => [
'displayErrorDetails' => true,
],
Server::class => function () {
// Setup the authorization server
$server = new Server(
new ClientRepository(),
new AccessTokenRepository(),
new ScopeRepository(),
'file://' . __DIR__ . '/../private.key',
'file://' . __DIR__ . '/../public.key'
);
return $server;
},
]);
$app->add(
new \League\OAuth2\Server\Middleware\ResourceServerMiddleware(
$app->getContainer()->get(Server::class)
)
);
$app->get('/users', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
$users = [
[
'id' => 123,
'name' => 'Alex',
'email' => 'alex@thephpleague.com',
],
[
'id' => 124,
'name' => 'Frank',
'email' => 'frank@thephpleague.com',
],
[
'id' => 125,
'name' => 'Phil',
'email' => 'phil@thephpleague.com',
],
];
if (in_array('basic', $request->getAttribute('oauth_scopes')) === false) {
for ($i = 0; $i < count($users); $i++) {
unset($users[$i]['name']);
}
}
if (in_array('email', $request->getAttribute('oauth_scopes')) === false) {
for ($i = 0; $i < count($users); $i++) {
unset($users[$i]['email']);
}
}
$response->getBody()->write(json_encode($users));
return $response->withStatus(200);
});
$app->run();

View File

@@ -0,0 +1,91 @@
<?php
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Grant\AuthCodeGrant;
use League\OAuth2\Server\Server;
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
use OAuth2ServerExamples\Repositories\AuthCodeRepository;
use OAuth2ServerExamples\Repositories\ClientRepository;
use OAuth2ServerExamples\Repositories\RefreshTokenRepository;
use OAuth2ServerExamples\Repositories\ScopeRepository;
use OAuth2ServerExamples\Repositories\UserRepository;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\App;
use Zend\Diactoros\Stream;
include __DIR__ . '/../vendor/autoload.php';
$app = new App([
'settings' => [
'displayErrorDetails' => true,
],
Server::class => function () {
// Init our repositories
$clientRepository = new ClientRepository();
$scopeRepository = new ScopeRepository();
$accessTokenRepository = new AccessTokenRepository();
$authCodeRepository = new AuthCodeRepository();
$refreshTokenRepository = new RefreshTokenRepository();
$userRepository = new UserRepository();
$privateKeyPath = 'file://' . __DIR__ . '/../private.key';
$publicKeyPath = 'file://' . __DIR__ . '/../public.key';
// Setup the authorization server
$server = new Server(
$clientRepository,
$accessTokenRepository,
$scopeRepository,
$privateKeyPath,
$publicKeyPath
);
// Enable the authentication code grant on the server with a token TTL of 1 hour
$server->enableGrantType(
new AuthCodeGrant(
$authCodeRepository,
$refreshTokenRepository,
$userRepository,
new \DateInterval('PT10M')
),
new \DateInterval('PT1H')
);
return $server;
},
]);
$app->any('/authorize', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
/* @var \League\OAuth2\Server\Server $server */
$server = $app->getContainer()->get(Server::class);
try {
return $server->respondToRequest($request, $response);
} catch (OAuthServerException $exception) {
return $exception->generateHttpResponse($response);
} catch (\Exception $exception) {
$body = new Stream('php://temp', 'r+');
$body->write($exception->getMessage());
return $response->withStatus(500)->withBody($body);
}
});
$app->post('/access_token', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
/* @var \League\OAuth2\Server\Server $server */
$server = $app->getContainer()->get(Server::class);
try {
return $server->respondToRequest($request, $response);
} catch (OAuthServerException $exception) {
return $exception->generateHttpResponse($response);
} catch (\Exception $exception) {
$body = new Stream('php://temp', 'r+');
$body->write($exception->getMessage());
return $response->withStatus(500)->withBody($body);
}
});
$app->run();

View File

@@ -0,0 +1,64 @@
<?php
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Grant\ClientCredentialsGrant;
use League\OAuth2\Server\Server;
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
use OAuth2ServerExamples\Repositories\ClientRepository;
use OAuth2ServerExamples\Repositories\ScopeRepository;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\App;
use Zend\Diactoros\Stream;
include __DIR__ . '/../vendor/autoload.php';
$app = new App([
'settings' => [
'displayErrorDetails' => true,
],
Server::class => function () {
// Init our repositories
$clientRepository = new ClientRepository();
$accessTokenRepository = new AccessTokenRepository();
$scopeRepository = new ScopeRepository();
$privateKeyPath = 'file://' . __DIR__ . '/../private.key';
$publicKeyPath = 'file://' . __DIR__ . '/../public.key';
// Setup the authorization server
$server = new Server(
$clientRepository,
$accessTokenRepository,
$scopeRepository,
$privateKeyPath,
$publicKeyPath
);
// Enable the client credentials grant on the server with a token TTL of 1 hour
$server->enableGrantType(
new ClientCredentialsGrant(),
new \DateInterval('PT1H')
);
return $server;
},
]);
$app->post('/access_token', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
/* @var \League\OAuth2\Server\Server $server */
$server = $app->getContainer()->get(Server::class);
try {
return $server->respondToRequest($request, $response);
} catch (OAuthServerException $exception) {
return $exception->generateHttpResponse($response);
} catch (\Exception $exception) {
$body = new Stream('php://temp', 'r+');
$body->write($exception->getMessage());
return $response->withStatus(500)->withBody($body);
}
});
$app->run();

View File

@@ -0,0 +1,66 @@
<?php
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Grant\ImplicitGrant;
use League\OAuth2\Server\Server;
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
use OAuth2ServerExamples\Repositories\ClientRepository;
use OAuth2ServerExamples\Repositories\ScopeRepository;
use OAuth2ServerExamples\Repositories\UserRepository;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\App;
use Zend\Diactoros\Stream;
include __DIR__ . '/../vendor/autoload.php';
$app = new App([
'settings' => [
'displayErrorDetails' => true,
],
Server::class => function () {
// Init our repositories
$clientRepository = new ClientRepository();
$scopeRepository = new ScopeRepository();
$accessTokenRepository = new AccessTokenRepository();
$userRepository = new UserRepository();
$privateKeyPath = 'file://' . __DIR__ . '/../private.key';
$publicKeyPath = 'file://' . __DIR__ . '/../public.key';
// Setup the authorization server
$server = new Server(
$clientRepository,
$accessTokenRepository,
$scopeRepository,
$privateKeyPath,
$publicKeyPath
);
// Enable the implicit grant on the server with a token TTL of 1 hour
$server->enableGrantType(
new ImplicitGrant($userRepository),
new \DateInterval('PT1H')
);
return $server;
},
]);
$app->any('/authorize', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
/* @var \League\OAuth2\Server\Server $server */
$server = $app->getContainer()->get(Server::class);
try {
return $server->respondToRequest($request, $response);
} catch (OAuthServerException $exception) {
return $exception->generateHttpResponse($response);
} catch (\Exception $exception) {
$body = new Stream('php://temp', 'r+');
$body->write($exception->getMessage());
return $response->withStatus(500)->withBody($body);
}
});
$app->run();

View File

@@ -0,0 +1,95 @@
<?php
use League\OAuth2\Server\Grant\AuthCodeGrant;
use League\OAuth2\Server\Grant\RefreshTokenGrant;
use League\OAuth2\Server\Middleware\AuthenticationServerMiddleware;
use League\OAuth2\Server\Middleware\ResourceServerMiddleware;
use League\OAuth2\Server\Server;
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
use OAuth2ServerExamples\Repositories\AuthCodeRepository;
use OAuth2ServerExamples\Repositories\ClientRepository;
use OAuth2ServerExamples\Repositories\RefreshTokenRepository;
use OAuth2ServerExamples\Repositories\ScopeRepository;
use OAuth2ServerExamples\Repositories\UserRepository;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\App;
use Zend\Diactoros\Stream;
include __DIR__ . '/../vendor/autoload.php';
$app = new App([
'settings' => [
'displayErrorDetails' => true,
],
Server::class => function () {
// Init our repositories
$clientRepository = new ClientRepository();
$accessTokenRepository = new AccessTokenRepository();
$scopeRepository = new ScopeRepository();
$authCodeRepository = new AuthCodeRepository();
$refreshTokenRepository = new RefreshTokenRepository();
$userRepository = new UserRepository();
$privateKeyPath = 'file://' . __DIR__ . '/../private.key';
$publicKeyPath = 'file://' . __DIR__ . '/../public.key';
// Setup the authorization server
$server = new Server(
$clientRepository,
$accessTokenRepository,
$scopeRepository,
$privateKeyPath,
$publicKeyPath
);
// Enable the authentication code grant on the server with a token TTL of 1 hour
$server->enableGrantType(
new AuthCodeGrant(
$authCodeRepository,
$refreshTokenRepository,
$userRepository,
new \DateInterval('PT10M')
),
new \DateInterval('PT1H')
);
// Enable the refresh token grant on the server with a token TTL of 1 month
$server->enableGrantType(
new RefreshTokenGrant($refreshTokenRepository),
new \DateInterval('PT1M')
);
return $server;
},
]);
// Access token issuer
$app->post('/access_token', function () {
})->add(new AuthenticationServerMiddleware($app->getContainer()->get(Server::class)));
// Secured API
$app->group('/api', function () {
$this->get('/user', function (ServerRequestInterface $request, ResponseInterface $response) {
$params = [];
if (in_array('basic', $request->getAttribute('oauth_scopes', []))) {
$params = [
'id' => 1,
'name' => 'Alex',
'city' => 'London',
];
}
if (in_array('email', $request->getAttribute('oauth_scopes', []))) {
$params['email'] = 'alex@example.com';
}
$body = new Stream('php://temp', 'r+');
$body->write(json_encode($params));
return $response->withBody($body);
});
})->add(new ResourceServerMiddleware($app->getContainer()->get(Server::class)));
$app->run();

View File

@@ -0,0 +1,68 @@
<?php
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Grant\PasswordGrant;
use League\OAuth2\Server\Server;
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
use OAuth2ServerExamples\Repositories\ClientRepository;
use OAuth2ServerExamples\Repositories\RefreshTokenRepository;
use OAuth2ServerExamples\Repositories\ScopeRepository;
use OAuth2ServerExamples\Repositories\UserRepository;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\App;
use Zend\Diactoros\Stream;
include __DIR__ . '/../vendor/autoload.php';
$app = new App([
'settings' => [
'displayErrorDetails' => true,
],
Server::class => function () {
// Init our repositories
$clientRepository = new ClientRepository();
$accessTokenRepository = new AccessTokenRepository();
$scopeRepository = new ScopeRepository();
$userRepository = new UserRepository();
$refreshTokenRepository = new RefreshTokenRepository();
$privateKeyPath = 'file://' . __DIR__ . '/../private.key';
$publicKeyPath = 'file://' . __DIR__ . '/../public.key';
// Setup the authorization server
$server = new Server(
$clientRepository,
$accessTokenRepository,
$scopeRepository,
$privateKeyPath,
$publicKeyPath
);
// Enable the password grant on the server with a token TTL of 1 hour
$server->enableGrantType(
new PasswordGrant($userRepository, $refreshTokenRepository),
new \DateInterval('PT1H')
);
return $server;
},
]);
$app->post('/access_token', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
/* @var \League\OAuth2\Server\Server $server */
$server = $app->getContainer()->get(Server::class);
try {
return $server->respondToRequest($request, $response);
} catch (OAuthServerException $exception) {
return $exception->generateHttpResponse($response);
} catch (\Exception $exception) {
$body = new Stream('php://temp', 'r+');
$body->write($exception->getMessage());
return $response->withStatus(500)->withBody($body);
}
});
$app->run();

View File

@@ -0,0 +1,66 @@
<?php
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Grant\RefreshTokenGrant;
use League\OAuth2\Server\Server;
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
use OAuth2ServerExamples\Repositories\ClientRepository;
use OAuth2ServerExamples\Repositories\RefreshTokenRepository;
use OAuth2ServerExamples\Repositories\ScopeRepository;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\App;
use Zend\Diactoros\Stream;
include __DIR__ . '/../vendor/autoload.php';
$app = new App([
'settings' => [
'displayErrorDetails' => true,
],
Server::class => function () {
// Init our repositories
$clientRepository = new ClientRepository();
$accessTokenRepository = new AccessTokenRepository();
$scopeRepository = new ScopeRepository();
$refreshTokenRepository = new RefreshTokenRepository();
$privateKeyPath = 'file://' . __DIR__ . '/../private.key';
$publicKeyPath = 'file://' . __DIR__ . '/../public.key';
// Setup the authorization server
$server = new Server(
$clientRepository,
$accessTokenRepository,
$scopeRepository,
$privateKeyPath,
$publicKeyPath
);
// Enable the refresh token grant on the server with a token TTL of 1 hour
$server->enableGrantType(
new RefreshTokenGrant($refreshTokenRepository),
new \DateInterval('PT1H')
);
return $server;
},
]);
$app->post('/access_token', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
/* @var \League\OAuth2\Server\Server $server */
$server = $app->getContainer()->get(Server::class);
try {
return $server->respondToRequest($request, $response);
} catch (OAuthServerException $exception) {
return $exception->generateHttpResponse($response);
} catch (\Exception $exception) {
$body = new Stream('php://temp', 'r+');
$body->write($exception->getMessage());
return $response->withStatus(500)->withBody($body);
}
});
$app->run();

View File

@@ -1,25 +0,0 @@
<?php
namespace RelationalExample\Model;
use Illuminate\Database\Capsule\Manager as Capsule;
class Users
{
public function get($username = null)
{
$query = Capsule::table('users')->select(['username', 'password', 'name', 'email', 'photo']);
if ($username !== null) {
$query->where('username', '=', $username);
}
$result = $query->get();
if (count($result) > 0) {
return $result;
}
return;
}
}

View File

@@ -1,93 +0,0 @@
<?php
namespace RelationalExample\Storage;
use Illuminate\Database\Capsule\Manager as Capsule;
use League\OAuth2\Server\Entity\AccessTokenEntity;
use League\OAuth2\Server\Entity\ScopeEntity;
use League\OAuth2\Server\Storage\AbstractStorage;
use League\OAuth2\Server\Storage\AccessTokenInterface;
class AccessTokenStorage extends AbstractStorage implements AccessTokenInterface
{
/**
* {@inheritdoc}
*/
public function get($token)
{
$result = Capsule::table('oauth_access_tokens')
->where('access_token', $token)
->get();
if (count($result) === 1) {
$token = (new AccessTokenEntity($this->server))
->setId($result[0]['access_token'])
->setExpireTime($result[0]['expire_time']);
return $token;
}
return;
}
/**
* {@inheritdoc}
*/
public function getScopes(AccessTokenEntity $token)
{
$result = Capsule::table('oauth_access_token_scopes')
->select(['oauth_scopes.id', 'oauth_scopes.description'])
->join('oauth_scopes', 'oauth_access_token_scopes.scope', '=', 'oauth_scopes.id')
->where('access_token', $token->getId())
->get();
$response = [];
if (count($result) > 0) {
foreach ($result as $row) {
$scope = (new ScopeEntity($this->server))->hydrate([
'id' => $row['id'],
'description' => $row['description'],
]);
$response[] = $scope;
}
}
return $response;
}
/**
* {@inheritdoc}
*/
public function create($token, $expireTime, $sessionId)
{
Capsule::table('oauth_access_tokens')
->insert([
'access_token' => $token,
'session_id' => $sessionId,
'expire_time' => $expireTime,
]);
}
/**
* {@inheritdoc}
*/
public function associateScope(AccessTokenEntity $token, ScopeEntity $scope)
{
Capsule::table('oauth_access_token_scopes')
->insert([
'access_token' => $token->getId(),
'scope' => $scope->getId(),
]);
}
/**
* {@inheritdoc}
*/
public function delete(AccessTokenEntity $token)
{
Capsule::table('oauth_access_token_scopes')
->where('access_token', $token->getId())
->delete();
}
}

View File

@@ -1,93 +0,0 @@
<?php
namespace RelationalExample\Storage;
use Illuminate\Database\Capsule\Manager as Capsule;
use League\OAuth2\Server\Entity\AuthCodeEntity;
use League\OAuth2\Server\Entity\ScopeEntity;
use League\OAuth2\Server\Storage\AbstractStorage;
use League\OAuth2\Server\Storage\AuthCodeInterface;
class AuthCodeStorage extends AbstractStorage implements AuthCodeInterface
{
/**
* {@inheritdoc}
*/
public function get($code)
{
$result = Capsule::table('oauth_auth_codes')
->where('auth_code', $code)
->where('expire_time', '>=', time())
->get();
if (count($result) === 1) {
$token = new AuthCodeEntity($this->server);
$token->setId($result[0]['auth_code']);
$token->setRedirectUri($result[0]['client_redirect_uri']);
$token->setExpireTime($result[0]['expire_time']);
return $token;
}
return;
}
public function create($token, $expireTime, $sessionId, $redirectUri)
{
Capsule::table('oauth_auth_codes')
->insert([
'auth_code' => $token,
'client_redirect_uri' => $redirectUri,
'session_id' => $sessionId,
'expire_time' => $expireTime,
]);
}
/**
* {@inheritdoc}
*/
public function getScopes(AuthCodeEntity $token)
{
$result = Capsule::table('oauth_auth_code_scopes')
->select(['oauth_scopes.id', 'oauth_scopes.description'])
->join('oauth_scopes', 'oauth_auth_code_scopes.scope', '=', 'oauth_scopes.id')
->where('auth_code', $token->getId())
->get();
$response = [];
if (count($result) > 0) {
foreach ($result as $row) {
$scope = (new ScopeEntity($this->server))->hydrate([
'id' => $row['id'],
'description' => $row['description'],
]);
$response[] = $scope;
}
}
return $response;
}
/**
* {@inheritdoc}
*/
public function associateScope(AuthCodeEntity $token, ScopeEntity $scope)
{
Capsule::table('oauth_auth_code_scopes')
->insert([
'auth_code' => $token->getId(),
'scope' => $scope->getId(),
]);
}
/**
* {@inheritdoc}
*/
public function delete(AuthCodeEntity $token)
{
Capsule::table('oauth_auth_codes')
->where('auth_code', $token->getId())
->delete();
}
}

View File

@@ -1,70 +0,0 @@
<?php
namespace RelationalExample\Storage;
use Illuminate\Database\Capsule\Manager as Capsule;
use League\OAuth2\Server\Entity\ClientEntity;
use League\OAuth2\Server\Entity\SessionEntity;
use League\OAuth2\Server\Storage\AbstractStorage;
use League\OAuth2\Server\Storage\ClientInterface;
class ClientStorage extends AbstractStorage implements ClientInterface
{
/**
* {@inheritdoc}
*/
public function get($clientId, $clientSecret = null, $redirectUri = null, $grantType = null)
{
$query = Capsule::table('oauth_clients')
->select('oauth_clients.*')
->where('oauth_clients.id', $clientId);
if ($clientSecret !== null) {
$query->where('oauth_clients.secret', $clientSecret);
}
if ($redirectUri) {
$query->join('oauth_client_redirect_uris', 'oauth_clients.id', '=', 'oauth_client_redirect_uris.client_id')
->select(['oauth_clients.*', 'oauth_client_redirect_uris.*'])
->where('oauth_client_redirect_uris.redirect_uri', $redirectUri);
}
$result = $query->get();
if (count($result) === 1) {
$client = new ClientEntity($this->server);
$client->hydrate([
'id' => $result[0]['id'],
'name' => $result[0]['name'],
]);
return $client;
}
return;
}
/**
* {@inheritdoc}
*/
public function getBySession(SessionEntity $session)
{
$result = Capsule::table('oauth_clients')
->select(['oauth_clients.id', 'oauth_clients.name'])
->join('oauth_sessions', 'oauth_clients.id', '=', 'oauth_sessions.client_id')
->where('oauth_sessions.id', $session->getId())
->get();
if (count($result) === 1) {
$client = new ClientEntity($this->server);
$client->hydrate([
'id' => $result[0]['id'],
'name' => $result[0]['name'],
]);
return $client;
}
return;
}
}

View File

@@ -1,55 +0,0 @@
<?php
namespace RelationalExample\Storage;
use Illuminate\Database\Capsule\Manager as Capsule;
use League\OAuth2\Server\Entity\RefreshTokenEntity;
use League\OAuth2\Server\Storage\AbstractStorage;
use League\OAuth2\Server\Storage\RefreshTokenInterface;
class RefreshTokenStorage extends AbstractStorage implements RefreshTokenInterface
{
/**
* {@inheritdoc}
*/
public function get($token)
{
$result = Capsule::table('oauth_refresh_tokens')
->where('refresh_token', $token)
->get();
if (count($result) === 1) {
$token = (new RefreshTokenEntity($this->server))
->setId($result[0]['refresh_token'])
->setExpireTime($result[0]['expire_time'])
->setAccessTokenId($result[0]['access_token']);
return $token;
}
return;
}
/**
* {@inheritdoc}
*/
public function create($token, $expireTime, $accessToken)
{
Capsule::table('oauth_refresh_tokens')
->insert([
'refresh_token' => $token,
'access_token' => $accessToken,
'expire_time' => $expireTime,
]);
}
/**
* {@inheritdoc}
*/
public function delete(RefreshTokenEntity $token)
{
Capsule::table('oauth_refresh_tokens')
->where('refresh_token', $token->getId())
->delete();
}
}

View File

@@ -1,30 +0,0 @@
<?php
namespace RelationalExample\Storage;
use Illuminate\Database\Capsule\Manager as Capsule;
use League\OAuth2\Server\Entity\ScopeEntity;
use League\OAuth2\Server\Storage\AbstractStorage;
use League\OAuth2\Server\Storage\ScopeInterface;
class ScopeStorage extends AbstractStorage implements ScopeInterface
{
/**
* {@inheritdoc}
*/
public function get($scope, $grantType = null, $clientId = null)
{
$result = Capsule::table('oauth_scopes')
->where('id', $scope)
->get();
if (count($result) === 0) {
return;
}
return (new ScopeEntity($this->server))->hydrate([
'id' => $result[0]['id'],
'description' => $result[0]['description'],
]);
}
}

View File

@@ -1,109 +0,0 @@
<?php
namespace RelationalExample\Storage;
use Illuminate\Database\Capsule\Manager as Capsule;
use League\OAuth2\Server\Entity\AccessTokenEntity;
use League\OAuth2\Server\Entity\AuthCodeEntity;
use League\OAuth2\Server\Entity\ScopeEntity;
use League\OAuth2\Server\Entity\SessionEntity;
use League\OAuth2\Server\Storage\AbstractStorage;
use League\OAuth2\Server\Storage\SessionInterface;
class SessionStorage extends AbstractStorage implements SessionInterface
{
/**
* {@inheritdoc}
*/
public function getByAccessToken(AccessTokenEntity $accessToken)
{
$result = Capsule::table('oauth_sessions')
->select(['oauth_sessions.id', 'oauth_sessions.owner_type', 'oauth_sessions.owner_id', 'oauth_sessions.client_id', 'oauth_sessions.client_redirect_uri'])
->join('oauth_access_tokens', 'oauth_access_tokens.session_id', '=', 'oauth_sessions.id')
->where('oauth_access_tokens.access_token', $accessToken->getId())
->get();
if (count($result) === 1) {
$session = new SessionEntity($this->server);
$session->setId($result[0]['id']);
$session->setOwner($result[0]['owner_type'], $result[0]['owner_id']);
return $session;
}
return;
}
/**
* {@inheritdoc}
*/
public function getByAuthCode(AuthCodeEntity $authCode)
{
$result = Capsule::table('oauth_sessions')
->select(['oauth_sessions.id', 'oauth_sessions.owner_type', 'oauth_sessions.owner_id', 'oauth_sessions.client_id', 'oauth_sessions.client_redirect_uri'])
->join('oauth_auth_codes', 'oauth_auth_codes.session_id', '=', 'oauth_sessions.id')
->where('oauth_auth_codes.auth_code', $authCode->getId())
->get();
if (count($result) === 1) {
$session = new SessionEntity($this->server);
$session->setId($result[0]['id']);
$session->setOwner($result[0]['owner_type'], $result[0]['owner_id']);
return $session;
}
return;
}
/**
* {@inheritdoc}
*/
public function getScopes(SessionEntity $session)
{
$result = Capsule::table('oauth_sessions')
->select('oauth_scopes.*')
->join('oauth_session_scopes', 'oauth_sessions.id', '=', 'oauth_session_scopes.session_id')
->join('oauth_scopes', 'oauth_scopes.id', '=', 'oauth_session_scopes.scope')
->where('oauth_sessions.id', $session->getId())
->get();
$scopes = [];
foreach ($result as $scope) {
$scopes[] = (new ScopeEntity($this->server))->hydrate([
'id' => $scope['id'],
'description' => $scope['description'],
]);
}
return $scopes;
}
/**
* {@inheritdoc}
*/
public function create($ownerType, $ownerId, $clientId, $clientRedirectUri = null)
{
$id = Capsule::table('oauth_sessions')
->insertGetId([
'owner_type' => $ownerType,
'owner_id' => $ownerId,
'client_id' => $clientId,
]);
return $id;
}
/**
* {@inheritdoc}
*/
public function associateScope(SessionEntity $session, ScopeEntity $scope)
{
Capsule::table('oauth_session_scopes')
->insert([
'session_id' => $session->getId(),
'scope' => $scope->getId(),
]);
}
}

View File

@@ -1,135 +0,0 @@
<?php
use League\OAuth2\Server\ResourceServer;
use Orno\Http\Exception\NotFoundException;
use Orno\Http\Request;
use Orno\Http\Response;
use RelationalExample\Model;
use RelationalExample\Storage;
include __DIR__.'/vendor/autoload.php';
// Routing setup
$request = (new Request())->createFromGlobals();
$router = new \Orno\Route\RouteCollection();
$router->setStrategy(\Orno\Route\RouteStrategyInterface::RESTFUL_STRATEGY);
// Set up the OAuth 2.0 resource server
$sessionStorage = new Storage\SessionStorage();
$accessTokenStorage = new Storage\AccessTokenStorage();
$clientStorage = new Storage\ClientStorage();
$scopeStorage = new Storage\ScopeStorage();
$server = new ResourceServer(
$sessionStorage,
$accessTokenStorage,
$clientStorage,
$scopeStorage
);
// Routing setup
$request = (new Request())->createFromGlobals();
$router = new \Orno\Route\RouteCollection();
// GET /tokeninfo
$router->get('/tokeninfo', function (Request $request) use ($server) {
$accessToken = $server->getAccessToken();
$session = $server->getSessionStorage()->getByAccessToken($accessToken);
$token = [
'owner_id' => $session->getOwnerId(),
'owner_type' => $session->getOwnerType(),
'access_token' => $accessToken,
'client_id' => $session->getClient()->getId(),
'scopes' => $accessToken->getScopes(),
];
return new Response(json_encode($token));
});
// GET /users
$router->get('/users', function (Request $request) use ($server) {
$results = (new Model\Users())->get();
$users = [];
foreach ($results as $result) {
$user = [
'username' => $result['username'],
'name' => $result['name'],
];
if ($server->getAccessToken()->hasScope('email')) {
$user['email'] = $result['email'];
}
if ($server->getAccessToken()->hasScope('photo')) {
$user['photo'] = $result['photo'];
}
$users[] = $user;
}
return new Response(json_encode($users));
});
// GET /users/{username}
$router->get('/users/{username}', function (Request $request, Response $response, array $args) use ($server) {
$result = (new Model\Users())->get($args['username']);
if (count($result) === 0) {
throw new NotFoundException();
}
$user = [
'username' => $result[0]['username'],
'name' => $result[0]['name'],
];
if ($server->getAccessToken()->hasScope('email')) {
$user['email'] = $result[0]['email'];
}
if ($server->getAccessToken()->hasScope('photo')) {
$user['photo'] = $result[0]['photo'];
}
return new Response(json_encode($user));
});
$dispatcher = $router->getDispatcher();
try {
// Check that access token is present
$server->isValidRequest(false);
// A successful response
$response = $dispatcher->dispatch(
$request->getMethod(),
$request->getPathInfo()
);
} catch (\Orno\Http\Exception $e) {
// A failed response
$response = $e->getJsonResponse();
$response->setContent(json_encode(['status_code' => $e->getStatusCode(), 'message' => $e->getMessage()]));
} catch (\League\OAuth2\Server\Exception\OAuthException $e) {
$response = new Response(json_encode([
'error' => $e->errorType,
'message' => $e->getMessage(),
]), $e->httpStatusCode);
foreach ($e->getHttpHeaders() as $header) {
$response->headers($header);
}
} catch (\Exception $e) {
$response = new Orno\Http\Response();
$response->setStatusCode(500);
$response->setContent(json_encode(['status_code' => 500, 'message' => $e->getMessage()]));
} finally {
// Return the response
$response->headers->set('Content-type', 'application/json');
$response->send();
}

View File

@@ -1,117 +0,0 @@
<?php
use Orno\Http\Request;
use Orno\Http\Response;
use RelationalExample\Storage;
include __DIR__.'/vendor/autoload.php';
// Routing setup
$request = (new Request())->createFromGlobals();
$router = new \Orno\Route\RouteCollection();
$router->setStrategy(\Orno\Route\RouteStrategyInterface::RESTFUL_STRATEGY);
// Set up the OAuth 2.0 authorization server
$server = new \League\OAuth2\Server\AuthorizationServer();
$server->setSessionStorage(new Storage\SessionStorage());
$server->setAccessTokenStorage(new Storage\AccessTokenStorage());
$server->setRefreshTokenStorage(new Storage\RefreshTokenStorage());
$server->setClientStorage(new Storage\ClientStorage());
$server->setScopeStorage(new Storage\ScopeStorage());
$server->setAuthCodeStorage(new Storage\AuthCodeStorage());
$authCodeGrant = new \League\OAuth2\Server\Grant\AuthCodeGrant();
$server->addGrantType($authCodeGrant);
$refrehTokenGrant = new \League\OAuth2\Server\Grant\RefreshTokenGrant();
$server->addGrantType($refrehTokenGrant);
// Routing setup
$request = (new Request())->createFromGlobals();
$router = new \Orno\Route\RouteCollection();
$router->get('/authorize', function (Request $request) use ($server) {
// First ensure the parameters in the query string are correct
try {
$authParams = $server->getGrantType('authorization_code')->checkAuthorizeParams();
} catch (\Exception $e) {
return new Response(
json_encode([
'error' => $e->errorType,
'message' => $e->getMessage(),
]),
$e->httpStatusCode,
$e->getHttpHeaders()
);
}
// Normally at this point you would show the user a sign-in screen and ask them to authorize the requested scopes
// ...
// ...
// ...
// Create a new authorize request which will respond with a redirect URI that the user will be redirected to
$redirectUri = $server->getGrantType('authorization_code')->newAuthorizeRequest('user', 1, $authParams);
$response = new Response('', 200, [
'Location' => $redirectUri
]);
return $response;
});
$router->post('/access_token', function (Request $request) use ($server) {
try {
$response = $server->issueAccessToken();
return new Response(json_encode($response), 200);
} catch (\Exception $e) {
return new Response(
json_encode([
'error' => $e->errorType,
'message' => $e->getMessage(),
]),
$e->httpStatusCode,
$e->getHttpHeaders()
);
}
});
$dispatcher = $router->getDispatcher();
try {
// A successful response
$response = $dispatcher->dispatch(
$request->getMethod(),
$request->getPathInfo()
);
} catch (\Orno\Http\Exception $e) {
// A failed response
$response = $e->getJsonResponse();
$response->setContent(json_encode(['status_code' => $e->getStatusCode(), 'message' => $e->getMessage()]));
} catch (\League\OAuth2\Server\Exception\OAuthException $e) {
$response = new Response(json_encode([
'error' => $e->errorType,
'message' => $e->getMessage(),
]), $e->httpStatusCode);
foreach ($e->getHttpHeaders() as $header) {
$response->headers($header);
}
} catch (\Exception $e) {
$response = new Orno\Http\Response();
$response->setStatusCode(500);
$response->setContent(json_encode(['status_code' => 500, 'message' => $e->getMessage()]));
} finally {
// Return the response
$response->headers->set('Content-type', 'application/json');
$response->send();
}

View File

@@ -1,17 +0,0 @@
{
"require": {
"illuminate/database": "4.1.*",
"orno/route": "1.*",
"ircmaxell/password-compat": "1.0.2",
"league/event": "0.2.0"
},
"autoload": {
"psr-4": {
"League\\OAuth2\\Server\\": "../../src/",
"RelationalExample\\": "."
},
"files": [
"config/db.php"
]
}
}

View File

@@ -1,18 +0,0 @@
<?php
namespace RelationalExample\Config;
use Illuminate\Database\Capsule\Manager as Capsule;
include __DIR__.'/../vendor/autoload.php';
$capsule = new Capsule();
$capsule->addConnection([
'driver' => 'sqlite',
'database' => __DIR__.'/oauth2.sqlite3',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
]);
$capsule->setAsGlobal();

View File

@@ -1,249 +0,0 @@
<?php
namespace RelationalExample\Config;
use Illuminate\Database\Capsule\Manager as Capsule;
include __DIR__.'/../vendor/autoload.php';
@unlink(__DIR__.'/oauth2.sqlite3');
touch(__DIR__.'/oauth2.sqlite3');
Capsule::statement('PRAGMA foreign_keys = ON');
/******************************************************************************/
print 'Creating users table'.PHP_EOL;
Capsule::schema()->create('users', function ($table) {
$table->increments('id');
$table->string('username');
$table->string('password');
$table->string('name');
$table->string('email');
$table->string('photo');
});
Capsule::table('users')->insert([
'username' => 'alexbilbie',
'password' => password_hash('whisky', PASSWORD_DEFAULT),
'name' => 'Alex Bilbie',
'email' => 'hello@alexbilbie.com',
'photo' => 'https://s.gravatar.com/avatar/14902eb1dac66b8458ebbb481d80f0a3',
]);
Capsule::table('users')->insert([
'username' => 'philsturgeon',
'password' => password_hash('cider', PASSWORD_DEFAULT),
'name' => 'Phil Sturgeon',
'email' => 'email@philsturgeon.co.uk',
'photo' => 'https://s.gravatar.com/avatar/14df293d6c5cd6f05996dfc606a6a951',
]);
/******************************************************************************/
print 'Creating clients table'.PHP_EOL;
Capsule::schema()->create('oauth_clients', function ($table) {
$table->string('id');
$table->string('secret');
$table->string('name');
$table->primary('id');
});
Capsule::table('oauth_clients')->insert([
'id' => 'testclient',
'secret' => 'secret',
'name' => 'Test Client',
]);
/******************************************************************************/
print 'Creating client redirect uris table'.PHP_EOL;
Capsule::schema()->create('oauth_client_redirect_uris', function ($table) {
$table->increments('id');
$table->string('client_id');
$table->string('redirect_uri');
});
Capsule::table('oauth_client_redirect_uris')->insert([
'client_id' => 'testclient',
'redirect_uri' => 'http://example.com/redirect',
]);
/******************************************************************************/
print 'Creating scopes table'.PHP_EOL;
Capsule::schema()->create('oauth_scopes', function ($table) {
$table->string('id');
$table->string('description');
$table->primary('id');
});
Capsule::table('oauth_scopes')->insert([
'id' => 'basic',
'description' => 'Basic details about your account',
]);
Capsule::table('oauth_scopes')->insert([
'id' => 'email',
'description' => 'Your email address',
]);
Capsule::table('oauth_scopes')->insert([
'id' => 'photo',
'description' => 'Your photo',
]);
/******************************************************************************/
print 'Creating sessions table'.PHP_EOL;
Capsule::schema()->create('oauth_sessions', function ($table) {
$table->increments('id')->unsigned();
$table->string('owner_type');
$table->string('owner_id');
$table->string('client_id');
$table->string('client_redirect_uri')->nullable();
$table->foreign('client_id')->references('id')->on('oauth_clients')->onDelete('cascade');
});
Capsule::table('oauth_sessions')->insert([
'owner_type' => 'client',
'owner_id' => 'testclient',
'client_id' => 'testclient',
]);
Capsule::table('oauth_sessions')->insert([
'owner_type' => 'user',
'owner_id' => '1',
'client_id' => 'testclient',
]);
Capsule::table('oauth_sessions')->insert([
'owner_type' => 'user',
'owner_id' => '2',
'client_id' => 'testclient',
]);
/******************************************************************************/
print 'Creating access tokens table'.PHP_EOL;
Capsule::schema()->create('oauth_access_tokens', function ($table) {
$table->string('access_token')->primary();
$table->integer('session_id')->unsigned();
$table->integer('expire_time');
$table->foreign('session_id')->references('id')->on('oauth_sessions')->onDelete('cascade');
});
Capsule::table('oauth_access_tokens')->insert([
'access_token' => 'iamgod',
'session_id' => '1',
'expire_time' => time() + 86400,
]);
Capsule::table('oauth_access_tokens')->insert([
'access_token' => 'iamalex',
'session_id' => '2',
'expire_time' => time() + 86400,
]);
Capsule::table('oauth_access_tokens')->insert([
'access_token' => 'iamphil',
'session_id' => '3',
'expire_time' => time() + 86400,
]);
/******************************************************************************/
print 'Creating refresh tokens table'.PHP_EOL;
Capsule::schema()->create('oauth_refresh_tokens', function ($table) {
$table->string('refresh_token')->primary();
$table->integer('expire_time');
$table->string('access_token');
$table->foreign('access_token')->references('access_token')->on('oauth_access_tokens')->onDelete('cascade');
});
/******************************************************************************/
print 'Creating auth codes table'.PHP_EOL;
Capsule::schema()->create('oauth_auth_codes', function ($table) {
$table->string('auth_code')->primary();
$table->integer('session_id')->unsigned();
$table->integer('expire_time');
$table->string('client_redirect_uri');
$table->foreign('session_id')->references('id')->on('oauth_sessions')->onDelete('cascade');
});
/******************************************************************************/
print 'Creating oauth access token scopes table'.PHP_EOL;
Capsule::schema()->create('oauth_access_token_scopes', function ($table) {
$table->increments('id')->unsigned();
$table->string('access_token');
$table->string('scope');
$table->foreign('access_token')->references('access_token')->on('oauth_access_tokens')->onDelete('cascade');
$table->foreign('scope')->references('id')->on('oauth_scopes')->onDelete('cascade');
});
Capsule::table('oauth_access_token_scopes')->insert([
'access_token' => 'iamgod',
'scope' => 'basic',
]);
Capsule::table('oauth_access_token_scopes')->insert([
'access_token' => 'iamgod',
'scope' => 'email',
]);
Capsule::table('oauth_access_token_scopes')->insert([
'access_token' => 'iamgod',
'scope' => 'photo',
]);
Capsule::table('oauth_access_token_scopes')->insert([
'access_token' => 'iamphil',
'scope' => 'email',
]);
Capsule::table('oauth_access_token_scopes')->insert([
'access_token' => 'iamalex',
'scope' => 'photo',
]);
/******************************************************************************/
print 'Creating oauth auth code scopes table'.PHP_EOL;
Capsule::schema()->create('oauth_auth_code_scopes', function ($table) {
$table->increments('id');
$table->string('auth_code');
$table->string('scope');
$table->foreign('auth_code')->references('auth_code')->on('oauth_auth_codes')->onDelete('cascade');
$table->foreign('scope')->references('id')->on('oauth_scopes')->onDelete('cascade');
});
/******************************************************************************/
print 'Creating oauth session scopes table'.PHP_EOL;
Capsule::schema()->create('oauth_session_scopes', function ($table) {
$table->increments('id')->unsigned();
$table->integer('session_id')->unsigned();
$table->string('scope');
$table->foreign('session_id')->references('id')->on('oauth_sessions')->onDelete('cascade');
$table->foreign('scope')->references('id')->on('oauth_scopes')->onDelete('cascade');
});

View File

@@ -1,97 +0,0 @@
<?php
use Orno\Http\Request;
use Orno\Http\Response;
use RelationalExample\Model;
use RelationalExample\Storage;
include __DIR__.'/vendor/autoload.php';
// Routing setup
$request = (new Request())->createFromGlobals();
$router = new \Orno\Route\RouteCollection();
$router->setStrategy(\Orno\Route\RouteStrategyInterface::RESTFUL_STRATEGY);
// Set up the OAuth 2.0 authorization server
$server = new \League\OAuth2\Server\AuthorizationServer();
$server->setSessionStorage(new Storage\SessionStorage());
$server->setAccessTokenStorage(new Storage\AccessTokenStorage());
$server->setRefreshTokenStorage(new Storage\RefreshTokenStorage());
$server->setClientStorage(new Storage\ClientStorage());
$server->setScopeStorage(new Storage\ScopeStorage());
$server->setAuthCodeStorage(new Storage\AuthCodeStorage());
$clientCredentials = new \League\OAuth2\Server\Grant\ClientCredentialsGrant();
$server->addGrantType($clientCredentials);
$passwordGrant = new \League\OAuth2\Server\Grant\PasswordGrant();
$passwordGrant->setVerifyCredentialsCallback(function ($username, $password) {
$result = (new Model\Users())->get($username);
if (count($result) !== 1) {
return false;
}
if (password_verify($password, $result[0]['password'])) {
return $username;
}
return false;
});
$server->addGrantType($passwordGrant);
$refrehTokenGrant = new \League\OAuth2\Server\Grant\RefreshTokenGrant();
$server->addGrantType($refrehTokenGrant);
// Routing setup
$request = (new Request())->createFromGlobals();
$router = new \Orno\Route\RouteCollection();
$router->post('/access_token', function (Request $request) use ($server) {
try {
$response = $server->issueAccessToken();
return new Response(json_encode($response), 200);
} catch (\Exception $e) {
return new Response(
json_encode([
'error' => $e->errorType,
'message' => $e->getMessage(),
]),
$e->httpStatusCode,
$e->getHttpHeaders()
);
}
});
$dispatcher = $router->getDispatcher();
try {
// A successful response
$response = $dispatcher->dispatch(
$request->getMethod(),
$request->getPathInfo()
);
} catch (\Orno\Http\Exception $e) {
// A failed response
$response = $e->getJsonResponse();
$response->setContent(json_encode(['status_code' => $e->getStatusCode(), 'message' => $e->getMessage()]));
} catch (\League\OAuth2\Server\Exception\OAuthException $e) {
$response = new Response(json_encode([
'error' => $e->errorType,
'message' => $e->getMessage(),
]), $e->httpStatusCode);
foreach ($e->getHttpHeaders() as $header) {
$response->headers($header);
}
} catch (\Exception $e) {
$response = new Orno\Http\Response();
$response->setStatusCode(500);
$response->setContent(json_encode(['status_code' => 500, 'message' => $e->getMessage()]));
} finally {
// Return the response
$response->headers->set('Content-type', 'application/json');
$response->send();
}

View File

@@ -0,0 +1,85 @@
<?php
namespace OAuth2ServerExamples\Entities;
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
use League\OAuth2\Server\Entities\Traits\EntityTrait;
class ClientEntity implements ClientEntityInterface
{
use EntityTrait;
private $name;
private $secret;
private $redirectUri;
/**
* Get the client's name.
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set the client's name.
*
* @param string $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* @param string $secret
*/
public function setSecret($secret)
{
$this->secret = $secret;
}
/**
* Get the hashed client secret
*
* @return string
*/
public function getSecret()
{
return $this->secret;
}
/**
* Set the client's redirect uri.
*
* @param string $redirectUri
*/
public function setRedirectUri($redirectUri)
{
$this->redirectUri = $redirectUri;
}
/**
* Returns the registered redirect URI.
*
* @return string
*/
public function getRedirectUri()
{
return $this->redirectUri;
}
/**
* Returns true if the client is capable of keeping it's secrets secret.
*
* @return bool
*/
public function canKeepASecret()
{
return $this->secret !== null;
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace OAuth2ServerExamples\Entities;
use League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface;
use League\OAuth2\Server\Entities\Traits\EntityTrait;
class ScopeEntity implements ScopeEntityInterface
{
use EntityTrait;
public function jsonSerialize()
{
return $this->getIdentifier();
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace OAuth2ServerExamples\Entities;
use League\OAuth2\Server\Entities\Interfaces\UserEntityInterface;
class UserEntity implements UserEntityInterface
{
/**
* Return the user's identifier.
*
* @return mixed
*/
public function getIdentifier()
{
return 1;
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace OAuth2ServerExamples\Repositories;
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
class AccessTokenRepository implements AccessTokenRepositoryInterface
{
/**
* Persists a new access token to permanent storage.
*
* @param \League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface $accessTokenEntity
*/
public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity)
{
// TODO: Implement persistNewAccessToken() method.
}
/**
* Revoke an access token.
*
* @param string $tokenId
*/
public function revokeAccessToken($tokenId)
{
// TODO: Implement revokeAccessToken() method.
}
/**
* Check if the access token has been revoked.
*
* @param string $tokenId
*
* @return bool Return true if this token has been revoked
*/
public function isAccessTokenRevoked($tokenId)
{
// TODO: Implement isAccessTokenRevoked() method.
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace OAuth2ServerExamples\Repositories;
use League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface;
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
class AuthCodeRepository implements AuthCodeRepositoryInterface
{
/**
* Persists a new auth code to permanent storage.
*
* @param \League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface $authCodeEntity
*/
public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity)
{
// TODO: Implement persistNewAuthCode() method.
}
/**
* Revoke an auth code.
*
* @param string $codeId
*/
public function revokeAuthCode($codeId)
{
// TODO: Implement revokeAuthCode() method.
}
/**
* Check if the auth code has been revoked.
*
* @param string $codeId
*
* @return bool Return true if this code has been revoked
*/
public function isAuthCodeRevoked($codeId)
{
// TODO: Implement isAuthCodeRevoked() method.
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace OAuth2ServerExamples\Repositories;
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
use OAuth2ServerExamples\Entities\ClientEntity;
class ClientRepository implements ClientRepositoryInterface
{
/**
* {@inheritdoc}
*/
public function getClientEntity($clientIdentifier, $clientSecret = null, $redirectUri = null, $grantType = null)
{
$clients = [
'myawesomeapp' => [
'secret' => password_hash('abc123', PASSWORD_BCRYPT),
'name' => 'My Awesome App',
'redirect_uri' => 'http://foo/bar',
],
];
// Check if client is registered
if (array_key_exists($clientIdentifier, $clients) === false) {
return;
}
$client = new ClientEntity();
$client->setIdentifier($clientIdentifier);
$client->setName($clients[$clientIdentifier]['name']);
$client->setRedirectUri($clients[$clientIdentifier]['redirect_uri']);
$client->setSecret($clients[$clientIdentifier]['secret']);
return $client;
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace OAuth2ServerExamples\Repositories;
use League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface;
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
class RefreshTokenRepository implements RefreshTokenRepositoryInterface
{
/**
* Create a new refresh token_name.
*
* @param \League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface $refreshTokenEntityInterface
*/
public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntityInterface)
{
// TODO: Implement persistNewRefreshToken() method.
}
/**
* Revoke the refresh token.
*
* @param string $tokenId
*/
public function revokeRefreshToken($tokenId)
{
// TODO: Implement revokeRefreshToken() method.
}
/**
* Check if the refresh token has been revoked.
*
* @param string $tokenId
*
* @return bool Return true if this token has been revoked
*/
public function isRefreshTokenRevoked($tokenId)
{
// TODO: Implement isRefreshTokenRevoked() method.
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace OAuth2ServerExamples\Repositories;
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
use OAuth2ServerExamples\Entities\ScopeEntity;
class ScopeRepository implements ScopeRepositoryInterface
{
/**
* {@inheritdoc}
*/
public function getScopeEntityByIdentifier($scopeIdentifier)
{
$scopes = [
'basic' => [
'description' => 'Basic details about you',
],
'email' => [
'description' => 'Your email address',
],
];
if (array_key_exists($scopeIdentifier, $scopes) === false) {
return;
}
$scope = new ScopeEntity();
$scope->setIdentifier($scopeIdentifier);
return $scope;
}
/**
* {@inheritdoc}
*/
public function finalizeScopes(
array $scopes,
$grantType,
ClientEntityInterface $clientEntity,
$userIdentifier = null
) {
return $scopes;
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace OAuth2ServerExamples\Repositories;
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
use OAuth2ServerExamples\Entities\ScopeEntity;
use OAuth2ServerExamples\Entities\UserEntity;
class UserRepository implements UserRepositoryInterface
{
/**
* {@inheritdoc}
*/
public function getUserEntityByUserCredentials(
$username,
$password,
$grantType,
ClientEntityInterface $clientEntity
) {
if ($username === 'alex' && $password === 'whisky') {
$scope = new ScopeEntity();
$scope->setIdentifier('email');
$scopes[] = $scope;
return new UserEntity();
}
return;
}
}

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" stopOnError="true" stopOnFailure="true" stopOnIncomplete="false" stopOnSkipped="false" bootstrap="tests/unit/Bootstrap.php">
<testsuites>
<testsuite name="Tests">
<directory>./tests/unit/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist addUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src</directory>
</whitelist>
</filter>
<logging>
<!-- <log type="coverage-text" target="php://stdout" title="thephpleague/oauth2-server" charset="UTF-8" yui="true" highlight="true" lowUpperBound="60" highLowerBound="90"/> -->
<log type="coverage-html" target="build/coverage" title="thephpleague/oauth2-server" charset="UTF-8" yui="true" highlight="true" lowUpperBound="60" highLowerBound="90"/>
</logging>
</phpunit>

24
phpunit.xml.dist Normal file
View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" stopOnError="true"
stopOnFailure="true" stopOnIncomplete="false" stopOnSkipped="false" bootstrap="tests/Bootstrap.php">
<testsuites>
<testsuite name="Tests">
<directory>./tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist addUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src</directory>
<exclude>
<directory suffix=".php">src/ResponseTypes/DefaultTemplates</directory>
<directory suffix=".php">src/TemplateRenderer</directory>
</exclude>
</whitelist>
</filter>
<logging>
<log type="coverage-text" target="php://stdout" title="thephpleague/oauth2-server" charset="UTF-8" yui="true"
highlight="true" lowUpperBound="60" highLowerBound="90"/>
<log type="coverage-html" target="build/coverage" title="thephpleague/oauth2-server" charset="UTF-8" yui="true"
highlight="true" lowUpperBound="60" highLowerBound="90"/>
</logging>
</phpunit>

View File

@@ -1,357 +0,0 @@
<?php
/**
* OAuth 2.0 Abstract Server
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server;
use League\Event\Emitter;
use League\OAuth2\Server\Storage\AccessTokenInterface;
use League\OAuth2\Server\Storage\AuthCodeInterface;
use League\OAuth2\Server\Storage\ClientInterface;
use League\OAuth2\Server\Storage\MacTokenInterface;
use League\OAuth2\Server\Storage\RefreshTokenInterface;
use League\OAuth2\Server\Storage\ScopeInterface;
use League\OAuth2\Server\Storage\SessionInterface;
use League\OAuth2\Server\TokenType\TokenTypeInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* OAuth 2.0 Resource Server
*/
abstract class AbstractServer
{
/**
* The request object
*
* @var \Symfony\Component\HttpFoundation\Request
*/
protected $request;
/**
* Session storage
*
* @var \League\OAuth2\Server\Storage\SessionInterface
*/
protected $sessionStorage;
/**
* Access token storage
*
* @var \League\OAuth2\Server\Storage\AccessTokenInterface
*/
protected $accessTokenStorage;
/**
* Refresh token storage
*
* @var \League\OAuth2\Server\Storage\RefreshTokenInterface
*/
protected $refreshTokenStorage;
/**
* Auth code storage
*
* @var \League\OAuth2\Server\Storage\AuthCodeInterface
*/
protected $authCodeStorage;
/**
* Scope storage
*
* @var \League\OAuth2\Server\Storage\ScopeInterface
*/
protected $scopeStorage;
/**
* Client storage
*
* @var \League\OAuth2\Server\Storage\ClientInterface
*/
protected $clientStorage;
/**
* @var \League\OAuth2\Server\Storage\MacTokenInterface
*/
protected $macStorage;
/**
* Token type
*
* @var \League\OAuth2\Server\TokenType\TokenTypeInterface
*/
protected $tokenType;
/**
* Event emitter
*
* @var \League\Event\Emitter
*/
protected $eventEmitter;
/**
* Abstract server constructor
*/
public function __construct()
{
$this->setEventEmitter();
}
/**
* Set an event emitter
*
* @param object $emitter Event emitter object
*/
public function setEventEmitter($emitter = null)
{
if ($emitter === null) {
$this->eventEmitter = new Emitter();
} else {
$this->eventEmitter = $emitter;
}
}
/**
* Add an event listener to the event emitter
*
* @param string $eventName Event name
* @param callable $listener Callable function or method
*/
public function addEventListener($eventName, callable $listener)
{
$this->eventEmitter->addListener($eventName, $listener);
}
/**
* Returns the event emitter
*
* @return \League\Event\Emitter
*/
public function getEventEmitter()
{
return $this->eventEmitter;
}
/**
* Sets the Request Object
*
* @param \Symfony\Component\HttpFoundation\Request The Request Object
*
* @return self
*/
public function setRequest($request)
{
$this->request = $request;
return $this;
}
/**
* Gets the Request object. It will create one from the globals if one is not set.
*
* @return \Symfony\Component\HttpFoundation\Request
*/
public function getRequest()
{
if ($this->request === null) {
$this->request = Request::createFromGlobals();
}
return $this->request;
}
/**
* Set the client storage
*
* @param \League\OAuth2\Server\Storage\ClientInterface $storage
*
* @return self
*/
public function setClientStorage(ClientInterface $storage)
{
$storage->setServer($this);
$this->clientStorage = $storage;
return $this;
}
/**
* Set the session storage
*
* @param \League\OAuth2\Server\Storage\SessionInterface $storage
*
* @return self
*/
public function setSessionStorage(SessionInterface $storage)
{
$storage->setServer($this);
$this->sessionStorage = $storage;
return $this;
}
/**
* Set the access token storage
*
* @param \League\OAuth2\Server\Storage\AccessTokenInterface $storage
*
* @return self
*/
public function setAccessTokenStorage(AccessTokenInterface $storage)
{
$storage->setServer($this);
$this->accessTokenStorage = $storage;
return $this;
}
/**
* Set the refresh token storage
*
* @param \League\OAuth2\Server\Storage\RefreshTokenInterface $storage
*
* @return self
*/
public function setRefreshTokenStorage(RefreshTokenInterface $storage)
{
$storage->setServer($this);
$this->refreshTokenStorage = $storage;
return $this;
}
/**
* Set the auth code storage
*
* @param \League\OAuth2\Server\Storage\AuthCodeInterface $storage
*
* @return self
*/
public function setAuthCodeStorage(AuthCodeInterface $storage)
{
$storage->setServer($this);
$this->authCodeStorage = $storage;
return $this;
}
/**
* Set the scope storage
*
* @param \League\OAuth2\Server\Storage\ScopeInterface $storage
*
* @return self
*/
public function setScopeStorage(ScopeInterface $storage)
{
$storage->setServer($this);
$this->scopeStorage = $storage;
return $this;
}
/**
* Return the client storage
*
* @return \League\OAuth2\Server\Storage\ClientInterface
*/
public function getClientStorage()
{
return $this->clientStorage;
}
/**
* Return the scope storage
*
* @return \League\OAuth2\Server\Storage\ScopeInterface
*/
public function getScopeStorage()
{
return $this->scopeStorage;
}
/**
* Return the session storage
*
* @return \League\OAuth2\Server\Storage\SessionInterface
*/
public function getSessionStorage()
{
return $this->sessionStorage;
}
/**
* Return the refresh token storage
*
* @return \League\OAuth2\Server\Storage\RefreshTokenInterface
*/
public function getRefreshTokenStorage()
{
return $this->refreshTokenStorage;
}
/**
* Return the access token storage
*
* @return \League\OAuth2\Server\Storage\AccessTokenInterface
*/
public function getAccessTokenStorage()
{
return $this->accessTokenStorage;
}
/**
* Return the auth code storage
*
* @return \League\OAuth2\Server\Storage\AuthCodeInterface
*/
public function getAuthCodeStorage()
{
return $this->authCodeStorage;
}
/**
* Set the access token type
*
* @param TokenTypeInterface $tokenType The token type
*
* @return void
*/
public function setTokenType(TokenTypeInterface $tokenType)
{
$tokenType->setServer($this);
$this->tokenType = $tokenType;
}
/**
* Get the access token type
*
* @return TokenTypeInterface
*/
public function getTokenType()
{
return $this->tokenType;
}
/**
* @return MacTokenInterface
*/
public function getMacStorage()
{
return $this->macStorage;
}
/**
* @param MacTokenInterface $macStorage
*/
public function setMacStorage(MacTokenInterface $macStorage)
{
$this->macStorage = $macStorage;
}
}

View File

@@ -1,295 +0,0 @@
<?php
/**
* OAuth 2.0 Authorization Server
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server;
use League\OAuth2\Server\Grant\GrantTypeInterface;
use League\OAuth2\Server\TokenType\Bearer;
/**
* OAuth 2.0 authorization server class
*/
class AuthorizationServer extends AbstractServer
{
/**
* The delimeter between scopes specified in the scope query string parameter
* The OAuth 2 specification states it should be a space but most use a comma
*
* @var string
*/
protected $scopeDelimiter = ' ';
/**
* The TTL (time to live) of an access token in seconds (default: 3600)
*
* @var integer
*/
protected $accessTokenTTL = 3600;
/**
* The registered grant response types
*
* @var array
*/
protected $responseTypes = [];
/**
* The registered grant types
*
* @var array
*/
protected $grantTypes = [];
/**
* Require the "scope" parameter to be in checkAuthoriseParams()
*
* @var boolean
*/
protected $requireScopeParam = false;
/**
* Default scope(s) to be used if none is provided
*
* @var string|array
*/
protected $defaultScope;
/**
* Require the "state" parameter to be in checkAuthoriseParams()
*
* @var boolean
*/
protected $requireStateParam = false;
/**
* Create a new OAuth2 authorization server
*
* @return self
*/
public function __construct()
{
// Set Bearer as the default token type
$this->setTokenType(new Bearer());
parent::__construct();
return $this;
}
/**
* 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)
*
* @return self
*/
public function addGrantType(GrantTypeInterface $grantType, $identifier = null)
{
if (is_null($identifier)) {
$identifier = $grantType->getIdentifier();
}
// Inject server into grant
$grantType->setAuthorizationServer($this);
$this->grantTypes[$identifier] = $grantType;
if (!is_null($grantType->getResponseType())) {
$this->responseTypes[] = $grantType->getResponseType();
}
return $this;
}
/**
* 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 function hasGrantType($identifier)
{
return (array_key_exists($identifier, $this->grantTypes));
}
/**
* Returns response types
*
* @return array
*/
public function getResponseTypes()
{
return $this->responseTypes;
}
/**
* Require the "scope" parameter in checkAuthoriseParams()
*
* @param boolean $require
*
* @return self
*/
public function requireScopeParam($require = true)
{
$this->requireScopeParam = $require;
return $this;
}
/**
* Is the scope parameter required?
*
* @return bool
*/
public function scopeParamRequired()
{
return $this->requireScopeParam;
}
/**
* Default scope to be used if none is provided and requireScopeParam() is false
*
* @param string $default Name of the default scope
*
* @return self
*/
public function setDefaultScope($default = null)
{
$this->defaultScope = $default;
return $this;
}
/**
* Default scope to be used if none is provided and requireScopeParam is false
*
* @return string|null
*/
public function getDefaultScope()
{
return $this->defaultScope;
}
/**
* Require the "state" parameter in checkAuthoriseParams()
*
* @return bool
*/
public function stateParamRequired()
{
return $this->requireStateParam;
}
/**
* Require the "state" parameter in checkAuthoriseParams()
*
* @param boolean $require
*
* @return self
*/
public function requireStateParam($require = true)
{
$this->requireStateParam = $require;
return $this;
}
/**
* Get the scope delimiter
*
* @return string The scope delimiter (default: ",")
*/
public function getScopeDelimiter()
{
return $this->scopeDelimiter;
}
/**
* Set the scope delimiter
*
* @param string $scopeDelimiter
*
* @return self
*/
public function setScopeDelimiter($scopeDelimiter = ' ')
{
$this->scopeDelimiter = $scopeDelimiter;
return $this;
}
/**
* Get the TTL for an access token
*
* @return int The TTL
*/
public function getAccessTokenTTL()
{
return $this->accessTokenTTL;
}
/**
* Set the TTL for an access token
*
* @param int $accessTokenTTL The new TTL
*
* @return self
*/
public function setAccessTokenTTL($accessTokenTTL = 3600)
{
$this->accessTokenTTL = $accessTokenTTL;
return $this;
}
/**
* Issue an access token
*
* @return array Authorise request parameters
*
* @throws
*/
public function issueAccessToken()
{
$grantType = $this->getRequest()->request->get('grant_type');
if (is_null($grantType)) {
throw new Exception\InvalidRequestException('grant_type');
}
// Ensure grant type is one that is recognised and is enabled
if (!in_array($grantType, array_keys($this->grantTypes))) {
throw new Exception\UnsupportedGrantTypeException($grantType);
}
// Complete the flow
return $this->getGrantType($grantType)->completeFlow();
}
/**
* Return a grant type class
*
* @param string $grantType The grant type identifier
*
* @return Grant\GrantTypeInterface
*
* @throws
*/
public function getGrantType($grantType)
{
if (isset($this->grantTypes[$grantType])) {
return $this->grantTypes[$grantType];
}
throw new Exception\InvalidGrantException($grantType);
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace League\OAuth2\Server\AuthorizationValidators;
use Psr\Http\Message\ServerRequestInterface;
interface AuthorizationValidatorInterface
{
/**
* Determine the access token in the authorization header and append OAUth properties to the request
* as attributes.
*
* @param ServerRequestInterface $request
*
* @return ServerRequestInterface
*/
public function validateAuthorization(ServerRequestInterface $request);
}

View File

@@ -0,0 +1,66 @@
<?php
namespace League\OAuth2\Server\AuthorizationValidators;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Rsa\Sha256;
use League\OAuth2\Server\CryptTrait;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use Psr\Http\Message\ServerRequestInterface;
class BearerTokenValidator implements AuthorizationValidatorInterface
{
use CryptTrait;
/**
* @var \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface
*/
private $accessTokenRepository;
/**
* BearerTokenValidator constructor.
*
* @param \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface $accessTokenRepository
*/
public function __construct(AccessTokenRepositoryInterface $accessTokenRepository)
{
$this->accessTokenRepository = $accessTokenRepository;
}
/**
* {@inheritdoc}
*/
public function validateAuthorization(ServerRequestInterface $request)
{
if ($request->hasHeader('authorization') === false) {
throw OAuthServerException::accessDenied('Missing "Authorization" header');
}
$header = $request->getHeader('authorization');
$jwt = trim(preg_replace('/^(?:\s+)?Bearer\s/', '', $header[0]));
try {
// Attempt to parse and validate the JWT
$token = (new Parser())->parse($jwt);
if ($token->verify(new Sha256(), $this->publicKeyPath) === false) {
throw OAuthServerException::accessDenied('Access token could not be verified');
}
// Check if token has been revoked
if ($this->accessTokenRepository->isAccessTokenRevoked($token->getClaim('jti'))) {
throw OAuthServerException::accessDenied('Access token has been revoked');
}
// Return the request with additional attributes
return $request
->withAttribute('oauth_access_token_id', $token->getClaim('jti'))
->withAttribute('oauth_client_id', $token->getClaim('aud'))
->withAttribute('oauth_user_id', $token->getClaim('sub'))
->withAttribute('oauth_scopes', $token->getClaim('scopes'));
} catch (\InvalidArgumentException $exception) {
// JWT couldn't be parsed so return the request as is
throw OAuthServerException::accessDenied($exception->getMessage());
}
}
}

122
src/CryptTrait.php Normal file
View File

@@ -0,0 +1,122 @@
<?php
/**
* Public/private key encryption.
*
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server;
trait CryptTrait
{
/**
* @var string
*/
protected $privateKeyPath;
/**
* @var string
*/
protected $publicKeyPath;
/**
* Set path to private key.
*
* @param string $privateKeyPath
*/
public function setPrivateKeyPath($privateKeyPath)
{
if (strpos($privateKeyPath, 'file://') !== 0) {
$privateKeyPath = 'file://' . $privateKeyPath;
}
$this->privateKeyPath = $privateKeyPath;
}
/**
* Set path to public key.
*
* @param string $publicKeyPath
*/
public function setPublicKeyPath($publicKeyPath)
{
if (strpos($publicKeyPath, 'file://') !== 0) {
$publicKeyPath = 'file://' . $publicKeyPath;
}
$this->publicKeyPath = $publicKeyPath;
}
/**
* Encrypt data with a private key.
*
* @param string $unencryptedData
*
* @return string
*/
protected function encrypt($unencryptedData)
{
$privateKey = openssl_pkey_get_private($this->privateKeyPath);
$privateKeyDetails = @openssl_pkey_get_details($privateKey);
if ($privateKeyDetails === null) {
throw new \LogicException(sprintf('Could not get details of private key: %s', $this->privateKeyPath));
}
$chunkSize = ceil($privateKeyDetails['bits'] / 8) - 11;
$output = '';
while ($unencryptedData) {
$chunk = substr($unencryptedData, 0, $chunkSize);
$unencryptedData = substr($unencryptedData, $chunkSize);
if (openssl_private_encrypt($chunk, $encrypted, $privateKey) === false) {
// @codeCoverageIgnoreStart
throw new \LogicException('Failed to encrypt data');
// @codeCoverageIgnoreEnd
}
$output .= $encrypted;
}
openssl_free_key($privateKey);
return base64_encode($output);
}
/**
* Decrypt data with a public key.
*
* @param string $encryptedData
*
* @throws \LogicException
*
* @return string
*/
protected function decrypt($encryptedData)
{
$publicKey = openssl_pkey_get_public($this->publicKeyPath);
$publicKeyDetails = @openssl_pkey_get_details($publicKey);
if ($publicKeyDetails === null) {
throw new \LogicException(sprintf('Could not get details of public key: %s', $this->publicKeyPath));
}
$chunkSize = ceil($publicKeyDetails['bits'] / 8);
$output = '';
$encryptedData = base64_decode($encryptedData);
while ($encryptedData) {
$chunk = substr($encryptedData, 0, $chunkSize);
$encryptedData = substr($encryptedData, $chunkSize);
if (openssl_public_decrypt($chunk, $decrypted, $publicKey/*, OPENSSL_PKCS1_OAEP_PADDING*/) === false) {
// @codeCoverageIgnoreStart
throw new \LogicException('Failed to decrypt data');
// @codeCoverageIgnoreEnd
}
$output .= $decrypted;
}
openssl_free_key($publicKey);
return $output;
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace League\OAuth2\Server\Entities;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Signer\Rsa\Sha256;
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\Traits\EntityTrait;
use League\OAuth2\Server\Entities\Traits\TokenEntityTrait;
class AccessTokenEntity implements AccessTokenEntityInterface
{
use EntityTrait, TokenEntityTrait;
/**
* Generate a JWT from the access token
*
* @param string $privateKeyPath
*
* @return string
*/
public function convertToJWT($privateKeyPath)
{
return (new Builder())
->setAudience($this->getClient()->getIdentifier())
->setId($this->getIdentifier(), true)
->setIssuedAt(time())
->setNotBefore(time())
->setExpiration($this->getExpiryDateTime()->getTimestamp())
->setSubject($this->getUserIdentifier())
->set('scopes', $this->getScopes())
->sign(new Sha256(), new Key($privateKeyPath))
->getToken();
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace League\OAuth2\Server\Entities;
use League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface;
use League\OAuth2\Server\Entities\Traits\EntityTrait;
use League\OAuth2\Server\Entities\Traits\TokenEntityTrait;
/**
* Class AuthCodeEntity.
*/
class AuthCodeEntity implements AuthCodeEntityInterface
{
use EntityTrait, TokenEntityTrait;
protected $redirectUri;
/**
* @return string
*/
public function getRedirectUri()
{
return $this->redirectUri;
}
/**
* @param string $uri
*/
public function setRedirectUri($uri)
{
$this->redirectUri = $uri;
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace League\OAuth2\Server\Entities\Interfaces;
interface AccessTokenEntityInterface extends TokenInterface
{
/**
* Generate a JWT from the access token
*
* @param string $privateKeyPath
*
* @return string
*/
public function convertToJWT($privateKeyPath);
}

View File

@@ -0,0 +1,16 @@
<?php
namespace League\OAuth2\Server\Entities\Interfaces;
interface AuthCodeEntityInterface extends TokenInterface
{
/**
* @return string
*/
public function getRedirectUri();
/**
* @param string $uri
*/
public function setRedirectUri($uri);
}

View File

@@ -0,0 +1,48 @@
<?php
namespace League\OAuth2\Server\Entities\Interfaces;
interface ClientEntityInterface
{
/**
* Get the client's identifier.
*
* @return string
*/
public function getIdentifier();
/**
* Set the client's identifier.
*
* @param $identifier
*/
public function setIdentifier($identifier);
/**
* Get the client's name.
*
* @return string
*/
public function getName();
/**
* Set the client's name.
*
* @param string $name
*/
public function setName($name);
/**
* Set the client's redirect uri.
*
* @param string $redirectUri
*/
public function setRedirectUri($redirectUri);
/**
* Returns the registered redirect URI.
*
* @return string
*/
public function getRedirectUri();
}

View File

@@ -0,0 +1,55 @@
<?php
namespace League\OAuth2\Server\Entities\Interfaces;
interface RefreshTokenEntityInterface
{
/**
* Get the token's identifier.
*
* @return string
*/
public function getIdentifier();
/**
* Set the token's identifier.
*
* @param $identifier
*/
public function setIdentifier($identifier);
/**
* Get the token's expiry date time.
*
* @return \DateTime
*/
public function getExpiryDateTime();
/**
* Set the date time when the token expires.
*
* @param \DateTime $dateTime
*/
public function setExpiryDateTime(\DateTime $dateTime);
/**
* Set the access token that the refresh token was associated with.
*
* @param \League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface $accessToken
*/
public function setAccessToken(AccessTokenEntityInterface $accessToken);
/**
* Get the access token that the refresh token was originally associated with.
*
* @return \League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface
*/
public function getAccessToken();
/**
* Has the token expired?
*
* @return bool
*/
public function isExpired();
}

View File

@@ -0,0 +1,20 @@
<?php
namespace League\OAuth2\Server\Entities\Interfaces;
interface ScopeEntityInterface extends \JsonSerializable
{
/**
* Get the scope's identifier.
*
* @return string
*/
public function getIdentifier();
/**
* Set the scope's identifier.
*
* @param $identifier
*/
public function setIdentifier($identifier);
}

View File

@@ -0,0 +1,83 @@
<?php
namespace League\OAuth2\Server\Entities\Interfaces;
interface TokenInterface
{
/**
* Get the token's identifier.
*
* @return string
*/
public function getIdentifier();
/**
* Set the token's identifier.
*
* @param $identifier
*/
public function setIdentifier($identifier);
/**
* Get the token's expiry date time.
*
* @return \DateTime
*/
public function getExpiryDateTime();
/**
* Set the date time when the token expires.
*
* @param \DateTime $dateTime
*/
public function setExpiryDateTime(\DateTime $dateTime);
/**
* Set the identifier of the user associated with the token.
*
* @param string|int $identifier The identifier of the user
*/
public function setUserIdentifier($identifier);
/**
* Get the token user's identifier.
*
* @return string|int
*/
public function getUserIdentifier();
/**
* Get the client that the token was issued to.
*
* @return ClientEntityInterface
*/
public function getClient();
/**
* Set the client that the token was issued to.
*
* @param \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface $client
*/
public function setClient(ClientEntityInterface $client);
/**
* Associate a scope with the token.
*
* @param \League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface $scope
*/
public function addScope(ScopeEntityInterface $scope);
/**
* Return an array of scopes associated with the token.
*
* @return ScopeEntityInterface[]
*/
public function getScopes();
/**
* Has the token expired?
*
* @return bool
*/
public function isExpired();
}

View File

@@ -0,0 +1,13 @@
<?php
namespace League\OAuth2\Server\Entities\Interfaces;
interface UserEntityInterface
{
/**
* Return the user's identifier.
*
* @return mixed
*/
public function getIdentifier();
}

View File

@@ -0,0 +1,15 @@
<?php
namespace League\OAuth2\Server\Entities;
use League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface;
use League\OAuth2\Server\Entities\Traits\EntityTrait;
use League\OAuth2\Server\Entities\Traits\RefreshTokenTrait;
/**
* Class RefreshTokenEntity.
*/
class RefreshTokenEntity implements RefreshTokenEntityInterface
{
use EntityTrait, RefreshTokenTrait;
}

View File

@@ -0,0 +1,27 @@
<?php
namespace League\OAuth2\Server\Entities\Traits;
trait EntityTrait
{
/*
* @var string
*/
protected $identifier;
/**
* @return mixed
*/
public function getIdentifier()
{
return $this->identifier;
}
/**
* @param mixed $identifier
*/
public function setIdentifier($identifier)
{
$this->identifier = $identifier;
}
}

View File

@@ -0,0 +1,65 @@
<?php
namespace League\OAuth2\Server\Entities\Traits;
use DateTime;
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
trait RefreshTokenTrait
{
/**
* @var AccessTokenEntityInterface
*/
protected $accessToken;
/**
* @var DateTime
*/
protected $expiryDateTime;
/**
* {@inheritdoc}
*/
public function setAccessToken(AccessTokenEntityInterface $accessToken)
{
$this->accessToken = $accessToken;
}
/**
* {@inheritdoc}
*/
public function getAccessToken()
{
return $this->accessToken;
}
/**
* Get the token's expiry date time.
*
* @return DateTime
*/
public function getExpiryDateTime()
{
return $this->expiryDateTime;
}
/**
* Set the date time when the token expires.
*
* @param DateTime $dateTime
*/
public function setExpiryDateTime(DateTime $dateTime)
{
$this->expiryDateTime = $dateTime;
}
/**
* Has the token expired?
*
* @return bool
*/
public function isExpired()
{
return (new DateTime()) > $this->getExpiryDateTime();
}
}

View File

@@ -0,0 +1,120 @@
<?php
namespace League\OAuth2\Server\Entities\Traits;
use DateTime;
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
use League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface;
trait TokenEntityTrait
{
/**
* @var ScopeEntityInterface[]
*/
protected $scopes = [];
/**
* @var DateTime
*/
protected $expiryDateTime;
/**
* @var string|int
*/
protected $userIdentifier;
/**
* @var ClientEntityInterface
*/
protected $client;
/**
* Associate a scope with the token.
*
* @param \League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface $scope
*/
public function addScope(ScopeEntityInterface $scope)
{
$this->scopes[$scope->getIdentifier()] = $scope;
}
/**
* Return an array of scopes associated with the token.
*
* @return ScopeEntityInterface[]
*/
public function getScopes()
{
return array_values($this->scopes);
}
/**
* Get the token's expiry date time.
*
* @return DateTime
*/
public function getExpiryDateTime()
{
return $this->expiryDateTime;
}
/**
* Set the date time when the token expires.
*
* @param DateTime $dateTime
*/
public function setExpiryDateTime(DateTime $dateTime)
{
$this->expiryDateTime = $dateTime;
}
/**
* Set the identifier of the user associated with the token.
*
* @param string|int $identifier The identifier of the user
*/
public function setUserIdentifier($identifier)
{
$this->userIdentifier = $identifier;
}
/**
* Get the token user's identifier.
*
* @return string|int
*/
public function getUserIdentifier()
{
return $this->userIdentifier;
}
/**
* Get the client that the token was issued to.
*
* @return ClientEntityInterface
*/
public function getClient()
{
return $this->client;
}
/**
* Set the client that the token was issued to.
*
* @param \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface $client
*/
public function setClient(ClientEntityInterface $client)
{
$this->client = $client;
}
/**
* Has the token expired?
*
* @return bool
*/
public function isExpired()
{
return (new DateTime()) > $this->getExpiryDateTime();
}
}

View File

@@ -1,209 +0,0 @@
<?php
/**
* OAuth 2.0 Abstract token
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Entity;
use League\OAuth2\Server\AbstractServer;
use League\OAuth2\Server\Util\SecureKey;
/**
* Abstract token class
*/
abstract class AbstractTokenEntity
{
/**
* Token identifier
*
* @var string
*/
protected $id;
/**
* Associated session
*
* @var \League\OAuth2\Server\Entity\SessionEntity
*/
protected $session;
/**
* Session scopes
*
* @var \League\OAuth2\Server\Entity\ScopeEntity[]
*/
protected $scopes;
/**
* Token expire time
*
* @var int
*/
protected $expireTime = 0;
/**
* Authorization or resource server
*
* @var \League\OAuth2\Server\AbstractServer
*/
protected $server;
/**
* __construct
*
* @param \League\OAuth2\Server\AbstractServer $server
*
* @return self
*/
public function __construct(AbstractServer $server)
{
$this->server = $server;
return $this;
}
/**
* Set session
*
* @param \League\OAuth2\Server\Entity\SessionEntity $session
*
* @return self
*/
public function setSession(SessionEntity $session)
{
$this->session = $session;
return $this;
}
/**
* Set the expire time of the token
*
* @param integer $expireTime Unix time stamp
*
* @return self
*/
public function setExpireTime($expireTime)
{
$this->expireTime = $expireTime;
return $this;
}
/**
* Return token expire time
*
* @return int
*/
public function getExpireTime()
{
return $this->expireTime;
}
/**
* Is the token expired?
*
* @return bool
*/
public function isExpired()
{
return ((time() - $this->expireTime) > 0);
}
/**
* Set token ID
*
* @param string $id Token ID
*
* @return self
*/
public function setId($id = null)
{
$this->id = ($id !== null) ? $id : SecureKey::generate();
return $this;
}
/**
* Get the token ID
*
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* Associate a scope
*
* @param \League\OAuth2\Server\Entity\ScopeEntity $scope
*
* @return self
*/
public function associateScope(ScopeEntity $scope)
{
if (!isset($this->scopes[$scope->getId()])) {
$this->scopes[$scope->getId()] = $scope;
}
return $this;
}
/**
* Format the local scopes array
*
* @param \League\OAuth2\Server\Entity\ScopeEntity[]
*
* @return array
*/
protected function formatScopes($unformatted = [])
{
if (is_null($unformatted)) {
return [];
}
$scopes = [];
foreach ($unformatted as $scope) {
if ($scope instanceof ScopeEntity) {
$scopes[$scope->getId()] = $scope;
}
}
return $scopes;
}
/**
* Returns the token as a string if the object is cast as a string
*
* @return string
*/
public function __toString()
{
if ($this->id === null) {
return '';
}
return $this->id;
}
/**
* Expire the token
*
* @return void
*/
abstract public function expire();
/**
* Save the token
*
* @return void
*/
abstract public function save();
}

View File

@@ -1,93 +0,0 @@
<?php
/**
* OAuth 2.0 Access token entity
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Entity;
/**
* Access token entity class
*/
class AccessTokenEntity extends AbstractTokenEntity
{
/**
* Get session
*
* @return \League\OAuth2\Server\Entity\SessionEntity
*/
public function getSession()
{
if ($this->session instanceof SessionEntity) {
return $this->session;
}
$this->session = $this->server->getSessionStorage()->getByAccessToken($this);
return $this->session;
}
/**
* Check if access token has an associated scope
*
* @param string $scope Scope to check
*
* @return bool
*/
public function hasScope($scope)
{
if ($this->scopes === null) {
$this->getScopes();
}
return isset($this->scopes[$scope]);
}
/**
* Return all scopes associated with the access token
*
* @return \League\OAuth2\Server\Entity\ScopeEntity[]
*/
public function getScopes()
{
if ($this->scopes === null) {
$this->scopes = $this->formatScopes(
$this->server->getAccessTokenStorage()->getScopes($this)
);
}
return $this->scopes;
}
/**
* {@inheritdoc}
*/
public function save()
{
$this->server->getAccessTokenStorage()->create(
$this->getId(),
$this->getExpireTime(),
$this->getSession()->getId()
);
// Associate the scope with the token
foreach ($this->getScopes() as $scope) {
$this->server->getAccessTokenStorage()->associateScope($this, $scope);
}
return $this;
}
/**
* {@inheritdoc}
*/
public function expire()
{
$this->server->getAccessTokenStorage()->delete($this);
}
}

View File

@@ -1,128 +0,0 @@
<?php
/**
* OAuth 2.0 Auth code entity
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Entity;
/**
* Access token entity class
*/
class AuthCodeEntity extends AbstractTokenEntity
{
/**
* Redirect URI
*
* @var string
*/
protected $redirectUri = '';
/**
* Set the redirect URI for the authorization request
*
* @param string $redirectUri
*
* @return self
*/
public function setRedirectUri($redirectUri)
{
$this->redirectUri = $redirectUri;
return $this;
}
/**
* Get the redirect URI
*
* @return string
*/
public function getRedirectUri()
{
return $this->redirectUri;
}
/**
* Generate a redirect URI
*
* @param string $state The state parameter if set by the client
* @param string $queryDelimeter The query delimiter ('?' for auth code grant, '#' for implicit grant)
*
* @return string
*/
public function generateRedirectUri($state = null, $queryDelimeter = '?')
{
$uri = $this->getRedirectUri();
$uri .= (strstr($this->getRedirectUri(), $queryDelimeter) === false) ? $queryDelimeter : '&';
return $uri.http_build_query([
'code' => $this->getId(),
'state' => $state,
]);
}
/**
* Get session
*
* @return \League\OAuth2\Server\Entity\SessionEntity
*/
public function getSession()
{
if ($this->session instanceof SessionEntity) {
return $this->session;
}
$this->session = $this->server->getSessionStorage()->getByAuthCode($this);
return $this->session;
}
/**
* Return all scopes associated with the session
*
* @return \League\OAuth2\Server\Entity\ScopeEntity[]
*/
public function getScopes()
{
if ($this->scopes === null) {
$this->scopes = $this->formatScopes(
$this->server->getAuthCodeStorage()->getScopes($this)
);
}
return $this->scopes;
}
/**
* {@inheritdoc}
*/
public function save()
{
$this->server->getAuthCodeStorage()->create(
$this->getId(),
$this->getExpireTime(),
$this->getSession()->getId(),
$this->getRedirectUri()
);
// Associate the scope with the token
foreach ($this->getScopes() as $scope) {
$this->server->getAuthCodeStorage()->associateScope($this, $scope);
}
return $this;
}
/**
* {@inheritdoc}
*/
public function expire()
{
$this->server->getAuthCodeStorage()->delete($this);
}
}

View File

@@ -1,111 +0,0 @@
<?php
/**
* OAuth 2.0 Client entity
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Entity;
use League\OAuth2\Server\AbstractServer;
/**
* Client entity class
*/
class ClientEntity
{
use EntityTrait;
/**
* Client identifier
*
* @var string
*/
protected $id = null;
/**
* Client secret
*
* @var string
*/
protected $secret = null;
/**
* Client name
*
* @var string
*/
protected $name = null;
/**
* Client redirect URI
*
* @var string
*/
protected $redirectUri = null;
/**
* Authorization or resource server
*
* @var \League\OAuth2\Server\AbstractServer
*/
protected $server;
/**
* __construct
*
* @param \League\OAuth2\Server\AbstractServer $server
*
* @return self
*/
public function __construct(AbstractServer $server)
{
$this->server = $server;
return $this;
}
/**
* Return the client identifier
*
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* Return the client secret
*
* @return string
*/
public function getSecret()
{
return $this->secret;
}
/**
* Get the client name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Returnt the client redirect URI
*
* @return string
*/
public function getRedirectUri()
{
return $this->redirectUri;
}
}

View File

@@ -1,33 +0,0 @@
<?php
/**
* OAuth 2.0 Entity trait
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Entity;
trait EntityTrait
{
/**
* Hydrate an entity with properites
*
* @param array $properties
*
* @return self
*/
public function hydrate(array $properties)
{
foreach ($properties as $prop => $val) {
if (property_exists($this, $prop)) {
$this->{$prop} = $val;
}
}
return $this;
}
}

View File

@@ -1,94 +0,0 @@
<?php
/**
* OAuth 2.0 Refresh token entity
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Entity;
/**
* Refresh token entity class
*/
class RefreshTokenEntity extends AbstractTokenEntity
{
/**
* Access token associated to refresh token
*
* @var \League\OAuth2\Server\Entity\AccessTokenEntity
*/
protected $accessTokenEntity;
/**
* Id of the access token
*
* @var string
*/
protected $accessTokenId;
/**
* Set the ID of the associated access token
*
* @param string $accessTokenId
*
* @return self
*/
public function setAccessTokenId($accessTokenId)
{
$this->accessTokenId = $accessTokenId;
return $this;
}
/**
* Associate an access token
*
* @param \League\OAuth2\Server\Entity\AccessTokenEntity $accessTokenEntity
*
* @return self
*/
public function setAccessToken(AccessTokenEntity $accessTokenEntity)
{
$this->accessTokenEntity = $accessTokenEntity;
return $this;
}
/**
* Return access token
*
* @return AccessTokenEntity
*/
public function getAccessToken()
{
if (! $this->accessTokenEntity instanceof AccessTokenEntity) {
$this->accessTokenEntity = $this->server->getAccessTokenStorage()->get($this->accessTokenId);
}
return $this->accessTokenEntity;
}
/**
* {@inheritdoc}
*/
public function save()
{
$this->server->getRefreshTokenStorage()->create(
$this->getId(),
$this->getExpireTime(),
$this->getAccessToken()->getId()
);
}
/**
* {@inheritdoc}
*/
public function expire()
{
$this->server->getRefreshTokenStorage()->delete($this);
}
}

View File

@@ -1,90 +0,0 @@
<?php
/**
* OAuth 2.0 scope entity
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Entity;
use League\OAuth2\Server\AbstractServer;
/**
* Scope entity class
*/
class ScopeEntity implements \JsonSerializable
{
use EntityTrait;
/**
* Scope identifier
*
* @var string
*/
protected $id;
/**
* Scope description
*
* @var string
*/
protected $description;
/**
* Authorization or resource server
*
* @var \League\OAuth2\Server\AbstractServer
*/
protected $server;
/**
* __construct
*
* @param \League\OAuth2\Server\AbstractServer $server
*
* @return self
*/
public function __construct(AbstractServer $server)
{
$this->server = $server;
return $this;
}
/**
* Return the scope identifer
*
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* Return the scope's description
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Returns a JSON object when entity is passed into json_encode
*
* @return array
*/
public function jsonSerialize()
{
return [
'id' => $this->getId(),
'description' => $this->getDescription()
];
}
}

View File

@@ -1,308 +0,0 @@
<?php
/**
* OAuth 2.0 session entity
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Entity;
use League\OAuth2\Server\AbstractServer;
use League\OAuth2\Server\Event\SessionOwnerEvent;
/**
* Session entity grant
*/
class SessionEntity
{
/**
* Session identifier
*
* @var string
*/
protected $id;
/**
* Client identifier
*
* @var \League\OAuth2\Server\Entity\ClientEntity
*/
protected $client;
/**
* Session owner identifier
*
* @var string
*/
protected $ownerId;
/**
* Session owner type (e.g. "user")
*
* @var string
*/
protected $ownerType;
/**
* Auth code
*
* @var \League\OAuth2\Server\Entity\AuthCodeEntity
*/
protected $authCode;
/**
* Access token
*
* @var \League\OAuth2\Server\Entity\AccessTokenEntity
*/
protected $accessToken;
/**
* Refresh token
*
* @var \League\OAuth2\Server\Entity\RefreshTokenEntity
*/
protected $refreshToken;
/**
* Session scopes
*
* @var \Symfony\Component\HttpFoundation\ParameterBag
*/
protected $scopes;
/**
* Authorization or resource server
*
* @var \League\OAuth2\Server\AuthorizationServer|\League\OAuth2\Server\ResourceServer
*/
protected $server;
/**
* __construct
*
* @param \League\OAuth2\Server\AbstractServer $server
*
* @return self
*/
public function __construct(AbstractServer $server)
{
$this->server = $server;
return $this;
}
/**
* Set the session identifier
*
* @param string $id
*
* @return self
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* Return the session identifier
*
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* Associate a scope
*
* @param \League\OAuth2\Server\Entity\ScopeEntity $scope
*
* @return self
*/
public function associateScope(ScopeEntity $scope)
{
if (!isset($this->scopes[$scope->getId()])) {
$this->scopes[$scope->getId()] = $scope;
}
return $this;
}
/**
* Check if access token has an associated scope
*
* @param string $scope Scope to check
*
* @return bool
*/
public function hasScope($scope)
{
if ($this->scopes === null) {
$this->getScopes();
}
return isset($this->scopes[$scope]);
}
/**
* Return all scopes associated with the session
*
* @return \League\OAuth2\Server\Entity\ScopeEntity[]
*/
public function getScopes()
{
if ($this->scopes === null) {
$this->scopes = $this->formatScopes($this->server->getSessionStorage()->getScopes($this));
}
return $this->scopes;
}
/**
* Format the local scopes array
*
* @param \League\OAuth2\Server\Entity\Scope[]
*
* @return array
*/
private function formatScopes($unformatted = [])
{
$scopes = [];
if (is_array($unformatted)) {
foreach ($unformatted as $scope) {
if ($scope instanceof ScopeEntity) {
$scopes[$scope->getId()] = $scope;
}
}
}
return $scopes;
}
/**
* Associate an access token with the session
*
* @param \League\OAuth2\Server\Entity\AccessTokenEntity $accessToken
*
* @return self
*/
public function associateAccessToken(AccessTokenEntity $accessToken)
{
$this->accessToken = $accessToken;
return $this;
}
/**
* Associate a refresh token with the session
*
* @param \League\OAuth2\Server\Entity\RefreshTokenEntity $refreshToken
*
* @return self
*/
public function associateRefreshToken(RefreshTokenEntity $refreshToken)
{
$this->refreshToken = $refreshToken;
return $this;
}
/**
* Associate a client with the session
*
* @param \League\OAuth2\Server\Entity\ClientEntity $client The client
*
* @return self
*/
public function associateClient(ClientEntity $client)
{
$this->client = $client;
return $this;
}
/**
* Return the session client
*
* @return \League\OAuth2\Server\Entity\ClientEntity
*/
public function getClient()
{
if ($this->client instanceof ClientEntity) {
return $this->client;
}
$this->client = $this->server->getClientStorage()->getBySession($this);
return $this->client;
}
/**
* Set the session owner
*
* @param string $type The type of the owner (e.g. user, app)
* @param string $id The identifier of the owner
*
* @return self
*/
public function setOwner($type, $id)
{
$this->ownerType = $type;
$this->ownerId = $id;
$this->server->getEventEmitter()->emit(new SessionOwnerEvent($this));
return $this;
}
/**
* Return session owner identifier
*
* @return string
*/
public function getOwnerId()
{
return $this->ownerId;
}
/**
* Return session owner type
*
* @return string
*/
public function getOwnerType()
{
return $this->ownerType;
}
/**
* Save the session
*
* @return void
*/
public function save()
{
// Save the session and get an identifier
$id = $this->server->getSessionStorage()->create(
$this->getOwnerType(),
$this->getOwnerId(),
$this->getClient()->getId(),
$this->getClient()->getRedirectUri()
);
$this->setId($id);
// Associate the scope with the session
foreach ($this->getScopes() as $scope) {
$this->server->getSessionStorage()->associateScope($this, $scope);
}
}
}

View File

@@ -1,55 +0,0 @@
<?php
/**
* OAuth 2.0 client authentication failed event
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Event;
use League\Event\AbstractEvent;
use Symfony\Component\HttpFoundation\Request;
class ClientAuthenticationFailedEvent extends AbstractEvent
{
/**
* Request
*
* @var \Symfony\Component\HttpFoundation\Request
*/
private $request;
/**
* Init the event with a request
*
* @param \Symfony\Component\HttpFoundation\Request $request
*/
public function __construct(Request $request)
{
$this->request = $request;
}
/**
* The name of the event
*
* @return string
*/
public function getName()
{
return 'error.auth.client';
}
/**
* Return request
*
* @return \Symfony\Component\HttpFoundation\Request
*/
public function getRequest()
{
return $this->request;
}
}

View File

@@ -1,55 +0,0 @@
<?php
/**
* OAuth 2.0 session owner event
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Event;
use League\Event\AbstractEvent;
use League\OAuth2\Server\Entity\SessionEntity;
class SessionOwnerEvent extends AbstractEvent
{
/**
* Session entity
*
* @var \League\OAuth2\Server\Entity\SessionEntity
*/
private $session;
/**
* Init the event with a session
*
* @param \League\OAuth2\Server\Entity\SessionEntity $session
*/
public function __construct(SessionEntity $session)
{
$this->session = $session;
}
/**
* The name of the event
*
* @return string
*/
public function getName()
{
return 'session.owner';
}
/**
* Return session
*
* @return \League\OAuth2\Server\Entity\SessionEntity
*/
public function getSession()
{
return $this->session;
}
}

View File

@@ -1,55 +0,0 @@
<?php
/**
* OAuth 2.0 user authentication failed event
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Event;
use League\Event\AbstractEvent;
use Symfony\Component\HttpFoundation\Request;
class UserAuthenticationFailedEvent extends AbstractEvent
{
/**
* Request
*
* @var \Symfony\Component\HttpFoundation\Request
*/
private $request;
/**
* Init the event with a request
*
* @param \Symfony\Component\HttpFoundation\Request $request
*/
public function __construct(Request $request)
{
$this->request = $request;
}
/**
* The name of the event
*
* @return string
*/
public function getName()
{
return 'error.auth.user';
}
/**
* Return request
*
* @return \Symfony\Component\HttpFoundation\Request
*/
public function getRequest()
{
return $this->request;
}
}

View File

@@ -1,36 +0,0 @@
<?php
/**
* OAuth 2.0 Access Denied Exception
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Exception;
/**
* Exception class
*/
class AccessDeniedException extends OAuthException
{
/**
* {@inheritdoc}
*/
public $httpStatusCode = 401;
/**
* {@inheritdoc}
*/
public $errorType = 'access_denied';
/**
* {@inheritdoc}
*/
public function __construct()
{
parent::__construct('The resource owner or authorization server denied the request.');
}
}

View File

@@ -1,36 +0,0 @@
<?php
/**
* OAuth 2.0 Invalid Client Exception
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Exception;
/**
* Exception class
*/
class InvalidClientException extends OAuthException
{
/**
* {@inheritdoc}
*/
public $httpStatusCode = 401;
/**
* {@inheritdoc}
*/
public $errorType = 'invalid_client';
/**
* {@inheritdoc}
*/
public function __construct()
{
parent::__construct('Client authentication failed.');
}
}

View File

@@ -1,36 +0,0 @@
<?php
/**
* OAuth 2.0 Invalid Credentials Exception
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Exception;
/**
* Exception class
*/
class InvalidCredentialsException extends OAuthException
{
/**
* {@inheritdoc}
*/
public $httpStatusCode = 401;
/**
* {@inheritdoc}
*/
public $errorType = 'invalid_credentials';
/**
* {@inheritdoc}
*/
public function __construct()
{
parent::__construct('The user credentials were incorrect.');
}
}

View File

@@ -1,42 +0,0 @@
<?php
/**
* OAuth 2.0 Invalid Grant Exception
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Exception;
/**
* Exception class
*/
class InvalidGrantException extends OAuthException
{
/**
* {@inheritdoc}
*/
public $httpStatusCode = 400;
/**
* {@inheritdoc}
*/
public $errorType = 'invalid_grant';
/**
* {@inheritdoc}
*/
public function __construct($parameter)
{
parent::__construct(
sprintf(
'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.',
$parameter
)
);
}
}

View File

@@ -1,36 +0,0 @@
<?php
/**
* OAuth 2.0 Invalid Refresh Exception
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Exception;
/**
* Exception class
*/
class InvalidRefreshException extends OAuthException
{
/**
* {@inheritdoc}
*/
public $httpStatusCode = 400;
/**
* {@inheritdoc}
*/
public $errorType = 'invalid_request';
/**
* {@inheritdoc}
*/
public function __construct()
{
parent::__construct('The refresh token is invalid.');
}
}

View File

@@ -1,44 +0,0 @@
<?php
/**
* OAuth 2.0 Invalid Request Exception
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Exception;
/**
* Exception class
*/
class InvalidRequestException extends OAuthException
{
/**
* {@inheritdoc}
*/
public $httpStatusCode = 400;
/**
* {@inheritdoc}
*/
public $errorType = 'invalid_request';
/**
* {@inheritdoc}
*/
public function __construct($parameter, $redirectUri = null)
{
parent::__construct(
sprintf(
'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.',
$parameter
)
);
$this->redirectUri = $redirectUri;
}
}

View File

@@ -1,44 +0,0 @@
<?php
/**
* OAuth 2.0 Invalid Scope Exception
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Exception;
/**
* Exception class
*/
class InvalidScopeException extends OAuthException
{
/**
* {@inheritdoc}
*/
public $httpStatusCode = 400;
/**
* {@inheritdoc}
*/
public $errorType = 'invalid_scope';
/**
* {@inheritdoc}
*/
public function __construct($parameter, $redirectUri = null)
{
parent::__construct(
sprintf(
'The requested scope is invalid, unknown, or malformed. Check the "%s" scope.',
$parameter
)
);
$this->redirectUri = $redirectUri;
}
}

View File

@@ -1,130 +0,0 @@
<?php
/**
* OAuth 2.0 Base Exception
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Exception;
use League\OAuth2\Server\Util\RedirectUri;
use Symfony\Component\HttpFoundation\Request;
/**
* Exception class
*/
class OAuthException extends \Exception
{
/**
* The HTTP status code for this exception that should be sent in the response
*/
public $httpStatusCode = 400;
/**
* Redirect URI if the server should redirect back to the client
*
* @var string|null
*/
public $redirectUri = null;
/**
* The exception type
*/
public $errorType = '';
/**
* Throw a new exception
*
* @param string $msg Exception Message
*/
public function __construct($msg = 'An error occured')
{
parent::__construct($msg);
}
/**
* Should the server redirect back to the client?
*
* @return bool
*/
public function shouldRedirect()
{
return is_null($this->redirectUri) ? false : true;
}
/**
* Return redirect URI if set
*
* @return string|null
*/
public function getRedirectUri()
{
return RedirectUri::make(
$this->redirectUri,
[
'error' => $this->errorType,
'message' => $this->getMessage(),
]
);
}
/**
* Get all headers that have to be send with the error response
*
* @return array Array with header values
*/
public function getHttpHeaders()
{
$headers = [];
switch ($this->httpStatusCode) {
case 401:
$headers[] = 'HTTP/1.1 401 Unauthorized';
break;
case 500:
$headers[] = 'HTTP/1.1 500 Internal Server Error';
break;
case 501:
$headers[] = 'HTTP/1.1 501 Not Implemented';
break;
case 400:
default:
$headers[] = 'HTTP/1.1 400 Bad Request';
break;
}
// Add "WWW-Authenticate" header
//
// RFC 6749, section 5.2.:
// "If the client attempted to authenticate via the 'Authorization'
// request header field, the authorization server MUST
// respond with an HTTP 401 (Unauthorized) status code and
// include the "WWW-Authenticate" response header field
// matching the authentication scheme used by the client.
// @codeCoverageIgnoreStart
if ($this->errorType === 'invalid_client') {
$authScheme = null;
$request = new Request();
if ($request->getUser() !== null) {
$authScheme = 'Basic';
} else {
$authHeader = $request->headers->get('Authorization');
if ($authHeader !== null) {
if (strpos($authHeader, 'Bearer') === 0) {
$authScheme = 'Bearer';
} elseif (strpos($authHeader, 'Basic') === 0) {
$authScheme = 'Basic';
}
}
}
if ($authScheme !== null) {
$headers[] = 'WWW-Authenticate: '.$authScheme.' realm=""';
}
}
// @codeCoverageIgnoreEnd
return $headers;
}
}

View File

@@ -0,0 +1,265 @@
<?php
namespace League\OAuth2\Server\Exception;
use Psr\Http\Message\ResponseInterface;
class OAuthServerException extends \Exception
{
/**
* @var int
*/
private $httpStatusCode;
/**
* @var string
*/
private $errorType;
/**
* @var null|string
*/
private $hint;
/**
* @var null|string
*/
private $redirectUri;
/**
* Throw a new exception.
*
* @param string $message Error message
* @param int $code Error code
* @param string $errorType Error type
* @param int $httpStatusCode HTTP status code to send (default = 400)
* @param null|string $hint A helper hint
* @param null|string $redirectUri A HTTP URI to redirect the user back to
*/
public function __construct($message, $code, $errorType, $httpStatusCode = 400, $hint = null, $redirectUri = null)
{
parent::__construct($message, $code);
$this->httpStatusCode = $httpStatusCode;
$this->errorType = $errorType;
$this->hint = $hint;
$this->redirectUri = $redirectUri;
}
/**
* Unsupported grant type error.
*
* @return static
*/
public static function unsupportedGrantType()
{
$errorMessage = 'The authorization grant type is not supported by the authorization server.';
$hint = 'Check the `grant_type` parameter';
return new static($errorMessage, 2, 'unsupported_grant_type', 400, $hint);
}
/**
* Invalid request error.
*
* @param string $parameter The invalid parameter
* @param string|null $hint
*
* @return static
*/
public static function invalidRequest($parameter, $hint = null)
{
$errorMessage = 'The request is missing a required parameter, includes an invalid parameter value, ' .
'includes a parameter more than once, or is otherwise malformed.';
$hint = ($hint === null) ? sprintf('Check the `%s` parameter', $parameter) : $hint;
return new static($errorMessage, 3, 'invalid_request', 400, $hint);
}
/**
* Invalid client error.
*
* @return static
*/
public static function invalidClient()
{
$errorMessage = 'Client authentication failed';
return new static($errorMessage, 4, 'invalid_client', 401);
}
/**
* Invalid scope error.
*
* @param string $scope The bad scope
* @param null|string $redirectUri A HTTP URI to redirect the user back to
*
* @return static
*/
public static function invalidScope($scope, $redirectUri = null)
{
$errorMessage = 'The requested scope is invalid, unknown, or malformed';
$hint = sprintf('Check the `%s` scope', $scope);
return new static($errorMessage, 5, 'invalid_scope', 400, $hint, $redirectUri);
}
/**
* Invalid credentials error.
*
* @return static
*/
public static function invalidCredentials()
{
return new static('The user credentials were incorrect.', 6, 'invalid_credentials', 401);
}
/**
* Server error.
*
* @param $hint
*
* @return static
*/
public static function serverError($hint)
{
return new static(
'The authorization server encountered an unexpected condition which prevented it from fulfilling'
. ' the request: ' . $hint,
7,
'server_error',
500
);
}
/**
* Invalid refresh token.
*
* @param string|null $hint
*
* @return static
*/
public static function invalidRefreshToken($hint = null)
{
return new static('The refresh token is invalid.', 8, 'invalid_request', 400, $hint);
}
/**
* Access denied.
*
* @param string|null $hint
* @param string|null $redirectUri
*
* @return static
*/
public static function accessDenied($hint = null, $redirectUri = null)
{
return new static(
'The resource owner or authorization server denied the request.',
9,
'access_denied',
401,
$hint,
$redirectUri
);
}
/**
* @return string
*/
public function getErrorType()
{
return $this->errorType;
}
/**
* Generate a HTTP response.
*
* @param \Psr\Http\Message\ResponseInterface $response
* @param bool $useFragment True if errors should be in the URI fragment instead of
* query string
*
* @return \Psr\Http\Message\ResponseInterface
*/
public function generateHttpResponse(ResponseInterface $response, $useFragment = false)
{
$headers = $this->getHttpHeaders();
$payload = [
'error' => $this->getErrorType(),
'message' => $this->getMessage(),
];
if ($this->hint !== null) {
$payload['hint'] = $this->hint;
}
if ($this->redirectUri !== null) {
if ($useFragment === true) {
$this->redirectUri .= (strstr($this->redirectUri, '#') === false) ? '#' : '&';
} else {
$this->redirectUri .= (strstr($this->redirectUri, '?') === false) ? '?' : '&';
}
return $response->withStatus(302)->withHeader('Location', $this->redirectUri . http_build_query($payload));
}
foreach ($headers as $header => $content) {
$response = $response->withHeader($header, $content);
}
$response->getBody()->write(json_encode($payload));
return $response->withStatus($this->getHttpStatusCode());
}
/**
* Get all headers that have to be send with the error response.
*
* @return array Array with header values
*/
public function getHttpHeaders()
{
$headers = [
'Content-type' => 'application/json',
];
// Add "WWW-Authenticate" header
//
// RFC 6749, section 5.2.:
// "If the client attempted to authenticate via the 'Authorization'
// request header field, the authorization server MUST
// respond with an HTTP 401 (Unauthorized) status code and
// include the "WWW-Authenticate" response header field
// matching the authentication scheme used by the client.
// @codeCoverageIgnoreStart
if ($this->errorType === 'invalid_client') {
$authScheme = 'Basic';
if (array_key_exists('HTTP_AUTHORIZATION', $_SERVER) !== false
&& strpos($_SERVER['HTTP_AUTHORIZATION'], 'Bearer') === 0
) {
$authScheme = 'Bearer';
}
$headers[] = 'WWW-Authenticate: ' . $authScheme . ' realm="OAuth"';
}
// @codeCoverageIgnoreEnd
return $headers;
}
/**
* Returns the HTTP status code to send when the exceptions is output.
*
* @return int
*/
public function getHttpStatusCode()
{
return $this->httpStatusCode;
}
/**
* @return null|string
*/
public function getHint()
{
return $this->hint;
}
}

View File

@@ -1,37 +0,0 @@
<?php
/**
* OAuth 2.0 Server Error Exception
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Exception;
/**
* Exception class
*/
class ServerErrorException extends OAuthException
{
/**
* {@inheritdoc}
*/
public $httpStatusCode = 500;
/**
* {@inheritdoc}
*/
public $errorType = 'server_error';
/**
* {@inheritdoc}
*/
public function __construct($parameter = null)
{
$parameter = is_null($parameter) ? 'The authorization server encountered an unexpected condition which prevented it from fulfilling the request.' : $parameter;
parent::__construct($parameter);
}
}

View File

@@ -1,36 +0,0 @@
<?php
/**
* OAuth 2.0 Unauthorized Client Exception
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Exception;
/**
* Exception class
*/
class UnauthorizedClientException extends OAuthException
{
/**
* {@inheritdoc}
*/
public $httpStatusCode = 400;
/**
* {@inheritdoc}
*/
public $errorType = 'unauthorized_client';
/**
* {@inheritdoc}
*/
public function __construct()
{
parent::__construct('The client is not authorized to request an access token using this method.');
}
}

View File

@@ -1,42 +0,0 @@
<?php
/**
* OAuth 2.0 Invalid Request Exception
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Exception;
/**
* Exception class
*/
class UnsupportedGrantTypeException extends OAuthException
{
/**
* {@inheritdoc}
*/
public $httpStatusCode = 400;
/**
* {@inheritdoc}
*/
public $errorType = 'unsupported_grant_type';
/**
* {@inheritdoc}
*/
public function __construct($parameter)
{
parent::__construct(
sprintf(
'The authorization grant type "%s" is not supported by the authorization server.',
$parameter
)
);
}
}

View File

@@ -1,37 +0,0 @@
<?php
/**
* OAuth 2.0 Unsupported Response Type Exception
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Exception;
/**
* Exception class
*/
class UnsupportedResponseTypeException extends OAuthException
{
/**
* {@inheritdoc}
*/
public $httpStatusCode = 400;
/**
* {@inheritdoc}
*/
public $errorType = 'unsupported_response_type';
/**
* {@inheritdoc}
*/
public function __construct($parameter, $redirectUri = null)
{
parent::__construct('The authorization server does not support obtaining an access token using this method.');
$this->redirectUri = $redirectUri;
}
}

View File

@@ -0,0 +1,66 @@
<?php
/**
* Abstract authorization grant.
*
* @author Julián Gutiérrez <juliangut@gmail.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Grant;
use League\OAuth2\Server\TemplateRenderer\PlatesRenderer;
use League\OAuth2\Server\TemplateRenderer\RendererInterface;
use League\Plates\Engine;
abstract class AbstractAuthorizeGrant extends AbstractGrant
{
/**
* @var \League\OAuth2\Server\TemplateRenderer\RendererInterface
*/
protected $templateRenderer;
/**
* Set the template renderer
*
* @param RendererInterface $templateRenderer
*/
public function setTemplateRenderer(RendererInterface $templateRenderer)
{
$this->templateRenderer = $templateRenderer;
}
/**
* Retrieve template renderer.
*
* @return \League\OAuth2\Server\TemplateRenderer\RendererInterface
*/
protected function getTemplateRenderer()
{
if (!$this->templateRenderer instanceof RendererInterface) {
$this->templateRenderer = new PlatesRenderer(
new Engine(__DIR__ . '/../TemplateRenderer/DefaultTemplates'),
'login_user',
'authorize_client'
);
}
return $this->templateRenderer;
}
/**
* @param string $uri
* @param array $params
* @param string $queryDelimiter
*
* @return string
*/
public function makeRedirectUri($uri, $params = [], $queryDelimiter = '?')
{
$uri .= (strstr($uri, $queryDelimiter) === false) ? $queryDelimiter : '&';
return $uri . http_build_query($params);
}
}

View File

@@ -1,197 +1,397 @@
<?php
/**
* OAuth 2.0 Abstract grant
* OAuth 2.0 Abstract grant.
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Grant;
use League\OAuth2\Server\AuthorizationServer;
use League\OAuth2\Server\Entity\ClientEntity;
use League\OAuth2\Server\Entity\ScopeEntity;
use League\OAuth2\Server\Exception;
use League\Event\EmitterAwareTrait;
use League\OAuth2\Server\CryptTrait;
use League\OAuth2\Server\Entities\AccessTokenEntity;
use League\OAuth2\Server\Entities\AuthCodeEntity;
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
use League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface;
use League\OAuth2\Server\Entities\RefreshTokenEntity;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
use League\OAuth2\Server\RequestEvent;
use Psr\Http\Message\ServerRequestInterface;
/**
* Abstract grant class
* Abstract grant class.
*/
abstract class AbstractGrant implements GrantTypeInterface
{
/**
* Grant identifier
*
* @var string
*/
protected $identifier = '';
use EmitterAwareTrait, CryptTrait;
const SCOPE_DELIMITER_STRING = ' ';
/**
* Response type
*
* @var string
* @var ServerRequestInterface
*/
protected $responseType;
protected $request;
/**
* Callback to authenticate a user's name and password
*
* @var callable
* @var ClientRepositoryInterface
*/
protected $callback;
protected $clientRepository;
/**
* AuthServer instance
*
* @var \League\OAuth2\Server\AuthorizationServer
* @var AccessTokenRepositoryInterface
*/
protected $server;
protected $accessTokenRepository;
/**
* Access token expires in override
*
* @var int
* @var ScopeRepositoryInterface
*/
protected $accessTokenTTL;
protected $scopeRepository;
/**
* {@inheritdoc}
* @var \League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface
*/
public function getIdentifier()
protected $authCodeRepository;
/**
* @var \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface
*/
protected $refreshTokenRepository;
/**
* @var \League\OAuth2\Server\Repositories\UserRepositoryInterface
*/
protected $userRepository;
/**
* @var \DateInterval
*/
protected $refreshTokenTTL;
/**
* @param ClientRepositoryInterface $clientRepository
*/
public function setClientRepository(ClientRepositoryInterface $clientRepository)
{
return $this->identifier;
$this->clientRepository = $clientRepository;
}
/**
* @param AccessTokenRepositoryInterface $accessTokenRepository
*/
public function setAccessTokenRepository(AccessTokenRepositoryInterface $accessTokenRepository)
{
$this->accessTokenRepository = $accessTokenRepository;
}
/**
* @param ScopeRepositoryInterface $scopeRepository
*/
public function setScopeRepository(ScopeRepositoryInterface $scopeRepository)
{
$this->scopeRepository = $scopeRepository;
}
/**
* @param \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface $refreshTokenRepository
*/
public function setRefreshTokenRepository(RefreshTokenRepositoryInterface $refreshTokenRepository)
{
$this->refreshTokenRepository = $refreshTokenRepository;
}
/**
* @param \League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface $authCodeRepository
*/
public function setAuthCodeRepository(AuthCodeRepositoryInterface $authCodeRepository)
{
$this->authCodeRepository = $authCodeRepository;
}
/**
* @param \League\OAuth2\Server\Repositories\UserRepositoryInterface $userRepository
*/
public function setUserRepository(UserRepositoryInterface $userRepository)
{
$this->userRepository = $userRepository;
}
/**
* {@inheritdoc}
*/
public function setIdentifier($identifier)
public function setRefreshTokenTTL(\DateInterval $refreshTokenTTL)
{
$this->identifier = $identifier;
return $this;
$this->refreshTokenTTL = $refreshTokenTTL;
}
/**
* {@inheritdoc}
*/
public function getResponseType()
{
return $this->responseType;
}
/**
* Get the TTL for an access token
* Validate the client.
*
* @return int The TTL
* @param \Psr\Http\Message\ServerRequestInterface $request
*
* @throws \League\OAuth2\Server\Exception\OAuthServerException
*
* @return \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface
*/
public function getAccessTokenTTL()
protected function validateClient(ServerRequestInterface $request)
{
if ($this->accessTokenTTL) {
return $this->accessTokenTTL;
$clientId = $this->getRequestParameter(
'client_id',
$request,
$this->getServerParameter('PHP_AUTH_USER', $request)
);
if (is_null($clientId)) {
throw OAuthServerException::invalidRequest('client_id', '`%s` parameter is missing');
}
return $this->server->getAccessTokenTTL();
// If the client is confidential require the client secret
$clientSecret = $this->getRequestParameter(
'client_secret',
$request,
$this->getServerParameter('PHP_AUTH_PW', $request)
);
$client = $this->clientRepository->getClientEntity(
$clientId,
$this->getIdentifier(),
$clientSecret
);
if (!$client instanceof ClientEntityInterface) {
$this->getEmitter()->emit(new RequestEvent('client.authentication.failed', $request));
throw OAuthServerException::invalidClient();
}
// If a redirect URI is provided ensure it matches what is pre-registered
$redirectUri = $this->getRequestParameter('redirect_uri', $request, null);
if ($redirectUri !== null && (strcmp($client->getRedirectUri(), $redirectUri) !== 0)) {
throw OAuthServerException::invalidClient();
}
return $client;
}
/**
* Override the default access token expire time
* Validate scopes in the request.
*
* @param int $accessTokenTTL
* @param string $scopes
* @param \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface $client
* @param string $redirectUri
*
* @return self
* @throws \League\OAuth2\Server\Exception\OAuthServerException
*
* @return \League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface[]
*/
public function setAccessTokenTTL($accessTokenTTL)
{
$this->accessTokenTTL = $accessTokenTTL;
return $this;
}
/**
* {@inheritdoc}
*/
public function setAuthorizationServer(AuthorizationServer $server)
{
$this->server = $server;
return $this;
}
/**
* Given a list of scopes, validate them and return an array of Scope entities
*
* @param string $scopeParam A string of scopes (e.g. "profile email birthday")
* @param \League\OAuth2\Server\Entity\ClientEntity $client Client entity
* @param string|null $redirectUri The redirect URI to return the user to
*
* @return \League\OAuth2\Server\Entity\ScopeEntity[]
*
* @throws \League\OAuth2\Server\Exception\InvalidScopeException If scope is invalid, or no scopes passed when required
* @throws
*/
public function validateScopes($scopeParam = '', ClientEntity $client, $redirectUri = null)
{
$scopesList = explode($this->server->getScopeDelimiter(), $scopeParam);
for ($i = 0; $i < count($scopesList); $i++) {
$scopesList[$i] = trim($scopesList[$i]);
if ($scopesList[$i] === '') {
unset($scopesList[$i]); // Remove any junk scopes
public function validateScopes(
$scopes,
ClientEntityInterface $client,
$redirectUri = null
) {
$scopesList = array_filter(
explode(self::SCOPE_DELIMITER_STRING, trim($scopes)),
function ($scope) {
return !empty($scope);
}
}
if (
$this->server->scopeParamRequired() === true
&& $this->server->getDefaultScope() === null
&& count($scopesList) === 0
) {
throw new Exception\InvalidRequestException('scope');
} elseif (count($scopesList) === 0 && $this->server->getDefaultScope() !== null) {
if (is_array($this->server->getDefaultScope())) {
$scopesList = $this->server->getDefaultScope();
} else {
$scopesList = [0 => $this->server->getDefaultScope()];
}
}
);
$scopes = [];
foreach ($scopesList as $scopeItem) {
$scope = $this->server->getScopeStorage()->get(
$scopeItem,
$this->getIdentifier(),
$client->getId()
);
$scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeItem);
if (($scope instanceof ScopeEntity) === false) {
throw new Exception\InvalidScopeException($scopeItem, $redirectUri);
if (($scope instanceof ScopeEntityInterface) === false) {
throw OAuthServerException::invalidScope($scopeItem, $redirectUri);
}
$scopes[$scope->getId()] = $scope;
$scopes[] = $scope;
}
return $scopes;
}
/**
* Format the local scopes array
* Retrieve request parameter.
*
* @param \League\OAuth2\Server\Entity\ScopeEntity[]
* @param string $parameter
* @param \Psr\Http\Message\ServerRequestInterface $request
* @param mixed $default
*
* @return array
* @return null|string
*/
protected function formatScopes($unformated = [])
protected function getRequestParameter($parameter, ServerRequestInterface $request, $default = null)
{
$scopes = [];
foreach ($unformated as $scope) {
if ($scope instanceof ScopeEntity) {
$scopes[$scope->getId()] = $scope;
}
$requestParameters = (array) $request->getParsedBody();
return isset($requestParameters[$parameter]) ? $requestParameters[$parameter] : $default;
}
/**
* Retrieve query string parameter.
*
* @param string $parameter
* @param \Psr\Http\Message\ServerRequestInterface $request
* @param mixed $default
*
* @return null|string
*/
protected function getQueryStringParameter($parameter, ServerRequestInterface $request, $default = null)
{
return isset($request->getQueryParams()[$parameter]) ? $request->getQueryParams()[$parameter] : $default;
}
/**
* Retrieve cookie parameter.
*
* @param string $parameter
* @param \Psr\Http\Message\ServerRequestInterface $request
* @param mixed $default
*
* @return null|string
*/
protected function getCookieParameter($parameter, ServerRequestInterface $request, $default = null)
{
return isset($request->getCookieParams()[$parameter]) ? $request->getCookieParams()[$parameter] : $default;
}
/**
* Retrieve server parameter.
*
* @param string $parameter
* @param \Psr\Http\Message\ServerRequestInterface $request
* @param mixed $default
*
* @return null|string
*/
protected function getServerParameter($parameter, ServerRequestInterface $request, $default = null)
{
return isset($request->getServerParams()[$parameter]) ? $request->getServerParams()[$parameter] : $default;
}
/**
* Issue an access token.
*
* @param \DateInterval $accessTokenTTL
* @param \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface $client
* @param string $userIdentifier
* @param \League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface[] $scopes
*
* @return \League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface
*/
protected function issueAccessToken(
\DateInterval $accessTokenTTL,
ClientEntityInterface $client,
$userIdentifier,
array $scopes = []
) {
$accessToken = new AccessTokenEntity();
$accessToken->setIdentifier($this->generateUniqueIdentifier());
$accessToken->setExpiryDateTime((new \DateTime())->add($accessTokenTTL));
$accessToken->setClient($client);
$accessToken->setUserIdentifier($userIdentifier);
foreach ($scopes as $scope) {
$accessToken->addScope($scope);
}
return $scopes;
$this->accessTokenRepository->persistNewAccessToken($accessToken);
return $accessToken;
}
/**
* Issue an auth code.
*
* @param \DateInterval $authCodeTTL
* @param \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface $client
* @param string $userIdentifier
* @param string $redirectUri
* @param \League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface[] $scopes
*
* @return \League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface
*/
protected function issueAuthCode(
\DateInterval $authCodeTTL,
ClientEntityInterface $client,
$userIdentifier,
$redirectUri,
array $scopes = []
) {
$authCode = new AuthCodeEntity();
$authCode->setIdentifier($this->generateUniqueIdentifier());
$authCode->setExpiryDateTime((new \DateTime())->add($authCodeTTL));
$authCode->setClient($client);
$authCode->setUserIdentifier($userIdentifier);
$authCode->setRedirectUri($redirectUri);
foreach ($scopes as $scope) {
$authCode->addScope($scope);
}
$this->authCodeRepository->persistNewAuthCode($authCode);
return $authCode;
}
/**
* @param \League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface $accessToken
*
* @return \League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface
*/
protected function issueRefreshToken(AccessTokenEntityInterface $accessToken)
{
$refreshToken = new RefreshTokenEntity();
$refreshToken->setIdentifier($this->generateUniqueIdentifier());
$refreshToken->setExpiryDateTime((new \DateTime())->add($this->refreshTokenTTL));
$refreshToken->setAccessToken($accessToken);
$this->refreshTokenRepository->persistNewRefreshToken($refreshToken);
return $refreshToken;
}
/**
* Generate a new unique identifier.
*
* @param int $length
*
* @throws \League\OAuth2\Server\Exception\OAuthServerException
*
* @return string
*/
protected function generateUniqueIdentifier($length = 40)
{
try {
return bin2hex(random_bytes($length));
// @codeCoverageIgnoreStart
} catch (\TypeError $e) {
throw OAuthServerException::serverError('An unexpected error has occurred');
} catch (\Error $e) {
throw OAuthServerException::serverError('An unexpected error has occurred');
} catch (\Exception $e) {
// If you get this message, the CSPRNG failed hard.
throw OAuthServerException::serverError('Could not generate a random string');
}
// @codeCoverageIgnoreEnd
}
/**
* {@inheritdoc}
*/
public function canRespondToRequest(ServerRequestInterface $request)
{
$requestParameters = (array) $request->getParsedBody();
return (
array_key_exists('grant_type', $requestParameters)
&& $requestParameters['grant_type'] === $this->getIdentifier()
);
}
}

View File

@@ -1,273 +1,350 @@
<?php
/**
* OAuth 2.0 Auth code grant
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Grant;
use League\OAuth2\Server\Entity\AccessTokenEntity;
use League\OAuth2\Server\Entity\AuthCodeEntity;
use League\OAuth2\Server\Entity\ClientEntity;
use League\OAuth2\Server\Entity\RefreshTokenEntity;
use League\OAuth2\Server\Entity\SessionEntity;
use League\OAuth2\Server\Event;
use League\OAuth2\Server\Exception;
use League\OAuth2\Server\Util\SecureKey;
use DateInterval;
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
use League\OAuth2\Server\Entities\Interfaces\UserEntityInterface;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
use League\OAuth2\Server\RequestEvent;
use League\OAuth2\Server\ResponseTypes\HtmlResponse;
use League\OAuth2\Server\ResponseTypes\RedirectResponse;
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
use League\OAuth2\Server\TemplateRenderer\RendererInterface;
use Psr\Http\Message\ServerRequestInterface;
/**
* Auth code grant class
*/
class AuthCodeGrant extends AbstractGrant
class AuthCodeGrant extends AbstractAuthorizeGrant
{
/**
* Grant identifier
*
* @var string
* @var \DateInterval
*/
protected $identifier = 'authorization_code';
private $authCodeTTL;
/**
* Response type
*
* @var string
* @param \League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface $authCodeRepository
* @param \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface $refreshTokenRepository
* @param \League\OAuth2\Server\Repositories\UserRepositoryInterface $userRepository
* @param \DateInterval $authCodeTTL
* @param \League\OAuth2\Server\TemplateRenderer\RendererInterface|null $templateRenderer
*/
protected $responseType = 'code';
/**
* AuthServer instance
*
* @var \League\OAuth2\Server\AuthorizationServer
*/
protected $server = null;
/**
* Access token expires in override
*
* @var int
*/
protected $accessTokenTTL = null;
/**
* The TTL of the auth token
*
* @var integer
*/
protected $authTokenTTL = 600;
/**
* Override the default access token expire time
*
* @param int $authTokenTTL
*
* @return void
*/
public function setAuthTokenTTL($authTokenTTL)
{
$this->authTokenTTL = $authTokenTTL;
public function __construct(
AuthCodeRepositoryInterface $authCodeRepository,
RefreshTokenRepositoryInterface $refreshTokenRepository,
UserRepositoryInterface $userRepository,
\DateInterval $authCodeTTL,
RendererInterface $templateRenderer = null
) {
$this->setAuthCodeRepository($authCodeRepository);
$this->setRefreshTokenRepository($refreshTokenRepository);
$this->setUserRepository($userRepository);
$this->authCodeTTL = $authCodeTTL;
$this->refreshTokenTTL = new \DateInterval('P1M');
$this->templateRenderer = $templateRenderer;
}
/**
* Check authorize parameters
* Respond to an authorization request.
*
* @return array Authorize request parameters
* @param \Psr\Http\Message\ServerRequestInterface $request
*
* @throws
* @throws \League\OAuth2\Server\Exception\OAuthServerException
*
* @return \Psr\Http\Message\ResponseInterface
*/
public function checkAuthorizeParams()
{
// Get required params
$clientId = $this->server->getRequest()->query->get('client_id', null);
protected function respondToAuthorizationRequest(
ServerRequestInterface $request
) {
$clientId = $this->getQueryStringParameter(
'client_id',
$request,
$this->getServerParameter('PHP_AUTH_USER', $request)
);
if (is_null($clientId)) {
throw new Exception\InvalidRequestException('client_id');
throw OAuthServerException::invalidRequest('client_id');
}
$redirectUri = $this->server->getRequest()->query->get('redirect_uri', null);
if (is_null($redirectUri)) {
throw new Exception\InvalidRequestException('redirect_uri');
}
// Validate client ID and redirect URI
$client = $this->server->getClientStorage()->get(
$client = $this->clientRepository->getClientEntity(
$clientId,
null,
$redirectUri,
$this->getIdentifier()
);
if (($client instanceof ClientEntity) === false) {
$this->server->getEventEmitter()->emit(new Event\ClientAuthenticationFailedEvent($this->server->getRequest()));
throw new Exception\InvalidClientException();
if ($client instanceof ClientEntityInterface === false) {
$this->getEmitter()->emit(new RequestEvent('client.authentication.failed', $request));
throw OAuthServerException::invalidClient();
}
$state = $this->server->getRequest()->query->get('state', null);
if ($this->server->stateParamRequired() === true && is_null($state)) {
throw new Exception\InvalidRequestException('state', $redirectUri);
$redirectUriParameter = $this->getQueryStringParameter('redirect_uri', $request, $client->getRedirectUri());
if ($redirectUriParameter !== $client->getRedirectUri()) {
$this->getEmitter()->emit(new RequestEvent('client.authentication.failed', $request));
throw OAuthServerException::invalidClient();
}
$responseType = $this->server->getRequest()->query->get('response_type', null);
if (is_null($responseType)) {
throw new Exception\InvalidRequestException('response_type', $redirectUri);
}
// Ensure response type is one that is recognised
if (!in_array($responseType, $this->server->getResponseTypes())) {
throw new Exception\UnsupportedResponseTypeException($responseType, $redirectUri);
}
// Validate any scopes that are in the request
$scopeParam = $this->server->getRequest()->query->get('scope', '');
$scopes = $this->validateScopes($scopeParam, $client, $redirectUri);
return [
'client' => $client,
'redirect_uri' => $redirectUri,
'state' => $state,
'response_type' => $responseType,
'scopes' => $scopes
];
}
/**
* Parse a new authorize request
*
* @param string $type The session owner's type
* @param string $typeId The session owner's ID
* @param array $authParams The authorize request $_GET parameters
*
* @return string An authorisation code
*/
public function newAuthorizeRequest($type, $typeId, $authParams = [])
{
// Create a new session
$session = new SessionEntity($this->server);
$session->setOwner($type, $typeId);
$session->associateClient($authParams['client']);
$session->save();
// Create a new auth code
$authCode = new AuthCodeEntity($this->server);
$authCode->setId(SecureKey::generate());
$authCode->setRedirectUri($authParams['redirect_uri']);
$authCode->setExpireTime(time() + $this->authTokenTTL);
foreach ($authParams['scopes'] as $scope) {
$authCode->associateScope($scope);
}
$authCode->setSession($session);
$authCode->save();
return $authCode->generateRedirectUri($authParams['state']);
}
/**
* Complete the auth code grant
*
* @return array
*
* @throws
*/
public function completeFlow()
{
// Get the required params
$clientId = $this->server->getRequest()->request->get('client_id', $this->server->getRequest()->getUser());
if (is_null($clientId)) {
throw new Exception\InvalidRequestException('client_id');
}
$clientSecret = $this->server->getRequest()->request->get('client_secret',
$this->server->getRequest()->getPassword());
if (is_null($clientSecret)) {
throw new Exception\InvalidRequestException('client_secret');
}
$redirectUri = $this->server->getRequest()->request->get('redirect_uri', null);
if (is_null($redirectUri)) {
throw new Exception\InvalidRequestException('redirect_uri');
}
// Validate client ID and client secret
$client = $this->server->getClientStorage()->get(
$clientId,
$clientSecret,
$redirectUri,
$this->getIdentifier()
$scopes = $this->validateScopes(
$this->getQueryStringParameter('scope', $request),
$client,
$client->getRedirectUri()
);
if (($client instanceof ClientEntity) === false) {
$this->server->getEventEmitter()->emit(new Event\ClientAuthenticationFailedEvent($this->server->getRequest()));
throw new Exception\InvalidClientException();
$postbackUri = sprintf(
'//%s%s',
$request->getServerParams()['HTTP_HOST'],
$request->getServerParams()['REQUEST_URI']
);
$userId = null;
$userHasApprovedClient = null;
if ($this->getRequestParameter('action', $request, null) !== null) {
$userHasApprovedClient = ($this->getRequestParameter('action', $request) === 'approve');
}
// Validate the auth code
$authCode = $this->server->getRequest()->request->get('code', null);
if (is_null($authCode)) {
throw new Exception\InvalidRequestException('code');
// Check if the user has been authenticated
$oauthCookie = $this->getCookieParameter('oauth_authorize_request', $request, null);
if ($oauthCookie !== null) {
try {
$oauthCookiePayload = json_decode($this->decrypt($oauthCookie));
if (is_object($oauthCookiePayload)) {
$userId = $oauthCookiePayload->user_id;
}
} catch (\LogicException $e) {
throw OAuthServerException::serverError($e->getMessage());
}
}
$code = $this->server->getAuthCodeStorage()->get($authCode);
if (($code instanceof AuthCodeEntity) === false) {
throw new Exception\InvalidRequestException('code');
// The username + password might be available in $_POST
$usernameParameter = $this->getRequestParameter('username', $request, null);
$passwordParameter = $this->getRequestParameter('password', $request, null);
$loginError = null;
// Assert if the user has logged in already
if ($userId === null && $usernameParameter !== null && $passwordParameter !== null) {
$userEntity = $this->userRepository->getUserEntityByUserCredentials(
$usernameParameter,
$passwordParameter,
$this->getIdentifier(),
$client
);
if ($userEntity instanceof UserEntityInterface) {
$userId = $userEntity->getIdentifier();
} else {
$loginError = 'Incorrect username or password';
}
}
// Ensure the auth code hasn't expired
if ($code->isExpired() === true) {
throw new Exception\InvalidRequestException('code');
// The user hasn't logged in yet so show a login form
if ($userId === null) {
$html = $this->getTemplateRenderer()->renderLogin([
'error' => $loginError,
'postback_uri' => $this->makeRedirectUri(
$postbackUri,
$request->getQueryParams()
),
]);
$htmlResponse = new HtmlResponse($this->accessTokenRepository);
$htmlResponse->setStatusCode(403);
$htmlResponse->setHtml($html);
return $htmlResponse;
}
// Check redirect URI presented matches redirect URI originally used in authorize request
if ($code->getRedirectUri() !== $redirectUri) {
throw new Exception\InvalidRequestException('redirect_uri');
// The user hasn't approved the client yet so show an authorize form
if ($userId !== null && $userHasApprovedClient === null) {
$html = $this->getTemplateRenderer()->renderAuthorize([
'client' => $client,
'scopes' => $scopes,
'postback_uri' => $this->makeRedirectUri(
$postbackUri,
$request->getQueryParams()
),
]);
$htmlResponse = new HtmlResponse($this->accessTokenRepository);
$htmlResponse->setStatusCode(200);
$htmlResponse->setHtml($html);
$htmlResponse->setHeader('set-cookie', sprintf(
'oauth_authorize_request=%s; Expires=%s',
urlencode($this->encrypt(
json_encode([
'user_id' => $userId,
])
)),
(new \DateTime())->add(new \DateInterval('PT5M'))->format('D, d M Y H:i:s e')
));
return $htmlResponse;
}
$session = $code->getSession();
$session->associateClient($client);
// The user has either approved or denied the client, so redirect them back
$redirectUri = $client->getRedirectUri();
$redirectPayload = [];
$authCodeScopes = $code->getScopes();
// Generate the access token
$accessToken = new AccessTokenEntity($this->server);
$accessToken->setId(SecureKey::generate());
$accessToken->setExpireTime($this->getAccessTokenTTL() + time());
foreach ($authCodeScopes as $authCodeScope) {
$session->associateScope($authCodeScope);
$stateParameter = $this->getQueryStringParameter('state', $request);
if ($stateParameter !== null) {
$redirectPayload['state'] = $stateParameter;
}
foreach ($session->getScopes() as $scope) {
$accessToken->associateScope($scope);
// THe user approved the client, redirect them back with an auth code
if ($userHasApprovedClient === true) {
// Finalize the requested scopes
$scopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client, $userId);
$authCode = $this->issueAuthCode(
$this->authCodeTTL,
$client,
$userId,
$redirectUri,
$scopes
);
$redirectPayload['code'] = $this->encrypt(
json_encode(
[
'client_id' => $authCode->getClient()->getIdentifier(),
'redirect_uri' => $authCode->getRedirectUri(),
'auth_code_id' => $authCode->getIdentifier(),
'scopes' => $authCode->getScopes(),
'user_id' => $authCode->getUserIdentifier(),
'expire_time' => (new \DateTime())->add($this->authCodeTTL)->format('U'),
]
)
);
$response = new RedirectResponse($this->accessTokenRepository);
$response->setRedirectUri(
$this->makeRedirectUri(
$redirectUri,
$redirectPayload
)
);
return $response;
}
$this->server->getTokenType()->setSession($session);
$this->server->getTokenType()->setParam('access_token', $accessToken->getId());
$this->server->getTokenType()->setParam('expires_in', $this->getAccessTokenTTL());
// The user denied the client, redirect them back with an error
throw OAuthServerException::accessDenied('The user denied the request', (string) $redirectUri);
}
// Associate a refresh token if set
if ($this->server->hasGrantType('refresh_token')) {
$refreshToken = new RefreshTokenEntity($this->server);
$refreshToken->setId(SecureKey::generate());
$refreshToken->setExpireTime($this->server->getGrantType('refresh_token')->getRefreshTokenTTL() + time());
$this->server->getTokenType()->setParam('refresh_token', $refreshToken->getId());
/**
* Respond to an access token request.
*
* @param \Psr\Http\Message\ServerRequestInterface $request
* @param \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface $responseType
* @param \DateInterval $accessTokenTTL
*
* @throws \League\OAuth2\Server\Exception\OAuthServerException
*
* @return \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface
*/
protected function respondToAccessTokenRequest(
ServerRequestInterface $request,
ResponseTypeInterface $responseType,
DateInterval $accessTokenTTL
) {
// The redirect URI is required in this request
$redirectUri = $this->getRequestParameter('redirect_uri', $request, null);
if (is_null($redirectUri)) {
throw OAuthServerException::invalidRequest('redirect_uri');
}
// Expire the auth code
$code->expire();
// Validate request
$client = $this->validateClient($request);
$encryptedAuthCode = $this->getRequestParameter('code', $request, null);
// Save all the things
$accessToken->setSession($session);
$accessToken->save();
if (isset($refreshToken) && $this->server->hasGrantType('refresh_token')) {
$refreshToken->setAccessToken($accessToken);
$refreshToken->save();
if ($encryptedAuthCode === null) {
throw OAuthServerException::invalidRequest('code');
}
return $this->server->getTokenType()->generateResponse();
// Validate the authorization code
try {
$authCodePayload = json_decode($this->decrypt($encryptedAuthCode));
if (time() > $authCodePayload->expire_time) {
throw OAuthServerException::invalidRequest('code', 'Authorization code has expired');
}
if ($this->authCodeRepository->isAuthCodeRevoked($authCodePayload->auth_code_id) === true) {
throw OAuthServerException::invalidRequest('code', 'Authorization code has been revoked');
}
if ($authCodePayload->client_id !== $client->getIdentifier()) {
throw OAuthServerException::invalidRequest('code', 'Authorization code was not issued to this client');
}
if ($authCodePayload->redirect_uri !== $redirectUri) {
throw OAuthServerException::invalidRequest('redirect_uri', 'Invalid redirect URI');
}
$scopes = [];
foreach ($authCodePayload->scopes as $scopeId) {
$scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeId);
if (!$scope) {
// @codeCoverageIgnoreStart
throw OAuthServerException::invalidScope($scopeId);
// @codeCoverageIgnoreEnd
}
$scopes[] = $scope;
}
} catch (\LogicException $e) {
throw OAuthServerException::invalidRequest('code', 'Cannot decrypt the authorization code');
}
// Issue and persist access + refresh tokens
$accessToken = $this->issueAccessToken($accessTokenTTL, $client, $authCodePayload->user_id, $scopes);
$refreshToken = $this->issueRefreshToken($accessToken);
// Inject tokens into response type
$responseType->setAccessToken($accessToken);
$responseType->setRefreshToken($refreshToken);
return $responseType;
}
/**
* {@inheritdoc}
*/
public function respondToRequest(
ServerRequestInterface $request,
ResponseTypeInterface $responseType,
\DateInterval $accessTokenTTL
) {
if (
array_key_exists('response_type', $request->getQueryParams())
&& $request->getQueryParams()['response_type'] === 'code'
) {
return $this->respondToAuthorizationRequest($request);
}
return $this->respondToAccessTokenRequest($request, $responseType, $accessTokenTTL);
}
/**
* {@inheritdoc}
*/
public function canRespondToRequest(ServerRequestInterface $request)
{
return
(
array_key_exists('response_type', $request->getQueryParams())
&& $request->getQueryParams()['response_type'] === 'code'
&& isset($request->getQueryParams()['client_id'])
)
|| parent::canRespondToRequest($request);
}
/**
* Return the grant identifier that can be used in matching up requests.
*
* @return string
*/
public function getIdentifier()
{
return 'authorization_code';
}
}

View File

@@ -1,122 +1,52 @@
<?php
/**
* OAuth 2.0 Client credentials grant
* OAuth 2.0 Client credentials grant.
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Grant;
use League\OAuth2\Server\Entity\AccessTokenEntity;
use League\OAuth2\Server\Entity\ClientEntity;
use League\OAuth2\Server\Entity\SessionEntity;
use League\OAuth2\Server\Event;
use League\OAuth2\Server\Exception;
use League\OAuth2\Server\Util\SecureKey;
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
use Psr\Http\Message\ServerRequestInterface;
/**
* Client credentials grant class
* Client credentials grant class.
*/
class ClientCredentialsGrant extends AbstractGrant
{
/**
* Grant identifier
*
* @var string
* {@inheritdoc}
*/
protected $identifier = 'client_credentials';
public function respondToRequest(
ServerRequestInterface $request,
ResponseTypeInterface $responseType,
\DateInterval $accessTokenTTL
) {
// Validate request
$client = $this->validateClient($request);
$scopes = $this->validateScopes($this->getRequestParameter('scope', $request), $client);
// Finalize the requested scopes
$scopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client);
// Issue and persist access token
$accessToken = $this->issueAccessToken($accessTokenTTL, $client, $client->getIdentifier(), $scopes);
// Inject access token into response type
$responseType->setAccessToken($accessToken);
return $responseType;
}
/**
* Response type
*
* @var string
* {@inheritdoc}
*/
protected $responseType = null;
/**
* AuthServer instance
*
* @var \League\OAuth2\Server\AuthorizationServer
*/
protected $server = null;
/**
* Access token expires in override
*
* @var int
*/
protected $accessTokenTTL = null;
/**
* Complete the client credentials grant
*
* @return array
*
* @throws
*/
public function completeFlow()
public function getIdentifier()
{
// Get the required params
$clientId = $this->server->getRequest()->request->get('client_id', $this->server->getRequest()->getUser());
if (is_null($clientId)) {
throw new Exception\InvalidRequestException('client_id');
}
$clientSecret = $this->server->getRequest()->request->get('client_secret',
$this->server->getRequest()->getPassword());
if (is_null($clientSecret)) {
throw new Exception\InvalidRequestException('client_secret');
}
// Validate client ID and client secret
$client = $this->server->getClientStorage()->get(
$clientId,
$clientSecret,
null,
$this->getIdentifier()
);
if (($client instanceof ClientEntity) === false) {
$this->server->getEventEmitter()->emit(new Event\ClientAuthenticationFailedEvent($this->server->getRequest()));
throw new Exception\InvalidClientException();
}
// Validate any scopes that are in the request
$scopeParam = $this->server->getRequest()->request->get('scope', '');
$scopes = $this->validateScopes($scopeParam, $client);
// Create a new session
$session = new SessionEntity($this->server);
$session->setOwner('client', $client->getId());
$session->associateClient($client);
// Generate an access token
$accessToken = new AccessTokenEntity($this->server);
$accessToken->setId(SecureKey::generate());
$accessToken->setExpireTime($this->getAccessTokenTTL() + time());
// Associate scopes with the session and access token
foreach ($scopes as $scope) {
$session->associateScope($scope);
}
foreach ($session->getScopes() as $scope) {
$accessToken->associateScope($scope);
}
// Save everything
$session->save();
$accessToken->setSession($session);
$accessToken->save();
$this->server->getTokenType()->setSession($session);
$this->server->getTokenType()->setParam('access_token', $accessToken->getId());
$this->server->getTokenType()->setParam('expires_in', $this->getAccessTokenTTL());
return $this->server->getTokenType()->generateResponse();
return 'client_credentials';
}
}

View File

@@ -1,59 +1,102 @@
<?php
/**
* OAuth 2.0 Grant type interface
* OAuth 2.0 Grant type interface.
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Grant;
use League\OAuth2\Server\AuthorizationServer;
use League\Event\EmitterAwareInterface;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
use Psr\Http\Message\ServerRequestInterface;
/**
* Grant type interface
* Grant type interface.
*/
interface GrantTypeInterface
interface GrantTypeInterface extends EmitterAwareInterface
{
/**
* Return the identifier
* Set refresh token TTL.
*
* @param \DateInterval $refreshTokenTTL
*/
public function setRefreshTokenTTL(\DateInterval $refreshTokenTTL);
/**
* Return the grant identifier that can be used in matching up requests.
*
* @return string
*/
public function getIdentifier();
/**
* Return the identifier
* Respond to an incoming request.
*
* @param string $identifier
* @param \Psr\Http\Message\ServerRequestInterface $request
* @param \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface $responseType
* @param \DateInterval $accessTokenTTL
*
* @return self
* @return \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface
*/
public function setIdentifier($identifier);
public function respondToRequest(
ServerRequestInterface $request,
ResponseTypeInterface $responseType,
\DateInterval $accessTokenTTL
);
/**
* Return the response type
* The grant type should return true if it is able to respond to this request.
*
* @return string
* For example most grant types will check that the $_POST['grant_type'] property matches it's identifier property.
*
* Some grants, such as the authorization code grant can respond to multiple requests
* - i.e. a client requesting an authorization code and requesting an access token
*
* @param \Psr\Http\Message\ServerRequestInterface $request
*
* @return bool
*/
public function getResponseType();
public function canRespondToRequest(ServerRequestInterface $request);
/**
* Inject the authorization server into the grant
* Set the client repository.
*
* @param \League\OAuth2\Server\AuthorizationServer $server The authorization server instance
*
* @return self
* @param \League\OAuth2\Server\Repositories\ClientRepositoryInterface $clientRepository
*/
public function setAuthorizationServer(AuthorizationServer $server);
public function setClientRepository(ClientRepositoryInterface $clientRepository);
/**
* Complete the grant flow
* Set the access token repository.
*
* @return array
* @param \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface $accessTokenRepository
*/
public function completeFlow();
public function setAccessTokenRepository(AccessTokenRepositoryInterface $accessTokenRepository);
/**
* Set the scope repository.
*
* @param \League\OAuth2\Server\Repositories\ScopeRepositoryInterface $scopeRepository
*/
public function setScopeRepository(ScopeRepositoryInterface $scopeRepository);
/**
* Set the path to the private key.
*
* @param string $privateKeyPath
*/
public function setPrivateKeyPath($privateKeyPath);
/**
* Set the path to the public key.
*
* @param string $publicKeyPath
*/
public function setPublicKeyPath($publicKeyPath);
}

219
src/Grant/ImplicitGrant.php Normal file
View File

@@ -0,0 +1,219 @@
<?php
namespace League\OAuth2\Server\Grant;
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
use League\OAuth2\Server\Entities\Interfaces\UserEntityInterface;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
use League\OAuth2\Server\RequestEvent;
use League\OAuth2\Server\ResponseTypes\HtmlResponse;
use League\OAuth2\Server\ResponseTypes\RedirectResponse;
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
use League\OAuth2\Server\TemplateRenderer\RendererInterface;
use Psr\Http\Message\ServerRequestInterface;
class ImplicitGrant extends AbstractAuthorizeGrant
{
/**
* @param \League\OAuth2\Server\Repositories\UserRepositoryInterface $userRepository
* @param \League\OAuth2\Server\TemplateRenderer\RendererInterface|null $templateRenderer
*/
public function __construct(UserRepositoryInterface $userRepository, RendererInterface $templateRenderer = null)
{
$this->setUserRepository($userRepository);
$this->refreshTokenTTL = new \DateInterval('P1M');
$this->templateRenderer = $templateRenderer;
}
/**
* {@inheritdoc}
*/
public function canRespondToRequest(ServerRequestInterface $request)
{
return (array_key_exists('response_type', $request->getQueryParams())
&& $request->getQueryParams()['response_type'] === 'token');
}
/**
* Return the grant identifier that can be used in matching up requests.
*
* @return string
*/
public function getIdentifier()
{
return 'implicit';
}
/**
* {@inheritdoc}
*/
public function respondToRequest(
ServerRequestInterface $request,
ResponseTypeInterface $responseType,
\DateInterval $accessTokenTTL
) {
$clientId = $this->getQueryStringParameter(
'client_id',
$request,
$this->getServerParameter('PHP_AUTH_USER', $request)
);
if (is_null($clientId)) {
throw OAuthServerException::invalidRequest('client_id');
}
$client = $this->clientRepository->getClientEntity(
$clientId,
$this->getIdentifier()
);
if ($client instanceof ClientEntityInterface === false) {
$this->getEmitter()->emit(new RequestEvent('client.authentication.failed', $request));
throw OAuthServerException::invalidClient();
}
$redirectUriParameter = $this->getQueryStringParameter('redirect_uri', $request, $client->getRedirectUri());
if ($redirectUriParameter !== $client->getRedirectUri()) {
$this->getEmitter()->emit(new RequestEvent('client.authentication.failed', $request));
throw OAuthServerException::invalidClient();
}
$scopes = $this->validateScopes(
$this->getQueryStringParameter('scope', $request),
$client,
$client->getRedirectUri()
);
$postbackUri = sprintf(
'//%s%s',
$request->getServerParams()['HTTP_HOST'],
$request->getServerParams()['REQUEST_URI']
);
$userId = null;
$userHasApprovedClient = null;
if ($this->getRequestParameter('action', $request, null) !== null) {
$userHasApprovedClient = ($this->getRequestParameter('action', $request) === 'approve');
}
// Check if the user has been authenticated
$oauthCookie = $this->getCookieParameter('oauth_authorize_request', $request, null);
if ($oauthCookie !== null) {
try {
$oauthCookiePayload = json_decode($this->decrypt($oauthCookie));
if (is_object($oauthCookiePayload)) {
$userId = $oauthCookiePayload->user_id;
}
} catch (\LogicException $e) {
throw OAuthServerException::serverError($e->getMessage());
}
}
// The username + password might be available in $_POST
$usernameParameter = $this->getRequestParameter('username', $request, null);
$passwordParameter = $this->getRequestParameter('password', $request, null);
$loginError = null;
// Assert if the user has logged in already
if ($userId === null && $usernameParameter !== null && $passwordParameter !== null) {
$userEntity = $this->userRepository->getUserEntityByUserCredentials(
$usernameParameter,
$passwordParameter,
$this->getIdentifier(),
$client
);
if ($userEntity instanceof UserEntityInterface) {
$userId = $userEntity->getIdentifier();
} else {
$loginError = 'Incorrect username or password';
}
}
// The user hasn't logged in yet so show a login form
if ($userId === null) {
$html = $this->getTemplateRenderer()->renderLogin([
'error' => $loginError,
'postback_uri' => $this->makeRedirectUri(
$postbackUri,
$request->getQueryParams()
),
]);
$htmlResponse = new HtmlResponse($this->accessTokenRepository);
$htmlResponse->setStatusCode(403);
$htmlResponse->setHtml($html);
return $htmlResponse;
}
// The user hasn't approved the client yet so show an authorize form
if ($userId !== null && $userHasApprovedClient === null) {
$html = $this->getTemplateRenderer()->renderAuthorize([
'client' => $client,
'scopes' => $scopes,
'postback_uri' => $this->makeRedirectUri(
$postbackUri,
$request->getQueryParams()
),
]);
$htmlResponse = new HtmlResponse($this->accessTokenRepository);
$htmlResponse->setStatusCode(200);
$htmlResponse->setHtml($html);
$htmlResponse->setHeader('set-cookie', sprintf(
'oauth_authorize_request=%s; Expires=%s',
urlencode($this->encrypt(
json_encode([
'user_id' => $userId,
])
)),
(new \DateTime())->add(new \DateInterval('PT5M'))->format('D, d M Y H:i:s e')
));
return $htmlResponse;
}
// The user has either approved or denied the client, so redirect them back
$redirectUri = $client->getRedirectUri();
$redirectPayload = [];
$stateParameter = $this->getQueryStringParameter('state', $request);
if ($stateParameter !== null) {
$redirectPayload['state'] = $stateParameter;
}
// THe user approved the client, redirect them back with an access token
if ($userHasApprovedClient === true) {
// Finalize the requested scopes
$scopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client, $userId);
$accessToken = $this->issueAccessToken(
$accessTokenTTL,
$client,
$userId,
$scopes
);
$redirectPayload['access_token'] = (string) $accessToken->convertToJWT($this->privateKeyPath);
$redirectPayload['token_type'] = 'bearer';
$redirectPayload['expires_in'] = time() - $accessToken->getExpiryDateTime()->getTimestamp();
$response = new RedirectResponse($this->accessTokenRepository);
$response->setRedirectUri(
$this->makeRedirectUri(
$redirectUri,
$redirectPayload,
'#'
)
);
return $response;
}
// The user denied the client, redirect them back with an error
throw OAuthServerException::accessDenied('The user denied the request', (string) $redirectUri);
}
}

View File

@@ -1,182 +1,110 @@
<?php
/**
* OAuth 2.0 Password grant
* OAuth 2.0 Password grant.
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Grant;
use League\OAuth2\Server\Entity\AccessTokenEntity;
use League\OAuth2\Server\Entity\ClientEntity;
use League\OAuth2\Server\Entity\RefreshTokenEntity;
use League\OAuth2\Server\Entity\SessionEntity;
use League\OAuth2\Server\Event;
use League\OAuth2\Server\Exception;
use League\OAuth2\Server\Util\SecureKey;
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
use League\OAuth2\Server\Entities\Interfaces\UserEntityInterface;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
use League\OAuth2\Server\RequestEvent;
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
use Psr\Http\Message\ServerRequestInterface;
/**
* Password grant class
* Password grant class.
*/
class PasswordGrant extends AbstractGrant
{
/**
* Grant identifier
*
* @var string
* @param \League\OAuth2\Server\Repositories\UserRepositoryInterface $userRepository
* @param \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface $refreshTokenRepository
*/
protected $identifier = 'password';
public function __construct(
UserRepositoryInterface $userRepository,
RefreshTokenRepositoryInterface $refreshTokenRepository
) {
$this->setUserRepository($userRepository);
$this->setRefreshTokenRepository($refreshTokenRepository);
/**
* Response type
*
* @var string
*/
protected $responseType;
/**
* Callback to authenticate a user's name and password
*
* @var callable
*/
protected $callback;
/**
* Access token expires in override
*
* @var int
*/
protected $accessTokenTTL;
/**
* Set the callback to verify a user's username and password
*
* @param callable $callback The callback function
*
* @return void
*/
public function setVerifyCredentialsCallback(callable $callback)
{
$this->callback = $callback;
$this->refreshTokenTTL = new \DateInterval('P1M');
}
/**
* Return the callback function
*
* @return callable
*
* @throws
* {@inheritdoc}
*/
protected function getVerifyCredentialsCallback()
{
if (is_null($this->callback) || !is_callable($this->callback)) {
throw new Exception\ServerErrorException('Null or non-callable callback set on Password grant');
}
public function respondToRequest(
ServerRequestInterface $request,
ResponseTypeInterface $responseType,
\DateInterval $accessTokenTTL
) {
// Validate request
$client = $this->validateClient($request);
$scopes = $this->validateScopes($this->getRequestParameter('scope', $request), $client);
$user = $this->validateUser($request, $client);
return $this->callback;
// Finalize the requested scopes
$scopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client, $user->getIdentifier());
// Issue and persist new tokens
$accessToken = $this->issueAccessToken($accessTokenTTL, $client, $user->getIdentifier(), $scopes);
$refreshToken = $this->issueRefreshToken($accessToken);
// Inject tokens into response
$responseType->setAccessToken($accessToken);
$responseType->setRefreshToken($refreshToken);
return $responseType;
}
/**
* Complete the password grant
* @param \Psr\Http\Message\ServerRequestInterface $request
* @param \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface $client
*
* @return array
* @throws \League\OAuth2\Server\Exception\OAuthServerException
*
* @throws
* @return \League\OAuth2\Server\Entities\Interfaces\UserEntityInterface
*/
public function completeFlow()
protected function validateUser(ServerRequestInterface $request, ClientEntityInterface $client)
{
// Get the required params
$clientId = $this->server->getRequest()->request->get('client_id', $this->server->getRequest()->getUser());
if (is_null($clientId)) {
throw new Exception\InvalidRequestException('client_id');
}
$clientSecret = $this->server->getRequest()->request->get('client_secret',
$this->server->getRequest()->getPassword());
if (is_null($clientSecret)) {
throw new Exception\InvalidRequestException('client_secret');
}
// Validate client ID and client secret
$client = $this->server->getClientStorage()->get(
$clientId,
$clientSecret,
null,
$this->getIdentifier()
);
if (($client instanceof ClientEntity) === false) {
$this->server->getEventEmitter()->emit(new Event\ClientAuthenticationFailedEvent($this->server->getRequest()));
throw new Exception\InvalidClientException();
}
$username = $this->server->getRequest()->request->get('username', null);
$username = $this->getRequestParameter('username', $request);
if (is_null($username)) {
throw new Exception\InvalidRequestException('username');
throw OAuthServerException::invalidRequest('username', '`%s` parameter is missing');
}
$password = $this->server->getRequest()->request->get('password', null);
$password = $this->getRequestParameter('password', $request);
if (is_null($password)) {
throw new Exception\InvalidRequestException('password');
throw OAuthServerException::invalidRequest('password', '`%s` parameter is missing');
}
// Check if user's username and password are correct
$userId = call_user_func($this->getVerifyCredentialsCallback(), $username, $password);
$user = $this->userRepository->getUserEntityByUserCredentials(
$username,
$password,
$this->getIdentifier(),
$client
);
if (!$user instanceof UserEntityInterface) {
$this->getEmitter()->emit(new RequestEvent('user.authentication.failed', $request));
if ($userId === false) {
$this->server->getEventEmitter()->emit(new Event\UserAuthenticationFailedEvent($this->server->getRequest()));
throw new Exception\InvalidCredentialsException();
throw OAuthServerException::invalidCredentials();
}
// Validate any scopes that are in the request
$scopeParam = $this->server->getRequest()->request->get('scope', '');
$scopes = $this->validateScopes($scopeParam, $client);
return $user;
}
// Create a new session
$session = new SessionEntity($this->server);
$session->setOwner('user', $userId);
$session->associateClient($client);
// Generate an access token
$accessToken = new AccessTokenEntity($this->server);
$accessToken->setId(SecureKey::generate());
$accessToken->setExpireTime($this->getAccessTokenTTL() + time());
// Associate scopes with the session and access token
foreach ($scopes as $scope) {
$session->associateScope($scope);
}
foreach ($session->getScopes() as $scope) {
$accessToken->associateScope($scope);
}
$this->server->getTokenType()->setSession($session);
$this->server->getTokenType()->setParam('access_token', $accessToken->getId());
$this->server->getTokenType()->setParam('expires_in', $this->getAccessTokenTTL());
// Associate a refresh token if set
if ($this->server->hasGrantType('refresh_token')) {
$refreshToken = new RefreshTokenEntity($this->server);
$refreshToken->setId(SecureKey::generate());
$refreshToken->setExpireTime($this->server->getGrantType('refresh_token')->getRefreshTokenTTL() + time());
$this->server->getTokenType()->setParam('refresh_token', $refreshToken->getId());
}
// Save everything
$session->save();
$accessToken->setSession($session);
$accessToken->save();
if ($this->server->hasGrantType('refresh_token')) {
$refreshToken->setAccessToken($accessToken);
$refreshToken->save();
}
return $this->server->getTokenType()->generateResponse();
/**
* {@inheritdoc}
*/
public function getIdentifier()
{
return 'password';
}
}

View File

@@ -1,193 +1,135 @@
<?php
/**
* OAuth 2.0 Refresh token grant
* OAuth 2.0 Refresh token grant.
*
* @package league/oauth2-server
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Grant;
use League\OAuth2\Server\Entity\AccessTokenEntity;
use League\OAuth2\Server\Entity\ClientEntity;
use League\OAuth2\Server\Entity\RefreshTokenEntity;
use League\OAuth2\Server\Event;
use League\OAuth2\Server\Exception;
use League\OAuth2\Server\Util\SecureKey;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
use League\OAuth2\Server\RequestEvent;
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
use Psr\Http\Message\ServerRequestInterface;
/**
* Referesh token grant
* Refresh token grant.
*/
class RefreshTokenGrant extends AbstractGrant
{
/**
* {@inheritdoc}
* @param \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface $refreshTokenRepository
*/
protected $identifier = 'refresh_token';
/**
* Refresh token TTL (default = 604800 | 1 week)
*
* @var integer
*/
protected $refreshTokenTTL = 604800;
/**
* Rotate token (default = true)
*
* @var integer
*/
protected $refreshTokenRotate = true;
/**
* Set the TTL of the refresh token
*
* @param int $refreshTokenTTL
*
* @return void
*/
public function setRefreshTokenTTL($refreshTokenTTL)
public function __construct(RefreshTokenRepositoryInterface $refreshTokenRepository)
{
$this->refreshTokenTTL = $refreshTokenTTL;
}
$this->setRefreshTokenRepository($refreshTokenRepository);
/**
* Get the TTL of the refresh token
*
* @return int
*/
public function getRefreshTokenTTL()
{
return $this->refreshTokenTTL;
}
/**
* Set the rotation boolean of the refresh token
* @param bool $refreshTokenRotate
*/
public function setRefreshTokenRotation($refreshTokenRotate = true)
{
$this->refreshTokenRotate = $refreshTokenRotate;
}
/**
* Get rotation boolean of the refresh token
*
* @return bool
*/
public function shouldRotateRefreshTokens()
{
return $this->refreshTokenRotate;
$this->refreshTokenTTL = new \DateInterval('P1M');
}
/**
* {@inheritdoc}
*/
public function completeFlow()
public function respondToRequest(
ServerRequestInterface $request,
ResponseTypeInterface $responseType,
\DateInterval $accessTokenTTL
) {
// Validate request
$client = $this->validateClient($request);
$oldRefreshToken = $this->validateOldRefreshToken($request, $client->getIdentifier());
$scopes = $this->validateScopes($this->getRequestParameter('scope', $request), $client);
// If no new scopes are requested then give the access token the original session scopes
if (count($scopes) === 0) {
$scopes = array_map(function ($scopeId) use ($client) {
$scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeId);
if (!$scope) {
// @codeCoverageIgnoreStart
throw OAuthServerException::invalidScope($scopeId);
// @codeCoverageIgnoreEnd
}
return $scope;
}, $oldRefreshToken['scopes']);
} else {
// The OAuth spec says that a refreshed access token can have the original scopes or fewer so ensure
// the request doesn't include any new scopes
foreach ($scopes as $scope) {
if (in_array($scope->getIdentifier(), $oldRefreshToken['scopes']) === false) {
throw OAuthServerException::invalidScope($scope->getIdentifier());
}
}
}
// Expire old tokens
$this->accessTokenRepository->revokeAccessToken($oldRefreshToken['access_token_id']);
$this->refreshTokenRepository->revokeRefreshToken($oldRefreshToken['refresh_token_id']);
// Issue and persist new tokens
$accessToken = $this->issueAccessToken($accessTokenTTL, $client, $oldRefreshToken['user_id'], $scopes);
$refreshToken = $this->issueRefreshToken($accessToken);
// Inject tokens into response
$responseType->setAccessToken($accessToken);
$responseType->setRefreshToken($refreshToken);
return $responseType;
}
/**
* @param \Psr\Http\Message\ServerRequestInterface $request
* @param string $clientId
*
* @throws \League\OAuth2\Server\Exception\OAuthServerException
*
* @return array
*/
protected function validateOldRefreshToken(ServerRequestInterface $request, $clientId)
{
$clientId = $this->server->getRequest()->request->get('client_id', $this->server->getRequest()->getUser());
if (is_null($clientId)) {
throw new Exception\InvalidRequestException('client_id');
}
$clientSecret = $this->server->getRequest()->request->get('client_secret',
$this->server->getRequest()->getPassword());
if (is_null($clientSecret)) {
throw new Exception\InvalidRequestException('client_secret');
}
// Validate client ID and client secret
$client = $this->server->getClientStorage()->get(
$clientId,
$clientSecret,
null,
$this->getIdentifier()
);
if (($client instanceof ClientEntity) === false) {
$this->server->getEventEmitter()->emit(new Event\ClientAuthenticationFailedEvent($this->server->getRequest()));
throw new Exception\InvalidClientException();
}
$oldRefreshTokenParam = $this->server->getRequest()->request->get('refresh_token', null);
if ($oldRefreshTokenParam === null) {
throw new Exception\InvalidRequestException('refresh_token');
$encryptedRefreshToken = $this->getRequestParameter('refresh_token', $request);
if (is_null($encryptedRefreshToken)) {
throw OAuthServerException::invalidRequest('refresh_token');
}
// Validate refresh token
$oldRefreshToken = $this->server->getRefreshTokenStorage()->get($oldRefreshTokenParam);
if (($oldRefreshToken instanceof RefreshTokenEntity) === false) {
throw new Exception\InvalidRefreshException();
try {
$refreshToken = $this->decrypt($encryptedRefreshToken);
} catch (\LogicException $e) {
throw OAuthServerException::invalidRefreshToken('Cannot parse refresh token: ' . $e->getMessage());
}
// Ensure the old refresh token hasn't expired
if ($oldRefreshToken->isExpired() === true) {
throw new Exception\InvalidRefreshException();
$refreshTokenData = json_decode($refreshToken, true);
if ($refreshTokenData['client_id'] !== $clientId) {
$this->getEmitter()->emit(new RequestEvent('refresh_token.client.failed', $request));
throw OAuthServerException::invalidRefreshToken(
'Token is not linked to client,' .
' got: ' . $clientId .
' expected: ' . $refreshTokenData['client_id']
);
}
$oldAccessToken = $oldRefreshToken->getAccessToken();
// Get the scopes for the original session
$session = $oldAccessToken->getSession();
$scopes = $this->formatScopes($session->getScopes());
// Get and validate any requested scopes
$requestedScopesString = $this->server->getRequest()->request->get('scope', '');
$requestedScopes = $this->validateScopes($requestedScopesString, $client);
// If no new scopes are requested then give the access token the original session scopes
if (count($requestedScopes) === 0) {
$newScopes = $scopes;
} else {
// The OAuth spec says that a refreshed access token can have the original scopes or fewer so ensure
// the request doesn't include any new scopes
foreach ($requestedScopes as $requestedScope) {
if (!isset($scopes[$requestedScope->getId()])) {
throw new Exception\InvalidScopeException($requestedScope->getId());
}
}
$newScopes = $requestedScopes;
if ($refreshTokenData['expire_time'] < time()) {
throw OAuthServerException::invalidRefreshToken('Token has expired');
}
// Generate a new access token and assign it the correct sessions
$newAccessToken = new AccessTokenEntity($this->server);
$newAccessToken->setId(SecureKey::generate());
$newAccessToken->setExpireTime($this->getAccessTokenTTL() + time());
$newAccessToken->setSession($session);
foreach ($newScopes as $newScope) {
$newAccessToken->associateScope($newScope);
if ($this->refreshTokenRepository->isRefreshTokenRevoked($refreshTokenData['refresh_token_id']) === true) {
throw OAuthServerException::invalidRefreshToken('Token has been revoked');
}
// Expire the old token and save the new one
$oldAccessToken->expire();
$newAccessToken->save();
return $refreshTokenData;
}
$this->server->getTokenType()->setSession($session);
$this->server->getTokenType()->setParam('access_token', $newAccessToken->getId());
$this->server->getTokenType()->setParam('expires_in', $this->getAccessTokenTTL());
if ($this->shouldRotateRefreshTokens()) {
// Expire the old refresh token
$oldRefreshToken->expire();
// Generate a new refresh token
$newRefreshToken = new RefreshTokenEntity($this->server);
$newRefreshToken->setId(SecureKey::generate());
$newRefreshToken->setExpireTime($this->getRefreshTokenTTL() + time());
$newRefreshToken->setAccessToken($newAccessToken);
$newRefreshToken->save();
$this->server->getTokenType()->setParam('refresh_token', $newRefreshToken->getId());
} else {
$this->server->getTokenType()->setParam('refresh_token', $oldRefreshToken->getId());
}
return $this->server->getTokenType()->generateResponse();
/**
* {@inheritdoc}
*/
public function getIdentifier()
{
return 'refresh_token';
}
}

View File

@@ -0,0 +1,51 @@
<?php
namespace League\OAuth2\Server\Middleware;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Server;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class AuthenticationServerMiddleware
{
/**
* @var \League\OAuth2\Server\Server
*/
private $server;
/**
* AuthenticationServerMiddleware constructor.
*
* @param \League\OAuth2\Server\Server $server
*/
public function __construct(Server $server)
{
$this->server = $server;
}
/**
* @param \Psr\Http\Message\ServerRequestInterface $request
* @param \Psr\Http\Message\ResponseInterface $response
* @param callable $next
*
* @return \Psr\Http\Message\ResponseInterface
*/
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next)
{
try {
$response = $this->server->respondToRequest($request, $response);
} catch (OAuthServerException $exception) {
return $exception->generateHttpResponse($response);
// @codeCoverageIgnoreStart
} catch (\Exception $exception) {
$response->getBody()->write($exception->getMessage());
return $response->withStatus(500);
// @codeCoverageIgnoreEnd
}
// Pass the request and response on to the next responder in the chain
return $next($request, $response);
}
}

View File

@@ -0,0 +1,51 @@
<?php
namespace League\OAuth2\Server\Middleware;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Server;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class ResourceServerMiddleware
{
/**
* @var \League\OAuth2\Server\Server
*/
private $server;
/**
* ResourceServerMiddleware constructor.
*
* @param \League\OAuth2\Server\Server $server
*/
public function __construct(Server $server)
{
$this->server = $server;
}
/**
* @param \Psr\Http\Message\ServerRequestInterface $request
* @param \Psr\Http\Message\ResponseInterface $response
* @param callable $next
*
* @return \Psr\Http\Message\ResponseInterface
*/
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next)
{
try {
$request = $this->server->validateAuthenticatedRequest($request);
} catch (OAuthServerException $exception) {
return $exception->generateHttpResponse($response);
// @codeCoverageIgnoreStart
} catch (\Exception $exception) {
$response->getBody()->write($exception->getMessage());
return $response->withStatus(500);
// @codeCoverageIgnoreEnd
}
// Pass the request and response on to the next responder in the chain
return $next($request, $response);
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* OAuth 2.0 Access token storage interface.
*
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Repositories;
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
/**
* Access token interface.
*/
interface AccessTokenRepositoryInterface extends RepositoryInterface
{
/**
* Persists a new access token to permanent storage.
*
* @param \League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface $accessTokenEntity
*/
public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity);
/**
* Revoke an access token.
*
* @param string $tokenId
*/
public function revokeAccessToken($tokenId);
/**
* Check if the access token has been revoked.
*
* @param string $tokenId
*
* @return bool Return true if this token has been revoked
*/
public function isAccessTokenRevoked($tokenId);
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* OAuth 2.0 Auth code storage interface.
*
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Repositories;
use League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface;
/**
* Auth code storage interface.
*/
interface AuthCodeRepositoryInterface extends RepositoryInterface
{
/**
* Persists a new auth code to permanent storage.
*
* @param \League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface $authCodeEntity
*/
public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity);
/**
* Revoke an auth code.
*
* @param string $codeId
*/
public function revokeAuthCode($codeId);
/**
* Check if the auth code has been revoked.
*
* @param string $codeId
*
* @return bool Return true if this code has been revoked
*/
public function isAuthCodeRevoked($codeId);
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* OAuth 2.0 Client storage interface.
*
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Repositories;
/**
* Client storage interface.
*/
interface ClientRepositoryInterface extends RepositoryInterface
{
/**
* Get a client.
*
* @param string $clientIdentifier The client's identifier
* @param string $grantType The grant type used
* @param null|string $clientSecret The client's secret (if sent)
*
* @return \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface
*/
public function getClientEntity($clientIdentifier, $grantType, $clientSecret = null);
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* OAuth 2.0 MAC Token Interface.
*
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Storage;
use League\OAuth2\Server\Repositories\RepositoryInterface;
/**
* MacTokenInterface.
*/
interface MacTokenInterface extends RepositoryInterface
{
/**
* Create a MAC key linked to an access token.
*
* @param string $macKey
* @param string $accessToken
*/
public function persistMacTokenEntity($macKey, $accessToken);
/**
* Get a MAC key by access token.
*
* @param string $accessToken
*
* @return string
*/
public function getMacKeyByAccessTokenString($accessToken);
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* OAuth 2.0 Refresh token storage interface.
*
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace League\OAuth2\Server\Repositories;
use League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface;
/**
* Refresh token interface.
*/
interface RefreshTokenRepositoryInterface extends RepositoryInterface
{
/**
* Create a new refresh token_name.
*
* @param \League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface $refreshTokenEntity
*/
public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntity);
/**
* Revoke the refresh token.
*
* @param string $tokenId
*/
public function revokeRefreshToken($tokenId);
/**
* Check if the refresh token has been revoked.
*
* @param string $tokenId
*
* @return bool Return true if this token has been revoked
*/
public function isRefreshTokenRevoked($tokenId);
}

Some files were not shown because too many files have changed in this diff Show More