Compare commits

...

223 Commits

Author SHA1 Message Date
Alex Bilbie
6b18a9441a Updated changelog 2016-05-04 09:13:20 +01:00
Alex Bilbie
44ff7b33a1 Merge branch 'master' of github.com:thephpleague/oauth2-server 2016-05-04 09:10:11 +01:00
Alex Bilbie
db055f790d Revert "Remove redundant parameters in example" #553
This reverts commit 9a93dca05c.
2016-05-04 09:10:05 +01:00
Alex Bilbie
d1bc4848c8 Revert "Remove redundant parameters in example"
This reverts commit 9a93dca05c.
2016-05-04 09:07:50 +01:00
Alex Bilbie
cf63403585 Merge branch 'master' of github.com:thephpleague/oauth2-server 2016-05-04 08:56:04 +01:00
Alex Bilbie
cdf43e498e Use constant for event name instead of explicit string. Fixes #563 2016-05-04 08:55:57 +01:00
Alex Bilbie
a12fc98b0d Merge pull request #569 from ismailbaskin/patch-2
Correct wrong phpdoc
2016-05-04 08:45:58 +01:00
Alex Bilbie
019d285235 Merge pull request #570 from Themodem/master
Fixed typo in exception string
2016-05-04 08:45:37 +01:00
Lee
0bb968f413 Fixed typo in exception string 2016-05-04 15:13:48 +08:00
ismail BASKIN
88b19ad2d0 Correct wrong phpdoc 2016-05-04 00:54:36 +03:00
Alex Bilbie
6856699cab Merge pull request #564 from ismailbaskin/patch-1
Remove unused request property
2016-04-30 12:16:12 +01:00
ismail BASKIN
72cd9a62e1 Remove unused request property 2016-04-30 05:08:28 +03:00
Alex Bilbie
acf262f879 Merge pull request #553 from markinjapan/patch-1
Remove redundant parameters in getNewToken()
2016-04-27 20:58:29 +01:00
Alex Bilbie
5241309bdb Fixes #560 2016-04-27 20:53:12 +01:00
Mark
9a93dca05c Remove redundant parameters in example 2016-04-20 16:52:54 +09:00
Mark
a6b7a5cedc Remove use of redundant parameters 2016-04-20 16:52:36 +09:00
Mark
78b6bddc4d Remove redundant parameters 2016-04-20 16:29:37 +09:00
Alex Bilbie
14b6761c0f Changelog update 2016-04-19 10:28:20 +01:00
Alex Bilbie
7c61922f07 Merge pull request #551 from ivyhjk/patch-1
wrong comment "month"
2016-04-19 09:53:17 +01:00
ivyhjk
20535ad95b wrong comment "month" 2016-04-18 18:08:27 -03:00
Alex Bilbie
e885114714 Improved examples 2016-04-18 12:23:21 +01:00
Alex Bilbie
f80d0d39a4 Updated .scrutenizer.yml 2016-04-18 12:23:13 +01:00
Alex Bilbie
7bfd5b7d0d Added abstract methods for required methods 2016-04-18 12:22:15 +01:00
Alex Bilbie
143a2e32f7 Client may return an array of redirect URIs 2016-04-18 12:21:42 +01:00
Alex Bilbie
8f418cff08 Added missing state parameter in redirect response 2016-04-18 12:19:54 +01:00
Alex Bilbie
fcec1f3442 Cody tidy 2016-04-18 12:19:36 +01:00
Alex Bilbie
46e7eef14e Client could potentially return an array of redirect URIs 2016-04-18 12:12:36 +01:00
Alex Bilbie
51f44fdf17 Code tidy 2016-04-18 12:12:06 +01:00
Alex Bilbie
f8b2e80ef3 Removed unnecessary parameter usage 2016-04-18 12:10:57 +01:00
Alex Bilbie
7045785d89 Spelling fix 2016-04-18 08:41:00 +01:00
Alex Bilbie
301ddc53c7 Updated changelog 2016-04-18 08:40:34 +01:00
Alex Bilbie
2a6f900323 Updated examples 2016-04-18 08:32:58 +01:00
Alex Bilbie
fb8f47e868 Added $mustValidateSecret parameter to ClientRepositoryInterface:: getClientEntity(). Fixes #550 2016-04-18 08:32:49 +01:00
Alex Bilbie
5b192b3548 Updated README 2016-04-17 13:32:20 +01:00
Alex Bilbie
bf55ce1f73 Merge branch 'V5-WIP'
Conflicts:
	.travis.yml
	CHANGELOG.md
	composer.json
	examples/relational/Storage/AccessTokenStorage.php
	examples/relational/api.php
	src/AbstractServer.php
	src/AuthorizationServer.php
	src/Entity/AuthCodeEntity.php
	src/Exception/InvalidGrantException.php
	src/Exception/InvalidRequestException.php
	src/Exception/InvalidScopeException.php
	src/Exception/OAuthException.php
	src/Exception/ServerErrorException.php
	src/Exception/UnsupportedGrantTypeException.php
	src/Exception/UnsupportedResponseTypeException.php
	src/Grant/AuthCodeGrant.php
	src/Grant/RefreshTokenGrant.php
	src/ResourceServer.php
	src/Storage/AccessTokenInterface.php
	src/Storage/AuthCodeInterface.php
	src/Storage/ClientInterface.php
	src/Storage/RefreshTokenInterface.php
	src/Storage/ScopeInterface.php
	src/Storage/SessionInterface.php
	src/TokenType/Bearer.php
	src/TokenType/MAC.php
	tests/unit/Grant/RefreshTokenGrantTest.php
	tests/unit/TokenType/MacTest.php
2016-04-17 13:21:22 +01:00
Alex Bilbie
4942585f4f Updated changelog 2016-04-17 13:18:12 +01:00
Alex Bilbie
1575128162 Merge pull request #549 from thephpleague/analysis-8L3Emw
Applied fixes from StyleCI
2016-04-17 13:07:29 +01:00
Alex Bilbie
78c2067698 Merge pull request #548 from thephpleague/analysis-z9mQxo
Applied fixes from StyleCI
2016-04-17 13:07:15 +01:00
Alex Bilbie
f765f134c9 Applied fixes from StyleCI 2016-04-17 08:07:03 -04:00
Alex Bilbie
257318e524 Merge pull request #547 from lookyman/scope-fixes
Fix scope loading in grants
2016-04-17 13:06:57 +01:00
Alex Bilbie
77737e7894 Applied fixes from StyleCI 2016-04-17 08:06:17 -04:00
Alex Bilbie
f007e25070 Added copyright docblocks 2016-04-17 13:06:05 +01:00
Alex Bilbie
25c2e9b31b Code tidy client_credentials 2016-04-17 13:00:49 +01:00
Alex Bilbie
6ed9cbf701 Class rename fixes 2016-04-17 12:54:49 +01:00
Alex Bilbie
7c35778316 Added tests for resource server middleware 2016-04-17 12:54:39 +01:00
Alex Bilbie
f6f39698d9 Renamed Server to AuthorizationServer 2016-04-17 12:54:25 +01:00
Lukáš Unger
3904767873 Fix scope loading in grants 2016-04-17 13:50:56 +02:00
Alex Bilbie
c3a7c418da Updated composer.json 2016-04-17 12:43:25 +01:00
Alex Bilbie
af5a06098b Removed --no-dev statement 2016-04-17 12:43:13 +01:00
Alex Bilbie
6205611a71 Removed unused methods 2016-04-17 12:42:42 +01:00
Alex Bilbie
9f3648039b Use resource server instead 2016-04-17 12:41:28 +01:00
Alex Bilbie
08c356a1e1 Added ResourceServer class 2016-04-17 12:33:29 +01:00
Alex Bilbie
70e32ce9bf Updated changelog 2016-04-17 12:23:38 +01:00
Alex Bilbie
94a1c18fa9 Implict grant does not return return refresh tokens 2016-04-17 12:12:49 +01:00
Alex Bilbie
88b01b792a Clarified example 2016-04-12 20:23:05 +01:00
Alex Bilbie
0178a837d4 Merge pull request #538 from lucadegasperi/patch-4
Update AbstractGrant.php
2016-04-11 15:28:26 +01:00
Alex Bilbie
2025bd6a30 Merge pull request #540 from vinkla/patch-2
Allow phpunit 5.0
2016-04-11 15:28:13 +01:00
Alex Bilbie
e7f18911f3 Merge pull request #539 from vinkla/patch-1
Add 5.5.9 to travis
2016-04-11 15:27:47 +01:00
Vincent Klaiber
8e8ac35dcb Allow phpunit 5.0
We can allow phpunit 5.0
2016-04-11 16:23:24 +02:00
Vincent Klaiber
16ed4ea51c Add 5.5.9 to travis
We should test against 5.5.9 as well since that is the lowest requirement.
2016-04-11 16:22:20 +02:00
Luca Degasperi
de635f826f Update AbstractGrant.php
The hint is not necessary since it gets created by the exception with the parameter.
2016-04-11 15:59:47 +02:00
Alex Bilbie
3e8577f889 Merge pull request #536 from Bobselp/V5-WIP
less verbose exceptions for RefreshTokenGrant
2016-04-11 08:24:31 +01:00
Alex Bilbie
525b9b3d3e Merge pull request #537 from ivyhjk/V5-WIP
Update refresh token expire_time
2016-04-11 08:24:07 +01:00
ivyhjk
f7413c2f15 Update BearerTokenResponse.php 2016-04-10 19:05:32 -03:00
Bobselp
6e583fdf8a less verbose exceptions for RefreshTokenGrant
For the LogicException you could also use `throw OAuthServerException::invalidRequest('refresh_token', 'Cannot decrypt the authorization code');`, to get the exact same error AuthCodeGrant-php throws if decryption of `code` fails there.
The second error hint provides information which doesn't help users of the API, although it is next to impossible to trigger this error due to the encryption.
2016-04-10 22:19:42 +02:00
Alex Bilbie
f9bde23799 Merge pull request #535 from thephpleague/analysis-z4xGnw
Applied fixes from StyleCI
2016-04-10 17:18:01 +01:00
Alex Bilbie
2328f59601 Applied fixes from StyleCI 2016-04-10 12:16:40 -04:00
Alex Bilbie
103b0cc50d Fixed broken test 2016-04-10 17:15:48 +01:00
Bobselp
eb7526ae97 finalize scopes for AuthCodeGrant 2016-04-10 18:07:18 +02:00
Bobselp
03e8eb6157 revoke an used auth code 2016-04-10 18:05:16 +02:00
Alex Bilbie
7b803365f9 Updated links 2016-04-10 16:31:55 +01:00
Alex Bilbie
204706f1ff Updated README 2016-04-10 16:31:05 +01:00
Alex Bilbie
4c6dab3f55 openssl extension requirement added 2016-04-10 16:28:54 +01:00
Alex Bilbie
54bedda11b Merge branch 'V5-WIP' of github.com:thephpleague/oauth2-server into V5-WIP 2016-04-10 16:27:17 +01:00
Alex Bilbie
883ba8b573 Updated changelog 2016-04-10 16:27:07 +01:00
Alex Bilbie
0d1e61422a Merge pull request #533 from thephpleague/analysis-qorbl5
Applied fixes from StyleCI
2016-04-10 16:21:28 +01:00
Alex Bilbie
a722659200 Applied fixes from StyleCI 2016-04-10 11:20:06 -04:00
Alex Bilbie
a80310b01c Merge branch 'V5-authorization-request-flow' of github.com:thephpleague/oauth2-server into V5-authorization-request-flow 2016-04-10 16:15:35 +01:00
Alex Bilbie
c017b59342 Removed dead code 2016-04-10 16:15:26 +01:00
Alex Bilbie
920c0c296a Merge pull request #530 from thephpleague/analysis-Xkab1a
Applied fixes from StyleCI
2016-04-10 16:15:06 +01:00
Alex Bilbie
b0db04461f Merge pull request #531 from thephpleague/analysis-8m4bQ1
Applied fixes from StyleCI
2016-04-10 16:14:55 +01:00
Alex Bilbie
495b55d1e8 Applied fixes from StyleCI 2016-04-10 11:14:08 -04:00
Alex Bilbie
92a483b3bd Improved tests 2016-04-10 16:14:01 +01:00
Alex Bilbie
6083870603 Applied fixes from StyleCI 2016-04-10 10:58:33 -04:00
Alex Bilbie
6359535e32 Updated examples composer requirements 2016-04-10 15:58:23 +01:00
Alex Bilbie
5969082963 Fix tests and improve code coverate 2016-04-10 15:58:01 +01:00
Alex Bilbie
7a6d9a4510 Fixed broken AuthCodeGrant tests 2016-04-10 15:15:29 +01:00
Alex Bilbie
7c86d3b848 Merge branch 'V5-authorization-request-flow' of github.com:thephpleague/oauth2-server into V5-authorization-request-flow 2016-04-10 14:31:25 +01:00
Alex Bilbie
d3a7b442ce Updated implicit grant example 2016-04-10 14:31:21 +01:00
Alex Bilbie
ba30e34511 Lazy set $accessTokenTTL 2016-04-10 14:31:05 +01:00
Alex Bilbie
e24dff2723 Fixed expires_in 2016-04-10 14:30:44 +01:00
Alex Bilbie
625876f7ae Merge pull request #528 from thephpleague/analysis-qrdb5g
Applied fixes from StyleCI
2016-04-10 14:23:38 +01:00
Alex Bilbie
4f2dfc20b9 Merge pull request #527 from thephpleague/analysis-Xpeb42
Applied fixes from StyleCI
2016-04-10 14:23:28 +01:00
Alex Bilbie
1512960d92 Applied fixes from StyleCI 2016-04-10 09:23:10 -04:00
Alex Bilbie
273ea0ba68 Updated implicit grant to use the new auth request flow 2016-04-10 14:22:56 +01:00
Alex Bilbie
096a4a2883 Remove unused params 2016-04-10 14:22:32 +01:00
Alex Bilbie
a68f07f734 Applied fixes from StyleCI 2016-04-10 08:53:54 -04:00
Alex Bilbie
a0c4900ee7 Client is not required here because of finalizeScopes method 2016-04-10 13:53:16 +01:00
Alex Bilbie
4c0c10ae98 HTTPS link 2016-04-10 13:49:25 +01:00
Alex Bilbie
0fb0100088 Merge branch 'V5-authorization-request-flow' of github.com:thephpleague/oauth2-server into V5-authorization-request-flow 2016-04-10 13:26:37 +01:00
Alex Bilbie
8f50e58ba9 Remove templating packages 2016-04-10 13:26:31 +01:00
Alex Bilbie
8225b4e697 OpenSSL extension is required by lcobucci/jwt 2016-04-10 13:26:01 +01:00
Alex Bilbie
236a3a0358 Merge pull request #525 from thephpleague/analysis-864kdl
Applied fixes from StyleCI
2016-04-10 11:56:53 +01:00
Alex Bilbie
b00a4e169e Merge pull request #526 from thephpleague/analysis-zOM7lk
Applied fixes from StyleCI
2016-04-10 11:56:43 +01:00
Alex Bilbie
c034c3b13c Merge pull request #524 from thephpleague/analysis-qJ2LoW
Applied fixes from StyleCI
2016-04-10 11:56:33 +01:00
Alex Bilbie
287c371586 Applied fixes from StyleCI 2016-04-10 06:56:21 -04:00
Alex Bilbie
634578997f Merge pull request #523 from thephpleague/analysis-XajbB0
Applied fixes from StyleCI
2016-04-10 11:56:17 +01:00
Alex Bilbie
b8c5056c31 Applied fixes from StyleCI 2016-04-10 06:55:24 -04:00
Alex Bilbie
79aa1988d8 Removed HtmlResponse 2016-04-10 11:55:17 +01:00
Alex Bilbie
7c35985c1e Applied fixes from StyleCI 2016-04-10 06:52:27 -04:00
Alex Bilbie
c75d0e0f0e Removed templating code 2016-04-10 11:52:18 +01:00
Alex Bilbie
5d3516c7b4 Applied fixes from StyleCI 2016-04-10 06:48:46 -04:00
Alex Bilbie
d4fb00628e Updated server methods 2016-04-10 11:48:32 +01:00
Alex Bilbie
4bc835c007 Updated AuthCodeGrant with new methods to validate and complete an authorization request 2016-04-10 11:48:21 +01:00
Alex Bilbie
fdb1d70874 Updated header key 2016-04-10 11:47:41 +01:00
Alex Bilbie
6f71a2d178 Remove unnecessary call 2016-04-10 11:47:28 +01:00
Alex Bilbie
651709b70f Added helper methods 2016-04-10 11:47:15 +01:00
Alex Bilbie
3f6e91575d Updated auth code example 2016-04-10 11:47:09 +01:00
Alex Bilbie
8f5e0ce9f7 Update example composer 2016-04-10 11:45:59 +01:00
Alex Bilbie
5410a42bb6 Fix to broken methods 2016-04-10 10:28:12 +01:00
Alex Bilbie
b7064befe4 Checkin 2016-04-10 10:07:08 +01:00
Alex Bilbie
44937f3600 Updated method calls 2016-04-09 16:22:22 +01:00
Alex Bilbie
76ea6b5a6c Renamed grant type canRespondToRequest to canRespondToAccessTokenRequest 2016-04-09 16:22:00 +01:00
Alex Bilbie
4689802c30 Renamed server respondToRequest to respondToAccessTokenRequest 2016-04-09 16:20:30 +01:00
Alex Bilbie
6ee71754c4 Merge pull request #520 from thephpleague/analysis-qgObld
Applied fixes from StyleCI
2016-04-09 15:47:53 +01:00
Alex Bilbie
b3329dbeac Merge pull request #521 from thephpleague/analysis-z3wZr5
Applied fixes from StyleCI
2016-04-09 15:47:41 +01:00
Alex Bilbie
0ca2511d1e Applied fixes from StyleCI 2016-04-09 10:46:46 -04:00
Alex Bilbie
2c2ef800d4 Applied fixes from StyleCI 2016-04-09 10:46:40 -04:00
Alex Bilbie
d8d49f742e Removed unnecessary abstract classes 2016-04-09 15:46:30 +01:00
Alex Bilbie
e758121458 Merge branch 'V5-WIP' of github.com:thephpleague/oauth2-server into V5-WIP 2016-04-09 15:44:42 +01:00
Alex Bilbie
47656cd9b5 Fix broken tests 2016-04-09 15:44:38 +01:00
Alex Bilbie
b59106dc64 Added ClientTrait 2016-04-09 15:27:44 +01:00
Alex Bilbie
c6faa228fe Updated references to interfaces 2016-04-09 15:25:45 +01:00
Alex Bilbie
4eee48ca4e Moved entity interfaces into parent folder. Fixes #504 2016-04-09 15:25:32 +01:00
Alex Bilbie
00518dded7 Removed built-in entities, all functinality available using traits 2016-04-09 15:21:15 +01:00
Alex Bilbie
3615cbeedf Merge pull request #517 from thephpleague/analysis-8L3eKK
Applied fixes from StyleCI
2016-04-09 15:20:26 +01:00
Alex Bilbie
6773db66c6 Applied fixes from StyleCI 2016-04-09 10:19:40 -04:00
Alex Bilbie
5ca2152313 Updated examples 2016-04-09 15:17:11 +01:00
Alex Bilbie
5cba35456f Updated access token repository example 2016-04-09 15:09:22 +01:00
Alex Bilbie
be9bd76f35 Added AccessTokenTrait 2016-04-09 15:09:13 +01:00
Alex Bilbie
3c0a7f14ab Fixed broken tests 2016-04-09 14:15:10 +01:00
Alex Bilbie
198f4c4b6f Merge branch 'token_from_repo' of https://github.com/frederikbosch/oauth2-server into frederikbosch-token_from_repo
# Conflicts:
#	tests/Grant/AuthCodeGrantTest.php
#	tests/Grant/ImplicitGrantTest.php
#	tests/Grant/RefreshTokenGrantTest.php
2016-04-09 14:12:06 +01:00
Alex Bilbie
6f0a0cca4e Merge pull request #498 from frederikbosch/client_user_id_replaced
Client identifier passed where user identifier is expected
2016-04-09 13:55:16 +01:00
Alex Bilbie
5430ddb230 Merge pull request #516 from thephpleague/analysis-8jLba7
Applied fixes from StyleCI
2016-04-09 13:54:13 +01:00
Alex Bilbie
1ccfd9be32 Applied fixes from StyleCI 2016-04-09 08:53:29 -04:00
Alex Bilbie
a83c56f570 Comment improvement 2016-04-09 13:53:14 +01:00
Alex Bilbie
d7dd07cf18 Merge branch 'v5-fix' of https://github.com/assembledadam/oauth2-server into assembledadam-v5-fix 2016-04-09 13:51:57 +01:00
Alex Bilbie
0fed56a265 Merge branch 'V5-WIP' of https://github.com/frederikbosch/oauth2-server into frederikbosch-V5-WIP
# Conflicts:
#	src/Entities/Interfaces/ClientEntityInterface.php
2016-04-09 13:48:53 +01:00
Alex Bilbie
fc9e912e06 Fixed broken test 2016-04-09 13:45:38 +01:00
Alex Bilbie
39281a6f38 Merge branch 'repository_on_response' of https://github.com/juliangut/oauth2-server into juliangut-repository_on_response
# Conflicts:
#	tests/ResponseTypes/BearerResponseTypeTest.php
2016-04-09 13:43:33 +01:00
Alex Bilbie
656a8d7a56 Merge pull request #502 from juliangut/passphrase
V5 - Handle RSA key passphrase
2016-04-09 13:40:28 +01:00
Alex Bilbie
6c942f25f4 Merge pull request #503 from juliangut/mac_token_interface
V5 - Remove unused mac token interface
2016-04-09 13:37:54 +01:00
Alex Bilbie
8274c56fc2 Allow multiple client redirect URIs. Fixes #511 2016-04-09 13:36:08 +01:00
Frederik Bosch
de8f6ff539 add getNewAccessToken getNewRefreshToken and getNewAuthCode to repositories 2016-04-04 10:37:06 +02:00
Adam McCann
8f69f4f9a9 Access denied on token expiry (or value before nbf/not before) - issue #506 2016-03-31 18:50:36 +01:00
Julián Gutiérrez
4d2ccac8ed remove unused mac token interface 2016-03-29 09:31:34 +02:00
Julián Gutiérrez
a38b7f97f9 include keys in Server tests 2016-03-28 17:10:41 +02:00
Julián Gutiérrez
197657f2b9 handle RSA key passphrase 2016-03-28 16:42:34 +02:00
Julián Gutiérrez
e513b42117 remove access token repository from response types 2016-03-28 12:10:51 +02:00
Frederik Bosch
b1ce1f872b client identifier passed where user identifier is expected 2016-03-25 17:11:13 +01:00
Alex Bilbie
1de13cf892 Removed .travis.yml after_build stuff 2016-03-24 19:30:14 +00:00
Frederik Bosch
d8e1e0e00e remove unnecessary methods from interfaces 2016-03-24 15:01:55 +01:00
Alex Bilbie
1ad44d1ce0 Merge pull request #483 from mikicaivosevic/master
Bug fix
2016-03-23 11:27:41 +00:00
Mikica Ivosevic
b480373249 bug fix 2016-03-23 12:08:45 +01:00
Alex Bilbie
3ad97b4ef4 Merge pull request #434 from bitExpert/fix/getScopeDelimiterDockblock
Docblock stated that "," is the default scope delimiter but it is " ".
2016-01-20 11:33:36 +00:00
Stephan Hochdörfer
0490736861 Docblock stated that "," is the default scope delimiter but it is " ". 2016-01-18 22:37:39 +01:00
Alex Bilbie
abaf399f5f Merge pull request #429 from Bobselp/master
Add MAC Authentication to OAuthException->getHttpHeaders
2016-01-17 14:57:45 +00:00
Bobselp
55c8df8312 fix for thephpleague/oauth2-server#389 2016-01-17 15:50:34 +01:00
Alex Bilbie
c5db707e69 Updated changelog 2016-01-04 19:56:12 +00:00
Alex Bilbie
ed7f78179a Merge pull request #412 from derrabus/symfony-3
Allow Symfony 3.0
2015-12-20 20:38:02 +00:00
Alexander M. Turek
6e92239dd7 Allow Symfony 3.0. 2015-12-11 15:24:13 +01:00
Alex Bilbie
f5d731def9 Updated changelog 2015-11-13 17:52:27 +00:00
Alex Bilbie
03815cec6d Merge pull request #388 from m4tthumphrey/master
Added priority argument
2015-10-13 11:21:52 +01:00
Matt Humphrey
c71dc47459 Added priority argument 2015-10-13 11:16:49 +01:00
Alex Bilbie
3bcd8fc3f8 Removed runs and increased timeout 2015-09-26 11:26:17 +01:00
Alex Bilbie
db6d4e0dc6 Only send data to Scrutinizer only for PHP 5.6 2015-09-26 11:25:26 +01:00
Alex Bilbie
f19189a999 Merge pull request #345 from mpipet/master
Expose parameter passed to exceptions
2015-09-04 08:38:35 +01:00
Alex Bilbie
ec9c91cc11 Update .scrutinizer.yml 2015-09-04 08:37:12 +01:00
Alex Bilbie
c3457107ee Merge pull request #370 from michaelhogg/fix-bug-hmac-encoding
Fix bug: hash_hmac() should output raw binary data, not hexits
2015-09-04 08:36:33 +01:00
Alex Bilbie
a9f61fd3ed Merge pull request #377 from starJammer/master
AuthCodeGrant and RefreshTokenGrant don't require client_secret
2015-09-04 08:29:39 +01:00
Alex Bilbie
b78d8ca1d8 Merge pull request #364 from apollopy/master
Too idealistic. Should allow the client and server have some time difference.
2015-09-04 08:28:14 +01:00
Jerry Saravia
8f82e8ef86 Added test for setRequireClientSecret 2015-09-03 23:16:09 -04:00
Jerry Saravia
d88e01c7dd Making client secret optional during refresh and access token requsets. 2015-09-03 22:50:35 -04:00
Michael Hogg
d21374fb0b Merge remote-tracking branch 'thephpleague/master' into fix-bug-hmac-encoding 2015-09-02 09:50:46 +01:00
Alex Bilbie
31e5f4d33c Merge pull request #368 from apollopy/mac_token_only_header
Mac token only get to header
2015-09-01 14:33:58 +01:00
Alex Bilbie
a773405adf Merge pull request #369 from joaopramos/mac-refresh-tokens
Mac refresh tokens
2015-09-01 14:32:45 +01:00
Alex Bilbie
ccc845b195 Merge pull request #371 from michaelhogg/fix-bug-base64-regex
Fix bug: regex doesn't match all Base64 characters
2015-09-01 14:30:38 +01:00
Alex Bilbie
21cd917892 Merge pull request #372 from michaelhogg/fix-bug-request-uri
Fix bug: incorrect signature parameter
2015-09-01 14:29:41 +01:00
Michael Hogg
a2c418ee07 Fix bug: incorrect signature parameter 2015-08-28 16:41:12 +01:00
Michael Hogg
b220368583 Fix bug: regex doesn't match all Base64 characters 2015-08-28 14:01:22 +01:00
Michael Hogg
2d26c38d6c Update unit test: testDetermineAccessTokenInHeaderValid() 2015-08-28 13:11:20 +01:00
Michael Hogg
eeaa68400f Fix bug: hash_hmac() should output raw binary data, not hexits 2015-08-28 12:46:53 +01:00
joao
56c73d2427 ISSUE #356: added the refresh token to the mac token type response 2015-08-28 10:40:13 +00:00
joao
f632fcc997 ISSUE #356: added the refresh token to the mac token type response 2015-08-28 10:38:45 +00:00
ApolloPY
618d84ddcf Mac token only get to header 2015-08-22 01:47:59 +08:00
apollopy
ace42e89e0 change to 300 seconds 2015-08-21 20:02:42 +08:00
ApolloPY
c496df98e4 Too idealistic. Should allow the client and server have some time difference. 2015-08-21 17:17:51 +08:00
Alex Bilbie
2496653968 Merge pull request #342 from gaomd/master
Fix #328, strict check Bearer token
2015-08-21 09:00:02 +01:00
Alex Bilbie
abf66ef9c8 Merge pull request #346 from Korri/Korri-patch-removed-duplicate-routing
Removed duplicate routing setup code
2015-08-21 08:59:35 +01:00
Alex Bilbie
4b9ec488f4 Merge pull request #352 from daveblake/master
Fix typo in docblock
2015-07-13 21:55:43 +01:00
DavidBlake
726d879607 Fix typo in docblock 2015-06-18 13:27:58 +01:00
Mathieu Pipet
b256195421 Expose parameter passed to exceptions 2015-06-09 17:42:25 +02:00
Mathieu Pipet
c84ea1ea62 Expose parameter passed to exceptions 2015-06-09 17:30:13 +02:00
Hugo Vacher
16685ccde4 Removed duplicate routing setup code 2015-06-08 15:50:55 -04:00
Mengdi Gao
7934c7bb53 Fix #328, strict check Bearer token 2015-06-01 21:36:44 +08:00
Alex Bilbie
c174b6fc65 Merge pull request #341 from thephpleague/philsturgeon-patch-1
Added integration list to readme
2015-05-20 13:22:42 +01:00
Phil Sturgeon
75ced70248 Added integration list to readme
I figure it's a good idea to let people know where they can find their bridge packages to save em looking or building their own framework specific nonsense.
2015-05-17 13:33:50 -04:00
Alex Bilbie
5b7fdaeece Merge pull request #330 from jakeasmith/patch-1
Just a typo fix
2015-04-16 17:48:00 +01:00
Jake A. Smith
430a752315 Just a typo fix 2015-04-16 10:41:37 -05:00
Alex Bilbie
810544ec0a Changelog update 2015-03-22 23:32:45 +00:00
Alex Bilbie
34a6b66b8c More .travis.yml updates 2015-03-22 23:19:36 +00:00
Alex Bilbie
61738a7fe2 Added fast_finish: true to .travis.yml 2015-03-22 23:13:41 +00:00
Alex Bilbie
51184259d1 Merge pull request #323 from rdohms/interface-docs
Updated Interface Docs
2015-03-20 11:43:47 +00:00
rdohms
b21de11429 Updated Interface Docs
Made phpdocs match expectations like null when not found and using array notation for indicating array of <object>
2015-03-20 11:33:03 +01:00
Alex Bilbie
cf6e86c9d4 Merge pull request #319 from Fuxy22/patch-1
Fixed missing session scope
2015-03-13 11:03:05 +00:00
Alex Bilbie
f6fdbc7142 Added PHP 7.0 testing 2015-03-03 22:00:47 +00:00
Norbert Fuksz
7f7f45662a Fixed missing session scope
Close #297
2015-03-02 17:47:48 +00:00
Alex Bilbie
f92a68cc72 Merge branch 'master' of github.com:thephpleague/oauth2-server 2015-02-22 19:47:44 +00:00
Alex Bilbie
295d8ffa24 Updated league/event to ~2.1. Fixes #311 2015-02-22 19:47:27 +00:00
Alex Bilbie
3d08140651 Merge pull request #300 from vvllaadd/patch-2
Probable bug
2015-02-22 19:45:14 +00:00
Alex Bilbie
ec8a8393ee Merge pull request #310 from ismailbaskin/master
typo
2015-02-10 10:03:53 +00:00
Ismail BASKIN
3869b8f406 typo 2015-02-10 10:28:57 +02:00
Vlad
d43391564c Probable bug
AccessTokenStorage::delete should delete the token, not the scope associated with the token
2015-01-15 14:20:54 +01:00
109 changed files with 2809 additions and 2996 deletions

View File

@@ -2,7 +2,6 @@ filter:
excluded_paths:
- tests/*
- vendor/*
- examples/*
checks:
php:
code_rating: true
@@ -21,8 +20,7 @@ checks:
fix_doc_comments: true
tools:
external_code_coverage:
timeout: 600
runs: 3
timeout: 1800
php_code_coverage: false
php_code_sniffer:
config:
@@ -34,4 +32,4 @@ tools:
excluded_dirs: [vendor, tests, examples]
php_cpd:
enabled: true
excluded_dirs: [vendor, tests, examples]
excluded_dirs: [vendor, tests, examples]

View File

@@ -7,6 +7,7 @@ cache:
- vendor
php:
- 5.5.9
- 5.5
- 5.6
- 7.0
@@ -20,5 +21,4 @@ script:
branches:
only:
- master
- V5-WIP
- master

View File

@@ -1,5 +1,74 @@
# Changelog
## 5.0.3 (released 2016-05-04)
* Fix hints in PasswordGrant (Issue #560)
* Add meaning of `Resource owner` to terminology.md (Issue #561)
* Use constant for event name instead of explicit string (Issue #563)
* Remove unused request property (Issue #564)
* Correct wrong phpdoc (Issue #569)
* Fixed typo in exception string (Issue #570)
## 5.0.2 (released 2016-04-18)
* `state` parameter is now correctly returned after implicit grant authorization
* Small code and docblock improvements
## 5.0.1 (released 2016-04-18)
* Fixes an issue (#550) whereby it was unclear whether or not to validate a client's secret during a request.
## 5.0.0 (released 2016-04-17)
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
Changes since RC2:
* Renamed Server class to AuthorizationServer
* Added ResourceServer class
* Run unit tests again PHP 5.5.9 as it's the minimum supported version
* Enable PHPUnit 5.0 support
* Improved examples and documentation
* Make it clearer that the implicit grant doesn't support refresh tokens
* Improved refresh token validation errors
* Fixed refresh token expiry date
## 5.0.0-RC2 (released 2016-04-10)
Changes since RC1:
* Allow multiple client redirect URIs (Issue #511)
* Remove unused mac token interface (Issue #503)
* Handle RSA key passphrase (Issue #502)
* Remove access token repository from response types (Issue #501)
* Remove unnecessary methods from entity interfaces (Issue #490)
* Ensure incoming JWT hasn't expired (Issue #509)
* Fix client identifier passed where user identifier is expected (Issue #498)
* Removed built-in entities; added traits to for quick re-use (Issue #504)
* Redirect uri is required only if the "redirect_uri" parameter was included in the authorization request (Issue #514)
* Removed templating for auth code and implicit grants (Issue #499)
## 5.0.0-RC1 (release 2016-03-24)
Version 5 is a complete code rewrite.

View File

@@ -1,4 +1,4 @@
# PHP OAuth 2.0 Server by [@alexbilbie](https://twitter.com/alexbilbie)
# PHP OAuth 2.0 Server
[![Latest Version](http://img.shields.io/packagist/v/league/oauth2-server.svg?style=flat-square)](https://github.com/thephpleague/oauth2-server/releases)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md)
@@ -17,14 +17,7 @@ It supports out of the box the following grants:
* Resource owner password credentials grant
* Refresh grant
You can also easily define your own grants.
In addition it supports the following token response types:
* Bearer (JWT) tokens
* MAC tokens
You can also create you own tokens.
This library was created by Alex Bilbie. Find him on Twitter at [@alexbilbie](https://twitter.com/alexbilbie).
## Requirements
@@ -35,10 +28,12 @@ The following versions of PHP are supported:
* PHP 7.0
* HHVM
The `openssl` extension is also required.
## Documentation
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/).
The library documentation can be found at [https://oauth2.thephpleague.com](https://oauth2.thephpleague.com).
You can contribute to the documentation in the [gh-pages branch](https://github.com/thephpleague/oauth2-server/tree/gh-pages/).
## Changelog
@@ -56,7 +51,7 @@ If you have any questions about OAuth _please_ open a ticket here; please **don'
## Security
If you discover any security related issues, please email hello@alexbilbie.com instead of using the issue tracker.
If you discover any security related issues, please email `hello@alexbilbie.com` instead of using the issue tracker.
## License

View File

@@ -1,18 +1,18 @@
{
"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/",
"homepage": "https://oauth2.thephpleague.com/",
"license": "MIT",
"require": {
"php": ">=5.5.9",
"ext-openssl": "*",
"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",
"phpunit/phpunit": "^4.8 || ^5.0",
"zendframework/zend-diactoros": "^1.0"
},
"repositories": [
@@ -63,11 +63,5 @@
"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"
}
}

View File

@@ -2,7 +2,7 @@
## Installation
0. Run `composer install --no-dev` in this directory to install dependencies
0. Run `composer install` 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

View File

@@ -1,18 +1,17 @@
{
"repositories": [
{
"type": "path",
"url": ".."
}
],
"require": {
"slim/slim": "3.0.*",
"league/oauth2-server": "dev-V5-WIP",
"league/plates": "^3.1"
"slim/slim": "3.0.*"
},
"require-dev": {
"league/event": "^2.1",
"lcobucci/jwt": "^3.1",
"paragonie/random_compat": "^1.1",
"psr/http-message": "^1.0"
},
"autoload": {
"psr-4": {
"OAuth2ServerExamples\\": "src/"
"OAuth2ServerExamples\\": "src/",
"League\\OAuth2\\Server\\": "../src/"
}
}
}

452
examples/composer.lock generated
View File

@@ -4,8 +4,8 @@
"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",
"hash": "48bcb7a3514d7c7f271c554ba1440124",
"content-hash": "e41be75973527cb9d63f27ad14ac8624",
"packages": [
{
"name": "container-interop/container-interop",
@@ -34,243 +34,6 @@
"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",
@@ -314,54 +77,6 @@
],
"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",
@@ -524,12 +239,167 @@
"time": "2015-12-07 14:11:09"
}
],
"packages-dev": [],
"packages-dev": [
{
"name": "lcobucci/jwt",
"version": "3.1.1",
"source": {
"type": "git",
"url": "https://github.com/lcobucci/jwt.git",
"reference": "afea8e682e911a21574fd8519321b32522fa25b5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lcobucci/jwt/zipball/afea8e682e911a21574fd8519321b32522fa25b5",
"reference": "afea8e682e911a21574fd8519321b32522fa25b5",
"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": "2016-03-24 22:46:13"
},
{
"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": "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"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
"league/oauth2-server": 20
},
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],

View File

@@ -1,9 +1,7 @@
<?php
use League\OAuth2\Server\Server;
use League\OAuth2\Server\ResourceServer;
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;
@@ -11,64 +9,65 @@ 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'
// Add the resource server to the DI container
ResourceServer::class => function () {
$server = new ResourceServer(
new AccessTokenRepository(), // instance of AccessTokenRepositoryInterface
'file://' . __DIR__ . '/../public.key' // the authorization server's public key
);
return $server;
},
]);
// Add the resource server middleware which will intercept and validate requests
$app->add(
new \League\OAuth2\Server\Middleware\ResourceServerMiddleware(
$app->getContainer()->get(Server::class)
$app->getContainer()->get(ResourceServer::class)
)
);
$app->get('/users', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
// An example endpoint secured with OAuth 2.0
$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',
],
];
$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 the access token doesn't have the `basic` scope hide users' names
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']);
// If the access token doesn't have the `email` scope hide users' email addresses
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);
}
);
$response->getBody()->write(json_encode($users));
return $response->withStatus(200);
});
$app->run();
$app->run();

View File

@@ -1,14 +1,21 @@
<?php
/**
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
use League\OAuth2\Server\AuthorizationServer;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Grant\AuthCodeGrant;
use League\OAuth2\Server\Server;
use OAuth2ServerExamples\Entities\UserEntity;
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;
@@ -20,20 +27,19 @@ $app = new App([
'settings' => [
'displayErrorDetails' => true,
],
Server::class => function () {
AuthorizationServer::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(
$server = new AuthorizationServer(
$clientRepository,
$accessTokenRepository,
$scopeRepository,
@@ -46,7 +52,6 @@ $app = new App([
new AuthCodeGrant(
$authCodeRepository,
$refreshTokenRepository,
$userRepository,
new \DateInterval('PT10M')
),
new \DateInterval('PT1H')
@@ -56,12 +61,24 @@ $app = new App([
},
]);
$app->any('/authorize', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
/* @var \League\OAuth2\Server\Server $server */
$server = $app->getContainer()->get(Server::class);
$app->get('/authorize', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
/* @var \League\OAuth2\Server\AuthorizationServer $server */
$server = $app->getContainer()->get(AuthorizationServer::class);
try {
return $server->respondToRequest($request, $response);
// Validate the HTTP request and return an AuthorizationRequest object.
// The auth request object can be serialized into a user's session
$authRequest = $server->validateAuthorizationRequest($request);
// Once the user has logged in set the user on the AuthorizationRequest
$authRequest->setUser(new UserEntity());
// Once the user has approved or denied the client update the status
// (true = approved, false = denied)
$authRequest->setAuthorizationApproved(true);
// Return the HTTP redirect response
return $server->completeAuthorizationRequest($authRequest, $response);
} catch (OAuthServerException $exception) {
return $exception->generateHttpResponse($response);
} catch (\Exception $exception) {
@@ -73,11 +90,11 @@ $app->any('/authorize', function (ServerRequestInterface $request, ResponseInter
});
$app->post('/access_token', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
/* @var \League\OAuth2\Server\Server $server */
$server = $app->getContainer()->get(Server::class);
/* @var \League\OAuth2\Server\AuthorizationServer $server */
$server = $app->getContainer()->get(AuthorizationServer::class);
try {
return $server->respondToRequest($request, $response);
return $server->respondToAccessTokenRequest($request, $response);
} catch (OAuthServerException $exception) {
return $exception->generateHttpResponse($response);
} catch (\Exception $exception) {

View File

@@ -1,8 +1,14 @@
<?php
/**
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
use League\OAuth2\Server\AuthorizationServer;
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;
@@ -14,31 +20,33 @@ use Zend\Diactoros\Stream;
include __DIR__ . '/../vendor/autoload.php';
$app = new App([
'settings' => [
'settings' => [
'displayErrorDetails' => true,
],
Server::class => function () {
AuthorizationServer::class => function () {
// Init our repositories
$clientRepository = new ClientRepository();
$accessTokenRepository = new AccessTokenRepository();
$scopeRepository = new ScopeRepository();
$clientRepository = new ClientRepository(); // instance of ClientRepositoryInterface
$scopeRepository = new ScopeRepository(); // instance of ScopeRepositoryInterface
$accessTokenRepository = new AccessTokenRepository(); // instance of AccessTokenRepositoryInterface
$privateKeyPath = 'file://' . __DIR__ . '/../private.key';
$publicKeyPath = 'file://' . __DIR__ . '/../public.key';
// Path to public and private keys
$privateKey = 'file://'.__DIR__.'/../private.key';
//$privateKey = new CryptKey('file://path/to/private.key', 'passphrase'); // if private key has a pass phrase
$publicKey = 'file://'.__DIR__.'/../public.key';
// Setup the authorization server
$server = new Server(
$server = new AuthorizationServer(
$clientRepository,
$accessTokenRepository,
$scopeRepository,
$privateKeyPath,
$publicKeyPath
$privateKey,
$publicKey
);
// Enable the client credentials grant on the server with a token TTL of 1 hour
// Enable the client credentials grant on the server
$server->enableGrantType(
new ClientCredentialsGrant(),
new \DateInterval('PT1H')
new \League\OAuth2\Server\Grant\ClientCredentialsGrant(),
new \DateInterval('PT1H') // access tokens will expire after 1 hour
);
return $server;
@@ -46,14 +54,21 @@ $app = new App([
]);
$app->post('/access_token', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
/* @var \League\OAuth2\Server\Server $server */
$server = $app->getContainer()->get(Server::class);
/* @var \League\OAuth2\Server\AuthorizationServer $server */
$server = $app->getContainer()->get(AuthorizationServer::class);
try {
return $server->respondToRequest($request, $response);
// Try to respond to the request
return $server->respondToAccessTokenRequest($request, $response);
} catch (OAuthServerException $exception) {
// All instances of OAuthServerException can be formatted into a HTTP response
return $exception->generateHttpResponse($response);
} catch (\Exception $exception) {
// Unknown exception
$body = new Stream('php://temp', 'r+');
$body->write($exception->getMessage());

View File

@@ -1,12 +1,19 @@
<?php
/**
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
use League\OAuth2\Server\AuthorizationServer;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Grant\ImplicitGrant;
use League\OAuth2\Server\Server;
use OAuth2ServerExamples\Entities\UserEntity;
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;
@@ -18,18 +25,17 @@ $app = new App([
'settings' => [
'displayErrorDetails' => true,
],
Server::class => function () {
AuthorizationServer::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(
$server = new AuthorizationServer(
$clientRepository,
$accessTokenRepository,
$scopeRepository,
@@ -38,21 +44,30 @@ $app = new App([
);
// Enable the implicit grant on the server with a token TTL of 1 hour
$server->enableGrantType(
new ImplicitGrant($userRepository),
new \DateInterval('PT1H')
);
$server->enableGrantType(new ImplicitGrant(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);
$app->get('/authorize', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
/* @var \League\OAuth2\Server\AuthorizationServer $server */
$server = $app->getContainer()->get(AuthorizationServer::class);
try {
return $server->respondToRequest($request, $response);
// Validate the HTTP request and return an AuthorizationRequest object.
// The auth request object can be serialized into a user's session
$authRequest = $server->validateAuthorizationRequest($request);
// Once the user has logged in set the user on the AuthorizationRequest
$authRequest->setUser(new UserEntity());
// Once the user has approved or denied the client update the status
// (true = approved, false = denied)
$authRequest->setAuthorizationApproved(true);
// Return the HTTP redirect response
return $server->completeAuthorizationRequest($authRequest, $response);
} catch (OAuthServerException $exception) {
return $exception->generateHttpResponse($response);
} catch (\Exception $exception) {

View File

@@ -1,16 +1,22 @@
<?php
/**
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
use League\OAuth2\Server\AuthorizationServer;
use League\OAuth2\Server\Grant\AuthCodeGrant;
use League\OAuth2\Server\Grant\RefreshTokenGrant;
use League\OAuth2\Server\Middleware\AuthenticationServerMiddleware;
use League\OAuth2\Server\Middleware\AuthorizationServerMiddleware;
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;
@@ -19,23 +25,22 @@ use Zend\Diactoros\Stream;
include __DIR__ . '/../vendor/autoload.php';
$app = new App([
'settings' => [
'settings' => [
'displayErrorDetails' => true,
],
Server::class => function () {
AuthorizationServer::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(
$server = new AuthorizationServer(
$clientRepository,
$accessTokenRepository,
$scopeRepository,
@@ -48,7 +53,6 @@ $app = new App([
new AuthCodeGrant(
$authCodeRepository,
$refreshTokenRepository,
$userRepository,
new \DateInterval('PT10M')
),
new \DateInterval('PT1H')
@@ -66,7 +70,7 @@ $app = new App([
// Access token issuer
$app->post('/access_token', function () {
})->add(new AuthenticationServerMiddleware($app->getContainer()->get(Server::class)));
})->add(new AuthorizationServerMiddleware($app->getContainer()->get(AuthorizationServer::class)));
// Secured API
$app->group('/api', function () {
@@ -90,6 +94,6 @@ $app->group('/api', function () {
return $response->withBody($body);
});
})->add(new ResourceServerMiddleware($app->getContainer()->get(Server::class)));
})->add(new ResourceServerMiddleware($app->getContainer()->get(AuthorizationServer::class)));
$app->run();

View File

@@ -1,8 +1,8 @@
<?php
use League\OAuth2\Server\AuthorizationServer;
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;
@@ -11,58 +11,64 @@ 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';
// Add the authorization server to the DI container
AuthorizationServer::class => function () {
// Setup the authorization server
$server = new Server(
$clientRepository,
$accessTokenRepository,
$scopeRepository,
$privateKeyPath,
$publicKeyPath
$server = new AuthorizationServer(
new ClientRepository(), // instance of ClientRepositoryInterface
new AccessTokenRepository(), // instance of AccessTokenRepositoryInterface
new ScopeRepository(), // instance of ScopeRepositoryInterface
'file://'.__DIR__.'/../private.key', // path to private key
'file://'.__DIR__.'/../public.key' // path to public key
);
$grant = new PasswordGrant(
new UserRepository(), // instance of UserRepositoryInterface
new RefreshTokenRepository() // instance of RefreshTokenRepositoryInterface
);
$grant->setRefreshTokenTTL(new \DateInterval('P1M')); // refresh tokens will expire after 1 month
// Enable the password grant on the server with a token TTL of 1 hour
$server->enableGrantType(
new PasswordGrant($userRepository, $refreshTokenRepository),
new \DateInterval('PT1H')
$grant,
new \DateInterval('PT1H') // access tokens will expire after 1 hour
);
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);
$app->post(
'/access_token',
function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
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());
/* @var \League\OAuth2\Server\AuthorizationServer $server */
$server = $app->getContainer()->get(AuthorizationServer::class);
return $response->withStatus(500)->withBody($body);
try {
// Try to respond to the access token request
return $server->respondToAccessTokenRequest($request, $response);
} catch (OAuthServerException $exception) {
// All instances of OAuthServerException can be converted to a PSR-7 response
return $exception->generateHttpResponse($response);
} catch (\Exception $exception) {
// Catch unexpected exceptions
$body = $response->getBody();
$body->write($exception->getMessage());
return $response->withStatus(500)->withBody($body);
}
}
});
);
$app->run();

View File

@@ -1,8 +1,15 @@
<?php
/**
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
use League\OAuth2\Server\AuthorizationServer;
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;
@@ -18,7 +25,7 @@ $app = new App([
'settings' => [
'displayErrorDetails' => true,
],
Server::class => function () {
AuthorizationServer::class => function () {
// Init our repositories
$clientRepository = new ClientRepository();
$accessTokenRepository = new AccessTokenRepository();
@@ -29,7 +36,7 @@ $app = new App([
$publicKeyPath = 'file://' . __DIR__ . '/../public.key';
// Setup the authorization server
$server = new Server(
$server = new AuthorizationServer(
$clientRepository,
$accessTokenRepository,
$scopeRepository,
@@ -37,10 +44,13 @@ $app = new App([
$publicKeyPath
);
// Enable the refresh token grant on the server with a token TTL of 1 hour
// Enable the refresh token grant on the server
$grant = new RefreshTokenGrant($refreshTokenRepository);
$grant->setRefreshTokenTTL(new \DateInterval('P1M')); // The refresh token will expire in 1 month
$server->enableGrantType(
new RefreshTokenGrant($refreshTokenRepository),
new \DateInterval('PT1H')
$grant,
new \DateInterval('PT1H') // The new access token will expire after 1 hour
);
return $server;
@@ -48,11 +58,11 @@ $app = new App([
]);
$app->post('/access_token', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
/* @var \League\OAuth2\Server\Server $server */
$server = $app->getContainer()->get(Server::class);
/* @var \League\OAuth2\Server\AuthorizationServer $server */
$server = $app->getContainer()->get(AuthorizationServer::class);
try {
return $server->respondToRequest($request, $response);
return $server->respondToAccessTokenRequest($request, $response);
} catch (OAuthServerException $exception) {
return $exception->generateHttpResponse($response);
} catch (\Exception $exception) {

View File

@@ -0,0 +1,20 @@
<?php
/**
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace OAuth2ServerExamples\Entities;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\Traits\AccessTokenTrait;
use League\OAuth2\Server\Entities\Traits\EntityTrait;
use League\OAuth2\Server\Entities\Traits\TokenEntityTrait;
class AccessTokenEntity implements AccessTokenEntityInterface
{
use AccessTokenTrait, TokenEntityTrait, EntityTrait;
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace OAuth2ServerExamples\Entities;
use League\OAuth2\Server\Entities\AuthCodeEntityInterface;
use League\OAuth2\Server\Entities\Traits\AuthCodeTrait;
use League\OAuth2\Server\Entities\Traits\EntityTrait;
use League\OAuth2\Server\Entities\Traits\TokenEntityTrait;
class AuthCodeEntity implements AuthCodeEntityInterface
{
use EntityTrait, TokenEntityTrait, AuthCodeTrait;
}

View File

@@ -1,85 +1,29 @@
<?php
/**
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace OAuth2ServerExamples\Entities;
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Entities\Traits\ClientTrait;
use League\OAuth2\Server\Entities\Traits\EntityTrait;
class ClientEntity implements ClientEntityInterface
{
use EntityTrait;
use EntityTrait, ClientTrait;
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)
public function setRedirectUri($uri)
{
$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;
$this->redirectUri = $uri;
}
}

View File

@@ -0,0 +1,19 @@
<?php
/**
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace OAuth2ServerExamples\Entities;
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
use League\OAuth2\Server\Entities\Traits\EntityTrait;
use League\OAuth2\Server\Entities\Traits\RefreshTokenTrait;
class RefreshTokenEntity implements RefreshTokenEntityInterface
{
use RefreshTokenTrait, EntityTrait;
}

View File

@@ -1,8 +1,15 @@
<?php
/**
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace OAuth2ServerExamples\Entities;
use League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface;
use League\OAuth2\Server\Entities\ScopeEntityInterface;
use League\OAuth2\Server\Entities\Traits\EntityTrait;
class ScopeEntity implements ScopeEntityInterface

View File

@@ -1,8 +1,15 @@
<?php
/**
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace OAuth2ServerExamples\Entities;
use League\OAuth2\Server\Entities\Interfaces\UserEntityInterface;
use League\OAuth2\Server\Entities\UserEntityInterface;
class UserEntity implements UserEntityInterface
{

View File

@@ -1,41 +1,57 @@
<?php
/**
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace OAuth2ServerExamples\Repositories;
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use OAuth2ServerExamples\Entities\AccessTokenEntity;
class AccessTokenRepository implements AccessTokenRepositoryInterface
{
/**
* Persists a new access token to permanent storage.
*
* @param \League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface $accessTokenEntity
* {@inheritdoc}
*/
public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity)
{
// TODO: Implement persistNewAccessToken() method.
// Some logic here to save the access token to a database
}
/**
* Revoke an access token.
*
* @param string $tokenId
* {@inheritdoc}
*/
public function revokeAccessToken($tokenId)
{
// TODO: Implement revokeAccessToken() method.
// Some logic here to revoke the access token
}
/**
* Check if the access token has been revoked.
*
* @param string $tokenId
*
* @return bool Return true if this token has been revoked
* {@inheritdoc}
*/
public function isAccessTokenRevoked($tokenId)
{
// TODO: Implement isAccessTokenRevoked() method.
return false; // Access token hasn't been revoked
}
/**
* {@inheritdoc}
*/
public function getNewToken(ClientEntityInterface $clientEntity, array $scopes, $userIdentifier = null)
{
$accessToken = new AccessTokenEntity();
$accessToken->setClient($clientEntity);
foreach ($scopes as $scope) {
$accessToken->addScope($scope);
}
$accessToken->setUserIdentifier($userIdentifier);
return $accessToken;
}
}

View File

@@ -1,41 +1,49 @@
<?php
/**
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace OAuth2ServerExamples\Repositories;
use League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface;
use League\OAuth2\Server\Entities\AuthCodeEntityInterface;
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
use OAuth2ServerExamples\Entities\AuthCodeEntity;
class AuthCodeRepository implements AuthCodeRepositoryInterface
{
/**
* Persists a new auth code to permanent storage.
*
* @param \League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface $authCodeEntity
* {@inheritdoc}
*/
public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity)
{
// TODO: Implement persistNewAuthCode() method.
// Some logic to persist the auth code to a database
}
/**
* Revoke an auth code.
*
* @param string $codeId
* {@inheritdoc}
*/
public function revokeAuthCode($codeId)
{
// TODO: Implement revokeAuthCode() method.
// Some logic to revoke the auth code in a database
}
/**
* Check if the auth code has been revoked.
*
* @param string $codeId
*
* @return bool Return true if this code has been revoked
* {@inheritdoc}
*/
public function isAuthCodeRevoked($codeId)
{
// TODO: Implement isAuthCodeRevoked() method.
return false; // The auth code has not been revoked
}
/**
* {@inheritdoc}
*/
public function getNewAuthCode()
{
return new AuthCodeEntity();
}
}

View File

@@ -1,4 +1,11 @@
<?php
/**
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace OAuth2ServerExamples\Repositories;
@@ -10,13 +17,14 @@ class ClientRepository implements ClientRepositoryInterface
/**
* {@inheritdoc}
*/
public function getClientEntity($clientIdentifier, $clientSecret = null, $redirectUri = null, $grantType = null)
public function getClientEntity($clientIdentifier, $grantType, $clientSecret = null, $mustValidateSecret = true)
{
$clients = [
'myawesomeapp' => [
'secret' => password_hash('abc123', PASSWORD_BCRYPT),
'name' => 'My Awesome App',
'redirect_uri' => 'http://foo/bar',
'secret' => password_hash('abc123', PASSWORD_BCRYPT),
'name' => 'My Awesome App',
'redirect_uri' => 'http://foo/bar',
'is_confidential' => true,
],
];
@@ -25,11 +33,18 @@ class ClientRepository implements ClientRepositoryInterface
return;
}
if (
$mustValidateSecret === true
&& $clients[$clientIdentifier]['is_confidential'] === true
&& password_verify($clientSecret, $clients[$clientIdentifier]['secret']) === 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

@@ -1,41 +1,49 @@
<?php
/**
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace OAuth2ServerExamples\Repositories;
use League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface;
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
use OAuth2ServerExamples\Entities\RefreshTokenEntity;
class RefreshTokenRepository implements RefreshTokenRepositoryInterface
{
/**
* Create a new refresh token_name.
*
* @param \League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface $refreshTokenEntityInterface
* {@inheritdoc}
*/
public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntityInterface)
{
// TODO: Implement persistNewRefreshToken() method.
// Some logic to persist the refresh token in a database
}
/**
* Revoke the refresh token.
*
* @param string $tokenId
* {@inheritdoc}
*/
public function revokeRefreshToken($tokenId)
{
// TODO: Implement revokeRefreshToken() method.
// Some logic to revoke the refresh token in a database
}
/**
* Check if the refresh token has been revoked.
*
* @param string $tokenId
*
* @return bool Return true if this token has been revoked
* {@inheritdoc}
*/
public function isRefreshTokenRevoked($tokenId)
{
// TODO: Implement isRefreshTokenRevoked() method.
return false; // The refresh token has not been revoked
}
/**
* {@inheritdoc}
*/
public function getNewRefreshToken()
{
return new RefreshTokenEntity();
}
}

View File

@@ -1,8 +1,15 @@
<?php
/**
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace OAuth2ServerExamples\Repositories;
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
use OAuth2ServerExamples\Entities\ScopeEntity;

View File

@@ -1,8 +1,15 @@
<?php
/**
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
namespace OAuth2ServerExamples\Repositories;
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
use OAuth2ServerExamples\Entities\ScopeEntity;
use OAuth2ServerExamples\Entities\UserEntity;

View File

@@ -1,23 +1,29 @@
<?php
/**
* @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 DateInterval;
use League\Event\EmitterAwareInterface;
use League\Event\EmitterAwareTrait;
use League\OAuth2\Server\AuthorizationValidators\AuthorizationValidatorInterface;
use League\OAuth2\Server\AuthorizationValidators\BearerTokenValidator;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Grant\GrantTypeInterface;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
use League\OAuth2\Server\ResponseTypes\BearerTokenResponse;
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class Server implements EmitterAwareInterface
class AuthorizationServer implements EmitterAwareInterface
{
use EmitterAwareTrait;
@@ -32,20 +38,20 @@ class Server implements EmitterAwareInterface
protected $grantTypeAccessTokenTTL = [];
/**
* @var string
* @var \League\OAuth2\Server\CryptKey
*/
protected $privateKeyPath;
protected $privateKey;
/**
* @var \League\OAuth2\Server\CryptKey
*/
protected $publicKey;
/**
* @var ResponseTypeInterface
*/
protected $responseType;
/**
* @var string
*/
private $publicKeyPath;
/**
* @var \League\OAuth2\Server\Repositories\ClientRepositoryInterface
*/
@@ -61,38 +67,39 @@ class Server implements EmitterAwareInterface
*/
private $scopeRepository;
/**
* @var \League\OAuth2\Server\AuthorizationValidators\AuthorizationValidatorInterface
*/
private $authorizationValidator;
/**
* New server instance.
*
* @param \League\OAuth2\Server\Repositories\ClientRepositoryInterface $clientRepository
* @param \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface $accessTokenRepository
* @param \League\OAuth2\Server\Repositories\ScopeRepositoryInterface $scopeRepository
* @param string $privateKeyPath
* @param string $publicKeyPath
* @param null|\League\OAuth2\Server\ResponseTypes\ResponseTypeInterface $responseType
* @param null|\League\OAuth2\Server\AuthorizationValidators\AuthorizationValidatorInterface $authorizationValidator
* @param \League\OAuth2\Server\Repositories\ClientRepositoryInterface $clientRepository
* @param \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface $accessTokenRepository
* @param \League\OAuth2\Server\Repositories\ScopeRepositoryInterface $scopeRepository
* @param \League\OAuth2\Server\CryptKey|string $privateKey
* @param \League\OAuth2\Server\CryptKey|string $publicKey
* @param null|\League\OAuth2\Server\ResponseTypes\ResponseTypeInterface $responseType
*/
public function __construct(
ClientRepositoryInterface $clientRepository,
AccessTokenRepositoryInterface $accessTokenRepository,
ScopeRepositoryInterface $scopeRepository,
$privateKeyPath,
$publicKeyPath,
ResponseTypeInterface $responseType = null,
AuthorizationValidatorInterface $authorizationValidator = null
$privateKey,
$publicKey,
ResponseTypeInterface $responseType = null
) {
$this->clientRepository = $clientRepository;
$this->accessTokenRepository = $accessTokenRepository;
$this->scopeRepository = $scopeRepository;
$this->privateKeyPath = $privateKeyPath;
$this->publicKeyPath = $publicKeyPath;
if (!$privateKey instanceof CryptKey) {
$privateKey = new CryptKey($privateKey);
}
$this->privateKey = $privateKey;
if (!$publicKey instanceof CryptKey) {
$publicKey = new CryptKey($publicKey);
}
$this->publicKey = $publicKey;
$this->responseType = $responseType;
$this->authorizationValidator = $authorizationValidator;
}
/**
@@ -101,37 +108,80 @@ class Server implements EmitterAwareInterface
* @param \League\OAuth2\Server\Grant\GrantTypeInterface $grantType
* @param \DateInterval $accessTokenTTL
*/
public function enableGrantType(GrantTypeInterface $grantType, DateInterval $accessTokenTTL)
public function enableGrantType(GrantTypeInterface $grantType, DateInterval $accessTokenTTL = null)
{
if ($accessTokenTTL instanceof DateInterval === false) {
$accessTokenTTL = new \DateInterval('PT1H');
}
$grantType->setAccessTokenRepository($this->accessTokenRepository);
$grantType->setClientRepository($this->clientRepository);
$grantType->setScopeRepository($this->scopeRepository);
$grantType->setPrivateKeyPath($this->privateKeyPath);
$grantType->setPublicKeyPath($this->publicKeyPath);
$grantType->setPrivateKey($this->privateKey);
$grantType->setPublicKey($this->publicKey);
$grantType->setEmitter($this->getEmitter());
$this->enabledGrantTypes[$grantType->getIdentifier()] = $grantType;
$this->grantTypeAccessTokenTTL[$grantType->getIdentifier()] = $accessTokenTTL;
}
/**
* Validate an authorization request
*
* @param \Psr\Http\Message\ServerRequestInterface $request
*
* @throws \League\OAuth2\Server\Exception\OAuthServerException
*
* @return \League\OAuth2\Server\RequestTypes\AuthorizationRequest|null
*/
public function validateAuthorizationRequest(ServerRequestInterface $request)
{
$authRequest = null;
$enabledGrantTypes = $this->enabledGrantTypes;
while ($authRequest === null && $grantType = array_shift($enabledGrantTypes)) {
/** @var \League\OAuth2\Server\Grant\GrantTypeInterface $grantType */
if ($grantType->canRespondToAuthorizationRequest($request)) {
$authRequest = $grantType->validateAuthorizationRequest($request);
return $authRequest;
}
}
throw OAuthServerException::unsupportedGrantType();
}
/**
* Complete an authorization request
*
* @param \League\OAuth2\Server\RequestTypes\AuthorizationRequest $authRequest
* @param \Psr\Http\Message\ResponseInterface $response
*
* @return \Psr\Http\Message\ResponseInterface
*/
public function completeAuthorizationRequest(AuthorizationRequest $authRequest, ResponseInterface $response)
{
return $this->enabledGrantTypes[$authRequest->getGrantTypeId()]
->completeAuthorizationRequest($authRequest)
->generateHttpResponse($response);
}
/**
* Return an access token response.
*
* @param \Psr\Http\Message\ServerRequestInterface|null $request
* @param \Psr\Http\Message\ResponseInterface|null $response
* @param \Psr\Http\Message\ServerRequestInterface $request
* @param \Psr\Http\Message\ResponseInterface $response
*
* @throws \League\OAuth2\Server\Exception\OAuthServerException
*
* @return \Psr\Http\Message\ResponseInterface
*/
public function respondToRequest(ServerRequestInterface $request, ResponseInterface $response)
public function respondToAccessTokenRequest(ServerRequestInterface $request, ResponseInterface $response)
{
$tokenResponse = null;
while ($tokenResponse === null && $grantType = array_shift($this->enabledGrantTypes)) {
/** @var \League\OAuth2\Server\Grant\GrantTypeInterface $grantType */
if ($grantType->canRespondToRequest($request)) {
$tokenResponse = $grantType->respondToRequest(
if ($grantType->canRespondToAccessTokenRequest($request)) {
$tokenResponse = $grantType->respondToAccessTokenRequest(
$request,
$this->getResponseType(),
$this->grantTypeAccessTokenTTL[$grantType->getIdentifier()]
@@ -146,20 +196,6 @@ class Server implements EmitterAwareInterface
throw OAuthServerException::unsupportedGrantType();
}
/**
* Determine the access token validity.
*
* @param \Psr\Http\Message\ServerRequestInterface $request
*
* @throws \League\OAuth2\Server\Exception\OAuthServerException
*
* @return \Psr\Http\Message\ServerRequestInterface
*/
public function validateAuthenticatedRequest(ServerRequestInterface $request)
{
return $this->getAuthorizationValidator()->validateAuthorization($request);
}
/**
* Get the token type that grants will return in the HTTP response.
*
@@ -168,27 +204,11 @@ class Server implements EmitterAwareInterface
protected function getResponseType()
{
if (!$this->responseType instanceof ResponseTypeInterface) {
$this->responseType = new BearerTokenResponse($this->accessTokenRepository);
$this->responseType = new BearerTokenResponse();
}
$this->responseType->setPublicKeyPath($this->publicKeyPath);
$this->responseType->setPrivateKeyPath($this->privateKeyPath);
$this->responseType->setPrivateKey($this->privateKey);
return $this->responseType;
}
/**
* @return \League\OAuth2\Server\AuthorizationValidators\AuthorizationValidatorInterface
*/
protected function getAuthorizationValidator()
{
if (!$this->authorizationValidator instanceof AuthorizationValidatorInterface) {
$this->authorizationValidator = new BearerTokenValidator($this->accessTokenRepository);
}
$this->authorizationValidator->setPublicKeyPath($this->publicKeyPath);
$this->authorizationValidator->setPrivateKeyPath($this->privateKeyPath);
return $this->authorizationValidator;
}
}

View File

@@ -1,4 +1,11 @@
<?php
/**
* @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\AuthorizationValidators;

View File

@@ -1,9 +1,17 @@
<?php
/**
* @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\AuthorizationValidators;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Rsa\Sha256;
use Lcobucci\JWT\ValidationData;
use League\OAuth2\Server\CryptTrait;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
@@ -43,10 +51,18 @@ class BearerTokenValidator implements AuthorizationValidatorInterface
try {
// Attempt to parse and validate the JWT
$token = (new Parser())->parse($jwt);
if ($token->verify(new Sha256(), $this->publicKeyPath) === false) {
if ($token->verify(new Sha256(), $this->publicKey->getKeyPath()) === false) {
throw OAuthServerException::accessDenied('Access token could not be verified');
}
// Ensure access token hasn't expired
$data = new ValidationData();
$data->setCurrentTime(time());
if ($token->validate($data) === false) {
throw OAuthServerException::accessDenied('Access token is invalid');
}
// Check if token has been revoked
if ($this->accessTokenRepository->isAccessTokenRevoked($token->getClaim('jti'))) {
throw OAuthServerException::accessDenied('Access token has been revoked');

62
src/CryptKey.php Normal file
View File

@@ -0,0 +1,62 @@
<?php
/**
* Cryptography key holder.
*
* @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;
class CryptKey
{
/**
* @var string
*/
protected $keyPath;
/**
* @var string
*/
protected $passPhrase;
/**
* @param string $keyPath
* @param null|string $passPhrase
*/
public function __construct($keyPath, $passPhrase = null)
{
if (strpos($keyPath, 'file://') !== 0) {
$keyPath = 'file://' . $keyPath;
}
if (!file_exists($keyPath) || !is_readable($keyPath)) {
throw new \LogicException(sprintf('Key path "%s" does not exist or is not readable', $keyPath));
}
$this->keyPath = $keyPath;
$this->passPhrase = $passPhrase;
}
/**
* Retrieve key path.
*
* @return string
*/
public function getKeyPath()
{
return $this->keyPath;
}
/**
* Retrieve key pass phrase.
*
* @return null|string
*/
public function getPassPhrase()
{
return $this->passPhrase;
}
}

View File

@@ -13,41 +13,33 @@ namespace League\OAuth2\Server;
trait CryptTrait
{
/**
* @var string
* @var \League\OAuth2\Server\CryptKey
*/
protected $privateKeyPath;
protected $privateKey;
/**
* @var string
* @var \League\OAuth2\Server\CryptKey
*/
protected $publicKeyPath;
protected $publicKey;
/**
* Set path to private key.
*
* @param string $privateKeyPath
* @param \League\OAuth2\Server\CryptKey $privateKey
*/
public function setPrivateKeyPath($privateKeyPath)
public function setPrivateKey(CryptKey $privateKey)
{
if (strpos($privateKeyPath, 'file://') !== 0) {
$privateKeyPath = 'file://' . $privateKeyPath;
}
$this->privateKeyPath = $privateKeyPath;
$this->privateKey = $privateKey;
}
/**
* Set path to public key.
*
* @param string $publicKeyPath
* @param \League\OAuth2\Server\CryptKey $publicKey
*/
public function setPublicKeyPath($publicKeyPath)
public function setPublicKey(CryptKey $publicKey)
{
if (strpos($publicKeyPath, 'file://') !== 0) {
$publicKeyPath = 'file://' . $publicKeyPath;
}
$this->publicKeyPath = $publicKeyPath;
$this->publicKey = $publicKey;
}
/**
@@ -59,10 +51,12 @@ trait CryptTrait
*/
protected function encrypt($unencryptedData)
{
$privateKey = openssl_pkey_get_private($this->privateKeyPath);
$privateKey = openssl_pkey_get_private($this->privateKey->getKeyPath(), $this->privateKey->getPassPhrase());
$privateKeyDetails = @openssl_pkey_get_details($privateKey);
if ($privateKeyDetails === null) {
throw new \LogicException(sprintf('Could not get details of private key: %s', $this->privateKeyPath));
throw new \LogicException(
sprintf('Could not get details of private key: %s', $this->privateKey->getKeyPath())
);
}
$chunkSize = ceil($privateKeyDetails['bits'] / 8) - 11;
@@ -78,7 +72,7 @@ trait CryptTrait
}
$output .= $encrypted;
}
openssl_free_key($privateKey);
openssl_pkey_free($privateKey);
return base64_encode($output);
}
@@ -94,10 +88,12 @@ trait CryptTrait
*/
protected function decrypt($encryptedData)
{
$publicKey = openssl_pkey_get_public($this->publicKeyPath);
$publicKey = openssl_pkey_get_public($this->publicKey->getKeyPath());
$publicKeyDetails = @openssl_pkey_get_details($publicKey);
if ($publicKeyDetails === null) {
throw new \LogicException(sprintf('Could not get details of public key: %s', $this->publicKeyPath));
throw new \LogicException(
sprintf('Could not get details of public key: %s', $this->publicKey->getKeyPath())
);
}
$chunkSize = ceil($publicKeyDetails['bits'] / 8);
@@ -115,7 +111,7 @@ trait CryptTrait
}
$output .= $decrypted;
}
openssl_free_key($publicKey);
openssl_pkey_free($publicKey);
return $output;
}

View File

@@ -1,36 +0,0 @@
<?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,24 @@
<?php
/**
* @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\Entities;
use League\OAuth2\Server\CryptKey;
interface AccessTokenEntityInterface extends TokenInterface
{
/**
* Generate a JWT from the access token
*
* @param \League\OAuth2\Server\CryptKey $privateKey
*
* @return string
*/
public function convertToJWT(CryptKey $privateKey);
}

View File

@@ -1,33 +0,0 @@
<?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,23 @@
<?php
/**
* @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\Entities;
interface AuthCodeEntityInterface extends TokenInterface
{
/**
* @return string
*/
public function getRedirectUri();
/**
* @param string $uri
*/
public function setRedirectUri($uri);
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* @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\Entities;
interface ClientEntityInterface
{
/**
* Get the client's identifier.
*
* @return string
*/
public function getIdentifier();
/**
* Get the client's name.
*
* @return string
*/
public function getName();
/**
* Returns the registered redirect URI (as a string).
*
* Alternatively return an indexed array of redirect URIs.
*
* @return string|string[]
*/
public function getRedirectUri();
}

View File

@@ -1,15 +0,0 @@
<?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

@@ -1,16 +0,0 @@
<?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

@@ -1,48 +0,0 @@
<?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

@@ -1,20 +0,0 @@
<?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

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

View File

@@ -1,15 +0,0 @@
<?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

@@ -1,6 +1,13 @@
<?php
/**
* @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\Entities\Interfaces;
namespace League\OAuth2\Server\Entities;
interface RefreshTokenEntityInterface
{
@@ -35,14 +42,14 @@ interface RefreshTokenEntityInterface
/**
* Set the access token that the refresh token was associated with.
*
* @param \League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface $accessToken
* @param \League\OAuth2\Server\Entities\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
* @return \League\OAuth2\Server\Entities\AccessTokenEntityInterface
*/
public function getAccessToken();

View File

@@ -0,0 +1,20 @@
<?php
/**
* @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\Entities;
interface ScopeEntityInterface extends \JsonSerializable
{
/**
* Get the scope's identifier.
*
* @return string
*/
public function getIdentifier();
}

View File

@@ -1,6 +1,13 @@
<?php
/**
* @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\Entities\Interfaces;
namespace League\OAuth2\Server\Entities;
interface TokenInterface
{
@@ -56,14 +63,14 @@ interface TokenInterface
/**
* Set the client that the token was issued to.
*
* @param \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface $client
* @param \League\OAuth2\Server\Entities\ClientEntityInterface $client
*/
public function setClient(ClientEntityInterface $client);
/**
* Associate a scope with the token.
*
* @param \League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface $scope
* @param \League\OAuth2\Server\Entities\ScopeEntityInterface $scope
*/
public function addScope(ScopeEntityInterface $scope);

View File

@@ -0,0 +1,61 @@
<?php
/**
* @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\Entities\Traits;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Signer\Rsa\Sha256;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Entities\ScopeEntityInterface;
trait AccessTokenTrait
{
/**
* Generate a JWT from the access token
*
* @param \League\OAuth2\Server\CryptKey $privateKey
*
* @return string
*/
public function convertToJWT(CryptKey $privateKey)
{
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($privateKey->getKeyPath(), $privateKey->getPassPhrase()))
->getToken();
}
/**
* @return ClientEntityInterface
*/
abstract public function getClient();
/**
* @return \DateTime
*/
abstract public function getExpiryDateTime();
/**
* @return string|int
*/
abstract public function getUserIdentifier();
/**
* @return ScopeEntityInterface[]
*/
abstract public function getScopes();
}

View File

@@ -0,0 +1,34 @@
<?php
/**
* @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\Entities\Traits;
trait AuthCodeTrait
{
/**
* @var null|string
*/
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,40 @@
<?php
/**
* @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\Entities\Traits;
trait ClientTrait
{
protected $name;
protected $redirectUri;
/**
* Get the client's name.
*
* @return string
* @codeCoverageIgnore
*/
public function getName()
{
return $this->name;
}
/**
* Returns the registered redirect URI (as a string).
*
* Alternatively return an indexed array of redirect URIs.
*
* @return string|string[]
*/
public function getRedirectUri()
{
return $this->redirectUri;
}
}

View File

@@ -1,4 +1,11 @@
<?php
/**
* @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\Entities\Traits;

View File

@@ -1,9 +1,16 @@
<?php
/**
* @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\Entities\Traits;
use DateTime;
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
trait RefreshTokenTrait
{

View File

@@ -1,10 +1,17 @@
<?php
/**
* @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\Entities\Traits;
use DateTime;
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
use League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Entities\ScopeEntityInterface;
trait TokenEntityTrait
{
@@ -31,7 +38,7 @@ trait TokenEntityTrait
/**
* Associate a scope with the token.
*
* @param \League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface $scope
* @param \League\OAuth2\Server\Entities\ScopeEntityInterface $scope
*/
public function addScope(ScopeEntityInterface $scope)
{
@@ -101,7 +108,7 @@ trait TokenEntityTrait
/**
* Set the client that the token was issued to.
*
* @param \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface $client
* @param \League\OAuth2\Server\Entities\ClientEntityInterface $client
*/
public function setClient(ClientEntityInterface $client)
{

View File

@@ -0,0 +1,20 @@
<?php
/**
* @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\Entities;
interface UserEntityInterface
{
/**
* Return the user's identifier.
*
* @return mixed
*/
public function getIdentifier();
}

View File

@@ -1,4 +1,11 @@
<?php
/**
* @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;
@@ -119,6 +126,8 @@ class OAuthServerException extends \Exception
* @param $hint
*
* @return static
*
* @codeCoverageIgnore
*/
public static function serverError($hint)
{

View File

@@ -11,45 +11,8 @@
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

View File

@@ -12,12 +12,9 @@ namespace League\OAuth2\Server\Grant;
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\Entities\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Entities\ScopeEntityInterface;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
@@ -26,6 +23,7 @@ use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
use League\OAuth2\Server\RequestEvent;
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
use Psr\Http\Message\ServerRequestInterface;
/**
@@ -37,11 +35,6 @@ abstract class AbstractGrant implements GrantTypeInterface
const SCOPE_DELIMITER_STRING = ' ';
/**
* @var ServerRequestInterface
*/
protected $request;
/**
* @var ClientRepositoryInterface
*/
@@ -140,7 +133,7 @@ abstract class AbstractGrant implements GrantTypeInterface
*
* @throws \League\OAuth2\Server\Exception\OAuthServerException
*
* @return \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface
* @return \League\OAuth2\Server\Entities\ClientEntityInterface
*/
protected function validateClient(ServerRequestInterface $request)
{
@@ -150,7 +143,7 @@ abstract class AbstractGrant implements GrantTypeInterface
$this->getServerParameter('PHP_AUTH_USER', $request)
);
if (is_null($clientId)) {
throw OAuthServerException::invalidRequest('client_id', '`%s` parameter is missing');
throw OAuthServerException::invalidRequest('client_id');
}
// If the client is confidential require the client secret
@@ -163,18 +156,31 @@ abstract class AbstractGrant implements GrantTypeInterface
$client = $this->clientRepository->getClientEntity(
$clientId,
$this->getIdentifier(),
$clientSecret
$clientSecret,
true
);
if (!$client instanceof ClientEntityInterface) {
$this->getEmitter()->emit(new RequestEvent('client.authentication.failed', $request));
$this->getEmitter()->emit(new RequestEvent(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();
if ($redirectUri !== null) {
if (
is_string($client->getRedirectUri())
&& (strcmp($client->getRedirectUri(), $redirectUri) !== 0)
) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient();
} elseif (
is_array($client->getRedirectUri())
&& in_array($redirectUri, $client->getRedirectUri()) === false
) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient();
}
}
return $client;
@@ -183,17 +189,15 @@ abstract class AbstractGrant implements GrantTypeInterface
/**
* Validate scopes in the request.
*
* @param string $scopes
* @param \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface $client
* @param string $redirectUri
* @param string $scopes
* @param string $redirectUri
*
* @throws \League\OAuth2\Server\Exception\OAuthServerException
*
* @return \League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface[]
* @return \League\OAuth2\Server\Entities\ScopeEntityInterface[]
*/
public function validateScopes(
$scopes,
ClientEntityInterface $client,
$redirectUri = null
) {
$scopesList = array_filter(
@@ -207,7 +211,7 @@ abstract class AbstractGrant implements GrantTypeInterface
foreach ($scopesList as $scopeItem) {
$scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeItem);
if (($scope instanceof ScopeEntityInterface) === false) {
if (!$scope instanceof ScopeEntityInterface) {
throw OAuthServerException::invalidScope($scopeItem, $redirectUri);
}
@@ -278,12 +282,12 @@ abstract class AbstractGrant implements GrantTypeInterface
/**
* 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
* @param \DateInterval $accessTokenTTL
* @param \League\OAuth2\Server\Entities\ClientEntityInterface $client
* @param string $userIdentifier
* @param \League\OAuth2\Server\Entities\ScopeEntityInterface[] $scopes
*
* @return \League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface
* @return \League\OAuth2\Server\Entities\AccessTokenEntityInterface
*/
protected function issueAccessToken(
\DateInterval $accessTokenTTL,
@@ -291,11 +295,11 @@ abstract class AbstractGrant implements GrantTypeInterface
$userIdentifier,
array $scopes = []
) {
$accessToken = new AccessTokenEntity();
$accessToken->setIdentifier($this->generateUniqueIdentifier());
$accessToken->setExpiryDateTime((new \DateTime())->add($accessTokenTTL));
$accessToken = $this->accessTokenRepository->getNewToken($client, $scopes, $userIdentifier);
$accessToken->setClient($client);
$accessToken->setUserIdentifier($userIdentifier);
$accessToken->setIdentifier($this->generateUniqueIdentifier());
$accessToken->setExpiryDateTime((new \DateTime())->add($accessTokenTTL));
foreach ($scopes as $scope) {
$accessToken->addScope($scope);
@@ -309,13 +313,13 @@ abstract class AbstractGrant implements GrantTypeInterface
/**
* 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
* @param \DateInterval $authCodeTTL
* @param \League\OAuth2\Server\Entities\ClientEntityInterface $client
* @param string $userIdentifier
* @param string $redirectUri
* @param \League\OAuth2\Server\Entities\ScopeEntityInterface[] $scopes
*
* @return \League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface
* @return \League\OAuth2\Server\Entities\AuthCodeEntityInterface
*/
protected function issueAuthCode(
\DateInterval $authCodeTTL,
@@ -324,7 +328,7 @@ abstract class AbstractGrant implements GrantTypeInterface
$redirectUri,
array $scopes = []
) {
$authCode = new AuthCodeEntity();
$authCode = $this->authCodeRepository->getNewAuthCode();
$authCode->setIdentifier($this->generateUniqueIdentifier());
$authCode->setExpiryDateTime((new \DateTime())->add($authCodeTTL));
$authCode->setClient($client);
@@ -341,13 +345,13 @@ abstract class AbstractGrant implements GrantTypeInterface
}
/**
* @param \League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface $accessToken
* @param \League\OAuth2\Server\Entities\AccessTokenEntityInterface $accessToken
*
* @return \League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface
* @return \League\OAuth2\Server\Entities\RefreshTokenEntityInterface
*/
protected function issueRefreshToken(AccessTokenEntityInterface $accessToken)
{
$refreshToken = new RefreshTokenEntity();
$refreshToken = $this->refreshTokenRepository->getNewRefreshToken();
$refreshToken->setIdentifier($this->generateUniqueIdentifier());
$refreshToken->setExpiryDateTime((new \DateTime())->add($this->refreshTokenTTL));
$refreshToken->setAccessToken($accessToken);
@@ -385,7 +389,7 @@ abstract class AbstractGrant implements GrantTypeInterface
/**
* {@inheritdoc}
*/
public function canRespondToRequest(ServerRequestInterface $request)
public function canRespondToAccessTokenRequest(ServerRequestInterface $request)
{
$requestParameters = (array) $request->getParsedBody();
@@ -394,4 +398,28 @@ abstract class AbstractGrant implements GrantTypeInterface
&& $requestParameters['grant_type'] === $this->getIdentifier()
);
}
/**
* {@inheritdoc}
*/
public function canRespondToAuthorizationRequest(ServerRequestInterface $request)
{
return false;
}
/**
* {@inheritdoc}
*/
public function validateAuthorizationRequest(ServerRequestInterface $request)
{
throw new \LogicException('This grant cannot validate an authorization request');
}
/**
* {@inheritdoc}
*/
public function completeAuthorizationRequest(AuthorizationRequest $authorizationRequest)
{
throw new \LogicException('This grant cannot complete an authorization request');
}
}

View File

@@ -1,19 +1,25 @@
<?php
/**
* @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 DateInterval;
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
use League\OAuth2\Server\Entities\Interfaces\UserEntityInterface;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Entities\ScopeEntityInterface;
use League\OAuth2\Server\Entities\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\RequestTypes\AuthorizationRequest;
use League\OAuth2\Server\ResponseTypes\RedirectResponse;
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
use League\OAuth2\Server\TemplateRenderer\RendererInterface;
use Psr\Http\Message\ServerRequestInterface;
class AuthCodeGrant extends AbstractAuthorizeGrant
@@ -26,208 +32,17 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
/**
* @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
*/
public function __construct(
AuthCodeRepositoryInterface $authCodeRepository,
RefreshTokenRepositoryInterface $refreshTokenRepository,
UserRepositoryInterface $userRepository,
\DateInterval $authCodeTTL,
RendererInterface $templateRenderer = null
\DateInterval $authCodeTTL
) {
$this->setAuthCodeRepository($authCodeRepository);
$this->setRefreshTokenRepository($refreshTokenRepository);
$this->setUserRepository($userRepository);
$this->authCodeTTL = $authCodeTTL;
$this->refreshTokenTTL = new \DateInterval('P1M');
$this->templateRenderer = $templateRenderer;
}
/**
* Respond to an authorization request.
*
* @param \Psr\Http\Message\ServerRequestInterface $request
*
* @throws \League\OAuth2\Server\Exception\OAuthServerException
*
* @return \Psr\Http\Message\ResponseInterface
*/
protected function respondToAuthorizationRequest(
ServerRequestInterface $request
) {
$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 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;
}
// The user denied the client, redirect them back with an error
throw OAuthServerException::accessDenied('The user denied the request', (string) $redirectUri);
}
/**
@@ -241,17 +56,11 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
*
* @return \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface
*/
protected function respondToAccessTokenRequest(
public 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');
}
// Validate request
$client = $this->validateClient($request);
$encryptedAuthCode = $this->getRequestParameter('code', $request, null);
@@ -275,6 +84,12 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
throw OAuthServerException::invalidRequest('code', 'Authorization code was not issued to this client');
}
// The redirect URI is required in this request
$redirectUri = $this->getRequestParameter('redirect_uri', $request, null);
if (empty($authCodePayload->redirect_uri) === false && $redirectUri === null) {
throw OAuthServerException::invalidRequest('redirect_uri');
}
if ($authCodePayload->redirect_uri !== $redirectUri) {
throw OAuthServerException::invalidRequest('redirect_uri', 'Invalid redirect URI');
}
@@ -283,7 +98,7 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
foreach ($authCodePayload->scopes as $scopeId) {
$scope = $this->scopeRepository->getScopeEntityByIdentifier($scopeId);
if (!$scope) {
if (!$scope instanceof ScopeEntityInterface) {
// @codeCoverageIgnoreStart
throw OAuthServerException::invalidScope($scopeId);
// @codeCoverageIgnoreEnd
@@ -291,6 +106,14 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
$scopes[] = $scope;
}
// Finalize the requested scopes
$scopes = $this->scopeRepository->finalizeScopes(
$scopes,
$this->getIdentifier(),
$client,
$authCodePayload->user_id
);
} catch (\LogicException $e) {
throw OAuthServerException::invalidRequest('code', 'Cannot decrypt the authorization code');
}
@@ -303,41 +126,12 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
$responseType->setAccessToken($accessToken);
$responseType->setRefreshToken($refreshToken);
// Revoke used auth code
$this->authCodeRepository->revokeAuthCode($authCodePayload->auth_code_id);
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.
*
@@ -347,4 +141,135 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
{
return 'authorization_code';
}
/**
* {@inheritdoc}
*/
public function canRespondToAuthorizationRequest(ServerRequestInterface $request)
{
return (
array_key_exists('response_type', $request->getQueryParams())
&& $request->getQueryParams()['response_type'] === 'code'
&& isset($request->getQueryParams()['client_id'])
);
}
/**
* {@inheritdoc}
*/
public function validateAuthorizationRequest(ServerRequestInterface $request)
{
$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(),
null,
false
);
if ($client instanceof ClientEntityInterface === false) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient();
}
$redirectUri = $this->getQueryStringParameter('redirect_uri', $request);
if ($redirectUri !== null) {
if (
is_string($client->getRedirectUri())
&& (strcmp($client->getRedirectUri(), $redirectUri) !== 0)
) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient();
} elseif (
is_array($client->getRedirectUri())
&& in_array($redirectUri, $client->getRedirectUri()) === false
) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient();
}
}
$scopes = $this->validateScopes(
$this->getQueryStringParameter('scope', $request),
is_array($client->getRedirectUri())
? $client->getRedirectUri()[0]
: $client->getRedirectUri()
);
$stateParameter = $this->getQueryStringParameter('state', $request);
$authorizationRequest = new AuthorizationRequest();
$authorizationRequest->setGrantTypeId($this->getIdentifier());
$authorizationRequest->setClient($client);
$authorizationRequest->setRedirectUri($redirectUri);
$authorizationRequest->setState($stateParameter);
$authorizationRequest->setScopes($scopes);
return $authorizationRequest;
}
/**
* {@inheritdoc}
*/
public function completeAuthorizationRequest(AuthorizationRequest $authorizationRequest)
{
if ($authorizationRequest->getUser() instanceof UserEntityInterface === false) {
throw new \LogicException('An instance of UserEntityInterface should be set on the AuthorizationRequest');
}
$finalRedirectUri = ($authorizationRequest->getRedirectUri() === null)
? is_array($authorizationRequest->getClient()->getRedirectUri())
? $authorizationRequest->getClient()->getRedirectUri()[0]
: $authorizationRequest->getClient()->getRedirectUri()
: $authorizationRequest->getRedirectUri();
// The user approved the client, redirect them back with an auth code
if ($authorizationRequest->isAuthorizationApproved() === true) {
$authCode = $this->issueAuthCode(
$this->authCodeTTL,
$authorizationRequest->getClient(),
$authorizationRequest->getUser()->getIdentifier(),
$authorizationRequest->getRedirectUri(),
$authorizationRequest->getScopes()
);
$response = new RedirectResponse();
$response->setRedirectUri(
$this->makeRedirectUri(
$finalRedirectUri,
[
'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'),
]
)
),
'state' => $authorizationRequest->getState(),
]
)
);
return $response;
}
// The user denied the client, redirect them back with an error
throw OAuthServerException::accessDenied(
'The user denied the request',
$finalRedirectUri
);
}
}

View File

@@ -21,20 +21,20 @@ class ClientCredentialsGrant extends AbstractGrant
/**
* {@inheritdoc}
*/
public function respondToRequest(
public function respondToAccessTokenRequest(
ServerRequestInterface $request,
ResponseTypeInterface $responseType,
\DateInterval $accessTokenTTL
) {
// Validate request
$client = $this->validateClient($request);
$scopes = $this->validateScopes($this->getRequestParameter('scope', $request), $client);
$scopes = $this->validateScopes($this->getRequestParameter('scope', $request));
// 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);
$accessToken = $this->issueAccessToken($accessTokenTTL, $client, null, $scopes);
// Inject access token into response type
$responseType->setAccessToken($accessToken);

View File

@@ -11,9 +11,11 @@
namespace League\OAuth2\Server\Grant;
use League\Event\EmitterAwareInterface;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
use Psr\Http\Message\ServerRequestInterface;
@@ -45,25 +47,55 @@ interface GrantTypeInterface extends EmitterAwareInterface
*
* @return \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface
*/
public function respondToRequest(
public function respondToAccessTokenRequest(
ServerRequestInterface $request,
ResponseTypeInterface $responseType,
\DateInterval $accessTokenTTL
);
/**
* The grant type should return true if it is able to respond to this request.
*
* 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
* The grant type should return true if it is able to response to an authorization request
*
* @param \Psr\Http\Message\ServerRequestInterface $request
*
* @return bool
*/
public function canRespondToRequest(ServerRequestInterface $request);
public function canRespondToAuthorizationRequest(ServerRequestInterface $request);
/**
* If the grant can respond to an authorization request this method should be called to validate the parameters of
* the request.
*
* If the validation is successful an AuthorizationRequest object will be returned. This object can be safely
* serialized in a user's session, and can be used during user authentication and authorization.
*
* @param \Psr\Http\Message\ServerRequestInterface $request
*
* @return AuthorizationRequest
*/
public function validateAuthorizationRequest(ServerRequestInterface $request);
/**
* Once a user has authenticated and authorized the client the grant can complete the authorization request.
* The AuthorizationRequest object's $userId property must be set to the authenticated user and the
* $authorizationApproved property must reflect their desire to authorize or deny the client.
*
* @param \League\OAuth2\Server\RequestTypes\AuthorizationRequest $authorizationRequest
*
* @return \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface
*/
public function completeAuthorizationRequest(AuthorizationRequest $authorizationRequest);
/**
* The grant type should return true if it is able to respond to this request.
*
* For example most grant types will check that the $_POST['grant_type'] property matches it's identifier property.
*
* @param \Psr\Http\Message\ServerRequestInterface $request
*
* @return bool
*/
public function canRespondToAccessTokenRequest(ServerRequestInterface $request);
/**
* Set the client repository.
@@ -89,14 +121,14 @@ interface GrantTypeInterface extends EmitterAwareInterface
/**
* Set the path to the private key.
*
* @param string $privateKeyPath
* @param \League\OAuth2\Server\CryptKey $privateKey
*/
public function setPrivateKeyPath($privateKeyPath);
public function setPrivateKey(CryptKey $privateKey);
/**
* Set the path to the public key.
*
* @param string $publicKeyPath
* @param \League\OAuth2\Server\CryptKey $publicKey
*/
public function setPublicKeyPath($publicKeyPath);
public function setPublicKey(CryptKey $publicKey);
}

View File

@@ -1,38 +1,65 @@
<?php
/**
* @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\Entities\Interfaces\ClientEntityInterface;
use League\OAuth2\Server\Entities\Interfaces\UserEntityInterface;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Entities\UserEntityInterface;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
use League\OAuth2\Server\RequestEvent;
use League\OAuth2\Server\ResponseTypes\HtmlResponse;
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
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
* @var \DateInterval
*/
public function __construct(UserRepositoryInterface $userRepository, RendererInterface $templateRenderer = null)
private $accessTokenTTL;
/**
* @param \DateInterval $accessTokenTTL
*/
public function __construct(\DateInterval $accessTokenTTL)
{
$this->setUserRepository($userRepository);
$this->refreshTokenTTL = new \DateInterval('P1M');
$this->templateRenderer = $templateRenderer;
$this->accessTokenTTL = $accessTokenTTL;
}
/**
* @param \DateInterval $refreshTokenTTL
*
* @throw \LogicException
*/
public function setRefreshTokenTTL(\DateInterval $refreshTokenTTL)
{
throw new \LogicException('The Implicit Grant does not return refresh tokens');
}
/**
* @param \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface $refreshTokenRepository
*
* @throw \LogicException
*/
public function setRefreshTokenRepository(RefreshTokenRepositoryInterface $refreshTokenRepository)
{
throw new \LogicException('The Implicit Grant does not return refresh tokens');
}
/**
* {@inheritdoc}
*/
public function canRespondToRequest(ServerRequestInterface $request)
public function canRespondToAccessTokenRequest(ServerRequestInterface $request)
{
return (array_key_exists('response_type', $request->getQueryParams())
&& $request->getQueryParams()['response_type'] === 'token');
return false;
}
/**
@@ -46,13 +73,39 @@ class ImplicitGrant extends AbstractAuthorizeGrant
}
/**
* {@inheritdoc}
* Respond to an incoming request.
*
* @param \Psr\Http\Message\ServerRequestInterface $request
* @param \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface $responseType
* @param \DateInterval $accessTokenTTL
*
* @return \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface
*/
public function respondToRequest(
public function respondToAccessTokenRequest(
ServerRequestInterface $request,
ResponseTypeInterface $responseType,
\DateInterval $accessTokenTTL
) {
throw new \LogicException('This grant does not used this method');
}
/**
* {@inheritdoc}
*/
public function canRespondToAuthorizationRequest(ServerRequestInterface $request)
{
return (
array_key_exists('response_type', $request->getQueryParams())
&& $request->getQueryParams()['response_type'] === 'token'
&& isset($request->getQueryParams()['client_id'])
);
}
/**
* {@inheritdoc}
*/
public function validateAuthorizationRequest(ServerRequestInterface $request)
{
$clientId = $this->getQueryStringParameter(
'client_id',
$request,
@@ -64,148 +117,86 @@ class ImplicitGrant extends AbstractAuthorizeGrant
$client = $this->clientRepository->getClientEntity(
$clientId,
$this->getIdentifier()
$this->getIdentifier(),
null,
false
);
if ($client instanceof ClientEntityInterface === false) {
$this->getEmitter()->emit(new RequestEvent('client.authentication.failed', $request));
$this->getEmitter()->emit(new RequestEvent(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();
$redirectUri = $this->getQueryStringParameter('redirect_uri', $request);
if ($redirectUri !== null) {
if (
is_string($client->getRedirectUri())
&& (strcmp($client->getRedirectUri(), $redirectUri) !== 0)
) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient();
} elseif (
is_array($client->getRedirectUri())
&& in_array($redirectUri, $client->getRedirectUri()) === false
) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient();
}
}
$scopes = $this->validateScopes(
$this->getQueryStringParameter('scope', $request),
$client,
$client->getRedirectUri()
is_array($client->getRedirectUri())
? $client->getRedirectUri()[0]
: $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;
$authorizationRequest = new AuthorizationRequest();
$authorizationRequest->setGrantTypeId($this->getIdentifier());
$authorizationRequest->setClient($client);
$authorizationRequest->setRedirectUri($redirectUri);
$authorizationRequest->setState($stateParameter);
$authorizationRequest->setScopes($scopes);
return $authorizationRequest;
}
/**
* {@inheritdoc}
*/
public function completeAuthorizationRequest(AuthorizationRequest $authorizationRequest)
{
if ($authorizationRequest->getUser() instanceof UserEntityInterface === false) {
throw new \LogicException('An instance of UserEntityInterface should be set on the AuthorizationRequest');
}
// 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);
$finalRedirectUri = ($authorizationRequest->getRedirectUri() === null)
? is_array($authorizationRequest->getClient()->getRedirectUri())
? $authorizationRequest->getClient()->getRedirectUri()[0]
: $authorizationRequest->getClient()->getRedirectUri()
: $authorizationRequest->getRedirectUri();
// The user approved the client, redirect them back with an access token
if ($authorizationRequest->isAuthorizationApproved() === true) {
$accessToken = $this->issueAccessToken(
$accessTokenTTL,
$client,
$userId,
$scopes
$this->accessTokenTTL,
$authorizationRequest->getClient(),
$authorizationRequest->getUser()->getIdentifier(),
$authorizationRequest->getScopes()
);
$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 = new RedirectResponse();
$response->setRedirectUri(
$this->makeRedirectUri(
$redirectUri,
$redirectPayload,
$finalRedirectUri,
[
'access_token' => (string) $accessToken->convertToJWT($this->privateKey),
'token_type' => 'bearer',
'expires_in' => $accessToken->getExpiryDateTime()->getTimestamp() - (new \DateTime())->getTimestamp(),
'state' => $authorizationRequest->getState(),
],
'#'
)
);
@@ -214,6 +205,9 @@ class ImplicitGrant extends AbstractAuthorizeGrant
}
// The user denied the client, redirect them back with an error
throw OAuthServerException::accessDenied('The user denied the request', (string) $redirectUri);
throw OAuthServerException::accessDenied(
'The user denied the request',
$finalRedirectUri
);
}
}

View File

@@ -10,8 +10,8 @@
*/
namespace League\OAuth2\Server\Grant;
use League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface;
use League\OAuth2\Server\Entities\Interfaces\UserEntityInterface;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Entities\UserEntityInterface;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
@@ -41,14 +41,14 @@ class PasswordGrant extends AbstractGrant
/**
* {@inheritdoc}
*/
public function respondToRequest(
public function respondToAccessTokenRequest(
ServerRequestInterface $request,
ResponseTypeInterface $responseType,
\DateInterval $accessTokenTTL
) {
// Validate request
$client = $this->validateClient($request);
$scopes = $this->validateScopes($this->getRequestParameter('scope', $request), $client);
$scopes = $this->validateScopes($this->getRequestParameter('scope', $request));
$user = $this->validateUser($request, $client);
// Finalize the requested scopes
@@ -66,23 +66,23 @@ class PasswordGrant extends AbstractGrant
}
/**
* @param \Psr\Http\Message\ServerRequestInterface $request
* @param \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface $client
* @param \Psr\Http\Message\ServerRequestInterface $request
* @param \League\OAuth2\Server\Entities\ClientEntityInterface $client
*
* @throws \League\OAuth2\Server\Exception\OAuthServerException
*
* @return \League\OAuth2\Server\Entities\Interfaces\UserEntityInterface
* @return \League\OAuth2\Server\Entities\UserEntityInterface
*/
protected function validateUser(ServerRequestInterface $request, ClientEntityInterface $client)
{
$username = $this->getRequestParameter('username', $request);
if (is_null($username)) {
throw OAuthServerException::invalidRequest('username', '`%s` parameter is missing');
throw OAuthServerException::invalidRequest('username');
}
$password = $this->getRequestParameter('password', $request);
if (is_null($password)) {
throw OAuthServerException::invalidRequest('password', '`%s` parameter is missing');
throw OAuthServerException::invalidRequest('password');
}
$user = $this->userRepository->getUserEntityByUserCredentials(
@@ -92,7 +92,7 @@ class PasswordGrant extends AbstractGrant
$client
);
if (!$user instanceof UserEntityInterface) {
$this->getEmitter()->emit(new RequestEvent('user.authentication.failed', $request));
$this->getEmitter()->emit(new RequestEvent(RequestEvent::USER_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidCredentials();
}

View File

@@ -10,6 +10,7 @@
*/
namespace League\OAuth2\Server\Grant;
use League\OAuth2\Server\Entities\ScopeEntityInterface;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
use League\OAuth2\Server\RequestEvent;
@@ -34,7 +35,7 @@ class RefreshTokenGrant extends AbstractGrant
/**
* {@inheritdoc}
*/
public function respondToRequest(
public function respondToAccessTokenRequest(
ServerRequestInterface $request,
ResponseTypeInterface $responseType,
\DateInterval $accessTokenTTL
@@ -42,14 +43,14 @@ class RefreshTokenGrant extends AbstractGrant
// Validate request
$client = $this->validateClient($request);
$oldRefreshToken = $this->validateOldRefreshToken($request, $client->getIdentifier());
$scopes = $this->validateScopes($this->getRequestParameter('scope', $request), $client);
$scopes = $this->validateScopes($this->getRequestParameter('scope', $request));
// 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) {
if (!$scope instanceof ScopeEntityInterface) {
// @codeCoverageIgnoreStart
throw OAuthServerException::invalidScope($scopeId);
// @codeCoverageIgnoreEnd
@@ -101,17 +102,13 @@ class RefreshTokenGrant extends AbstractGrant
try {
$refreshToken = $this->decrypt($encryptedRefreshToken);
} catch (\LogicException $e) {
throw OAuthServerException::invalidRefreshToken('Cannot parse refresh token: ' . $e->getMessage());
throw OAuthServerException::invalidRefreshToken('Cannot decrypt the refresh token');
}
$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']
);
$this->getEmitter()->emit(new RequestEvent(RequestEvent::REFRESH_TOKEN_CLIENT_FAILED, $request));
throw OAuthServerException::invalidRefreshToken('Token is not linked to client');
}
if ($refreshTokenData['expire_time'] < time()) {

View File

@@ -1,25 +1,32 @@
<?php
/**
* @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\Middleware;
use League\OAuth2\Server\AuthorizationServer;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Server;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class AuthenticationServerMiddleware
class AuthorizationServerMiddleware
{
/**
* @var \League\OAuth2\Server\Server
* @var \League\OAuth2\Server\AuthorizationServer
*/
private $server;
/**
* AuthenticationServerMiddleware constructor.
* AuthorizationServerMiddleware constructor.
*
* @param \League\OAuth2\Server\Server $server
* @param \League\OAuth2\Server\AuthorizationServer $server
*/
public function __construct(Server $server)
public function __construct(AuthorizationServer $server)
{
$this->server = $server;
}
@@ -34,7 +41,7 @@ class AuthenticationServerMiddleware
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next)
{
try {
$response = $this->server->respondToRequest($request, $response);
$response = $this->server->respondToAccessTokenRequest($request, $response);
} catch (OAuthServerException $exception) {
return $exception->generateHttpResponse($response);
// @codeCoverageIgnoreStart

View File

@@ -1,25 +1,32 @@
<?php
/**
* @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\Middleware;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Server;
use League\OAuth2\Server\ResourceServer;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class ResourceServerMiddleware
{
/**
* @var \League\OAuth2\Server\Server
* @var \League\OAuth2\Server\ResourceServer
*/
private $server;
/**
* ResourceServerMiddleware constructor.
*
* @param \League\OAuth2\Server\Server $server
* @param \League\OAuth2\Server\ResourceServer $server
*/
public function __construct(Server $server)
public function __construct(ResourceServer $server)
{
$this->server = $server;
}

View File

@@ -1,26 +1,37 @@
<?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;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\ClientEntityInterface;
/**
* Access token interface.
*/
interface AccessTokenRepositoryInterface extends RepositoryInterface
{
/**
* Create a new access token
*
* @param \League\OAuth2\Server\Entities\ClientEntityInterface $clientEntity
* @param \League\OAuth2\Server\Entities\ScopeEntityInterface[] $scopes
* @param mixed $userIdentifier
*
* @return AccessTokenEntityInterface
*/
public function getNewToken(ClientEntityInterface $clientEntity, array $scopes, $userIdentifier = null);
/**
* Persists a new access token to permanent storage.
*
* @param \League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface $accessTokenEntity
* @param \League\OAuth2\Server\Entities\AccessTokenEntityInterface $accessTokenEntity
*/
public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity);

View File

@@ -1,7 +1,5 @@
<?php
/**
* OAuth 2.0 Auth code storage interface.
*
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
@@ -10,17 +8,24 @@
*/
namespace League\OAuth2\Server\Repositories;
use League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface;
use League\OAuth2\Server\Entities\AuthCodeEntityInterface;
/**
* Auth code storage interface.
*/
interface AuthCodeRepositoryInterface extends RepositoryInterface
{
/**
* Creates a new AuthCode
*
* @return \League\OAuth2\Server\Entities\AuthCodeEntityInterface
*/
public function getNewAuthCode();
/**
* Persists a new auth code to permanent storage.
*
* @param \League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface $authCodeEntity
* @param \League\OAuth2\Server\Entities\AuthCodeEntityInterface $authCodeEntity
*/
public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity);

View File

@@ -1,7 +1,5 @@
<?php
/**
* OAuth 2.0 Client storage interface.
*
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
@@ -18,11 +16,13 @@ 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)
* @param string $clientIdentifier The client's identifier
* @param string $grantType The grant type used
* @param null|string $clientSecret The client's secret (if sent)
* @param bool $mustValidateSecret If true the client must attempt to validate the secret unless the client
* is confidential
*
* @return \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface
* @return \League\OAuth2\Server\Entities\ClientEntityInterface
*/
public function getClientEntity($clientIdentifier, $grantType, $clientSecret = null);
public function getClientEntity($clientIdentifier, $grantType, $clientSecret = null, $mustValidateSecret = true);
}

View File

@@ -1,36 +0,0 @@
<?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

@@ -1,7 +1,5 @@
<?php
/**
* OAuth 2.0 Refresh token storage interface.
*
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
@@ -10,17 +8,24 @@
*/
namespace League\OAuth2\Server\Repositories;
use League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface;
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
/**
* Refresh token interface.
*/
interface RefreshTokenRepositoryInterface extends RepositoryInterface
{
/**
* Creates a new refresh token
*
* @return RefreshTokenEntityInterface
*/
public function getNewRefreshToken();
/**
* Create a new refresh token_name.
*
* @param \League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface $refreshTokenEntity
* @param \League\OAuth2\Server\Entities\RefreshTokenEntityInterface $refreshTokenEntity
*/
public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntity);

View File

@@ -1,7 +1,5 @@
<?php
/**
* OAuth 2.0 Repository interface.
*
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/

View File

@@ -1,17 +1,16 @@
<?php
/**
* OAuth 2.0 Scope 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\ClientEntityInterface;
use League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Entities\ScopeEntityInterface;
/**
* Scope interface.
@@ -23,7 +22,7 @@ interface ScopeRepositoryInterface extends RepositoryInterface
*
* @param string $identifier The scope identifier
*
* @return \League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface
* @return \League\OAuth2\Server\Entities\ScopeEntityInterface
*/
public function getScopeEntityByIdentifier($identifier);
@@ -31,12 +30,12 @@ interface ScopeRepositoryInterface extends RepositoryInterface
* Given a client, grant type and optional user identifier validate the set of scopes requested are valid and optionally
* append additional scopes or remove requested scopes.
*
* @param ScopeEntityInterface[] $scopes
* @param string $grantType
* @param \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface $clientEntity
* @param null|string $userIdentifier
* @param ScopeEntityInterface[] $scopes
* @param string $grantType
* @param \League\OAuth2\Server\Entities\ClientEntityInterface $clientEntity
* @param null|string $userIdentifier
*
* @return \League\OAuth2\Server\Entities\Interfaces\ScopeEntityInterface[]
* @return \League\OAuth2\Server\Entities\ScopeEntityInterface[]
*/
public function finalizeScopes(
array $scopes,

View File

@@ -1,20 +1,27 @@
<?php
/**
* @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\ClientEntityInterface;
use League\OAuth2\Server\Entities\ClientEntityInterface;
interface UserRepositoryInterface extends RepositoryInterface
{
/**
* Get a user entity.
*
* @param string $username
* @param string $password
* @param string $grantType The grant type used
* @param \League\OAuth2\Server\Entities\Interfaces\ClientEntityInterface $clientEntity
* @param string $username
* @param string $password
* @param string $grantType The grant type used
* @param \League\OAuth2\Server\Entities\ClientEntityInterface $clientEntity
*
* @return \League\OAuth2\Server\Entities\Interfaces\UserEntityInterface
* @return \League\OAuth2\Server\Entities\UserEntityInterface
*/
public function getUserEntityByUserCredentials(
$username,

View File

@@ -1,5 +1,11 @@
<?php
/**
* @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\Event;
@@ -7,6 +13,10 @@ use Psr\Http\Message\ServerRequestInterface;
class RequestEvent extends Event
{
const CLIENT_AUTHENTICATION_FAILED = 'client.authentication.failed';
const USER_AUTHENTICATION_FAILED = 'user.authentication.failed';
const REFRESH_TOKEN_CLIENT_FAILED = 'refresh_token.client.failed';
/**
* @var \Psr\Http\Message\ServerRequestInterface
*/
@@ -26,6 +36,7 @@ class RequestEvent extends Event
/**
* @return ServerRequestInterface
* @codeCoverageIgnore
*/
public function getRequest()
{

View File

@@ -0,0 +1,178 @@
<?php
/**
* @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\RequestTypes;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Entities\ScopeEntityInterface;
use League\OAuth2\Server\Entities\UserEntityInterface;
class AuthorizationRequest
{
/**
* The grant type identifier
*
* @var string
*/
protected $grantTypeId;
/**
* The client identifier
*
* @var ClientEntityInterface
*/
protected $client;
/**
* The user identifier
*
* @var UserEntityInterface
*/
protected $user;
/**
* An array of scope identifiers
*
* @var ScopeEntityInterface[]
*/
protected $scopes = [];
/**
* Has the user authorized the authorization request
*
* @var bool
*/
protected $authorizationApproved = false;
/**
* The redirect URI used in the request
*
* @var string
*/
protected $redirectUri;
/**
* The state parameter on the authorization request
*
* @var string
*/
protected $state;
/**
* @return string
*/
public function getGrantTypeId()
{
return $this->grantTypeId;
}
/**
* @param string $grantTypeId
*/
public function setGrantTypeId($grantTypeId)
{
$this->grantTypeId = $grantTypeId;
}
/**
* @return ClientEntityInterface
*/
public function getClient()
{
return $this->client;
}
/**
* @param ClientEntityInterface $client
*/
public function setClient(ClientEntityInterface $client)
{
$this->client = $client;
}
/**
* @return UserEntityInterface
*/
public function getUser()
{
return $this->user;
}
/**
* @param UserEntityInterface $user
*/
public function setUser(UserEntityInterface $user)
{
$this->user = $user;
}
/**
* @return \League\OAuth2\Server\Entities\ScopeEntityInterface[]
*/
public function getScopes()
{
return $this->scopes;
}
/**
* @param \League\OAuth2\Server\Entities\ScopeEntityInterface[] $scopes
*/
public function setScopes($scopes)
{
$this->scopes = $scopes;
}
/**
* @return bool
*/
public function isAuthorizationApproved()
{
return $this->authorizationApproved;
}
/**
* @param bool $authorizationApproved
*/
public function setAuthorizationApproved($authorizationApproved)
{
$this->authorizationApproved = $authorizationApproved;
}
/**
* @return string
*/
public function getRedirectUri()
{
return $this->redirectUri;
}
/**
* @param string $redirectUri
*/
public function setRedirectUri($redirectUri)
{
$this->redirectUri = $redirectUri;
}
/**
* @return string
*/
public function getState()
{
return $this->state;
}
/**
* @param string $state
*/
public function setState($state)
{
$this->state = $state;
}
}

80
src/ResourceServer.php Normal file
View File

@@ -0,0 +1,80 @@
<?php
/**
* @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\AuthorizationValidators\AuthorizationValidatorInterface;
use League\OAuth2\Server\AuthorizationValidators\BearerTokenValidator;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use Psr\Http\Message\ServerRequestInterface;
class ResourceServer
{
/**
* @var \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface
*/
private $accessTokenRepository;
/**
* @var \League\OAuth2\Server\CryptKey|string
*/
private $publicKey;
/**
* @var \League\OAuth2\Server\AuthorizationValidators\AuthorizationValidatorInterface|null
*/
private $authorizationValidator;
/**
* New server instance.
*
* @param \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface $accessTokenRepository
* @param \League\OAuth2\Server\CryptKey|string $publicKey
* @param null|\League\OAuth2\Server\AuthorizationValidators\AuthorizationValidatorInterface $authorizationValidator
*/
public function __construct(
AccessTokenRepositoryInterface $accessTokenRepository,
$publicKey,
AuthorizationValidatorInterface $authorizationValidator = null
) {
$this->accessTokenRepository = $accessTokenRepository;
if (!$publicKey instanceof CryptKey) {
$publicKey = new CryptKey($publicKey);
}
$this->publicKey = $publicKey;
$this->authorizationValidator = $authorizationValidator;
}
/**
* @return \League\OAuth2\Server\AuthorizationValidators\AuthorizationValidatorInterface
*/
protected function getAuthorizationValidator()
{
if (!$this->authorizationValidator instanceof AuthorizationValidatorInterface) {
$this->authorizationValidator = new BearerTokenValidator($this->accessTokenRepository);
}
$this->authorizationValidator->setPublicKey($this->publicKey);
return $this->authorizationValidator;
}
/**
* Determine the access token validity.
*
* @param \Psr\Http\Message\ServerRequestInterface $request
*
* @throws \League\OAuth2\Server\Exception\OAuthServerException
*
* @return \Psr\Http\Message\ServerRequestInterface
*/
public function validateAuthenticatedRequest(ServerRequestInterface $request)
{
return $this->getAuthorizationValidator()->validateAuthorization($request);
}
}

View File

@@ -11,37 +11,23 @@
namespace League\OAuth2\Server\ResponseTypes;
use League\OAuth2\Server\CryptTrait;
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
abstract class AbstractResponseType implements ResponseTypeInterface
{
use CryptTrait;
/**
* @var \League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface
* @var \League\OAuth2\Server\Entities\AccessTokenEntityInterface
*/
protected $accessToken;
/**
* @var \League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface
* @var \League\OAuth2\Server\Entities\RefreshTokenEntityInterface
*/
protected $refreshToken;
/**
* @var \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface
*/
protected $accessTokenRepository;
/**
* @param \League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface $accessTokenRepository
*/
public function __construct(AccessTokenRepositoryInterface $accessTokenRepository)
{
$this->accessTokenRepository = $accessTokenRepository;
}
/**
* {@inheritdoc}
*/

View File

@@ -10,7 +10,7 @@
*/
namespace League\OAuth2\Server\ResponseTypes;
use League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface;
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
use Psr\Http\Message\ResponseInterface;
class BearerTokenResponse extends AbstractResponseType
@@ -22,7 +22,7 @@ class BearerTokenResponse extends AbstractResponseType
{
$expireDateTime = $this->accessToken->getExpiryDateTime()->getTimestamp();
$jwtAccessToken = $this->accessToken->convertToJWT($this->privateKeyPath);
$jwtAccessToken = $this->accessToken->convertToJWT($this->privateKey);
$responseParams = [
'token_type' => 'Bearer',
@@ -39,7 +39,7 @@ class BearerTokenResponse extends AbstractResponseType
'access_token_id' => $this->accessToken->getIdentifier(),
'scopes' => $this->accessToken->getScopes(),
'user_id' => $this->accessToken->getUserIdentifier(),
'expire_time' => $expireDateTime,
'expire_time' => $this->refreshToken->getExpiryDateTime()->getTimestamp(),
]
)
);

View File

@@ -1,66 +0,0 @@
<?php
namespace League\OAuth2\Server\ResponseTypes;
use Psr\Http\Message\ResponseInterface;
class HtmlResponse extends AbstractResponseType
{
/**
* @var string
*/
private $html = '';
/**
* @var int
*/
private $statusCode = 200;
/**
* @var array
*/
private $headers = [];
/**
* @param string $html
*/
public function setHtml($html)
{
$this->html = $html;
}
/**
* @param int $statusCode
*/
public function setStatusCode($statusCode = 200)
{
$this->statusCode = $statusCode;
}
/**
* @param ResponseInterface $response
*
* @return ResponseInterface
*/
public function generateHttpResponse(ResponseInterface $response)
{
$response->getBody()->write($this->html);
foreach ($this->headers as $key => $value) {
$response = $response->withHeader($key, $value);
}
return $response
->withStatus($this->statusCode)
->withHeader('content-type', 'text/html');
}
/**
* @param string $key
* @param string $value
*/
public function setHeader($key, $value)
{
$this->headers[$key] = $value;
}
}

View File

@@ -26,6 +26,6 @@ class RedirectResponse extends AbstractResponseType
*/
public function generateHttpResponse(ResponseInterface $response)
{
return $response->withStatus(302)->withHeader('location', $this->redirectUri);
return $response->withStatus(302)->withHeader('Location', $this->redirectUri);
}
}

View File

@@ -10,19 +10,19 @@
*/
namespace League\OAuth2\Server\ResponseTypes;
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
use Psr\Http\Message\ResponseInterface;
interface ResponseTypeInterface
{
/**
* @param \League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface $accessToken
* @param \League\OAuth2\Server\Entities\AccessTokenEntityInterface $accessToken
*/
public function setAccessToken(AccessTokenEntityInterface $accessToken);
/**
* @param \League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface $refreshToken
* @param \League\OAuth2\Server\Entities\RefreshTokenEntityInterface $refreshToken
*/
public function setRefreshToken(RefreshTokenEntityInterface $refreshToken);

View File

@@ -1,70 +0,0 @@
<?php
/**
* Base template renderer.
*
* @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\TemplateRenderer;
abstract class AbstractRenderer implements RendererInterface
{
/**
* @var string
*/
protected $loginTemplate;
/**
* @var string
*/
protected $authorizeTemplate;
/**
* PlatesRenderer constructor.
*
* @param string $loginTemplate
* @param string $authorizeTemplate
*/
public function __construct($loginTemplate, $authorizeTemplate)
{
$this->loginTemplate = $loginTemplate;
$this->authorizeTemplate = $authorizeTemplate;
}
/**
* Render login template.
*
* @param array $data
*
* @return string
*/
public function renderLogin(array $data = [])
{
return $this->render($this->loginTemplate, $data);
}
/**
* Render authorize template.
*
* @param array $data
*
* @return string
*/
public function renderAuthorize(array $data = [])
{
return $this->render($this->authorizeTemplate, $data);
}
/**
* Render template.
*
* @param string $template
* @param array $data
*
* @return string
*/
abstract protected function render($template, array $data = []);
}

View File

@@ -1,35 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Authorize <?=$this->e($client->getName())?></title>
</head>
<body>
<h1>
Authorize <?=$this->e($client->getName())?>
</h1>
<p>
Do you want to authorize <?=$this->e($client->getName())?> to access the following data?
</p>
<ul>
<?php foreach ($scopes as $scope): ?>
<li><?=$scope->getIdentifier()?></li>
<?php endforeach; ?>
</ul>
<form method="POST">
<input type="hidden" value="approve" name="action">
<button type="submit">Approve</button>
</form>
<form method="POST">
<input type="hidden" value="deny" name="action">
<button type="submit">Deny</button>
</form>
</body>
</html>

View File

@@ -1,35 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Login</title>
</head>
<body>
<h1>Login</h1>
<?php if ($error !== null): ?>
<div style="border:solid 1px red; padding: 1rem; margin-bottom:1rem">
<?=$this->e($error)?>
</div>
<?php endif; ?>
<form method="POST">
<label for="username">Username</label>
<input type="text" id="username" name="username">
<br>
<label for="password">Password</label>
<input type="password" id="password" name="password">
<br>
<input type="submit" value="Login">
</form>
</body>
</html>

View File

@@ -1,41 +0,0 @@
<?php
/**
* Mustache template renderer bridge.
*
* @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\TemplateRenderer;
class MustacheRenderer extends AbstractRenderer
{
/**
* @var \Mustache_Engine
*/
private $engine;
/**
* PlatesRenderer constructor.
*
* @param \Mustache_Engine $engine
* @param string $loginTemplate
* @param string $authorizeTemplate
*/
public function __construct(\Mustache_Engine $engine, $loginTemplate, $authorizeTemplate)
{
parent::__construct($loginTemplate, $authorizeTemplate);
$this->engine = $engine;
}
/**
* {@inheritdoc}
*/
public function render($template, array $data = [])
{
return $this->engine->render($template, $data);
}
}

View File

@@ -1,47 +0,0 @@
<?php
/**
* Plates template renderer bridge.
*
* @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\TemplateRenderer;
use League\Plates\Engine;
class PlatesRenderer extends AbstractRenderer
{
/**
* @var \League\Plates\Engine
*/
private $engine;
/**
* PlatesRenderer constructor.
*
* @param \League\Plates\Engine $engine
* @param string $loginTemplate
* @param string $authorizeTemplate
*/
public function __construct(Engine $engine, $loginTemplate, $authorizeTemplate)
{
parent::__construct($loginTemplate, $authorizeTemplate);
$this->engine = $engine;
}
/**
* {@inheritdoc}
*/
protected function render($template, array $data = [])
{
if ($this->engine->getFileExtension()) {
$template = preg_replace(sprintf('/\.%s$/', $this->engine->getFileExtension()), '', $template);
}
return $this->engine->render($template, $data);
}
}

View File

@@ -1,24 +0,0 @@
<?php
namespace League\OAuth2\Server\TemplateRenderer;
interface RendererInterface
{
/**
* Render login template.
*
* @param array $data
*
* @return string
*/
public function renderLogin(array $data = []);
/**
* Render authorize template.
*
* @param array $data
*
* @return string
*/
public function renderAuthorize(array $data = []);
}

View File

@@ -1,49 +0,0 @@
<?php
/**
* Smarty template renderer bridge.
*
* @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\TemplateRenderer;
class SmartyRenderer extends AbstractRenderer
{
/**
* Smarty class.
*
* @var \Smarty
*/
private $smarty;
/**
* PlatesRenderer constructor.
*
* @param \Smarty $smarty
* @param string $loginTemplate
* @param string $authorizeTemplate
*/
public function __construct(\Smarty $smarty, $loginTemplate, $authorizeTemplate)
{
parent::__construct($loginTemplate, $authorizeTemplate);
$this->smarty = $smarty;
}
/**
* {@inheritdoc}
*/
protected function render($template, array $data = [])
{
$this->smarty->assign($data);
$output = $this->smarty->fetch($template);
$this->smarty->clear_assign(array_keys($data));
return $output;
}
}

View File

@@ -1,41 +0,0 @@
<?php
/**
* Twig template renderer bridge.
*
* @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\TemplateRenderer;
class TwigRenderer extends AbstractRenderer
{
/**
* @var \Twig_Environment
*/
private $environment;
/**
* PlatesRenderer constructor.
*
* @param \Twig_Environment $environment
* @param string $loginTemplate
* @param string $authorizeTemplate
*/
public function __construct(\Twig_Environment $environment, $loginTemplate, $authorizeTemplate)
{
parent::__construct($loginTemplate, $authorizeTemplate);
$this->environment = $environment;
}
/**
* {@inheritdoc}
*/
protected function render($template, array $data = [])
{
return $this->environment->loadTemplate($template)->render($data);
}
}

View File

@@ -0,0 +1,204 @@
<?php
namespace LeagueTests;
use League\OAuth2\Server\AuthorizationServer;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Grant\AuthCodeGrant;
use League\OAuth2\Server\Grant\ClientCredentialsGrant;
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\RequestTypes\AuthorizationRequest;
use League\OAuth2\Server\ResponseTypes\BearerTokenResponse;
use LeagueTests\Stubs\AccessTokenEntity;
use LeagueTests\Stubs\AuthCodeEntity;
use LeagueTests\Stubs\ClientEntity;
use LeagueTests\Stubs\StubResponseType;
use LeagueTests\Stubs\UserEntity;
use Psr\Http\Message\ResponseInterface;
use Zend\Diactoros\Response;
use Zend\Diactoros\ServerRequest;
use Zend\Diactoros\ServerRequestFactory;
class AuthorizationServerTest extends \PHPUnit_Framework_TestCase
{
public function testRespondToRequestInvalidGrantType()
{
$server = new AuthorizationServer(
$this->getMock(ClientRepositoryInterface::class),
$this->getMock(AccessTokenRepositoryInterface::class),
$this->getMock(ScopeRepositoryInterface::class),
'file://' . __DIR__ . '/Stubs/private.key',
'file://' . __DIR__ . '/Stubs/public.key',
new StubResponseType()
);
$server->enableGrantType(new ClientCredentialsGrant(), new \DateInterval('PT1M'));
try {
$server->respondToAccessTokenRequest(ServerRequestFactory::fromGlobals(), new Response);
} catch (OAuthServerException $e) {
$this->assertEquals('unsupported_grant_type', $e->getErrorType());
$this->assertEquals(400, $e->getHttpStatusCode());
}
}
public function testRespondToRequest()
{
$clientRepository = $this->getMock(ClientRepositoryInterface::class);
$clientRepository->method('getClientEntity')->willReturn(new ClientEntity());
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
$accessTokenRepositoryMock = $this->getMock(AccessTokenRepositoryInterface::class);
$accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
$server = new AuthorizationServer(
$clientRepository,
$accessTokenRepositoryMock,
$scopeRepositoryMock,
'file://' . __DIR__ . '/Stubs/private.key',
'file://' . __DIR__ . '/Stubs/public.key',
new StubResponseType()
);
$server->enableGrantType(new ClientCredentialsGrant(), new \DateInterval('PT1M'));
$_POST['grant_type'] = 'client_credentials';
$_POST['client_id'] = 'foo';
$_POST['client_secret'] = 'bar';
$response = $server->respondToAccessTokenRequest(ServerRequestFactory::fromGlobals(), new Response);
$this->assertEquals(200, $response->getStatusCode());
}
public function testGetResponseType()
{
$clientRepository = $this->getMock(ClientRepositoryInterface::class);
$server = new AuthorizationServer(
$clientRepository,
$this->getMock(AccessTokenRepositoryInterface::class),
$this->getMock(ScopeRepositoryInterface::class),
'file://' . __DIR__ . '/Stubs/private.key',
'file://' . __DIR__ . '/Stubs/public.key'
);
$abstractGrantReflection = new \ReflectionClass($server);
$method = $abstractGrantReflection->getMethod('getResponseType');
$method->setAccessible(true);
$this->assertTrue($method->invoke($server) instanceof BearerTokenResponse);
}
public function testCompleteAuthorizationRequest()
{
$clientRepository = $this->getMock(ClientRepositoryInterface::class);
$server = new AuthorizationServer(
$clientRepository,
$this->getMock(AccessTokenRepositoryInterface::class),
$this->getMock(ScopeRepositoryInterface::class),
'file://' . __DIR__ . '/Stubs/private.key',
'file://' . __DIR__ . '/Stubs/public.key'
);
$authCodeRepository = $this->getMockBuilder(AuthCodeRepositoryInterface::class)->getMock();
$authCodeRepository->method('getNewAuthCode')->willReturn(new AuthCodeEntity());
$grant = new AuthCodeGrant(
$authCodeRepository,
$this->getMock(RefreshTokenRepositoryInterface::class),
new \DateInterval('PT10M')
);
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/Stubs/private.key'));
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/Stubs/public.key'));
$server->enableGrantType($grant);
$authRequest = new AuthorizationRequest();
$authRequest->setAuthorizationApproved(true);
$authRequest->setClient(new ClientEntity());
$authRequest->setGrantTypeId('authorization_code');
$authRequest->setUser(new UserEntity());
$this->assertTrue(
$server->completeAuthorizationRequest($authRequest, new Response) instanceof ResponseInterface
);
}
public function testValidateAuthorizationRequest()
{
$client = new ClientEntity();
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$grant = new AuthCodeGrant(
$this->getMock(AuthCodeRepositoryInterface::class),
$this->getMock(RefreshTokenRepositoryInterface::class),
new \DateInterval('PT10M')
);
$grant->setClientRepository($clientRepositoryMock);
$server = new AuthorizationServer(
$clientRepositoryMock,
$this->getMock(AccessTokenRepositoryInterface::class),
$this->getMock(ScopeRepositoryInterface::class),
'file://' . __DIR__ . '/Stubs/private.key',
'file://' . __DIR__ . '/Stubs/public.key'
);
$server->enableGrantType($grant);
$request = new ServerRequest(
[],
[],
null,
null,
'php://input',
$headers = [],
$cookies = [],
$queryParams = [
'response_type' => 'code',
'client_id' => 'foo',
]
);
$this->assertTrue($server->validateAuthorizationRequest($request) instanceof AuthorizationRequest);
}
/**
* @expectedException \League\OAuth2\Server\Exception\OAuthServerException
* @expectedExceptionCode 2
*/
public function testValidateAuthorizationRequestUnregistered()
{
$server = new AuthorizationServer(
$this->getMock(ClientRepositoryInterface::class),
$this->getMock(AccessTokenRepositoryInterface::class),
$this->getMock(ScopeRepositoryInterface::class),
'file://' . __DIR__ . '/Stubs/private.key',
'file://' . __DIR__ . '/Stubs/public.key'
);
$request = new ServerRequest(
[],
[],
null,
null,
'php://input',
$headers = [],
$cookies = [],
$queryParams = [
'response_type' => 'code',
'client_id' => 'foo',
]
);
$server->validateAuthorizationRequest($request);
}
}

View File

@@ -2,6 +2,7 @@
namespace LeagueTests\Utils;
use League\OAuth2\Server\CryptKey;
use LeagueTests\Stubs\CryptTraitStub;
class CryptTraitTest extends \PHPUnit_Framework_TestCase
@@ -31,7 +32,7 @@ class CryptTraitTest extends \PHPUnit_Framework_TestCase
*/
public function testBadPrivateKey()
{
$this->cryptStub->setPrivateKeyPath(__DIR__ . '/Stubs/public.key');
$this->cryptStub->setPrivateKey(new CryptKey(__DIR__ . '/Stubs/public.key'));
$this->cryptStub->doEncrypt('');
}
@@ -40,7 +41,15 @@ class CryptTraitTest extends \PHPUnit_Framework_TestCase
*/
public function testBadPublicKey()
{
$this->cryptStub->setPublicKeyPath(__DIR__ . '/Stubs/private.key');
$this->cryptStub->setPublicKey(new CryptKey(__DIR__ . '/Stubs/private.key'));
$this->cryptStub->doDecrypt('');
}
/**
* @expectedException \LogicException
*/
public function testNonExistentKey()
{
new CryptKey('foo/bar');
}
}

View File

@@ -3,17 +3,21 @@
namespace LeagueTests\Grant;
use League\Event\Emitter;
use League\OAuth2\Server\Entities\AccessTokenEntity;
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface;
use League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\AuthCodeEntityInterface;
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
use League\OAuth2\Server\Grant\AbstractGrant;
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\RequestTypes\AuthorizationRequest;
use LeagueTests\Stubs\AccessTokenEntity;
use LeagueTests\Stubs\AuthCodeEntity;
use LeagueTests\Stubs\ClientEntity;
use LeagueTests\Stubs\RefreshTokenEntity;
use LeagueTests\Stubs\ScopeEntity;
use Zend\Diactoros\ServerRequest;
@@ -23,8 +27,8 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase
{
/** @var AbstractGrant $grantMock */
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
$grantMock->setPrivateKeyPath('./private.key');
$grantMock->setPublicKeyPath('./public.key');
$grantMock->setPrivateKey(new CryptKey(__DIR__ . '/../Stubs/private.key'));
$grantMock->setPublicKey(new CryptKey(__DIR__ . '/../Stubs/public.key'));
$grantMock->setEmitter(new Emitter());
}
@@ -57,8 +61,6 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase
public function testValidateClientConfidential()
{
$client = new ClientEntity();
$client->setSecret('bar');
$client->setRedirectUri('http://foo/bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
@@ -175,8 +177,36 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase
$serverRequest = new ServerRequest();
$serverRequest = $serverRequest->withParsedBody([
'client_id' => 'foo',
'redirect_uri' => 'http://bar/foo',
'client_id' => 'foo',
'redirect_uri' => 'http://bar/foo',
]);
$validateClientMethod = $abstractGrantReflection->getMethod('validateClient');
$validateClientMethod->setAccessible(true);
$validateClientMethod->invoke($grantMock, $serverRequest, true, true);
}
/**
* @expectedException \League\OAuth2\Server\Exception\OAuthServerException
*/
public function testValidateClientInvalidRedirectUriArray()
{
$client = new ClientEntity();
$client->setRedirectUri(['http://foo/bar']);
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
/** @var AbstractGrant $grantMock */
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
$grantMock->setClientRepository($clientRepositoryMock);
$abstractGrantReflection = new \ReflectionClass($grantMock);
$serverRequest = new ServerRequest();
$serverRequest = $serverRequest->withParsedBody([
'client_id' => 'foo',
'redirect_uri' => 'http://bar/foo',
]);
$validateClientMethod = $abstractGrantReflection->getMethod('validateClient');
@@ -221,12 +251,16 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase
'grant_type' => 'foobar',
]);
$this->assertTrue($grantMock->canRespondToRequest($serverRequest));
$this->assertTrue($grantMock->canRespondToAccessTokenRequest($serverRequest));
}
public function testIssueRefreshToken()
{
$refreshTokenRepoMock = $this->getMock(RefreshTokenRepositoryInterface::class);
$refreshTokenRepoMock
->expects($this->once())
->method('getNewRefreshToken')
->willReturn(new RefreshTokenEntity());
/** @var AbstractGrant $grantMock */
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
@@ -248,6 +282,7 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase
public function testIssueAccessToken()
{
$accessTokenRepoMock = $this->getMock(AccessTokenRepositoryInterface::class);
$accessTokenRepoMock->method('getNewToken')->willReturn(new AccessTokenEntity());
/** @var AbstractGrant $grantMock */
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
@@ -272,6 +307,7 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase
public function testIssueAuthCode()
{
$authCodeRepoMock = $this->getMock(AuthCodeRepositoryInterface::class);
$authCodeRepoMock->expects($this->once())->method('getNewAuthCode')->willReturn(new AuthCodeEntity());
/** @var AbstractGrant $grantMock */
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
@@ -339,7 +375,7 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
$grantMock->setScopeRepository($scopeRepositoryMock);
$this->assertEquals([$scope], $grantMock->validateScopes('basic ', new ClientEntity()));
$this->assertEquals([$scope], $grantMock->validateScopes('basic '));
}
/**
@@ -354,7 +390,7 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
$grantMock->setScopeRepository($scopeRepositoryMock);
$grantMock->validateScopes('basic ', new ClientEntity());
$grantMock->validateScopes('basic ');
}
public function testGenerateUniqueIdentifier()
@@ -367,4 +403,28 @@ class AbstractGrantTest extends \PHPUnit_Framework_TestCase
$this->assertTrue(is_string($method->invoke($grantMock)));
}
public function testCanRespondToAuthorizationRequest()
{
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
$this->assertFalse($grantMock->canRespondToAuthorizationRequest(new ServerRequest()));
}
/**
* @expectedException \LogicException
*/
public function testValidateAuthorizationRequest()
{
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
$grantMock->validateAuthorizationRequest(new ServerRequest());
}
/**
* @expectedException \LogicException
*/
public function testCompleteAuthorizationRequest()
{
$grantMock = $this->getMockForAbstractClass(AbstractGrant::class);
$grantMock->completeAuthorizationRequest(new AuthorizationRequest());
}
}

View File

@@ -2,8 +2,9 @@
namespace LeagueTests\Grant;
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Grant\AuthCodeGrant;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
@@ -11,16 +12,16 @@ 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\ResponseTypes\HtmlResponse;
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
use League\OAuth2\Server\ResponseTypes\RedirectResponse;
use LeagueTests\Stubs\AccessTokenEntity;
use LeagueTests\Stubs\AuthCodeEntity;
use LeagueTests\Stubs\ClientEntity;
use LeagueTests\Stubs\CryptTraitStub;
use LeagueTests\Stubs\RefreshTokenEntity;
use LeagueTests\Stubs\ScopeEntity;
use LeagueTests\Stubs\StubResponseType;
use LeagueTests\Stubs\UserEntity;
use Psr\Http\Message\ResponseInterface;
use Zend\Diactoros\Response;
use Zend\Diactoros\ServerRequest;
class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase
@@ -40,19 +41,17 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase
$grant = new AuthCodeGrant(
$this->getMock(AuthCodeRepositoryInterface::class),
$this->getMock(RefreshTokenRepositoryInterface::class),
$this->getMock(UserRepositoryInterface::class),
new \DateInterval('PT10M')
);
$this->assertEquals('authorization_code', $grant->getIdentifier());
}
public function testCanRespondToRequest()
public function testCanRespondToAuthorizationRequest()
{
$grant = new AuthCodeGrant(
$this->getMock(AuthCodeRepositoryInterface::class),
$this->getMock(RefreshTokenRepositoryInterface::class),
$this->getMock(UserRepositoryInterface::class),
new \DateInterval('PT10M')
);
@@ -70,509 +69,257 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase
]
);
$this->assertTrue($grant->canRespondToRequest($request));
$this->assertTrue($grant->canRespondToAuthorizationRequest($request));
}
public function testRespondToAuthorizationRequest()
public function testValidateAuthorizationRequest()
{
$client = new ClientEntity();
$client->setRedirectUri('http://foo/bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$userEntity = new UserEntity();
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
$grant = new AuthCodeGrant(
$this->getMock(AuthCodeRepositoryInterface::class),
$this->getMock(RefreshTokenRepositoryInterface::class),
$userRepositoryMock,
new \DateInterval('PT10M')
);
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setScopeRepository($scopeRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$request = new ServerRequest(
[
'HTTP_HOST' => 'auth-server.tld',
'REQUEST_URI' => '/authorize',
],
[],
[],
null,
'POST',
null,
'php://input',
[],
[
'oauth_authorize_request' => $this->cryptStub->doEncrypt(json_encode(['user_id' => 123])),
],
[
$headers = [],
$cookies = [],
$queryParams = [
'response_type' => 'code',
'client_id' => 'foo',
'state' => 'foobar',
],
[
'username' => 'alex',
'password' => 'whisky',
'action' => 'approve',
'redirect_uri' => 'http://foo/bar',
]
);
$response = $grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
$this->assertTrue($response instanceof RedirectResponse);
$response = $response->generateHttpResponse(new Response);
$this->assertTrue(strstr($response->getHeader('location')[0], 'http://foo/bar') !== false);
$this->assertTrue($grant->validateAuthorizationRequest($request) instanceof AuthorizationRequest);
}
/**
* @expectedException \League\OAuth2\Server\Exception\OAuthServerException
* @expectedExceptionCode 9
*/
public function testRespondToAuthorizationRequestUserDenied()
public function testValidateAuthorizationRequestRedirectUriArray()
{
$client = new ClientEntity();
$client->setRedirectUri('http://foo/bar');
$client->setRedirectUri(['http://foo/bar']);
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$userEntity = new UserEntity();
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
$grant = new AuthCodeGrant(
$this->getMock(AuthCodeRepositoryInterface::class),
$this->getMock(RefreshTokenRepositoryInterface::class),
$userRepositoryMock,
new \DateInterval('PT10M')
);
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$request = new ServerRequest(
[
'HTTP_HOST' => 'auth-server.tld',
'REQUEST_URI' => '/authorize',
],
[],
[],
null,
'POST',
null,
'php://input',
[],
[
'oauth_authorize_request' => $this->cryptStub->doEncrypt(json_encode(['user_id' => 123])),
],
[
$headers = [],
$cookies = [],
$queryParams = [
'response_type' => 'code',
'client_id' => 'foo',
'state' => 'foobar',
],
[
'username' => 'alex',
'password' => 'whisky',
'action' => 'denied',
'redirect_uri' => 'http://foo/bar',
]
);
$grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
$this->assertTrue($grant->validateAuthorizationRequest($request) instanceof AuthorizationRequest);
}
/**
* @expectedException \League\OAuth2\Server\Exception\OAuthServerException
* @expectedExceptionCode 3
*/
public function testRespondToAuthorizationRequestMissingClientId()
public function testValidateAuthorizationRequestMissingClientId()
{
$client = new ClientEntity();
$client->setRedirectUri('http://foo/bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$userEntity = new UserEntity();
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
$grant = new AuthCodeGrant(
$this->getMock(AuthCodeRepositoryInterface::class),
$this->getMock(RefreshTokenRepositoryInterface::class),
$userRepositoryMock,
new \DateInterval('PT10M')
);
$grant->setClientRepository($clientRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$request = new ServerRequest(
[
'HTTP_HOST' => 'auth-server.tld',
'REQUEST_URI' => '/authorize',
],
[],
[],
null,
'POST',
null,
'php://input',
[],
[
'oauth_authorize_request' => $this->cryptStub->doEncrypt(json_encode(['user_id' => 123])),
],
[
$headers = [],
$cookies = [],
$queryParams = [
'response_type' => 'code',
],
[
'username' => 'alex',
'password' => 'whisky',
'action' => 'approve',
]
);
$grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
}
public function testRespondToAuthorizationRequestBadClient()
{
$client = null;
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$userEntity = new UserEntity();
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
$grant = new AuthCodeGrant(
$this->getMock(AuthCodeRepositoryInterface::class),
$this->getMock(RefreshTokenRepositoryInterface::class),
$userRepositoryMock,
new \DateInterval('PT10M')
);
$grant->setClientRepository($clientRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$request = new ServerRequest(
[
'HTTP_HOST' => 'auth-server.tld',
'REQUEST_URI' => '/authorize',
],
[],
null,
'POST',
'php://input',
[],
[
'oauth_authorize_request' => $this->cryptStub->doEncrypt(json_encode(['user_id' => 123])),
],
[
'response_type' => 'code',
'client_id' => 'foo',
],
[
'username' => 'alex',
'password' => 'whisky',
'action' => 'approve',
]
);
try {
/* @var StubResponseType $response */
$grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
} catch (OAuthServerException $e) {
$this->assertEquals($e->getMessage(), 'Client authentication failed');
}
}
public function testRespondToAuthorizationRequestBadRedirectUri()
{
$client = new ClientEntity();
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$userEntity = new UserEntity();
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
$grant = new AuthCodeGrant(
$this->getMock(AuthCodeRepositoryInterface::class),
$this->getMock(RefreshTokenRepositoryInterface::class),
$userRepositoryMock,
new \DateInterval('PT10M')
);
$grant->setClientRepository($clientRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$request = new ServerRequest(
[
'HTTP_HOST' => 'auth-server.tld',
'REQUEST_URI' => '/authorize',
],
[],
null,
'POST',
'php://input',
[],
[
'oauth_authorize_request' => $this->cryptStub->doEncrypt(json_encode(['user_id' => 123])),
],
[
'response_type' => 'code',
'client_id' => 'foo',
'redirect_uri' => 'sdfsdf',
],
[
'username' => 'alex',
'password' => 'whisky',
'action' => 'approve',
]
);
try {
/* @var StubResponseType $response */
$grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
} catch (OAuthServerException $e) {
$this->assertEquals($e->getMessage(), 'Client authentication failed');
}
$grant->validateAuthorizationRequest($request);
}
/**
* @expectedException \League\OAuth2\Server\Exception\OAuthServerException
* @expectedExceptionCode 7
* @expectedExceptionCode 4
*/
public function testRespondToAuthorizationRequestBadCookie()
public function testValidateAuthorizationRequestInvalidClientId()
{
$client = new ClientEntity();
$client->setRedirectUri('http://foo/bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$userEntity = new UserEntity();
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
$clientRepositoryMock->method('getClientEntity')->willReturn(null);
$grant = new AuthCodeGrant(
$this->getMock(AuthCodeRepositoryInterface::class),
$this->getMock(RefreshTokenRepositoryInterface::class),
$userRepositoryMock,
new \DateInterval('PT10M')
);
$grant->setClientRepository($clientRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$request = new ServerRequest(
[
'HTTP_HOST' => 'auth-server.tld',
'REQUEST_URI' => '/authorize',
],
[],
[],
null,
'POST',
null,
'php://input',
[],
[
'oauth_authorize_request' => 'blah',
],
[
$headers = [],
$cookies = [],
$queryParams = [
'response_type' => 'code',
'client_id' => 'foo',
],
[
'username' => 'alex',
'password' => 'whisky',
'action' => 'approve',
]
);
$grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
$grant->validateAuthorizationRequest($request);
}
public function testRespondToAuthorizationRequestTryLogin()
/**
* @expectedException \League\OAuth2\Server\Exception\OAuthServerException
* @expectedExceptionCode 4
*/
public function testValidateAuthorizationRequestBadRedirectUriString()
{
$client = new ClientEntity();
$client->setRedirectUri('http://foo/bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$userEntity = new UserEntity();
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
$grant = new AuthCodeGrant(
$this->getMock(AuthCodeRepositoryInterface::class),
$this->getMock(RefreshTokenRepositoryInterface::class),
$userRepositoryMock,
new \DateInterval('PT10M')
);
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setScopeRepository($scopeRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$request = new ServerRequest(
[
'HTTP_HOST' => 'auth-server.tld',
'REQUEST_URI' => '/authorize',
],
[],
[],
null,
'POST',
null,
'php://input',
[],
[
'oauth_authorize_request' => $this->cryptStub->doEncrypt(json_encode(['user_id' => null])),
],
[
$headers = [],
$cookies = [],
$queryParams = [
'response_type' => 'code',
'client_id' => 'foo',
],
[
'username' => 'alex',
'password' => 'whisky',
'action' => 'approve',
'redirect_uri' => 'http://bar',
]
);
$response = $grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
$this->assertTrue($response instanceof RedirectResponse);
$response = $response->generateHttpResponse(new Response);
$this->assertTrue(strstr($response->getHeader('location')[0], 'http://foo/bar') !== false);
$grant->validateAuthorizationRequest($request);
}
public function testRespondToAuthorizationRequestShowLoginForm()
/**
* @expectedException \League\OAuth2\Server\Exception\OAuthServerException
* @expectedExceptionCode 4
*/
public function testValidateAuthorizationRequestBadRedirectUriArray()
{
$client = new ClientEntity();
$client->setRedirectUri('http://foo/bar');
$client->setRedirectUri(['http://foo/bar']);
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$userEntity = null;
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
$grant = new AuthCodeGrant(
$this->getMock(AuthCodeRepositoryInterface::class),
$this->getMock(RefreshTokenRepositoryInterface::class),
$userRepositoryMock,
new \DateInterval('PT10M')
);
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$request = new ServerRequest(
[
'HTTP_HOST' => 'auth-server.tld',
'REQUEST_URI' => '/authorize',
],
[],
[],
null,
'POST',
null,
'php://input',
[],
[
'oauth_authorize_request' => $this->cryptStub->doEncrypt(json_encode(['user_id' => null])),
],
[
$headers = [],
$cookies = [],
$queryParams = [
'response_type' => 'code',
'client_id' => 'foo',
],
[
'username' => 'alex',
'password' => 'whisky',
'action' => 'approve',
'redirect_uri' => 'http://bar',
]
);
$response = $grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
$this->assertTrue($response instanceof HtmlResponse);
$response = $response->generateHttpResponse(new Response);
$this->assertTrue(strstr($response->getHeader('content-type')[0], 'text/html') !== false);
$this->assertTrue(strstr((string) $response->getBody(), 'Incorrect username or password') !== false);
$grant->validateAuthorizationRequest($request);
}
public function testRespondToAuthorizationRequestShowAuthorizeForm()
public function testCompleteAuthorizationRequest()
{
$client = new ClientEntity();
$client->setRedirectUri('http://foo/bar');
$client->setName('Test Client');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$authRequest = new AuthorizationRequest();
$authRequest->setAuthorizationApproved(true);
$authRequest->setClient(new ClientEntity());
$authRequest->setGrantTypeId('authorization_code');
$authRequest->setUser(new UserEntity());
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$userEntity = new UserEntity();
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
$authCodeRepository = $this->getMockBuilder(AuthCodeRepositoryInterface::class)->getMock();
$authCodeRepository->method('getNewAuthCode')->willReturn(new AuthCodeEntity());
$grant = new AuthCodeGrant(
$this->getMock(AuthCodeRepositoryInterface::class),
$authCodeRepository,
$this->getMock(RefreshTokenRepositoryInterface::class),
$userRepositoryMock,
new \DateInterval('PT10M')
);
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$request = new ServerRequest(
[
'HTTP_HOST' => 'auth-server.tld',
'REQUEST_URI' => '/authorize',
],
[],
null,
'POST',
'php://input',
[],
[
'oauth_authorize_request' => $this->cryptStub->doEncrypt(json_encode(['user_id' => 123])),
],
[
'response_type' => 'code',
'client_id' => 'foo',
],
[
'username' => 'alex',
'password' => 'whisky',
]
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$this->assertTrue($grant->completeAuthorizationRequest($authRequest) instanceof RedirectResponse);
}
/**
* @expectedException \League\OAuth2\Server\Exception\OAuthServerException
* @expectedExceptionCode 9
*/
public function testCompleteAuthorizationRequestDenied()
{
$authRequest = new AuthorizationRequest();
$authRequest->setAuthorizationApproved(false);
$authRequest->setClient(new ClientEntity());
$authRequest->setGrantTypeId('authorization_code');
$authRequest->setUser(new UserEntity());
$authCodeRepository = $this->getMockBuilder(AuthCodeRepositoryInterface::class)->getMock();
$authCodeRepository->method('getNewAuthCode')->willReturn(new AuthCodeEntity());
$grant = new AuthCodeGrant(
$authCodeRepository,
$this->getMock(RefreshTokenRepositoryInterface::class),
new \DateInterval('PT10M')
);
$response = $grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$response = $response->generateHttpResponse(new Response);
$this->assertTrue($response instanceof ResponseInterface);
$this->assertTrue(strstr($response->getHeader('set-cookie')[0], 'oauth_authorize_request') !== false);
$grant->completeAuthorizationRequest($authRequest);
}
public function testRespondToAccessTokenRequest()
@@ -583,32 +330,30 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$userEntity = new UserEntity();
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
$scopeEntity = new ScopeEntity();
$scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scopeEntity);
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
$refreshTokenRepositoryMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock();
$refreshTokenRepositoryMock->method('persistNewRefreshToken')->willReturnSelf();
$refreshTokenRepositoryMock->method('getNewRefreshToken')->willReturn(new RefreshTokenEntity());
$grant = new AuthCodeGrant(
$this->getMock(AuthCodeRepositoryInterface::class),
$this->getMock(RefreshTokenRepositoryInterface::class),
$userRepositoryMock,
new \DateInterval('PT10M')
);
$grant->setClientRepository($clientRepositoryMock);
$grant->setScopeRepository($scopeRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setRefreshTokenRepository($refreshTokenRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$request = new ServerRequest(
[],
@@ -639,7 +384,7 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase
);
/** @var StubResponseType $response */
$response = $grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
$response = $grant->respondToAccessTokenRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
$this->assertTrue($response->getAccessToken() instanceof AccessTokenEntityInterface);
$this->assertTrue($response->getRefreshToken() instanceof RefreshTokenEntityInterface);
@@ -652,21 +397,19 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase
public function testRespondToAccessTokenRequestMissingRedirectUri()
{
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$refreshTokenRepositoryMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock();
$grant = new AuthCodeGrant(
$this->getMock(AuthCodeRepositoryInterface::class),
$this->getMock(RefreshTokenRepositoryInterface::class),
$userRepositoryMock,
new \DateInterval('PT10M')
);
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setRefreshTokenRepository($refreshTokenRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$request = new ServerRequest(
[],
@@ -683,7 +426,7 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase
);
/* @var StubResponseType $response */
$grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
$grant->respondToAccessTokenRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
}
/**
@@ -693,26 +436,23 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase
public function testRespondToAccessTokenRequestMissingCode()
{
$client = new ClientEntity();
$client->setSecret('bar');
$client->setRedirectUri('http://foo/bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$refreshTokenRepositoryMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock();
$grant = new AuthCodeGrant(
$this->getMock(AuthCodeRepositoryInterface::class),
$this->getMock(RefreshTokenRepositoryInterface::class),
$userRepositoryMock,
new \DateInterval('PT10M')
);
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setRefreshTokenRepository($refreshTokenRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$request = new ServerRequest(
[],
@@ -732,7 +472,7 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase
);
/* @var StubResponseType $response */
$grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
$grant->respondToAccessTokenRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
}
public function testRespondToAccessTokenRequestExpiredCode()
@@ -743,10 +483,6 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$userEntity = new UserEntity();
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
@@ -756,14 +492,13 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase
$grant = new AuthCodeGrant(
$this->getMock(AuthCodeRepositoryInterface::class),
$this->getMock(RefreshTokenRepositoryInterface::class),
$userRepositoryMock,
new \DateInterval('PT10M')
);
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setRefreshTokenRepository($refreshTokenRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$request = new ServerRequest(
[],
@@ -795,7 +530,7 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase
try {
/* @var StubResponseType $response */
$grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
$grant->respondToAccessTokenRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
} catch (OAuthServerException $e) {
$this->assertEquals($e->getHint(), 'Authorization code has expired');
}
@@ -809,10 +544,6 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$userEntity = new UserEntity();
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
@@ -825,14 +556,13 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase
$grant = new AuthCodeGrant(
$authCodeRepositoryMock,
$this->getMock(RefreshTokenRepositoryInterface::class),
$userRepositoryMock,
new \DateInterval('PT10M')
);
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setRefreshTokenRepository($refreshTokenRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$request = new ServerRequest(
[],
@@ -864,7 +594,7 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase
try {
/* @var StubResponseType $response */
$grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
$grant->respondToAccessTokenRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
} catch (OAuthServerException $e) {
$this->assertEquals($e->getHint(), 'Authorization code has been revoked');
}
@@ -878,10 +608,6 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$userEntity = new UserEntity();
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
@@ -891,14 +617,13 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase
$grant = new AuthCodeGrant(
$this->getMock(AuthCodeRepositoryInterface::class),
$this->getMock(RefreshTokenRepositoryInterface::class),
$userRepositoryMock,
new \DateInterval('PT10M')
);
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setRefreshTokenRepository($refreshTokenRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$request = new ServerRequest(
[],
@@ -930,7 +655,7 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase
try {
/* @var StubResponseType $response */
$grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
$grant->respondToAccessTokenRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
} catch (OAuthServerException $e) {
$this->assertEquals($e->getHint(), 'Authorization code was not issued to this client');
}
@@ -944,10 +669,6 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$userEntity = new UserEntity();
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
@@ -957,14 +678,13 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase
$grant = new AuthCodeGrant(
$this->getMock(AuthCodeRepositoryInterface::class),
$this->getMock(RefreshTokenRepositoryInterface::class),
$userRepositoryMock,
new \DateInterval('PT10M')
);
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setRefreshTokenRepository($refreshTokenRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$request = new ServerRequest(
[],
@@ -985,7 +705,7 @@ class AuthCodeGrantTest extends \PHPUnit_Framework_TestCase
try {
/* @var StubResponseType $response */
$grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
$grant->respondToAccessTokenRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
} catch (OAuthServerException $e) {
$this->assertEquals($e->getHint(), 'Cannot decrypt the authorization code');
}

View File

@@ -2,11 +2,12 @@
namespace LeagueTests\Grant;
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
use League\OAuth2\Server\Grant\ClientCredentialsGrant;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
use LeagueTests\Stubs\AccessTokenEntity;
use LeagueTests\Stubs\ClientEntity;
use LeagueTests\Stubs\StubResponseType;
use Zend\Diactoros\ServerRequest;
@@ -22,11 +23,11 @@ class ClientCredentialsGrantTest extends \PHPUnit_Framework_TestCase
public function testRespondToRequest()
{
$client = new ClientEntity();
$client->setSecret('bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
@@ -46,7 +47,7 @@ class ClientCredentialsGrantTest extends \PHPUnit_Framework_TestCase
);
$responseType = new StubResponseType();
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
$this->assertTrue($responseType->getAccessToken() instanceof AccessTokenEntityInterface);
}

View File

@@ -2,19 +2,17 @@
namespace LeagueTests\Grant;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\Grant\ImplicitGrant;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
use League\OAuth2\Server\ResponseTypes\HtmlResponse;
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
use League\OAuth2\Server\ResponseTypes\RedirectResponse;
use LeagueTests\Stubs\AccessTokenEntity;
use LeagueTests\Stubs\ClientEntity;
use LeagueTests\Stubs\CryptTraitStub;
use LeagueTests\Stubs\StubResponseType;
use LeagueTests\Stubs\UserEntity;
use Zend\Diactoros\Response;
use Zend\Diactoros\ServerRequest;
class ImplicitGrantTest extends \PHPUnit_Framework_TestCase
@@ -31,14 +29,35 @@ class ImplicitGrantTest extends \PHPUnit_Framework_TestCase
public function testGetIdentifier()
{
$grant = new ImplicitGrant($this->getMock(UserRepositoryInterface::class));
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
$this->assertEquals('implicit', $grant->getIdentifier());
}
public function testCanRespondToRequest()
public function testCanRespondToAccessTokenRequest()
{
$grant = new ImplicitGrant($this->getMock(UserRepositoryInterface::class));
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
$this->assertFalse(
$grant->canRespondToAccessTokenRequest(new ServerRequest())
);
}
/**
* @expectedException \LogicException
*/
public function testRespondToAccessTokenRequest()
{
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
$grant->respondToAccessTokenRequest(
new ServerRequest(),
new StubResponseType(),
new \DateInterval('PT10M')
);
}
public function testCanRespondToAuthorizationRequest()
{
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
$request = new ServerRequest(
[],
@@ -46,389 +65,234 @@ class ImplicitGrantTest extends \PHPUnit_Framework_TestCase
null,
null,
'php://input',
[],
[],
[
$headers = [],
$cookies = [],
$queryParams = [
'response_type' => 'token',
'client_id' => 'foo',
]
);
$this->assertTrue($grant->canRespondToRequest($request));
$this->assertTrue($grant->canRespondToAuthorizationRequest($request));
}
public function testRespondToAuthorizationRequest()
public function testValidateAuthorizationRequest()
{
$client = new ClientEntity();
$client->setRedirectUri('http://foo/bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$userEntity = new UserEntity();
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
$grant = new ImplicitGrant($userRepositoryMock);
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setScopeRepository($scopeRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$request = new ServerRequest(
[
'HTTP_HOST' => 'auth-server.tld',
'REQUEST_URI' => '/authorize',
],
[],
[],
null,
'POST',
null,
'php://input',
[],
[],
[
'response_type' => 'token',
$headers = [],
$cookies = [],
$queryParams = [
'response_type' => 'code',
'client_id' => 'foo',
'state' => 'foobar',
],
[
'username' => 'alex',
'password' => 'whisky',
'action' => 'approve',
'redirect_uri' => 'http://foo/bar',
]
);
$response = $grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
$this->assertTrue($grant->validateAuthorizationRequest($request) instanceof AuthorizationRequest);
}
$this->assertTrue($response instanceof RedirectResponse);
public function testValidateAuthorizationRequestRedirectUriArray()
{
$client = new ClientEntity();
$client->setRedirectUri(['http://foo/bar']);
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
$grant->setClientRepository($clientRepositoryMock);
$request = new ServerRequest(
[],
[],
null,
null,
'php://input',
$headers = [],
$cookies = [],
$queryParams = [
'response_type' => 'code',
'client_id' => 'foo',
'redirect_uri' => 'http://foo/bar',
]
);
$this->assertTrue($grant->validateAuthorizationRequest($request) instanceof AuthorizationRequest);
}
/**
* @expectedException \League\OAuth2\Server\Exception\OAuthServerException
* @expectedExceptionCode 3
*/
public function testRespondToAuthorizationRequestMissingClientId()
public function testValidateAuthorizationRequestMissingClientId()
{
$grant = new ImplicitGrant($this->getMock(UserRepositoryInterface::class));
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$request = new ServerRequest(
[
'HTTP_HOST' => 'auth-server.tld',
'REQUEST_URI' => '/authorize',
],
[],
null,
'POST',
'php://input',
[],
[
'oauth_authorize_request' => $this->cryptStub->doEncrypt(json_encode(['user_id' => 123])),
],
[
'response_type' => 'token',
],
[
'username' => 'alex',
'password' => 'whisky',
'action' => 'approve',
]
);
$grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
}
public function testRespondToAuthorizationRequestBadClient()
{
$client = null;
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$grant = new ImplicitGrant($this->getMock(UserRepositoryInterface::class));
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
$grant->setClientRepository($clientRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$request = new ServerRequest(
[
'HTTP_HOST' => 'auth-server.tld',
'REQUEST_URI' => '/authorize',
],
[],
[],
null,
'POST',
null,
'php://input',
[],
[
'oauth_authorize_request' => $this->cryptStub->doEncrypt(json_encode(['user_id' => 123])),
],
[
'response_type' => 'token',
'client_id' => 'foo',
],
[
'username' => 'alex',
'password' => 'whisky',
'action' => 'approve',
$headers = [],
$cookies = [],
$queryParams = [
'response_type' => 'code',
]
);
try {
/* @var StubResponseType $response */
$grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
} catch (OAuthServerException $e) {
$this->assertEquals($e->getMessage(), 'Client authentication failed');
}
}
public function testRespondToAuthorizationRequestBadRedirectUri()
{
$client = new ClientEntity();
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$userEntity = new UserEntity();
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
$grant = new ImplicitGrant($this->getMock(UserRepositoryInterface::class));
$grant->setClientRepository($clientRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$request = new ServerRequest(
[
'HTTP_HOST' => 'auth-server.tld',
'REQUEST_URI' => '/authorize',
],
[],
null,
'POST',
'php://input',
[],
[
'oauth_authorize_request' => $this->cryptStub->doEncrypt(json_encode(['user_id' => 123])),
],
[
'response_type' => 'token',
'client_id' => 'foo',
'redirect_uri' => 'sdfsdf',
],
[
'username' => 'alex',
'password' => 'whisky',
'action' => 'approve',
]
);
try {
/* @var StubResponseType $response */
$grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
} catch (OAuthServerException $e) {
$this->assertEquals($e->getMessage(), 'Client authentication failed');
}
$grant->validateAuthorizationRequest($request);
}
/**
* @expectedException \League\OAuth2\Server\Exception\OAuthServerException
* @expectedExceptionCode 7
* @expectedExceptionCode 4
*/
public function testRespondToAuthorizationRequestBadCookie()
public function testValidateAuthorizationRequestInvalidClientId()
{
$client = new ClientEntity();
$client->setRedirectUri('http://foo/bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$clientRepositoryMock->method('getClientEntity')->willReturn(null);
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$userEntity = new UserEntity();
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
$grant = new ImplicitGrant($this->getMock(UserRepositoryInterface::class));
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
$grant->setClientRepository($clientRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$request = new ServerRequest(
[
'HTTP_HOST' => 'auth-server.tld',
'REQUEST_URI' => '/authorize',
],
[],
[],
null,
'POST',
'php://input',
[],
[
'oauth_authorize_request' => 'blah',
],
[
'response_type' => 'token',
'client_id' => 'foo',
],
[
'username' => 'alex',
'password' => 'whisky',
'action' => 'approve',
]
);
$grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
}
public function testRespondToAuthorizationRequestTryLogin()
{
$client = new ClientEntity();
$client->setRedirectUri('http://foo/bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$userEntity = new UserEntity();
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
$grant = new ImplicitGrant($this->getMock(UserRepositoryInterface::class));
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$request = new ServerRequest(
[
'HTTP_HOST' => 'auth-server.tld',
'REQUEST_URI' => '/authorize',
],
[],
null,
'POST',
'php://input',
[],
[
'oauth_authorize_request' => $this->cryptStub->doEncrypt(json_encode(['user_id' => null])),
],
[
'response_type' => 'token',
'client_id' => 'foo',
],
[
'username' => 'alex',
'password' => 'whisky',
'action' => 'approve',
]
);
$response = $grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
$this->assertTrue($response instanceof HtmlResponse);
$response = $response->generateHttpResponse(new Response);
$this->assertTrue(strstr((string) $response->getBody(), 'Incorrect username or password') !== false);
}
public function testRespondToAuthorizationRequestShowAuthorizeForm()
{
$client = new ClientEntity();
$client->setRedirectUri('http://foo/bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$userEntity = new UserEntity();
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
$grant = new ImplicitGrant($this->getMock(UserRepositoryInterface::class));
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$request = new ServerRequest(
[
'HTTP_HOST' => 'auth-server.tld',
'REQUEST_URI' => '/authorize',
],
[],
null,
'POST',
'php://input',
[],
[
'oauth_authorize_request' => $this->cryptStub->doEncrypt(json_encode(['user_id' => 123])),
],
[
$headers = [],
$cookies = [],
$queryParams = [
'response_type' => 'code',
'client_id' => 'foo',
],
[
'username' => 'alex',
'password' => 'whisky',
]
);
$response = $grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
$grant->validateAuthorizationRequest($request);
}
$this->assertTrue($response instanceof HtmlResponse);
/**
* @expectedException \League\OAuth2\Server\Exception\OAuthServerException
* @expectedExceptionCode 4
*/
public function testValidateAuthorizationRequestBadRedirectUriString()
{
$client = new ClientEntity();
$client->setRedirectUri('http://foo/bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$response = $response->generateHttpResponse(new Response);
$this->assertTrue(strstr($response->getHeader('set-cookie')[0], 'oauth_authorize_request') !== false);
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
$grant->setClientRepository($clientRepositoryMock);
$request = new ServerRequest(
[],
[],
null,
null,
'php://input',
$headers = [],
$cookies = [],
$queryParams = [
'response_type' => 'code',
'client_id' => 'foo',
'redirect_uri' => 'http://bar',
]
);
$grant->validateAuthorizationRequest($request);
}
/**
* @expectedException \League\OAuth2\Server\Exception\OAuthServerException
* @expectedExceptionCode 4
*/
public function testValidateAuthorizationRequestBadRedirectUriArray()
{
$client = new ClientEntity();
$client->setRedirectUri(['http://foo/bar']);
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
$grant->setClientRepository($clientRepositoryMock);
$request = new ServerRequest(
[],
[],
null,
null,
'php://input',
$headers = [],
$cookies = [],
$queryParams = [
'response_type' => 'code',
'client_id' => 'foo',
'redirect_uri' => 'http://bar',
]
);
$grant->validateAuthorizationRequest($request);
}
public function testCompleteAuthorizationRequest()
{
$authRequest = new AuthorizationRequest();
$authRequest->setAuthorizationApproved(true);
$authRequest->setClient(new ClientEntity());
$authRequest->setGrantTypeId('authorization_code');
$authRequest->setUser(new UserEntity());
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$this->assertTrue($grant->completeAuthorizationRequest($authRequest) instanceof RedirectResponse);
}
/**
* @expectedException \League\OAuth2\Server\Exception\OAuthServerException
* @expectedExceptionCode 9
*/
public function testRespondToAuthorizationRequestUserDenied()
public function testCompleteAuthorizationRequestDenied()
{
$client = new ClientEntity();
$client->setRedirectUri('http://foo/bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$authRequest = new AuthorizationRequest();
$authRequest->setAuthorizationApproved(false);
$authRequest->setClient(new ClientEntity());
$authRequest->setGrantTypeId('authorization_code');
$authRequest->setUser(new UserEntity());
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
$userEntity = new UserEntity();
$userRepositoryMock->method('getUserEntityByUserCredentials')->willReturn($userEntity);
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
$grant = new ImplicitGrant($this->getMock(UserRepositoryInterface::class));
$grant->setClientRepository($clientRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$grant = new ImplicitGrant(new \DateInterval('PT10M'));
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$request = new ServerRequest(
[
'HTTP_HOST' => 'auth-server.tld',
'REQUEST_URI' => '/authorize',
],
[],
null,
'POST',
'php://input',
[],
[
'oauth_authorize_request' => $this->cryptStub->doEncrypt(json_encode(['user_id' => 123])),
],
[
'response_type' => 'code',
'client_id' => 'foo',
'state' => 'foobar',
],
[
'username' => 'alex',
'password' => 'whisky',
'action' => 'denied',
]
);
$grant->respondToRequest($request, new StubResponseType(), new \DateInterval('PT10M'));
$grant->completeAuthorizationRequest($authRequest);
}
}

View File

@@ -2,15 +2,17 @@
namespace LeagueTests\Grant;
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
use League\OAuth2\Server\Grant\PasswordGrant;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
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 LeagueTests\Stubs\AccessTokenEntity;
use LeagueTests\Stubs\ClientEntity;
use LeagueTests\Stubs\RefreshTokenEntity;
use LeagueTests\Stubs\StubResponseType;
use LeagueTests\Stubs\UserEntity;
use Zend\Diactoros\ServerRequest;
@@ -29,11 +31,11 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase
public function testRespondToRequest()
{
$client = new ClientEntity();
$client->setSecret('bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
$userRepositoryMock = $this->getMockBuilder(UserRepositoryInterface::class)->getMock();
@@ -42,6 +44,7 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase
$refreshTokenRepositoryMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock();
$refreshTokenRepositoryMock->method('persistNewRefreshToken')->willReturnSelf();
$refreshTokenRepositoryMock->method('getNewRefreshToken')->willReturn(new RefreshTokenEntity());
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
@@ -62,7 +65,7 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase
);
$responseType = new StubResponseType();
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
$this->assertTrue($responseType->getAccessToken() instanceof AccessTokenEntityInterface);
$this->assertTrue($responseType->getRefreshToken() instanceof RefreshTokenEntityInterface);
@@ -74,7 +77,6 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase
public function testRespondToRequestMissingUsername()
{
$client = new ClientEntity();
$client->setSecret('bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
@@ -97,7 +99,7 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase
);
$responseType = new StubResponseType();
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
}
/**
@@ -106,7 +108,6 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase
public function testRespondToRequestMissingPassword()
{
$client = new ClientEntity();
$client->setSecret('bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
@@ -130,7 +131,7 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase
);
$responseType = new StubResponseType();
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
}
/**
@@ -139,7 +140,6 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase
public function testRespondToRequestBadCredentials()
{
$client = new ClientEntity();
$client->setSecret('bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
@@ -165,6 +165,6 @@ class PasswordGrantTest extends \PHPUnit_Framework_TestCase
);
$responseType = new StubResponseType();
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
}
}

View File

@@ -2,15 +2,18 @@
namespace LeagueTests\Grant;
use League\OAuth2\Server\Entities\Interfaces\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\Interfaces\RefreshTokenEntityInterface;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
use League\OAuth2\Server\Grant\RefreshTokenGrant;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
use LeagueTests\Stubs\AccessTokenEntity;
use LeagueTests\Stubs\ClientEntity;
use LeagueTests\Stubs\CryptTraitStub;
use LeagueTests\Stubs\RefreshTokenEntity;
use LeagueTests\Stubs\ScopeEntity;
use LeagueTests\Stubs\StubResponseType;
use Zend\Diactoros\ServerRequest;
@@ -39,7 +42,6 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
{
$client = new ClientEntity();
$client->setIdentifier('foo');
$client->setSecret('bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
@@ -48,11 +50,13 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
$scopeRepositoryMock->method('getScopeEntityByIdentifier')->willReturn($scopeEntity);
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
$accessTokenRepositoryMock
->expects($this->once())
->method('persistNewAccessToken')->willReturnSelf();
$refreshTokenRepositoryMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock();
$refreshTokenRepositoryMock->method('getNewRefreshToken')->willReturn(new RefreshTokenEntity());
$refreshTokenRepositoryMock
->expects($this->once())
->method('persistNewRefreshToken')->willReturnSelf();
@@ -61,8 +65,8 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
$grant->setClientRepository($clientRepositoryMock);
$grant->setScopeRepository($scopeRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$oldRefreshToken = $this->cryptStub->doEncrypt(
json_encode(
@@ -87,7 +91,7 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
);
$responseType = new StubResponseType();
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
$this->assertTrue($responseType->getAccessToken() instanceof AccessTokenEntityInterface);
$this->assertTrue($responseType->getRefreshToken() instanceof RefreshTokenEntityInterface);
@@ -97,15 +101,16 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
{
$client = new ClientEntity();
$client->setIdentifier('foo');
$client->setSecret('bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
$accessTokenRepositoryMock->method('persistNewAccessToken')->willReturnSelf();
$refreshTokenRepositoryMock = $this->getMockBuilder(RefreshTokenRepositoryInterface::class)->getMock();
$refreshTokenRepositoryMock->method('persistNewRefreshToken')->willReturnSelf();
$refreshTokenRepositoryMock->method('getNewRefreshToken')->willReturn(new RefreshTokenEntity());
$scope = new ScopeEntity();
$scope->setIdentifier('foo');
@@ -116,8 +121,8 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setScopeRepository($scopeRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$oldRefreshToken = $this->cryptStub->doEncrypt(
json_encode(
@@ -143,7 +148,7 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
);
$responseType = new StubResponseType();
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
$this->assertTrue($responseType->getAccessToken() instanceof AccessTokenEntityInterface);
$this->assertTrue($responseType->getRefreshToken() instanceof RefreshTokenEntityInterface);
@@ -157,7 +162,6 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
{
$client = new ClientEntity();
$client->setIdentifier('foo');
$client->setSecret('bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
@@ -176,8 +180,8 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setScopeRepository($scopeRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$oldRefreshToken = $this->cryptStub->doEncrypt(
json_encode(
@@ -203,7 +207,7 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
);
$responseType = new StubResponseType();
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
}
/**
@@ -214,7 +218,6 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
{
$client = new ClientEntity();
$client->setIdentifier('foo');
$client->setSecret('bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
@@ -224,8 +227,8 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
$grant = new RefreshTokenGrant($refreshTokenRepositoryMock);
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$serverRequest = new ServerRequest();
$serverRequest = $serverRequest->withParsedBody(
@@ -236,7 +239,7 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
);
$responseType = new StubResponseType();
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
}
/**
@@ -247,7 +250,6 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
{
$client = new ClientEntity();
$client->setIdentifier('foo');
$client->setSecret('bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
@@ -257,8 +259,8 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
$grant = new RefreshTokenGrant($refreshTokenRepositoryMock);
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$oldRefreshToken = 'foobar';
@@ -272,7 +274,7 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
);
$responseType = new StubResponseType();
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
}
/**
@@ -283,7 +285,6 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
{
$client = new ClientEntity();
$client->setIdentifier('foo');
$client->setSecret('bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
@@ -297,8 +298,8 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
$grant = new RefreshTokenGrant($refreshTokenRepositoryMock);
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$oldRefreshToken = $this->cryptStub->doEncrypt(
json_encode(
@@ -323,7 +324,7 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
);
$responseType = new StubResponseType();
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
}
/**
@@ -334,7 +335,6 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
{
$client = new ClientEntity();
$client->setIdentifier('foo');
$client->setSecret('bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
@@ -344,8 +344,8 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
$grant = new RefreshTokenGrant($refreshTokenRepositoryMock);
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$oldRefreshToken = $this->cryptStub->doEncrypt(
json_encode(
@@ -370,7 +370,7 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
);
$responseType = new StubResponseType();
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
}
/**
@@ -381,7 +381,6 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
{
$client = new ClientEntity();
$client->setIdentifier('foo');
$client->setSecret('bar');
$clientRepositoryMock = $this->getMockBuilder(ClientRepositoryInterface::class)->getMock();
$clientRepositoryMock->method('getClientEntity')->willReturn($client);
@@ -392,8 +391,8 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
$grant = new RefreshTokenGrant($refreshTokenRepositoryMock);
$grant->setClientRepository($clientRepositoryMock);
$grant->setAccessTokenRepository($accessTokenRepositoryMock);
$grant->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$grant->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$grant->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$grant->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$oldRefreshToken = $this->cryptStub->doEncrypt(
json_encode(
@@ -418,6 +417,6 @@ class RefreshTokenGrantTest extends \PHPUnit_Framework_TestCase
);
$responseType = new StubResponseType();
$grant->respondToRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
$grant->respondToAccessTokenRequest($serverRequest, $responseType, new \DateInterval('PT5M'));
}
}

View File

@@ -2,18 +2,20 @@
namespace LeagueTests\Middleware;
use League\OAuth2\Server\AuthorizationServer;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Grant\ClientCredentialsGrant;
use League\OAuth2\Server\Middleware\AuthenticationServerMiddleware;
use League\OAuth2\Server\Middleware\AuthorizationServerMiddleware;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
use League\OAuth2\Server\Server;
use LeagueTests\Stubs\AccessTokenEntity;
use LeagueTests\Stubs\ClientEntity;
use LeagueTests\Stubs\StubResponseType;
use Zend\Diactoros\Response;
use Zend\Diactoros\ServerRequestFactory;
class AuthenticationServerMiddlewareTest extends \PHPUnit_Framework_TestCase
class AuthorizationServerMiddlewareTest extends \PHPUnit_Framework_TestCase
{
public function testValidResponse()
{
@@ -23,16 +25,19 @@ class AuthenticationServerMiddlewareTest extends \PHPUnit_Framework_TestCase
$scopeRepositoryMock = $this->getMockBuilder(ScopeRepositoryInterface::class)->getMock();
$scopeRepositoryMock->method('finalizeScopes')->willReturnArgument(0);
$server = new Server(
$accessRepositoryMock = $this->getMock(AccessTokenRepositoryInterface::class);
$accessRepositoryMock->method('getNewToken')->willReturn(new AccessTokenEntity());
$server = new AuthorizationServer(
$clientRepository,
$this->getMock(AccessTokenRepositoryInterface::class),
$accessRepositoryMock,
$scopeRepositoryMock,
'',
'',
'file://' . __DIR__ . '/../Stubs/private.key',
'file://' . __DIR__ . '/../Stubs/public.key',
new StubResponseType()
);
$server->enableGrantType(new ClientCredentialsGrant(), new \DateInterval('PT1M'));
$server->enableGrantType(new ClientCredentialsGrant());
$_POST['grant_type'] = 'client_credentials';
$_POST['client_id'] = 'foo';
@@ -40,7 +45,7 @@ class AuthenticationServerMiddlewareTest extends \PHPUnit_Framework_TestCase
$request = ServerRequestFactory::fromGlobals();
$middleware = new AuthenticationServerMiddleware($server);
$middleware = new AuthorizationServerMiddleware($server);
$response = $middleware->__invoke(
$request,
new Response(),
@@ -56,12 +61,12 @@ class AuthenticationServerMiddlewareTest extends \PHPUnit_Framework_TestCase
$clientRepository = $this->getMock(ClientRepositoryInterface::class);
$clientRepository->method('getClientEntity')->willReturn(null);
$server = new Server(
$server = new AuthorizationServer(
$clientRepository,
$this->getMock(AccessTokenRepositoryInterface::class),
$this->getMock(ScopeRepositoryInterface::class),
'',
'',
'file://' . __DIR__ . '/../Stubs/private.key',
'file://' . __DIR__ . '/../Stubs/public.key',
new StubResponseType()
);
@@ -73,7 +78,7 @@ class AuthenticationServerMiddlewareTest extends \PHPUnit_Framework_TestCase
$request = ServerRequestFactory::fromGlobals();
$middleware = new AuthenticationServerMiddleware($server);
$middleware = new AuthorizationServerMiddleware($server);
$response = $middleware->__invoke(
$request,
@@ -85,4 +90,22 @@ class AuthenticationServerMiddlewareTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(401, $response->getStatusCode());
}
public function testOAuthErrorResponseRedirectUri()
{
$exception = OAuthServerException::invalidScope('test', 'http://foo/bar');
$response = $exception->generateHttpResponse(new Response());
$this->assertEquals(302, $response->getStatusCode());
$this->assertEquals('http://foo/bar?error=invalid_scope&message=The+requested+scope+is+invalid%2C+unknown%2C+or+malformed&hint=Check+the+%60test%60+scope', $response->getHeader('location')[0]);
}
public function testOAuthErrorResponseRedirectUriFragment()
{
$exception = OAuthServerException::invalidScope('test', 'http://foo/bar');
$response = $exception->generateHttpResponse(new Response(), true);
$this->assertEquals(302, $response->getStatusCode());
$this->assertEquals('http://foo/bar#error=invalid_scope&message=The+requested+scope+is+invalid%2C+unknown%2C+or+malformed&hint=Check+the+%60test%60+scope', $response->getHeader('location')[0]);
}
}

View File

@@ -2,14 +2,12 @@
namespace LeagueTests\Middleware;
use League\OAuth2\Server\Entities\AccessTokenEntity;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\Middleware\ResourceServerMiddleware;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use League\OAuth2\Server\Repositories\ClientRepositoryInterface;
use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
use League\OAuth2\Server\Server;
use League\OAuth2\Server\ResourceServer;
use LeagueTests\Stubs\AccessTokenEntity;
use LeagueTests\Stubs\ClientEntity;
use LeagueTests\Stubs\StubResponseType;
use Zend\Diactoros\Response;
use Zend\Diactoros\ServerRequest;
@@ -17,15 +15,9 @@ class ResourceServerMiddlewareTest extends \PHPUnit_Framework_TestCase
{
public function testValidResponse()
{
$clientRepository = $this->getMock(ClientRepositoryInterface::class);
$server = new Server(
$clientRepository,
$server = new ResourceServer(
$this->getMock(AccessTokenRepositoryInterface::class),
$this->getMock(ScopeRepositoryInterface::class),
'file://' . __DIR__ . '/../Stubs/private.key',
'file://' . __DIR__ . '/../Stubs/public.key',
new StubResponseType()
'file://' . __DIR__ . '/../Stubs/public.key'
);
$client = new ClientEntity();
@@ -37,7 +29,7 @@ class ResourceServerMiddlewareTest extends \PHPUnit_Framework_TestCase
$accessToken->setExpiryDateTime((new \DateTime())->add(new \DateInterval('PT1H')));
$accessToken->setClient($client);
$token = $accessToken->convertToJWT('file://' . __DIR__ . '/../Stubs/private.key');
$token = $accessToken->convertToJWT(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$request = new ServerRequest();
$request = $request->withHeader('authorization', sprintf('Bearer %s', $token));
@@ -56,17 +48,46 @@ class ResourceServerMiddlewareTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(200, $response->getStatusCode());
}
public function testValidResponseExpiredToken()
{
$server = new ResourceServer(
$this->getMock(AccessTokenRepositoryInterface::class),
'file://' . __DIR__ . '/../Stubs/public.key'
);
$client = new ClientEntity();
$client->setIdentifier('clientName');
$accessToken = new AccessTokenEntity();
$accessToken->setIdentifier('test');
$accessToken->setUserIdentifier(123);
$accessToken->setExpiryDateTime((new \DateTime())->sub(new \DateInterval('PT1H')));
$accessToken->setClient($client);
$token = $accessToken->convertToJWT(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$request = new ServerRequest();
$request = $request->withHeader('authorization', sprintf('Bearer %s', $token));
$middleware = new ResourceServerMiddleware($server);
$response = $middleware->__invoke(
$request,
new Response(),
function () {
$this->assertEquals('test', func_get_args()[0]->getAttribute('oauth_access_token_id'));
return func_get_args()[1];
}
);
$this->assertEquals(401, $response->getStatusCode());
}
public function testErrorResponse()
{
$clientRepository = $this->getMock(ClientRepositoryInterface::class);
$server = new Server(
$clientRepository,
$server = new ResourceServer(
$this->getMock(AccessTokenRepositoryInterface::class),
$this->getMock(ScopeRepositoryInterface::class),
'',
'',
new StubResponseType()
'file://' . __DIR__ . '/../Stubs/public.key'
);
$request = new ServerRequest();

View File

@@ -0,0 +1,26 @@
<?php
namespace LeagueTests;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use League\OAuth2\Server\ResourceServer;
use Zend\Diactoros\ServerRequestFactory;
class ResourceServerTest extends \PHPUnit_Framework_TestCase
{
public function testValidateAuthenticatedRequest()
{
$server = new ResourceServer(
$this->getMock(AccessTokenRepositoryInterface::class),
'file://' . __DIR__ . '/Stubs/public.key'
);
try {
$server->validateAuthenticatedRequest(ServerRequestFactory::fromGlobals());
} catch (OAuthServerException $e) {
$this->assertEquals('Missing "Authorization" header', $e->getHint());
}
}
}

View File

@@ -3,12 +3,13 @@
namespace LeagueTests\ResponseTypes;
use League\OAuth2\Server\AuthorizationValidators\BearerTokenValidator;
use League\OAuth2\Server\Entities\AccessTokenEntity;
use League\OAuth2\Server\Entities\RefreshTokenEntity;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use League\OAuth2\Server\ResponseTypes\BearerTokenResponse;
use LeagueTests\Stubs\AccessTokenEntity;
use LeagueTests\Stubs\ClientEntity;
use LeagueTests\Stubs\RefreshTokenEntity;
use LeagueTests\Stubs\ScopeEntity;
use Psr\Http\Message\ResponseInterface;
use Zend\Diactoros\Response;
@@ -21,8 +22,8 @@ class BearerResponseTypeTest extends \PHPUnit_Framework_TestCase
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$responseType = new BearerTokenResponse($accessTokenRepositoryMock);
$responseType->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$responseType->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$responseType->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$responseType->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$client = new ClientEntity();
$client->setIdentifier('clientName');
@@ -66,8 +67,8 @@ class BearerResponseTypeTest extends \PHPUnit_Framework_TestCase
$accessTokenRepositoryMock->method('isAccessTokenRevoked')->willReturn(false);
$responseType = new BearerTokenResponse($accessTokenRepositoryMock);
$responseType->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$responseType->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$responseType->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$responseType->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$client = new ClientEntity();
$client->setIdentifier('clientName');
@@ -89,9 +90,12 @@ class BearerResponseTypeTest extends \PHPUnit_Framework_TestCase
$response = $responseType->generateHttpResponse(new Response());
$json = json_decode((string) $response->getBody());
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('isAccessTokenRevoked')->willReturn(false);
$authorizationValidator = new BearerTokenValidator($accessTokenRepositoryMock);
$authorizationValidator->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$authorizationValidator->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$authorizationValidator->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$authorizationValidator->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$request = new ServerRequest();
$request = $request->withHeader('authorization', sprintf('Bearer %s', $json->access_token));
@@ -110,8 +114,8 @@ class BearerResponseTypeTest extends \PHPUnit_Framework_TestCase
$accessTokenRepositoryMock->method('isAccessTokenRevoked')->willReturn(false);
$responseType = new BearerTokenResponse($accessTokenRepositoryMock);
$responseType->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$responseType->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$responseType->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$responseType->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$client = new ClientEntity();
$client->setIdentifier('clientName');
@@ -134,8 +138,8 @@ class BearerResponseTypeTest extends \PHPUnit_Framework_TestCase
$json = json_decode((string) $response->getBody());
$authorizationValidator = new BearerTokenValidator($accessTokenRepositoryMock);
$authorizationValidator->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$authorizationValidator->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$authorizationValidator->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$authorizationValidator->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$request = new ServerRequest();
$request = $request->withHeader('authorization', sprintf('Bearer %s', $json->access_token . 'foo'));
@@ -152,12 +156,9 @@ class BearerResponseTypeTest extends \PHPUnit_Framework_TestCase
public function testDetermineAccessTokenInHeaderRevokedToken()
{
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('isAccessTokenRevoked')->willReturn(true);
$responseType = new BearerTokenResponse($accessTokenRepositoryMock);
$responseType->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$responseType->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$responseType = new BearerTokenResponse();
$responseType->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$responseType->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$client = new ClientEntity();
$client->setIdentifier('clientName');
@@ -179,9 +180,12 @@ class BearerResponseTypeTest extends \PHPUnit_Framework_TestCase
$response = $responseType->generateHttpResponse(new Response());
$json = json_decode((string) $response->getBody());
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$accessTokenRepositoryMock->method('isAccessTokenRevoked')->willReturn(true);
$authorizationValidator = new BearerTokenValidator($accessTokenRepositoryMock);
$authorizationValidator->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$authorizationValidator->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$authorizationValidator->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$authorizationValidator->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$request = new ServerRequest();
$request = $request->withHeader('authorization', sprintf('Bearer %s', $json->access_token));
@@ -201,12 +205,14 @@ class BearerResponseTypeTest extends \PHPUnit_Framework_TestCase
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$responseType = new BearerTokenResponse($accessTokenRepositoryMock);
$responseType->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$responseType->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$responseType->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$responseType->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$accessTokenRepositoryMock = $this->getMockBuilder(AccessTokenRepositoryInterface::class)->getMock();
$authorizationValidator = new BearerTokenValidator($accessTokenRepositoryMock);
$authorizationValidator->setPrivateKeyPath('file://' . __DIR__ . '/../Stubs/private.key');
$authorizationValidator->setPublicKeyPath('file://' . __DIR__ . '/../Stubs/public.key');
$authorizationValidator->setPrivateKey(new CryptKey('file://' . __DIR__ . '/../Stubs/private.key'));
$authorizationValidator->setPublicKey(new CryptKey('file://' . __DIR__ . '/../Stubs/public.key'));
$request = new ServerRequest();
$request = $request->withHeader('authorization', 'Bearer blah');

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